All Projects → beam-telemetry → Telemetry

beam-telemetry / Telemetry

Licence: apache-2.0
Dynamic dispatching library for metrics and instrumentations.

Programming Languages

elixir
2628 projects
erlang
1774 projects

Projects that are alternatives of or similar to Telemetry

Telemetry metrics
Collect and aggregate Telemetry events over time
Stars: ✭ 144 (-77.74%)
Mutual labels:  events, metrics, instrumentation
Telemetry poller
Periodically gather measurements and publish them as Telemetry events
Stars: ✭ 101 (-84.39%)
Mutual labels:  events, metrics, instrumentation
Mtail
extract internal monitoring data from application logs for collection in a timeseries database
Stars: ✭ 3,028 (+368.01%)
Mutual labels:  metrics, instrumentation
Vector
A reliable, high-performance tool for building observability data pipelines.
Stars: ✭ 8,736 (+1250.23%)
Mutual labels:  events, metrics
Inspectit
inspectIT is the leading Open Source APM (Application Performance Management) tool for analyzing your Java (EE) applications.
Stars: ✭ 513 (-20.71%)
Mutual labels:  metrics, instrumentation
Statix
Fast and reliable Elixir client for StatsD-compatible servers
Stars: ✭ 228 (-64.76%)
Mutual labels:  metrics, instrumentation
Prometheus rabbitmq exporter
Prometheus.io exporter as a RabbitMQ Managment Plugin plugin
Stars: ✭ 248 (-61.67%)
Mutual labels:  metrics, instrumentation
Go Http Metrics
Go modular http middleware to measure HTTP requests independent of metrics backend (with Prometheus and OpenCensus as backend implementations) and http framework/library
Stars: ✭ 128 (-80.22%)
Mutual labels:  metrics, instrumentation
splunk-otel-java
Splunk Distribution of OpenTelemetry Java
Stars: ✭ 39 (-93.97%)
Mutual labels:  metrics, instrumentation
Okanshi
mvno.github.io/okanshi
Stars: ✭ 14 (-97.84%)
Mutual labels:  metrics, instrumentation
auth0-instrumentation
The goal of this package is to make it easier to collect information about our services through logs, metrics and error catching.
Stars: ✭ 18 (-97.22%)
Mutual labels:  metrics, instrumentation
Client python
Prometheus instrumentation library for Python applications
Stars: ✭ 2,500 (+286.4%)
Mutual labels:  metrics, instrumentation
Opencensus Web
A stats collection and distributed tracing framework
Stars: ✭ 168 (-74.03%)
Mutual labels:  metrics, instrumentation
Opencensus Node
A stats collection and distributed tracing framework
Stars: ✭ 249 (-61.51%)
Mutual labels:  metrics, instrumentation
Appmetrics
App Metrics is an open-source and cross-platform .NET library used to record and report metrics within an application.
Stars: ✭ 1,986 (+206.96%)
Mutual labels:  metrics, instrumentation
Prometheus.ex
Prometheus.io Elixir client
Stars: ✭ 343 (-46.99%)
Mutual labels:  metrics, instrumentation
Fluxter
Fast and reliable InfluxDB writer for Elixir
Stars: ✭ 96 (-85.16%)
Mutual labels:  metrics, instrumentation
Client java
Prometheus instrumentation library for JVM applications
Stars: ✭ 1,644 (+154.1%)
Mutual labels:  metrics, instrumentation
prometheus-httpd
Expose Prometheus metrics using inets httpd.
Stars: ✭ 21 (-96.75%)
Mutual labels:  metrics, instrumentation
Prometheus.erl
Prometheus.io client in Erlang
Stars: ✭ 276 (-57.34%)
Mutual labels:  metrics, instrumentation

Telemetry

Codecov

Documentation

Telemetry is a dynamic dispatching library for metrics and instrumentations. It is lightweight, small and can be used in any Erlang or Elixir project.

In a nutshell, you register a custom module and function to be invoked for certain events, which are executed whenever there is such event. Event name is a list of atoms. Each event is composed of a numeric value and can have metadata attached to it. Let's see an example.

Imagine that you have a web application and you'd like to log latency and response status for each incoming request. With Telemetry, you can build a module which does exactly that whenever a response is sent. The first step is to execute a measurement.

In Elixir:

:telemetry.execute(
  [:web, :request, :done],
  %{latency: latency},
  %{request_path: path, status_code: status}
)

In Erlang:

telemetry:execute(
  [web, request, done],
  #{latency => Latency},
  #{request_path => Path, status_code => Status}
)

Then you can create a module to be invoked whenever the event happens.

In Elixir:

defmodule LogResponseHandler do
  require Logger

  def handle_event([:web, :request, :done], measurements, metadata, _config) do
    Logger.info("[#{metadata.request_path}] #{metadata.status_code} sent in #{measurements.latency}")
  end
end

In Erlang:

-module(log_response_handler).

-include_lib("kernel/include/logger.hrl")

handle_event([web, request, done], #{latency := Latency}, #{request_path := Path,
                                                            status_code := Status}, _Config) ->
  ?LOG_INFO("[~s] ~p sent in ~p", [Path, Status, Latency]).

Important note:

The handle_event callback of each handler is invoked synchronously on each telemetry:execute call. Therefore, it is extremely important to avoid blocking operations. If you need to perform any action that it is not immediate, consider offloading the work to a separate process (or a pool of processes) by sending a message.

Finally, all you need to do is to attach the module to the executed event.

In Elixir:

:ok = :telemetry.attach(
  # unique handler id
  "log-response-handler",
  [:web, :request, :done],
  &LogResponseHandler.handle_event/4,
  nil
)

In Erlang:

ok = telemetry:attach(
  %% unique handler id
  <<"log-response-handler">>,
  [web, request, done],
  fun log_response_handler:handle_event/4,
  []
)

You might think that it isn't very useful, because you could just as well write a log statement instead of Telemetry.execute/3 call - and you would be right! But now imagine that each Elixir library would publish its own set of events with information useful for introspection. Currently each library rolls their own instrumentation layer - Telemetry aims to provide a single interface for these use cases across whole ecosystem.

In order to provide uniform events that capture the start and end of discrete events, it is recommended that you use the telemetry:span/3 call. This function will generate a start event and a stop or exception event depending on whether the provided function successfully executed or raised and error. Under the hood, the telemetry:span/3 function leverages the telemetry:execute/3 function, so all the same usage patterns apply. If an exception does occur, an EventPrefix ++ [exception] event will be emitted and the caught error will be re-raised.

The measurements for the EventPrefix ++ [start] event will contain a key called system_time which is derived by calling erlang:system_time(). For EventPrefix ++ [stop] and EventPrefix ++ [exception] events, the measurements will contain a key called duration, whose value is derived by calling erlang:monotonic_time() - StartMonotonicTime. Both system_time and duration represent time as native units.

To convert the duration from native units you can use:

milliseconds = System.convert_time_unit(duration, :native, :millisecond)

To create span events, you would do something like so:

In Elixir:

def process_message(message) do
  start_metadata = %{message: message}
  result = :telemetry.span(
    [:worker, :processing],
    start_metadata,
    fn ->
      result = # Process the message
      {result, %{metadata: "Information related to the processing of the message"}}
    end
  )
end

In Erlang:

process_message(Message) ->
  StartMetadata =  #{message => Message},
  Result = telemetry:span(
    [worker, processing],
    StartMetadata,
    fun() ->
      Result = % Process the message
      {Result, #{metadata => "Information related to the processing of the message"}}
    end
  ).

To then attach to the events that telemetry:span/3 emits you would do the following:

In Elixir:

:ok = :telemetry.attach_many(
  "log-response-handler",
  [
    [:worker, :processing, :start],
    [:worker, :processing, :stop],
    [:worker, :processing, :exception]
  ],
  &LogResponseHandler.handle_event/4,
  nil
)

In Erlang:

ok = telemetry:attach_many(
  <<"log-response-handler">>,
  [
    [worker, processing, start],
    [worker, processing, stop],
    [worker, processing, exception]
  ],
  fun log_response_handler:handle_event/4,
  []
)

With the following event handler module defined:

In Elixir:

defmodule LogResponseHandler do
  require Logger

  def handle_event(event, measurements, metadata, _config) do
    Logger.info("Event: #{inspect(event)}")
    Logger.info("Measurements: #{inspect(measurements)}")
    Logger.info("Metadata: #{inspect(metadata)}")
  end
end

In Erlang:

-module(log_response_handler).

-include_lib("kernel/include/logger.hrl")

handle_event(Event, Measurements, Metadata, _Config) ->
  ?LOG_INFO("Event: ~p", [Event]),
  ?LOG_INFO("Measurements: ~p", [Measurements]),
  ?LOG_INFO("Metadata: ~p", [Metadata]).

See the documentation for more details.

Installation

Telemetry is available on Hex. To install, just add it to your dependencies in mix.exs:

defp deps() do
  [
    {:telemetry, "~> 0.4"}
  ]
end

or rebar.config:

{deps, [{telemetry, "~> 0.4"}]}.

Copyright and License

Telemetry is copyright (c) 2018 Chris McCord and Erlang Solutions.

Telemetry source code is released under Apache License, Version 2.0.

See LICENSE and NOTICE files for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].