Skip to content

open-telemetry/opentelemetry-erlang

OpenTelemetry Erlang/Elixir


Hex.pm Hex.pm Hex.pm EEF Observability WG project

GitHub Workflow Status Codecov


OpenTelemetry distributed tracing framework for Erlang and Elixir.

These applications implement version 1.8.0 of the OpenTelemetry Specification, see the spec compliance matrix for a list of features supported.

Requirements

  • Erlang/OTP 23+ (With best effort for OTP 22 support)

If using the Elixir API:

  • Elixir 1.13+

Contacting Us

We hold weekly meetings. See details at community page.

We use GitHub Discussions for support or general questions. Feel free to drop us a line.

We are also present in the #otel-erlang-elixir channel in the CNCF slack. Please join us for more informal discussions.

You can also find us in the #opentelemetry channel on Elixir Slack.

Getting Started

You can find a getting started guide on opentelemetry.io.

To start capturing distributed traces from your application it first needs to be instrumented. The easiest way to do this is by using an instrumentation library. There are a number of officially supported instrumentation libraries for popular Erlang and Elixir libraries and frameworks.

Design

The OpenTelemetry specification defines a language library as having two components, the API and the SDK. The API must not only define the interfaces of any implementation in that language but also be able to function as a noop implementation of the tracer. The SDK is the default implementation of the API that must be optional.

When instrumenting a project, your application should only depend on the OpenTelemetry API application, found in directory apps/opentelemetry_api of this repo. The API is published as the Hex package opentelemetry_api.

The SDK implementation, found under apps/opentelemetry and Hex package opentelemetry, should be included in an OTP Release along with an exporter.

Example of Release configuration in rebar.config:

{relx, [{release, {my_instrumented_release, "0.1.0"},
         [opentelemetry_exporter,
	      {opentelemetry, temporary},
          my_instrumented_app]},

       ...]}.

Example configuration for mix's Release task:

def project do
  [
    releases: [
      my_instrumented_release: [
        applications: [opentelemetry_exporter: :permanent, opentelemetry: :temporary]
      ],

      ...
    ]
  ]
end

Note that you also need to add opentelemetry_exporter before your other opentelemetry dependencies in mix.exs, so that it starts before opentelemetry does.

In the above example opentelemetry_exporter is listed first, ensuring that all of its dependencies are booted before opentelemetry attempts to start the exporter. opentelemetry is set to temporary so that if the opentelemetry application crashes, or is shutdown, it does not terminate the other applications in the project -- opentelemetry_exporter does not not need to be temporary because it does not have a startup and supervision tree. This is optional; the opentelemetry application purposely sticks to permanent for the processes started by the root supervisor to leave it up to the end user whether they want the crash or shutdown or opentelemetry to be ignored or cause the shutdown of the rest of the applications in the release.

Git Dependencies

While it is recommended to use the Hex packages for the API, SDK and OTLP exporter, there are times depending on the git repo is necessary. Because the OpenTelemetry OTP Applications are kept in a single repository, under the directory apps, either rebar3's git_subdir (rebar 3.14 or above is required) or mix's sparse feature must be used when using these as Git dependencies in a project. The blocks below show how the git repo for the API and/or SDK Applications can be used in rebar3 and mix.

{opentelemetry_api, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"}, "apps/opentelemetry_api"}},
{opentelemetry, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"},
"apps/opentelemetry"}},
{opentelemetry_exporter, {git_subdir, "http://github.com/open-telemetry/opentelemetry-erlang", {branch, "main"}, "apps/opentelemetry_exporter"}}
{:opentelemetry_api, github: "open-telemetry/opentelemetry-erlang", sparse:
"apps/opentelemetry_api", override: true},
{:opentelemetry, github: "open-telemetry/opentelemetry-erlang", sparse:
"apps/opentelemetry", override: true},
{:opentelemetry_exporter, github: "open-telemetry/opentelemetry-erlang", sparse: "apps/opentelemetry_exporter", override: true}

The override: true is required because the SDK Application, opentelemetry, has the API in its deps list of its rebar.config as a Hex dependency and this will clash when mix tries to resolve the dependencies and fail without the override. override: true is also used on the SDK because the opentelemetry_exporter application depends on it and the API as Hex deps so if it is included the override is necessary.

Benchmarks

Running benchmarks is done with benchee. Benchmark functions are stored in modules, under samples/. To run them, open a rebar3 shell in the bench profile:

$ rebar3 as bench shell

> otel_benchmarks:run().

If an Elixir script is wanted for the benchmarks they could be run (after running rebar3 as bench compile) as follows:

$ ERL_AFLAGS="-pa ./_build/bench/extras/samples/" ERL_LIBS=_build/bench/lib/ mix run --no-mix-exs samples/run.exs

W3C Trace Context Interop Tests

Start the interop web server in a shell:

$ rebar3 as interop shell

> w3c_trace_context_interop:start().

Then, clone the W3C Trace Context repo and run the tests:

$ cd test
$ python3 test.py http://127.0.0.1:5000/test

Contributing

Approvers (@open-telemetry/erlang-approvers):

Find more about the approver role in community repository.

Maintainers (@open-telemetry/erlang-maintainers):

Find more about the maintainer role in community repository.

Thanks to all the people who have contributed

contributors