Dependency-free client for the Ditliti ingestion API.
The client struct is immutable, matching normal Elixir data-flow: functions
that add context (add_breadcrumb/3, put_user/2, put_session/2) return
an updated struct rather than mutating anything in place.
Summary
Functions
Record a breadcrumb, keeping only the most recent 100.
Capture a rescued exception. Pass the __STACKTRACE__ from the rescue
clause via stacktrace: to include stack frames.
Reads the trace stashed by put_current_trace/1 (or start_trace/2) for this process, if any.
Record and send a span started via start_span/3.
Build a new client. endpoint is the ingestion API base URL.
Stashes trace in the current process's dictionary, so instrumentation
that runs later in the same process without access to the client struct
(e.g. an :telemetry handler attached via Ditliti.Db.attach_ecto_telemetry/3,
which Ecto/Postgrex invoke in the caller's process) can still correlate to
it via current_trace/0. start_trace/2 does this automatically.
Start a child span under the active trace (starting one implicitly if
none is active yet). Returns {updated_client, span}, where span is a
map you pass to finish_span/3 once the operation completes.
Start (or continue, if an inbound traceparent header is given) the
active trace. Downstream calls should read get_traceparent/1 and
forward it as the traceparent header of any outgoing HTTP request to
propagate the trace into the next service.
Types
@type t() :: %Ditliti{ api_key: String.t(), before_send: (map() -> map() | nil) | nil, breadcrumbs: [map()], endpoint: String.t(), environment: String.t() | nil, max_payload_bytes: pos_integer(), max_retries: non_neg_integer(), project_id: String.t(), release: String.t() | nil, retry_base_delay_ms: non_neg_integer(), session_id: String.t() | nil, trace: trace_context() | nil, user: map() | nil }
Functions
Record a breadcrumb, keeping only the most recent 100.
@spec capture_exception(t(), Exception.t(), keyword()) :: :ok | {:error, term()}
Capture a rescued exception. Pass the __STACKTRACE__ from the rescue
clause via stacktrace: to include stack frames.
@spec capture_profile(t(), non_neg_integer(), list(), keyword()) :: :ok | {:error, term()}
@spec current_trace() :: trace_context() | nil
Reads the trace stashed by put_current_trace/1 (or start_trace/2) for this process, if any.
Record and send a span started via start_span/3.
Build a new client. endpoint is the ingestion API base URL.
@spec put_current_trace(trace_context() | nil) :: trace_context() | nil
Stashes trace in the current process's dictionary, so instrumentation
that runs later in the same process without access to the client struct
(e.g. an :telemetry handler attached via Ditliti.Db.attach_ecto_telemetry/3,
which Ecto/Postgrex invoke in the caller's process) can still correlate to
it via current_trace/0. start_trace/2 does this automatically.
Start a child span under the active trace (starting one implicitly if
none is active yet). Returns {updated_client, span}, where span is a
map you pass to finish_span/3 once the operation completes.
Start (or continue, if an inbound traceparent header is given) the
active trace. Downstream calls should read get_traceparent/1 and
forward it as the traceparent header of any outgoing HTTP request to
propagate the trace into the next service.