Atex.Telemetry (atex v0.10.0)

View Source

Telemetry instrumentation for Atex.

Atex emits :telemetry events throughout its subsystems. To receive events, attach handlers using :telemetry.attach/4 or :telemetry.attach_many/4.

:telemetry is an optional dependency. If it is not present in your application's deps, all instrumentation calls compile to no-ops with zero runtime overhead. Add it to your mix.exs to enable instrumentation:

{:telemetry, "~> 1.0"}

Event catalogue

XRPC

[:atex, :xrpc, :request, :start | :stop | :exception]

Emitted for every outgoing XRPC HTTP request (all client types).

  • start measurements: %{system_time: integer()}
  • stop measurements: %{duration: integer()}
  • exception measurements: %{duration: integer()}
  • metadata (all events): %{method: :get | :post, resource: String.t(), endpoint: String.t(), client_type: :login | :oauth | :service_auth | :unauthed}

  • stop additional metadata: %{status: integer()}
  • exception additional metadata: %{kind: :error, reason: term(), stacktrace: list()}

[:atex, :xrpc, :token_refresh, :start | :stop | :exception]

Emitted when a client performs a token refresh (LoginClient or OAuthClient).

  • start measurements: %{system_time: integer()}
  • stop measurements: %{duration: integer()}
  • metadata: %{client_type: :login | :oauth}

Identity Resolver

[:atex, :identity_resolver, :resolve, :start | :stop | :exception]

Emitted for every call to Atex.IdentityResolver.resolve/2.

  • start measurements: %{system_time: integer()}
  • stop measurements: %{duration: integer()}
  • metadata: %{identifier: String.t(), identifier_type: :did | :handle}

[:atex, :identity_resolver, :cache, :hit | :miss]

Emitted at the cache check branch inside resolve/2. :hit means the result was served from cache; :miss means a fresh resolution was performed (including when skip_cache: true is passed).

  • measurements: %{system_time: integer()}
  • metadata: %{identifier: String.t()}

OAuth

All OAuth spans share:

  • start measurements: %{system_time: integer()}
  • stop measurements: %{duration: integer()}
  • metadata: %{issuer: String.t() | nil}

[:atex, :oauth, :authorization_url, :start | :stop | :exception]

Wraps Atex.OAuth.Flow.create_authorization_url/5 (PAR request + URL construction).

[:atex, :oauth, :code_exchange, :start | :stop | :exception]

Wraps Atex.OAuth.Flow.validate_authorization_code/5.

[:atex, :oauth, :token_refresh, :start | :stop | :exception]

Wraps Atex.OAuth.Flow.refresh_token/5.

[:atex, :oauth, :token_revocation, :start | :stop | :exception]

Wraps Atex.OAuth.Flow.revoke_tokens/2.

Service Auth

[:atex, :service_auth, :validate, :start | :stop | :exception]

Wraps Atex.ServiceAuth.validate_jwt/2.

  • start measurements: %{system_time: integer()}
  • stop measurements: %{duration: integer()}
  • metadata: %{iss: String.t() | nil, lxm: String.t() | nil}

Example handler

:telemetry.attach_many(
  "my-app-atex-handler",
  [
    [:atex, :xrpc, :request, :stop],
    [:atex, :identity_resolver, :resolve, :stop]
  ],
  fn event, measurements, metadata, _config ->
    Logger.debug(
      "Atex event: #{inspect(event)} " <>
        "duration=#{measurements.duration} " <>
        "metadata=#{inspect(metadata)}"
    )
  end,
  nil
)

Summary

Functions

Attach telemetry instrumentation to a Req.Request.

Execute a telemetry event.

Span a block with telemetry start/stop/exception events.

Functions

attach_req_plugin(req, opts \\ [])

@spec attach_req_plugin(
  Req.Request.t(),
  keyword()
) :: Req.Request.t()

Attach telemetry instrumentation to a Req.Request.

Adds request and response steps that emit [:atex, :xrpc, :request, ...] events. Pass client_type: to identify the XRPC client variant.

No-op when :telemetry is not loaded.

Options

  • :client_type — one of :login, :oauth, :service_auth, :unauthed (default: :unknown)

Example

Req.new(method: :get, url: url)
|> Atex.Telemetry.attach_req_plugin(client_type: :login)
|> Req.request()

execute(event, measurements, metadata)

@spec execute([atom()], map(), map()) :: :ok

Execute a telemetry event.

Delegates to :telemetry.execute/3. No-op when :telemetry is not loaded.

span(event_prefix, start_metadata, fun)

@spec span([atom()], map(), (-> {result, map()})) :: result when result: any()

Span a block with telemetry start/stop/exception events.

Emits event_prefix ++ [:start] before calling fun and event_prefix ++ [:stop] after it returns. The :start event carries %{system_time: System.system_time()} as measurements and start_metadata as metadata. The :stop event carries %{duration: duration} (in native time units) and the result of merging start_metadata with the extra metadata returned by fun.

fun must return {result, extra_stop_metadata}. This function returns result.

No-op (calls fun and returns result) when :telemetry is not loaded.