Impact (Impact v0.0.1)

Copy Markdown

Impact is an OpenTelemetry-native SDK for capturing LLM/AI traces from Elixir applications and exporting them to Impact via OTLP.

The Elixir SDK is the BEAM-side peer of impact-sdk (Python) and impact-sdk-js (JavaScript/TypeScript). The three SDKs share a canonical attribute schema:

  • impact.context.<key> for app-supplied request context
  • impact.trace.{type,name,path,input,output} for manual spans

Quick start

Impact.init(
  api_key: System.fetch_env!("IMPACT_API_KEY"),
  endpoint: System.get_env("IMPACT_BASE_URL"),
  mode: :auto
)

Impact.context(
  user_id: "u_123",
  interaction_id: "int_abc",
  attributes: %{team: "growth"}
)

Impact.trace [type: :workflow, name: "checkout"] do
  do_work()
end

Runtime modes

Mirrors the Python and JS SDKs:

  • :auto (default) — attach to an existing tracer provider if one is configured, otherwise bootstrap.
  • :bootstrap — always (re)configure :opentelemetry exporter + batch processor.
  • :attach — never replace caller-configured providers; raises if no usable provider is found.

Summary

Functions

Add a timestamped event to the currently active span. Useful for marking notable points within a long-running span (state transitions, retries, cache hits, etc).

Attach context to the current execution. Keys are emitted as impact.context.<key> span attributes for every span created under this process / OTel context.

Flush pending spans synchronously. Useful in scripts, Lambda-style runtimes, and tests.

Initialize Impact. Idempotent — calling twice replays the last configuration.

Returns the deterministic outcome of optional instrumentation activation, aligned with impact.instrumentationResults in the JS SDK.

Add attributes to the currently active span. Useful for response-side attributes that are only known after an operation completes.

Set the status of the currently active span. code is :ok | :error | :unset. message is an optional string (typically required for :error).

Flush and shut down Impact's exporter / batch processor. Safe to call from Application.stop/1.

Wrap an expression in a manual Impact span.

Types

init_opt()

@type init_opt() ::
  {:api_key, String.t() | nil}
  | {:endpoint, String.t() | nil}
  | {:service_name, String.t() | nil}
  | {:mode, :auto | :bootstrap | :attach}
  | {:capture_content, boolean()}
  | {:diag_log_level, :none | :error | :warn | :info | :debug | :verbose}

Functions

add_event(name, attrs \\ %{})

(macro)

Add a timestamped event to the currently active span. Useful for marking notable points within a long-running span (state transitions, retries, cache hits, etc).

Impact.add_event("cache_miss", %{key: cache_key})

context(ctx)

@spec context(keyword() | map()) :: :ok

Attach context to the current execution. Keys are emitted as impact.context.<key> span attributes for every span created under this process / OTel context.

Reserved keys are flattened from :attributes. The canonical reserved keys are: :user_id, :interaction_id, :version_id.

flush(timeout \\ 5000)

@spec flush(timeout :: pos_integer()) :: :ok

Flush pending spans synchronously. Useful in scripts, Lambda-style runtimes, and tests.

init(opts \\ [])

@spec init([init_opt()]) :: :ok | {:error, term()}

Initialize Impact. Idempotent — calling twice replays the last configuration.

instrumentation_results()

@spec instrumentation_results() :: %{optional(atom()) => :ok | {:error, term()}}

Returns the deterministic outcome of optional instrumentation activation, aligned with impact.instrumentationResults in the JS SDK.

set_attributes(attrs)

(macro)

Add attributes to the currently active span. Useful for response-side attributes that are only known after an operation completes.

Impact.trace [type: :llm, name: "bedrock_call", attributes: request_attrs] do
  result = call_llm()
  Impact.set_attributes(%{"gen_ai.usage.input_tokens" => result.tokens})
  result
end

Thin macro over OpenTelemetry.Tracer.set_attributes/1 — re-exported so apps don't need to add :opentelemetry_api to their deps just to set mid-span attributes.

set_status(code, message \\ "")

(macro)

Set the status of the currently active span. code is :ok | :error | :unset. message is an optional string (typically required for :error).

Impact.trace [type: :task, name: "do_thing"] do
  case do_thing() do
    {:ok, _} = ok -> ok
    {:error, reason} = err ->
      Impact.set_status(:error, inspect(reason))
      err
  end
end

shutdown(timeout \\ 5000)

@spec shutdown(timeout :: pos_integer()) :: :ok

Flush and shut down Impact's exporter / batch processor. Safe to call from Application.stop/1.

trace(opts, fun)

(macro)

Wrap an expression in a manual Impact span.

Both block and function forms are supported. Block form is a macro so the block body is evaluated lazily inside the span:

require Impact

Impact.trace [type: :task, name: "payment.authorize"] do
  authorize(order_id)
end

Function form for non-block use:

Impact.trace([type: :task, name: "payment.authorize"], fn ->
  authorize(order_id)
end)