View Source Telemetria (telemetria v0.21.0)

Telemetría is the opinionated wrapper for :telemetry (started with v0.19.0 it became agnostic to the actual telemetry backend and supports OpenTelemetry out of the box, allowing for more custom implementations of the said backend.) It provides handy macros to attach telemetry events to any function, private function, anonymous functions (on per-clause basis) and just random set of expressions.

Telemetría exports three macros:

  • deft/2 which is wrapping Kernel.def/2
  • defpt/2 which is wrapping Kernel.defp/2
  • t/2 which is wrapping the expression passed as the first parameter and adds the options passed as a keyword to the second parameter to the context of the respective telemetry event

Telemetría allows compile-time telemetry events definition and provides a compiler that is responsible for incremental builds and updates of the list of events telemetry is aware about.

Using module attribute

Besides the functions listed above, one might attach Telemetría to the function by annotating it with @telemetria module attribute.

There are several options to pass to this attribute:

  • true — attach the telemetry to the function
  • if: boolean() — compile-time condition
  • if: (result -> boolean()) — runtime condition
  • level: Logger,level() — specify a min logger level to attach telemetry
  • group: atom() — the configured group to manage event throttling, see :throttle setting in Telemetria.Options
  • locals: [atom()] — the list of names of local variables to be exported to the telemetry call
  • transform: [{:args, (list() -> list())}, {:result, (any() -> any())}] — the functions to be called on the incoming attributes and/or result to reshape them
  • reshape: (map() -> map()) — the function to be called on the resulting attributes to reshape them before sending to the actual telemetry handler; the default application-wide reshaper might be set in :telemetria, :reshaper config
  • messenger_channels: %{optional(atom()) => {module, keyword()} — more handy messenger management, several channels config with channels names associated with their implementations and properties

Example

The following code would emit the telemetry event for the function weather, returning result in Celcius and injecting farenheit value under locals

defmodule Forecast do
  use Telemetria

  @telemetria level: :info, group: :weather_reports, locals: [:farenheit]
  def weather(city) do
    fahrenheit = ExternalService.retrieve(city)
    Converter.fahrenheit_to_celcius(fahrenheit)
  end
end

Advantages

Telemetría takes care about managing events in the target application, makes it a single-letter change to turn a function into a function wrapped with telemetry call, measuring the execution time out of the box.

It also allows to easily convert expressions to be be telemetry-aware.

Besides that, telemetry: false flag allows to purge the calls in compile-time resulting in zero overhead (useful for benchmark, or like.)

Example

You need to include the compiler in mix.exs:

defmodule MyApp.MixProject do
  def project do
    [
      # ...
      compilers: [:telemetria | Mix.compilers()],
      # ...
    ]
  end
  # ...
end

In the modules you want to add telemetry to, you should require Telemetria (or, preferably, import Telemetria to make it available without FQN.) Once imported, the macros are available and tracked by the compiler.

defmodule MyMod do
  import Telemetria

  defpt pi, do: 3.14
  deft answer, do: 42 - pi()

  def inner do
    short_result = t(42 * 42)
    result =
      t do
        # long calculations
        :ok
      end
  end
end

Use in releases

:telemetria compiler keeps track of the events in the compiler manifest file to support incremental builds. Also it spits out config/.telemetria.config.json config for convenience. It might be used in in the release configuration as shown below.

releases: [
  configured: [
    # ...,
    config_providers: [{Telemetria.ConfigProvider, "/etc/telemetria.json"}]
  ]
]

Options

  • :otp_app (atom/0) - OTP application this telemetry is attached to. The default value is :telemetria.

  • :enabled (boolean/0) - Specifies whether telemetry should be enabled. The default value is true.

  • :backend (atom/0) - The backend to be used as an actual implementation The default value is Telemetria.Backend.Telemetry.

  • :messenger_channels (map/0) - The messenger channels as a map %{name => {impl, opts}} The default value is %{}.

  • :level - Telemetria level to skip logging beyond, as in Logger The default value is :debug.

  • :purge_level - Telemetria level to purge beyond, as in Logger The default value is :debug.

  • :throttle - The throttling mechanism for throttling through too many events The default value is :none.

  • :strict (boolean/0) - Ignore @telemetria tags without if clause The default value is false.

  • :smart_log (boolean/0) - Log format to use; when true, custom json would be used The default value is false.

  • :applications (keyword/0) - List the applications to enable Telemetria support for, with parameters The default value is [].

  • :json_config_path (String.t/0) - Relative path to JSON config The default value is "config/.telemetria.config.json".

  • :events - The application-specific events.

    See Telemetria.event_prefix/0 and Telemetria.event_name/0.

    The default value is [].

  • :handler - Event handler for this application’s telemetry events. Arity must be 4. The default value is {Telemetria.Handler.Default, :handle_event}.

  • :polling (keyword/0) - The default value is [enabled: false, flush: 5000, poll: 5000].

    • :enabled (boolean/0) - Specifies whether polling should be enabled. The default value is true.

    • :flush (non_neg_integer/0) - Flush interval. The default value is 5000.

    • :poll (non_neg_integer/0) - Poll interval. The default value is 5000.

  • :process_info (boolean/0) - Specifies whether each telemetry event should include process info. The default value is false.

Summary

Functions

Declares a private function with a telemetry attached, measuring execution time

Declares a function with a telemetry attached, measuring execution time

Attaches telemetry to anonymous function (per clause,) or to expression(s)

Types

event_measurements()

@type event_measurements() :: map()

event_metadata()

@type event_metadata() :: map()

event_name()

@type event_name() :: [atom(), ...] | String.t()

event_prefix()

@type event_prefix() :: [atom()]

event_value()

@type event_value() :: number()

handler_config()

@type handler_config() :: term()

Functions

defpt(call, expr)

(macro)

Declares a private function with a telemetry attached, measuring execution time

deft(call, expr)

(macro)

Declares a function with a telemetry attached, measuring execution time

t(ast, opts \\ [])

(macro)

Attaches telemetry to anonymous function (per clause,) or to expression(s)

telemetry_prefix(env, call)

@spec telemetry_prefix(
  Macro.Env.t(),
  {atom(), keyword(), tuple()} | nil | maybe_improper_list()
) :: [atom()]