# PromExpress
**PromExpress** is a small DSL for defining and emitting
[PromEx](https://hexdocs.pm/prom_ex) metrics with compile-time
validation and minimal boilerplate.
It lets you declare polling and event-based metrics in one place
and automatically generates a `PromEx.Plugin` implementation for discovery
by PromEx.
The aim is not to replace the great `PromEx` library (all credit goes there)
but just to provide a simpler (and opinionated) option for declaring metrics.
## Installation
Add `prom_express` to your dependencies:
```elixir
def deps do
[
{:prom_express, "~> 0.1.0"}
]
end
```
## Defining Metrics
Create a module and use PromExpress.Emitter.
### Event metrics
```elixir
defmodule MyApp.Metrics do
use PromExpress.Emitter, root_event: :my_app
event_metric :requests, :counter,
description: "Number of requests",
tags: [:status]
end
```
### Polling metrics
```elixir
defmodule MyApp.SystemMetrics do
use PromExpress.Emitter, root_event: :my_app, poll_rate: 5_000
polling_metric :memory, :last_value,
description: "Memory usage"
def poll_metrics do
%{memory: :erlang.memory(:total)}
end
end
```
If a module defines polling metrics, it must implement `poll_metrics/0`.
Missing implementations fail compilation.
## Emitting Metrics
### From the same module
```elixir
defmodule MyApp.Metrics do
use PromExpress.Emitter
event_metric :test, :last_value
def handle_request(status) do
PromExpress.metric_event(:requests, 1, %{status: status})
end
end
```
The metric name is validated at compile time when given as a literal atom.
### From another module
```elixir
defmodule MyWorker do
require PromExpress
def record(status) do
PromExpress.metric_event_in(MyApp.Metrics, :requests, 1, %{status: status})
end
end
```
When both the module and metric name are literals, invalid metric names cause
compile-time errors.
## Generated PromEx Plugin Code
Each module using PromExpress.Emitter automatically becomes a PromEx.Plugin
and is marked for discovery by PromEx.
Generated functions include:
- `polling_metrics/1`
- `event_metrics/1`
You can choose to manually register the plugins with your application's
`PromEx` module, or use the `PromExpress.metric_plugins/1` helper to
automatically retrieve all matching plugin modules for a given OTP app.
```elixir
@impl true
def plugins do
[
Plugins.Application,
...
] ++ PromExpress.metric_plugins(:my_app)
end
```
## License
MIT