Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What is telemetry all about

Avatar for Wu Qing Wu Qing
September 04, 2019

What is telemetry all about

Presented at Sept. 2019 meetup of Elixir Sydney
https://www.meetup.com/elixir-sydney/events/qfdzcryzmbgb/
and Elixir Camp 5 (October 25–28, 2019) in Camp Wombaroo, Mittagong, NSW

Avatar for Wu Qing

Wu Qing

September 04, 2019
Tweet

More Decks by Wu Qing

Other Decks in Programming

Transcript

  1. Custom Logger for Ecto 2 config :my_app, MyApp.Repo, url: System.get_env("DATABASE_URL"),

    loggers: [Ecto.LogEntry, {SpandexEcto.EctoLogger, :trace, ["my_repo"]}]
  2. Telemetry API attach(HandlerId, EventName, Function, Config) -> ok | {error,

    already_exists} HandlerId = handler_id() EventName = event_name() Function = handler_function() Config = handler_config() execute(EventName, Measurements, Metadata) -> ok EventName = event_name() Measurements = event_measurements() | event_value() Metadata = event_metadata()
  3. Leap year defmodule Leapyear do def leapyear?(year) do (rem(year, 4)

    == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end end
  4. Leap year defmodule Leapyear do def leapyear?(year) when is_integer(year) do

    (rem(year, 4) == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end end
  5. Leap year defmodule Leapyear do require Logger def leapyear?(year) when

    is_integer(year) do (rem(year, 4) == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end def leapyear?(year) do Logger.warn("Invalid year: #{inspect(year)}") false end end
  6. ! defmodule Leapyear do require Logger def leapyear?(year) when is_integer(year)

    do (rem(year, 4) == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end def leapyear?(year) do Logger.warn("Invalid year: #{inspect(year)}") Appsignal.send_error(%RuntimeError{}, "Invalid year: #{inspect(year)}") false end end
  7. defmodule Leapyear do require Logger def leapyear?(year, _) when is_integer(year)

    do (rem(year, 4) == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end def leapyear?(year, handler) do Logger.warn("Invalid year: #{inspect(year)}") handler.("Invalid year: #{inspect(year)}") false end end
  8. handler = fn msg -> Appsignal.send_error(%RuntimeError{}, msg) end # client

    code Leapyear.leapyear?(2009, handler) Leapyear.leapyear?("whatever", handler)
  9. Ad hoc function passing • Damage to library code !

    • Damage to client code " • Consistency #
  10. What do we want here? • data from the library

    • function from end user • clean API
  11. With telemetry defmodule Leapyear do def leapyear?(year) when is_integer(year) do

    (rem(year, 4) == 0 and rem(year, 100) != 0) or rem(year, 400) == 0 end def leapyear?(year) do metrics = %{message: "Invalid year: #{inspect(year)}} :telemetry.execute([:leapyear, :invalid_input], metrics) false end end
  12. defmodule MyApp.TelemetryAdapter do def handler([:leapyear, :invalid_input], %{message: message}, _meta, _config)

    Logger.warn(message) Appsignal.send_error(%RuntimeError{}, message) end end
  13. Example for Ecto and Datadog # in application.ex :telemetry.attach( "spandex-ecto",

    [:my_app, :repo, :query], &SpandexEcto.TelemetryAdapter.handle_event/4, nil )
  14. Example for Ecto and Datadog defmodule SpandexEcto.TelemetryAdapter do alias SpandexEcto.EctoLogger

    def handle_event([_, repo_name, :query], measurements, metadata, _config) do log_entry = %{ query: metadata.query, source: metadata.source, params: metadata.params, query_time: Map.get(measurements, :query_time, 0), decode_time: Map.get(measurements, :decode_time, 0), queue_time: Map.get(measurements, :queue_time, 0), result: wrap_result(metadata.result) } EctoLogger.trace(log_entry, "#{repo_name}_database") end end
  15. References Official Documentation Telemetry and metrics for all by Arkadiusz

    Gil The "How"s, "What"s, and "Why"s of Elixir Telemetry