pages/Probes.md

# Probes 

A probe is a persistent system metric that's updated at a
consistent rate.

Probes can be either functions, or a module that implements the
`Instruments.Probe` behaviour. If it's a module, its state is controlled by
another process, all implementers need to worry about is the
state transitions.

## Defining probes

First of all, probes must have unique names so their stats won't conflict
with one another. This is enforced at runtime, since it's possible to
define probes progammatically.

### Functions
The simplest way to define a probe is to specify a function:

```elixir
Probe.define("erlang.process_count", :gauge,
  function: fn -> :erlang.system_info(:process_count) end,
  report_interval: 60_000)
```

Since the above definiton doesn't pass in the sample_interval options,
the sample interval is the same as the report interval. The metric will
be sampled and reported every 60 seconds.

### MFA

A simplification of the above example uses the `:mfa` option to specify
a module, function and arguments to be called.
For example,

```elixir
Probe.define("erlang.process_count", :gauge, mfa: {:erlang, :system_info, [:process_count]})
```

You can also have a function that returns a keyword list of stats and
select which keys you want to report. The keys are added to the stat name

```elixir
Probe.define("erlang.memory", :gauge,
  function: fn -> :erlang.memory() end,
  keys: [:total, :atom, :processes],
  report_interval: 60_000)
```

While the `:erlang.memory()` returns a keyword list with 9 entries,
the above call will only produce three metrics, `erlang.memory.total`,
`erlang.memory.atom` and `erlang.memory.processes`.

## Module based Probes
If more control is desired, you can implement a probe module yourself.

```elixir
defmodule MyProbe do
  @behaviour Instruments.Probe
  # callback implementations...
end

# and then define the probe:
Probe.define("system.my_probe", :counter, module: MyProbe)
```

Your module is now a registered probe, and will receive all of the `Probe`
callbacks.