Mayfly.Extension (Mayfly v1.0.0-rc.1)

Copy Markdown View Source

Internal Lambda extension: registers with the Extensions API, subscribes to the Telemetry API, and turns platform telemetry into :telemetry events.

Off by default. Enable with MAYFLY_EXTENSION=1 (or config :mayfly, extension: true / the :extension option of Mayfly.start_link/1). When enabled, Mayfly.Supervisor registers the extension before the first /next poll, which is what Lambda requires of internal extensions, so the cost is one extra HTTP round trip plus the subscription at cold start.

What you get

  • :telemetry events [:mayfly, :platform, type] for every platform record, with the record's metrics (numbers) as measurements and the full record plus time as metadata. type is the part after platform. as an atom: :init_start, :init_runtime_done, :init_report, :start, :runtime_done, :report, :extension, :telemetry_subscription, :log_dropped, ... platform.report carries durationMs, billedDurationMs, memorySizeMB, maxMemoryUsedMB and, on cold starts, initDurationMs – numbers the function cannot otherwise see about itself. Mayfly.Metrics.attach_platform_metrics/2 publishes them as CloudWatch EMF metrics.
  • Every telemetry record is logged at debug level.

What you do not get from this module: a SHUTDOWN hook. Lambda only delivers SHUTDOWN to external extensions; internal extensions registering for it are rejected with ShutdownEventNotSupportedForInternalExtension, so Mayfly registers for INVOKE only. Graceful shutdown is provided separately by Mayfly.Shutdown together with the mayfly-shutdown extension layer.

How it works

  1. POST /2020-01-01/extension/register with Lambda-Extension-Name: mayfly and events ["INVOKE"]; the response header Lambda-Extension-Identifier authenticates later calls.
  2. A :gen_tcp listener is opened on sandbox.localdomain (the only host the Telemetry API may deliver to) and PUT /2022-07-01/telemetry subscribes to platform events with a small buffer (timeoutMs: 25, maxBytes: 262144, maxItems: 1000).
  3. A process loops on GET /2020-01-01/extension/event/next. INVOKE events are acknowledged and otherwise ignored (the pollers handle invocations). Should Lambda ever deliver SHUTDOWN to an internal extension, Mayfly flushes Logger and halts.

Telemetry is delivered after the invocation that produced it has completed (Lambda sends platform.report once the response is posted), so metrics derived from it are attributed by requestId, not by the current invocation. Nothing here runs in the request path.

Summary

Functions

True when the extension should be started (env MAYFLY_EXTENSION, app env, or option).

The identifier Lambda assigned at registration (for tests and diagnostics).

Port of the telemetry listener (for tests).

Functions

enabled?(opts)

@spec enabled?(keyword()) :: boolean()

True when the extension should be started (env MAYFLY_EXTENSION, app env, or option).

identifier(server \\ __MODULE__)

@spec identifier(GenServer.server()) :: String.t()

The identifier Lambda assigned at registration (for tests and diagnostics).

listener_port(server \\ __MODULE__)

@spec listener_port(GenServer.server()) :: :inet.port_number()

Port of the telemetry listener (for tests).