{"id":13563650,"url":"https://github.com/akoutmos/prom_ex","last_synced_at":"2025-05-14T17:03:07.974Z","repository":{"id":37899001,"uuid":"233431593","full_name":"akoutmos/prom_ex","owner":"akoutmos","description":"An Elixir Prometheus metrics collection library built on top of Telemetry with accompanying Grafana dashboards","archived":false,"fork":false,"pushed_at":"2024-10-31T02:27:33.000Z","size":4752,"stargazers_count":653,"open_issues_count":47,"forks_count":110,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-30T12:17:39.084Z","etag":null,"topics":["beam","elixir","grafana","prometheus","telemetry"],"latest_commit_sha":null,"homepage":"","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/akoutmos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["akoutmos"]}},"created_at":"2020-01-12T17:35:06.000Z","updated_at":"2025-04-29T13:40:11.000Z","dependencies_parsed_at":"2023-10-13T04:31:59.922Z","dependency_job_id":"9a36fe06-454d-4d00-aa3e-5c35b3b93be5","html_url":"https://github.com/akoutmos/prom_ex","commit_stats":{"total_commits":550,"total_committers":53,"mean_commits":"10.377358490566039","dds":0.1890909090909091,"last_synced_commit":"0eec6cb8571fda57cd44ab411c68a69018e1c927"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akoutmos%2Fprom_ex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akoutmos%2Fprom_ex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akoutmos%2Fprom_ex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akoutmos%2Fprom_ex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akoutmos","download_url":"https://codeload.github.com/akoutmos/prom_ex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190368,"owners_count":22029631,"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","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":["beam","elixir","grafana","prometheus","telemetry"],"created_at":"2024-08-01T13:01:21.772Z","updated_at":"2025-05-14T17:03:07.899Z","avatar_url":"https://github.com/akoutmos.png","language":"Elixir","funding_links":["https://github.com/sponsors/akoutmos","https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=58083","https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=58082","https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=17615"],"categories":["Instrumenting / Monitoring"],"sub_categories":[],"readme":"\u003c!--START--\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg align=\"center\" width=\"40%\" src=\"guides/images/logo.svg\" alt=\"PromEx Logo\"\u003e\n  \u003cimg align=\"center\" width=\"40%\" src=\"guides/images/logo_text.png\" alt=\"PromEx Logo\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  Prometheus metrics and Grafana dashboards for all of your favorite Elixir libraries\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://hex.pm/packages/prom_ex\"\u003e\n    \u003cimg alt=\"Hex.pm\" src=\"https://img.shields.io/hexpm/v/prom_ex?style=for-the-badge\"\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://github.com/akoutmos/prom_ex/actions\"\u003e\n    \u003cimg alt=\"GitHub Workflow Status (master)\" src=\"https://img.shields.io/github/actions/workflow/status/akoutmos/prom_ex/main.yml?label=Build%20Status\u0026style=for-the-badge\u0026branch=master\"\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://coveralls.io/github/akoutmos/prom_ex?branch=master\"\u003e\n    \u003cimg alt=\"Coveralls master branch\" src=\"https://img.shields.io/coveralls/github/akoutmos/prom_ex/master?style=for-the-badge\"\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://elixir-lang.slack.com/archives/C01NZ0FBFSR\"\u003e\n    \u003cimg alt=\"Elixir Slack Channel\" src=\"https://img.shields.io/badge/slack-%23prom__ex-orange.svg?style=for-the-badge\u0026logo=slack\"\u003e\n  \u003c/a\u003e\n\n  \u003ca href=\"https://github.com/sponsors/akoutmos\"\u003e\n    \u003cimg alt=\"Support PromEx\" src=\"https://img.shields.io/badge/Support%20PromEx-%E2%9D%A4-lightblue?style=for-the-badge\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\u003c!--END--\u003e\n\n# Contents\n\n- [Installation](#installation)\n- [Supporting PromEx](#supporting-promex)\n- [Setting Up PromEx](#setting-up-promex)\n- [Technical Support](#technical-support)\n- [Adding Your Metrics](#adding-your-metrics)\n- [Design Philosophy](#design-philosophy)\n- [Available Plugins](#available-plugins)\n- [Grafana Dashboards](#grafana-dashboards)\n- [Security Concerns](#security-concerns)\n- [Performance Concerns](#performance-concerns)\n- [Attribution](#attribution)\n\n## Installation\n\n[Available in Hex](https://hex.pm/packages/prom_ex), the package can be installed by adding `prom_ex` to your list of\ndependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:prom_ex, \"~\u003e 1.11.0\"}\n  ]\nend\n```\n\nDocumentation can be found at [https://hexdocs.pm/prom_ex](https://hexdocs.pm/prom_ex).\n\n## Supporting PromEx\n\nPromEx has an ambition goal: To provide Prometheus metrics and Grafana dashboards for as many of the libraries in the Elixir ecosystem as possible as well as a framework so that you can manage the lifecycle of your own metrics and dashboards.\n\nIf you rely on PromEx to monitor your production applications, it would much appreciated if you can give back to the\nproject in order to help ensure its continued development.\n\n### Gold Sponsors\n\n\u003ca href=\"https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=58083\"\u003e\n  \u003cimg align=\"center\" height=\"175\" src=\"guides/images/your_logo_here.png\" alt=\"Support the project\"\u003e\n\u003c/a\u003e\n\n### Silver Sponsors\n\n\u003ca href=\"https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=58082\"\u003e\n  \u003cimg align=\"center\" height=\"150\" src=\"guides/images/your_logo_here.png\" alt=\"Support the project\"\u003e\n\u003c/a\u003e\n\n### Bronze Sponsors\n\n\u003ca href=\"https://github.com/sponsors/akoutmos/sponsorships?sponsor=akoutmos\u0026tier_id=17615\"\u003e\n  \u003cimg align=\"center\" height=\"125\" src=\"guides/images/your_logo_here.png\" alt=\"Support the project\"\u003e\n\u003c/a\u003e\n\n## Setting Up PromEx\n\nThe goal of PromEx is to have metrics set up be as simple and streamlined as possible. In that spirit, all\nthat you need to do to start leveraging PromEx along with the built-in plugins is to run the following mix\ntask (the `YOUR_PROMETHEUS_DATASOURCE_ID` value should align with what is configured in Grafana as the name of the\nPrometheus data source):\n\n```\n$ mix prom_ex.gen.config --datasource YOUR_PROMETHEUS_DATASOURCE_ID\n```\n\nThen add the generated module to your `application.ex` file supervision tree (be sure to add it to the top of the\nsupervisor children list so that you do not miss any init-style events from other processes like Ecto.Repo for\nexample):\n\n```elixir\ndefmodule MyCoolApp.Application do\n  use Application\n\n  def start(_type, _args) do\n    children = [\n      # PromEx should be started before anything else as PromEx will caputre init events from\n      # libraries like Ecto, Phoenix and Oban. If it is started after those other supervision trees\n      # you will miss those events and metrics.\n      MyCoolApp.PromEx,\n\n      MyCoolApp.Repo,\n      MyCoolApp.Endpoint\n      ...\n    ]\n\n    opts = [strategy: :one_for_one, name: MyCoolApp.Supervisor]\n    Supervisor.start_link(children, opts)\n  end\nend\n```\n\nWith that in place, all that you need to do is then add the PromEx plug somewhere in your\n`endpoint.ex` file (I would suggest putting it before your `plug Plug.Telemetry` call so that\nyou do not pollute your logs with calls to `/metrics`):\n\n```elixir\ndefmodule MyCoolAppWeb.Endpoint do\n  use Phoenix.Endpoint, otp_app: :my_cool_app\n\n  ...\n\n  plug PromEx.Plug, prom_ex_module: MyCoolApp.PromEx\n  # Or plug PromEx.Plug, path: \"/some/other/metrics/path\", prom_ex_module: MyCoolApp.PromEx\n\n  ...\n\n  plug Plug.RequestId\n  plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]\n\n  ...\n\n  plug MyCoolAppWeb.Router\nend\n```\n\nWith that in place, all you need to do is start your server and you should be able to hit your\nmetrics endpoint and see your application metrics:\n\n```terminal\n$ curl localhost:4000/metrics\n# HELP my_cool_app_application_dependency_info Information regarding the application's dependencies.\n# TYPE my_cool_app_application_dependency_info gauge\nmy_cool_app_application_dependency_info{modules=\"69\",name=\"hex\",version=\"0.20.5\"} 1\nmy_cool_app_application_dependency_info{modules=\"1\",name=\"connection\",version=\"1.0.4\"} 1\nmy_cool_app_application_dependency_info{modules=\"4\",name=\"telemetry_poller\",version=\"0.5.1\"} 1\n...\n```\n\nBe sure to check out the module docs for each plugin that you choose to use to ensure that you are familiar\nwith all of the options that they provide.\n\n## Technical Support\n\nIs your company using or going to use PromEx in production and you need some help? Perhaps you want to create\nsome custom Grafana dashboards and PromEx plugins specific to your business KPIs? What ever your observability\nneeds may be, I can definitely help you and your business out!\n\nFeel free to reach out to me via [Twitter](https://twitter.com/akoutmos), [Elixir Slack](https://elixir-lang.slack.com/archives/D60LPD0N8),\nor my consultancy `Contact Us` form:\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://stagira.com\" target=\"_blank\"\u003e\n    \u003cimg align=\"center\" width=\"40%\" src=\"guides/images/stagira.png\" alt=\"Technical support\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Adding Your Metrics\n\nWhile PromEx provides plugins for a lot of the popular community libraries, you can also leverage it to collect\nmetrics specific to your application. Similarly to how you use the PromEx Ecto plugin to collect metrics\nrelevant to Ecto, you can write your own plugin to collect metrics specific to your application. In fact, the same\ntools that PromEx uses for its plugins are what you should use to create your own application specific plugins.\n\nTo write your own PromEx plugin, create a module that implements the `PromEx.Plugin` behaviour and collect the\nrelevant event/polling/manual metrics. Be sure to check out the 1st party PromEx plugins as a reference for how\nplugins are written and how to collect the different types of data points (also checkout the [Writing PromEx Plugins\n](https://hexdocs.pm/prom_ex/writing-promex-plugins.html) guide).\n\nAs a side note, PromEx will attach its own Telemetry handlers to events in order to capture Prometheus compatible\nmetrics and so any data points that are added to your `telemetry.ex` file (if you are using LiveDashboard) will\nnot show up in PromEx. One of the benefits of the Telemetry library is that you can have an arbitrary number of\nevent handlers attached to Telemetry events and so LiveDashboard and PromEx can operate in the same application\nwithout any issues.\n\n## Design Philosophy\n\nWith the widespread adoption of the Telemetry library and the other libraries in the [BEAM Telemetry GitHub\nOrg](https://github.com/beam-telemetry), we have reached a point in the Elixir ecosystem where we have a consistent\nmeans of surfacing application and library metrics. This allows us to have a great level of insight into our\napplications and dependencies given that they all leverage the same fundamental tooling. The goal of this project is to\nprovide a \"Plug-in\" style library where you can easily add new plug-ins to surface metrics so that Prometheus can scrape\nthem. Ideally, this project acts as the \"Metrics\" pillar in your application (in reference to [The Three Pillars of\nObservability](https://www.oreilly.com/library/view/distributed-systems-observability/9781492033431/ch04.html)).\n\nTo this end, while PromEx does provide a certain level of configurability (like the polling rate, starting behaviour for\nmanual metrics and all the options that the plugins receive), the goal is not to make an infinitely configurable tool.\nFor example, you are not able to edit the names/descriptions of Prometheus metrics via plugin options or even the tags\nthat are attached to the data points.\n\nInstead, if there things that you don't agree with or that are incompatible with your usage of a certain 1st party\nplugin and want to edit how the PromEx plugins react to Telemetry events, it is recommended that you fork the plugin in\nquestion and edit it to your specific use case. If you think that the community can benefit for your changes, do not\nhesitate to make a PR and I'll be sure to review it. This is not to say that event configurability will never come to\nPromEx, but I want to make sure that the public facing API is clean and straightforward and not bogged down with too\nmuch configuration. In addition, the Grafana dashboards would then have to have a lot of templatized logic to\naccommodate all this configurability (something which has been a pain-point in the Helm community for example).\n\nPromEx provides the following utilities to you in order to achieve your observability goals:\n\n- The `PromEx.Plug` module that can be used in your Phoenix or Plug application to expose the collected metrics\n- A standalone HTTP metrics server if Phoenix is not a dependency in your project\n- A Mix task to upload the provided complimentary Grafana dashboards\n- A Mix task to create a PromEx metrics capture module\n- A behaviour that defines the contract for PromEx plug-ins\n- A behaviour that defines the functionality of a PromEx metrics capture module\n- Grafana dashboards tailored to each specific Plugin so that metrics work out of the box with dashboards\n- Grafana API support to create/upload to dashboard folders and to create graph annotations to mark events in Grafana\n- EEx Grafana dashboard templates so you can dynamically tweak dashboards prior to uploading\n\n## Available Plugins\n\n| Plugin                           | Status      | Description                                                            |\n| -------------------------------- | ----------- | ---------------------------------------------------------------------- |\n| `PromEx.Plugins.Application`     | Stable      | Collect metrics on your application dependencies                       |\n| `PromEx.Plugins.Beam`            | Stable      | Collect metrics regarding the BEAM virtual machine                     |\n| `PromEx.Plugins.Phoenix`         | Stable      | Collect request metrics emitted by Phoenix                             |\n| `PromEx.Plugins.Ecto`            | Stable      | Collect query metrics emitted by Ecto                                  |\n| `PromEx.Plugins.Oban`            | Stable      | Collect queue processing metrics emitted by Oban                       |\n| `PromEx.Plugins.PhoenixLiveView` | Stable      | Collect metrics emitted by Phoenix LiveView                            |\n| `PromEx.Plugins.Absinthe`        | Stable      | Collect GraphQL metrics emitted by Absinthe                            |\n| `PromEx.Plugins.PlugCowboy`      | Stable      | Collect HTTP request metrics emitted by Plug.Cowboy                    |\n| `PromEx.Plugins.PlugRouter`      | Stable      | Collect HTTP request metrics emitted by Plug.Router and Plug.Telemetry |\n| `PromEx.Plugins.Broadway`        | Beta        | Collect message processing metrics emitted by Broadway                 |\n| `PromEx.Plugins.Finch`           | Coming soon | Collect HTTP request metrics emitted by Finch                          |\n| `PromEx.Plugins.Redix`           | Coming soon | Collect Redis request metrics emitted by Redix                         |\n| More to come...                  |             |                                                                        |\n\n## Grafana Dashboards\n\n\u003cimg align=\"center\" width=\"100%\" src=\"guides/images/dashboards_preview.png\" alt=\"PromEx Dashboards\"\u003e\n\nEach PromEx plugin comes with a custom tailored Grafana Dashboard. [Click here](https://hexdocs.pm/prom_ex/all.html)\nto check out sample screenshots of each Plugin specific Grafana Dashboard.\n\n## Security Concerns\n\nBy default, you can set up a Prometheus scrape target without providing any security authorization configuration. As a\nresult, PromEx does not enforce any security precautions by default, and it is up to you to secure your `/metrics`\nendpoint to ensure that people are not seeing sensitive information (sort of like Phoenix LiveDashboard where you need\nto set up your own basic authentication plug to guard access).\n\nThere are a couple of solutions to this problem:\n\n1. If your application is behind a load balancer or an API gateway, you can block access for any external requests to\n   `/metrics` (or whatever route you chose to expose metrics over).\n\n2. If your application is public facing, you can leverage the [Unplug](https://hex.pm/packages/unplug) library that I\n   maintain in order to only execute the `PromEx.Plug` plug when the incoming request fulfills your configured\n   requirements (see the [PromEx.Plug HexDocs](https://hexdocs.pm/prom_ex/1.1.1/PromEx.Plug.html) for an example).\n\n3. If Unplug doesn't suit your needs, you can invoke `PromEx.Plug`\n   [conditionally with your own logic](https://hexdocs.pm/plug/1.16.1/Plug.Builder.html#module-conditional-plugs).\n\n## Performance Concerns\n\nYou may think to yourself that with all these metrics being collected and scraped, that the performance of your\napplication may be negatively impacted. Luckily PromEx is built upon the solid foundation established by the `Telemetry`,\n`TelemetryMetrics`, and the `TelemetryMetricsPrometheus` projects. These libraries were designed to be as lightweight\nand performant as possible. From some basic stress tests that I have run, I have been unable to observe any meaningful\nperformance reduction (thank you OTP and particularly ETS ;)). Below are the results from a recent stress test using\nApacheBench:\n\n### With PromEx metrics collection\n\n```terminal\n$ ./benchmarks/ab-graph.sh -u http://localhost:4000 -n 1000 -c 50 -k\nServer Software:        Cowboy\nServer Hostname:        localhost\nServer Port:            4000\n\nDocument Path:          /\nDocument Length:        3389 bytes\n\nConcurrency Level:      50\nTime taken for tests:   4.144 seconds\nComplete requests:      1000\nFailed requests:        0\nKeep-Alive requests:    1000\nTotal transferred:      4060000 bytes\nHTML transferred:       3389000 bytes\nRequests per second:    241.32 [#/sec] (mean)\nTime per request:       207.191 [ms] (mean)\nTime per request:       4.144 [ms] (mean, across all concurrent requests)\nTransfer rate:          956.81 [Kbytes/sec] received\n\nConnection Times (ms)\n              min  mean[+/-sd] median   max\nConnect:        0    0   0.2      0       1\nProcessing:    39  202  24.3    203     264\nWaiting:       38  202  24.3    203     264\nTotal:         39  202  24.2    203     264\n\nPercentage of the requests served within a certain time (ms)\n  50%    203\n  66%    210\n  75%    215\n  80%    218\n  90%    227\n  95%    237\n  98%    246\n  99%    255\n 100%    264 (longest request)\n```\n\n### Without PromEx metrics collection\n\n```terminal\n$ ./benchmarks/ab-graph.sh -u http://localhost:4000 -n 1000 -c 50 -k\nServer Software:        Cowboy\nServer Hostname:        localhost\nServer Port:            4000\n\nDocument Path:          /\nDocument Length:        3389 bytes\n\nConcurrency Level:      50\nTime taken for tests:   4.156 seconds\nComplete requests:      1000\nFailed requests:        0\nKeep-Alive requests:    1000\nTotal transferred:      4060000 bytes\nHTML transferred:       3389000 bytes\nRequests per second:    240.59 [#/sec] (mean)\nTime per request:       207.822 [ms] (mean)\nTime per request:       4.156 [ms] (mean, across all concurrent requests)\nTransfer rate:          953.90 [Kbytes/sec] received\n\nConnection Times (ms)\n              min  mean[+/-sd] median   max\nConnect:        0    0   0.1      0       1\nProcessing:    38  202  23.1    205     267\nWaiting:       37  202  23.1    205     267\nTotal:         38  202  23.0    205     267\n\nPercentage of the requests served within a certain time (ms)\n  50%    205\n  66%    211\n  75%    215\n  80%    219\n  90%    226\n  95%    232\n  98%    238\n  99%    246\n 100%    267 (longest request)\n```\n\n### Plotting the stress test results\n\nIn the spirit of visualizing performance characteristics, the percentile data from the ApacheBench stress tests has been\noverlaid and plotted using Gnuplot (thanks to\n[apachebench-graphs](https://github.com/juanluisbaptiste/apachebench-graphs) for making Gnuplot-ing a lot more\nstreamlined :)). As we can see, the distributions track each other more or less 1:1 except for the slowest 5-10% of requests where\nwe see a slight performance hit. In other words, 90% of the time there was no measurable performance overhead in the\ninstrumented application.\n\n\u003cimg align=\"center\" width=\"100%\" src=\"guides/images/apache_bench_stress_test.png\" alt=\"PromEx Stress Test\"\u003e\n\n## Attribution\n\nIt wouldn't be right to not include somewhere in this project a \"thank you\" to the various projects and people that\nhelped make this possible:\n\n- The various projects available in [BEAM Telemetry](https://github.com/beam-telemetry)\n- All of the Prometheus libraries that Ilya Khaprov ([@deadtrickster](https://github.com/deadtrickster)) maintains\n- The logo for the project is an edited version of an SVG image from the [unDraw project](https://undraw.co/)\n- Juan Luis Baptiste for the nifty ApacheBench+Gnuplot shell scripts [apachebench-graphs](https://github.com/juanluisbaptiste/apachebench-graphs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakoutmos%2Fprom_ex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakoutmos%2Fprom_ex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakoutmos%2Fprom_ex/lists"}