View Source Telemetrex (telemetrex v0.2.2)

Elixir wrapper for :telemetry.

With the :telemetry library being written in a way that was both Erlang and Elixir friendly, the syntax can be heavy for adding telemetry to business rules. For example, given the following module:

defmodule MyApp.Users do
  def user_create(user_params) do
    %MyApp.User{}
    |> MyApp.User.create_changeset(users_params)
    |> MyApp.Repo.insert()
  end
end

If wanting to implement telemetry using :telemetry.span, it would result in the following:

defmodule MyApp.Users do
  def user_create(user_params) do
    :telemetry.span([:my_app, :user_create], %{params: user_params}, fn -> 
      %MyApp.User{}
      |> MyApp.User.create_changeset(users_params)
      |> MyApp.Repo.insert() 
      |> case do
        {:ok, %MyApp.User{} = user} = result ->
          {result, %{user: user}}
        {:error, changeset} = result ->
          {result, %{error: true, changeset: changeset}}
      end
    end)
  end
end

By adding telemetry with :telemetry.span, this operation created a lot of additional noise and was more intrusive to the business rules. By leveraging Elixir macros, much friendlier syntax can be achieved:

defmodule MyApp.Users do
  require Telemetrex

  def user_create(user_params) do
    Telemetrex.span event: [:my_app, :user_create], context: %{params: user_params} do
      %MyApp.User{}
      |> MyApp.User.create_changeset(user_params)
      |> MyApp.Repo.insert()
    after
      {:ok, %MyApp.User{} = user} ->
        %{user: user}

      {:error, changeset} ->
        %{error: true, changeset: changeset}
    end
  end
end

Summary

Functions

Provides a human-readable duration with correct units.

An Elixir-friendly wrapper for :telemetry.span.

Functions

Link to this function

pretty_duration(duration)

View Source

Provides a human-readable duration with correct units.

Pass the duration of the :telemetry span from the returned measurements to prettify the display for easier reading, i.e., in logs, etc.

Note: the duration's time unit is native to the machine where the code is running when coming from :telemetry

iex> Telemetrex.pretty_duration(2083)
"2µs"

iex> Telemetrex.pretty_duration(150_000_000)
"150ms"
Link to this macro

span(opts, clauses)

View Source (macro)

An Elixir-friendly wrapper for :telemetry.span.

Options

  • event - event prefix that will be added to start/stop events
  • context - initial context added to start event
  • merge? (default: true) - whether to merge start and stop metadata
def user_create(user_params) do
  Telemetrex.span event: [:my_app, :user_create], context: %{params: user_params} do
    %MyApp.User{}
    |> MyApp.User.create_changeset(user_params)
    |> MyApp.Repo.insert()
  after
    {:ok, %MyApp.User{} = user} ->
      %{user: user}

    {:error, changeset} ->
      %{error: true, changeset: changeset}
  end
end

Everything in the do block becomes the return value of the macro. This value is also passed to the optional after block, which can be used to set additional metadata for the ending event.

Unlike :telemetry.span, the metadata in the ending event is merged with the initial context. If you do not want them merged, set merged? to false. There are some areas where avoiding the overhead of the merge operation is desirable such as ecto or over high performance telemetry events.