README.md

![Tests](https://github.com/msramos/hackney_telemetry/actions/workflows/ci.yml/badge.svg)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)

> [!IMPORTANT]
> This is the new upstream of this project. The [TheRealReal](https://github.com/TheRealReal/hackney_telemetry) repository will no longer be mantained.

# hackney_telemetry

Telemetry adapter for Hackney metrics.

This module is a [metrics handler](https://github.com/benoitc/hackney/blob/master/README.md#metrics)
for the [Hackney](https://github.com/benoitc/hackney) HTTP client. It receives
calls from Hackney to update metrics and generates [Telemetry](https://github.com/beam-telemetry/telemetry) events.

Hackney supports storing metrics in [Folsom](https://hex.pm/packages/folsom) or
[Exometer](https://hex.pm/packages/exometer_core). Unfortunately, these
libraries do not export data in a way that is useful for Telemetry,
so we need to transform the metrics data before reporting it.

## Telemetry metrics

The following metrics are exported by this library to telemetry.

| Metric                      | Tags | Meaning                                               |
| --------------------------- | ---- | ----------------------------------------------------- |
| `hackney.nb_requests`       | -    | Current number of requests                            |
| `hackney.finished_requests` | -    | Total number of finished requests                     |
| `hackney.total_requests`    | -    | Total number of requests                              |
| `hackney_pool.free_count`   | pool | Number of free sockets in a connection pool           |
| `hackney_pool.in_use_count` | pool | Number of busy sockets in a connection pool           |
| `hackney_pool.no_socket`    | pool | Count of new connections                              |
| `hackney_pool.queue_count`  | pool | Number of requests waiting for a connection in a pool |
| `hackney_pool.take_rate`    | pool | Rate at which a connection is retrieved from the pool |

This module implements all the callbacks required by `hackney_metrics` but it does
not support host metrics.

To use it, configure Hackney `mod_metrics` to use this module and make sure
that the `hackney_telemetry` application starts before your application.

Hackney calls the module specified by `mod_metrics` to report instrumentation
metrics. This module receives the data from Hackney and passes it to a
`hackney_telemetry_worker` which keeps the current state of the metric and
generates Telemetry events.

A worker process has two jobs:

1.  Calculate metric values

    Hackney does not keep the state of its metrics, but instead emits events to
    the metrics engine, like "increase this counter by 1", "set this gauge to X",
    "add Y to this histogram". The job of a metric worker is to process these
    events and keep up-to-date state representing the value of the tracked metric.
    State updates run in constant time (O(1)), important since a single
    request generates about nine metric updates.

2.  Send metric values to Telemetry

    If we send the metric value to Telemetry after every update, then
    telemetry processing may not be able to keep up, and Telemetry will apply
    backpressure.

    Since the worker maintains the most up-to-date value, we can send the current
    value periodically. Gauge metrics may be less accurate, but it avoids overload.

## Installation

Install it from [Hex](https://hex.pm/packages/hackney_telemetry) or
[Github](https://github.com/msramos/hackney_telemetry).

## Configuration

Configure set Hackney to send metrics to this module:

**Erlang**

```erlang
{hackney, [{mod_metrics, hackney_telemetry}]}
```

**Elixir**

```elixir
config :hackney, mod_metrics: :hackney_telemetry
```

### Options

#### Report interval

By default, workers will report data to telemetry every 1000 milliseconds.
If set to 0, events are generated after every update.

You can change that by setting the `report_interval` option:

**Erlang**

```erlang
{hackney_telemetry, [{report_interval, 2000}]}
```

**Elixir**

```elixir
config :hackney_telemetry, report_interval: 2_000
```

## Usage

After installing the module, your application will receive Telemetry events.
You can handle them in your application, or install a reporting module such
as [Telemetry.Metrics](https://hex.pm/packages/telemetry_metrics)
or [prom_ex](https://hex.pm/packages/prom_ex).

## Elixir

```elixir
defmodule YourApplcation.Telemetry do
  import Telemetry.Metrics

  def metrics do
  [
    # other metrics

    last_value("hackney.nb_requests"),
    last_value("hackney.finished_requests"),
    last_value("hackney.total_requests"),
    last_value("hackney_pool.free_count", tags: [:pool]),
    last_value("hackney_pool.in_use_count", tags: [:pool]),
    last_value("hackney_pool.no_socket", tags: [:pool]),
    last_value("hackney_pool.queue_count", tags: [:pool]),
    last_value("hackney_pool.take_rate", tags: [:pool])
  ]
  end
end
```

## Building

To build the source code locally you'll need [rebar3](https://github.com/erlang/rebar3):

```
rebar3 compile
```

## Test

```console
rebar3 ct
```

## Docs

```console
rebar3 ex_doc
```

## Format code

```console
rebar3 format
```

## Code of Conduct

This project  Contributor Covenant version 2.1. Check [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file for more information.

## License

`hackney_telemetry` source code is released under Apache License 2.0.

Check [NOTICE](NOTICE) and [LICENSE](LICENSE) files for more information.