View Source Electric.Telemetry.OpenTelemetry (electric v0.9.5)

This module implements an API to cover parts of the code with tracing spans that are then exported using the OpenTelemetry protocol.

OpenTelemetry is an observability framework that is widely supported by observability tools.

This module's implementation is based on the opentelemetry-erlang suite of libraries. There is a rudimentary Elixir API there but it's incomplete and non-idiomatic. The idea with this module is to expose all of the functionality we're using in our code by wrapping opentelemetry-erlang's API.

The configuration for OpenTelemetry export is located in config/runtime.exs.

The API implemented here so far includes support for:

  • Defining a span to cover the execution of a piece of code. See with_span/3.

  • Propagating span context across Elixir processes, to allow for a span started in one process to be registered as a parent of a span started in a different process. See async_fun/4.

  • Adding dynamic attributes to the current span, after it has already started. See add_span_attributes/2.

  • Recording an error or an exception as a span event. See record_exception/4.

Summary

Functions

Add dynamic attributes to the current span.

Wrap the given fun in an anonymous function, attaching the current process' span context to it.

Retrieve the telemetry span attributes from the persistent term for this stack.

Add an error event to the current span.

Store the telemetry span attributes in the persistent term for this stack.

Executes the provided function and records its duration in microseconds. The duration is added to the current span as a span attribute named with the given name.

Create a span that starts at the current point in time and ends when fun returns.

Functions

Link to this function

add_span_attributes(span_ctx \\ nil, attributes)

View Source
@spec add_span_attributes(span_ctx() | nil, span_attrs()) :: boolean()

Add dynamic attributes to the current span.

For example, if a span is started prior to issuing a DB request, an attribute named num_rows_fetched can be added to it using this function once the DB query returns its result.

Link to this function

async_fun(span_ctx \\ nil, name, attributes, stack_id, fun)

View Source
@spec async_fun(span_ctx() | nil, span_name(), span_attrs(), String.t(), (-> t)) ::
  (-> t)
when t: term()

Wrap the given fun in an anonymous function, attaching the current process' span context to it.

If the wrapped function starts a new span in a different Elixir process, the attached span context will be used to establish the parent-child relationship between spans across the process boundary.

Link to this function

get_stack_span_attrs(stack_id)

View Source
@spec get_stack_span_attrs(String.t()) :: map()

Retrieve the telemetry span attributes from the persistent term for this stack.

Link to this function

record_exception(error_str, attributes \\ [])

View Source

Add an error event to the current span.

Link to this function

record_exception(kind, error, stacktrace, attributes \\ [])

View Source
Link to this function

set_current_context(span_ctx)

View Source
Link to this function

set_stack_span_attrs(stack_id, attrs)

View Source
@spec set_stack_span_attrs(String.t(), span_attrs()) :: :ok

Store the telemetry span attributes in the persistent term for this stack.

Link to this function

timed_fun(span_ctx \\ nil, name, fun)

View Source
@spec timed_fun(span_ctx() | nil, attr_name(), (-> term())) :: term()

Executes the provided function and records its duration in microseconds. The duration is added to the current span as a span attribute named with the given name.

Link to this function

with_span(name, attributes, stack_id, fun)

View Source
@spec with_span(span_name(), span_attrs(), String.t(), (-> t)) :: t when t: term()

Create a span that starts at the current point in time and ends when fun returns.

Returns the result of calling the function fun.

Calling this function inside another span establishes a parent-child relationship between the two, as long as both calls happen within the same Elixir process. See async_fun/4 for interprocess progragation of span context.