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

What is telemetry all about

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

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