{"id":30883279,"url":"https://github.com/globocom/alchemetrics","last_synced_at":"2025-09-08T09:44:12.955Z","repository":{"id":57478786,"uuid":"96434056","full_name":"globocom/alchemetrics","owner":"globocom","description":"Elixir metrics reporter and collector","archived":false,"fork":false,"pushed_at":"2021-12-01T13:19:20.000Z","size":434,"stargazers_count":35,"open_issues_count":1,"forks_count":6,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-08-13T16:00:36.142Z","etag":null,"topics":["elixir","exometer","gen-stage","metrics"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/globocom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-06T13:36:10.000Z","updated_at":"2024-03-21T16:08:00.000Z","dependencies_parsed_at":"2022-09-17T04:21:43.034Z","dependency_job_id":null,"html_url":"https://github.com/globocom/alchemetrics","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/globocom/alchemetrics","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/globocom%2Falchemetrics","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/globocom%2Falchemetrics/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/globocom%2Falchemetrics/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/globocom%2Falchemetrics/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/globocom","download_url":"https://codeload.github.com/globocom/alchemetrics/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/globocom%2Falchemetrics/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274166943,"owners_count":25233959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","exometer","gen-stage","metrics"],"created_at":"2025-09-08T09:44:08.352Z","updated_at":"2025-09-08T09:44:12.941Z","avatar_url":"https://github.com/globocom.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eAlchemetrics\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Alchemetrics\" src=\"https://github.com/globocom/alchemetrics/blob/master/assets/alchemetrics.png?raw=true\" width=\"128\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Metrics collection and reporting for Elixir applications.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/globocom/alchemetrics\"\u003e\n    \u003cimg alt=\"Travis\" src=\"https://travis-ci.org/globocom/alchemetrics.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href='https://coveralls.io/github/globocom/alchemetrics?branch=master'\u003e\n    \u003cimg src='https://coveralls.io/repos/github/globocom/alchemetrics/badge.svg?branch=master' alt='Coverage Status' /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hex.pm/packages/alchemetrics\"\u003e\n    \u003cimg alt=\"Hex\" src=\"https://img.shields.io/hexpm/dt/alchemetrics.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"http://inch-ci.org/github/globocom/alchemetrics\"\u003e\n    \u003cimg alt=\"Alchemetrics docs\" src=\"http://inch-ci.org/github/globocom/alchemetrics.svg?branch=master\u0026style=flat\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## About\nAlchemetrics makes life easier for anyone who wants to report and distribute metrics from an Elixir application. The metrics can help you to measure performance, detect errors or track information about your application.\n\nAlchemetrics makes use of [GenStage](https://hexdocs.pm/gen_stage/GenStage.html) to ensure that collecting and submitting metrics will not impact application performance.\n\nEach metric report creates a new event that follows the GenStage flow. With the help of the [ConsumerSupervisor](https://hexdocs.pm/gen_stage/ConsumerSupervisor.html), your metrics are distributed with little impact to the application performance.\n\nDocumentation is available at [HexDocs](https://hexdocs.pm/alchemetrics/api-reference.html)\n\n## Installation\n\nAlchemetrics is available on [Hex](https://hex.pm/packages/alchemetrics). All you have to do is to add it to `mix.exs` as a test dependency.\n\n```elixir\ndef deps do\n  [{:alchemetrics, \"~\u003e 0.5.2\"}]\nend\n```\n\n## Reports\nReports are made via calls to Alchemetrics functions. It is through reports that Alchemetrics stores a value to be measured and sent to the backends. Further details about reports can be found in the [documentation available in HexDocs](https://hexdocs.pm/alchemetrics/0.5.2/Alchemetrics.html).\n\n\n## Backends\nCollected metrics are typically stored in some type of datastore, such as Logstash and Influxdb. Alchemetrics uses the concept of backends to distribute the metrics to these data stores. More details can be found in the [documentation about custom backends](https://hexdocs.pm/alchemetrics/0.5.2/Alchemetrics.CustomBackend.html).\n\nWhen a dataset is created, it subscribes to all backends enabled on the application. Datasets created before a backend is enabled will not subscribe to the new backend. Also, when a backend is disabled, all datasets will unsubscribe from it.\n\n### ConsoleBackend\nAlchemetrics comes with a built-in backend called `Alchemetrics.ConsoleBackend`. This backend sends yor metrics to the console and is very useful when debugging.\n\nYou can enable `Alchemetrics.ConsoleBackend` when your application boot by adding it to yor backend list:\n\n```elixir\n# config/config.exs\n\nconfig :alchemetrics,\n  backends: [\n    {Alchemetrics.ConsoleBackend, []}\n  ]\n```\n\nYou can also enable it on the console:\n\n```elixir\n# iex -S mix\n\niex(1)\u003e Alchemetrics.ConsoleBackend.enable\nStarting Elixir.Alchemetrics.ConsoleBackend with following options: []\n:ok\niex(2)\u003e Alchemetrics.report(100, :test)\n:ok\niex(3)\u003e %{datapoint: :avg, name: :test, options: [], value: 100}\n%{datapoint: :max, name: :test, options: [], value: 100}\n%{datapoint: :min, name: :test, options: [], value: 100}\n%{datapoint: :p95, name: :test, options: [], value: 100}\n%{datapoint: :p99, name: :test, options: [], value: 100}\n%{datapoint: :last_interval, name: :test, options: [], value: 100}\n%{datapoint: :total, name: :test, options: [], value: 100}\n```\n\n## Erlang VM metrics\nAlchemetrics automatically collects some information about Erlang's VM, like memory and run queue. This is disabled by default, but you can enable it on the configs:\n\n```elixir\n# config/config.exs\nconfig :alchemetrics, instrument_beam: true\n```\n\nThis will enable the report of some data from Erlang's VM:\n\n```elixir\n%{datapoint: :memory_atom, options: [], type: :memory, value: 621465}\n%{datapoint: :memory_binary, options: [], type: :memory, value: 392504}\n%{datapoint: :memory_ets, options: [], type: :memory, value: 1365728}\n%{datapoint: :memory_processes, options: [], type: :memory, value: 10513080}\n%{datapoint: :memory_total, options: [], type: :memory, value: 38397232}\n%{datapoint: :system_runqueue, options: [], type: :system, value: 1}\n```\n\n### Getting Started: Instrumenting requests on a Phoenix application\nLet's show an example of how Alchemetrics could be used to instrument a Phoenix application with the help of Plug:\n\nIn this example application we will measure:\n\n  - The **number of requests** for each route of the application grouped by the status of the response;\n  - The **response times** (`average`, `percentiles`, `max` and `min`) of each route;\n\nThe collected metrics will be printed to the console by `Alchemetrics.ConsoleBackend`. To do this, we need to enable it in the settings:\n\n```elixir\n# config/config.exs\n\nconfig :alchemetrics,\n  backends: [\n    [module: Alchemetrics.ConsoleBackend, []]\n  ]\n```\n\n\u003e Let's create the RequestInstrumentor plug:\n\n```elixir\n# lib/my_app_web/plugs/request_count.ex\n\ndefmodule RequestInstrumentor do\n  @behaviour Plug\n\n  def init(opts \\\\ []), do: opts\n  def call(conn, opts), do: count_request(conn)\n\n  defp count_request(conn) do\n    start = System.monotonic_time()\n    Plug.Conn.register_before_send(conn, fn conn -\u003e\n      stop = System.monotonic_time()\n      diff = System.convert_time_unit(stop - start, :native, :micro_seconds)\n      # report throughput\n      Alchemetrics.increment(request_count: %{method: conn.method, path: conn.request_path, status: conn.status})\n      # report request time\n      Alchemetrics.report(diff, request_time: %{method: conn.method, path: conn.request_path})\n      conn\n    end)\n  end\nend\n```\n\n\u003e Plug it on Phoenix Endpoint:\n\n```elixir\ndefmodule MyAppWeb.Endpoint do\n  use Phoenix.Endpoint, otp_app: :my_app\n\n  plug RequestInstrumentor\n  ...\nend\n```\n\n\u003e Request your application:\n\n```bash\n$ mix phx.server\n$ curl localhost:4000/\n```\n\n\u003e Information about the request will show on application console:\n\n```elixir\n%{datapoint: :last_interval, options: [], requests_for: %{method: \"GET\", path: \"/\", status: 200}, value: 1}\n%{datapoint: :total, options: [], requests_for: %{method: \"GET\", path: \"/\", status: 200}, value: 1}\n%{datapoint: :avg, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :max, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :min, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :p95, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :p99, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :last_interval, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n%{datapoint: :total, options: [], request_time: %{method: \"GET\", path: \"/\", status: 200}, value: 44069}\n```\n\n\u003e If you request an inexistent route, the reports will show 404 status code:\n\n```elixir\n%{datapoint: :last_interval, options: [], requests_for: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 1}\n%{datapoint: :total, options: [], requests_for: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 1}\n%{datapoint: :avg, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :max, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :min, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :p95, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :p99, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :last_interval, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n%{datapoint: :total, options: [], request_time: %{method: \"GET\", path: \"/invalid_route\", status: 404}, value: 39558}\n```\n\nFor more details about reports, metrics, datasets, backends and all Alchemetrics concepts, take a look at the [docs](https://hexdocs.pm/alchemetrics/0.5.2/api-reference.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglobocom%2Falchemetrics","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglobocom%2Falchemetrics","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglobocom%2Falchemetrics/lists"}