# `Redix.Telemetry`
[🔗](https://github.com/whatyouhide/redix/blob/v1.9.1/lib/redix/telemetry.ex#L1)

Telemetry integration for event tracing, metrics, and logging.

Redix connections (both `Redix` and `Redix.PubSub`) execute the
following Telemetry events:

  * `[:redix, :connection]` - executed when a Redix connection establishes the
    connection to Redis. There are no measurements associated with this event.
    Metadata are:

    * `:cluster` - the cluster name (the atom passed as `:name` to
      `Redix.Cluster.start_link/1`). Only cluster connections include this field.
      *Available since v1.9.0*.
    * `:connection` - the PID of the Redix connection that emitted the event.
    * `:connection_name` - the name (passed to the `:name` option when the
    connection is started) of the Redix connection that emitted the event.
    `nil` if the connection was not registered with a name.
    * `:address` - the original host and port used to connect, or the Unix socket path.
    * `:peer_address` - the connected socket's IP address and port as a string,
      or its Unix socket path. `nil` if the peer address is unavailable.
      *Available since v1.9.0*.
    * `:reconnection` - a boolean that specifies whether this was a first
      connection to Redis or a reconnection after a disconnection. This can
      be useful for more granular logging.

  * `[:redix, :disconnection]` - executed when the connection is lost
    with the Redis server. There are no measurements associated with
    this event. Metadata are:

    * `:cluster` - the cluster name (the atom passed as `:name` to
      `Redix.Cluster.start_link/1`). Only cluster connections include this field.
      *Available since v1.9.0*.
    * `:connection` - the PID of the Redix connection that emitted the event.
    * `:connection_name` - the name (passed to the `:name` option when the
      connection is started) of the Redix connection that emitted the event.
      `nil` if the connection was not registered with a name.
    * `:address` - the original host and port used to connect, or the Unix socket path.
    * `:peer_address` - the peer address saved when the connection opened, in the
      same format as the connection event. `nil` if the peer address was unavailable.
      *Available since v1.9.0*.
    * `:reason` - the disconnection reason as a `Redix.ConnectionError` struct.

  * `[:redix, :failed_connection]` - executed when Redix can't connect to
    the specified Redis server, either when starting up the connection or
    after a disconnection. There are no measurements associated with this event.
    Metadata are:

    * `:cluster` - the cluster name (the atom passed as `:name` to
      `Redix.Cluster.start_link/1`). Only cluster connections include this field.
      *Available since v1.9.0*.
    * `:connection` - the PID of the Redix connection that emitted the event.
    * `:connection_name` - the name (passed to the `:name` option when the
      connection is started) of the Redix connection that emitted the event.
      `nil` if the connection was not registered with a name.
    * `:address` or `:sentinel_address` - the address the connection was trying
    to connect to (either a Redis server or a Redis Sentinel instance).
    * `:reason` - the disconnection reason as a `Redix.ConnectionError` struct.

`Redix` connections execute the following Telemetry events when commands or
pipelines of any kind are executed.

  * `[:redix, :pipeline, :start]` - executed right before a pipeline (or command,
    which is a pipeline with just one command) is sent to the Redis server.
    Measurements are:

    * `:system_time` (integer) - the system time (in the `:native` time unit)
      at the time the event is emitted. See `System.system_time/0`.

    Metadata are:

    * `:connection` - the PID of the Redix connection used to send the pipeline.
    * `:connection_name` - the name of the Redix connection used to sent the pipeline.
      This is `nil` if the connection was not registered with a name or if the
      pipeline function was called with a PID directly (for example, if you did
      `Process.whereis/1` manually).
    * `:commands` - the commands sent to the server. This is always a list of
      commands, so even if you do `Redix.command(conn, ["PING"])` then the
      list of commands will be `[["PING"]]`.
    * `:extra_metadata` - any term set by users via the `:telemetry_metadata` option
      in `Redix.pipeline/3` and other functions.

  * `[:redix, :pipeline, :stop]` - executed a response to a pipeline returns
    from the Redis server, regardless of whether it's an error response or a
    successful response. Measurements are:

    * `:duration` - the duration (in the `:native` time unit, see `t:System.time_unit/0`)
      of back-and-forth between client and server.

    Metadata are:

    * `:connection` - the PID of the Redix connection used to send the pipeline.
    * `:connection_name` - the name of the Redix connection used to sent the pipeline.
      This is `nil` if the connection was not registered with a name or if the
      pipeline function was called with a PID directly (for example, if you did
      `Process.whereis/1` manually).
    * `:commands` - the commands sent to the server. This is always a list of
      commands, so even if you do `Redix.command(conn, ["PING"])` then the
      list of commands will be `[["PING"]]`.
    * `:extra_metadata` - any term set by users via the `:telemetry_metadata` option
      in `Redix.pipeline/3` and other functions.

    If the response is an error, the following metadata will also be present:

    * `:kind` - the atom `:error`.
    * `:reason` - the error reason (such as a `Redix.ConnectionError` struct).

## Cluster events

`Redix.Cluster` connections execute the following Telemetry events:

  * `[:redix, :cluster, :pipeline, :start]` - executed when a
    `Redix.Cluster.command/3`, `pipeline/3`, or `transaction_pipeline/3` call
    starts. Measurements are `:system_time`. Metadata are:

    * `:cluster` - the name of the cluster (the atom passed as `:name`).
    * `:call` - `:pipeline` (for `command/3` and `pipeline/3`) or
      `:transaction_pipeline`.
    * `:route` - the resolved `:route` option (`:primary`, `:replica`, or
      `:prefer_replica`).
    * `:commands` - the commands passed to the call.
    * `:extra_metadata` - the `:telemetry_metadata` option passed to the call,
      or `%{}`.

    *Available since 1.7.0.*

  * `[:redix, :cluster, :pipeline, :stop]` - executed when the call returns.
    It covers every node request and every MOVED/ASK hop the call performed.
    Measurements are:

    * `:duration` - the total time of the call (in native units).
    * `:command_count` - the number of commands in the call.
    * `:node_count` - the number of nodes the commands were split across.
    * `:redirections` - the number of MOVED/ASK redirections followed.

    Metadata are the same as for `:start`, plus `:result` (the return value
    of the call).

    *Available since 1.7.0.*

  * `[:redix, :cluster, :pipeline, :exception]` - executed when the call raises
    or exits. Measurements are `:duration`. Metadata are the same as for
    `:start`, plus `:kind`, `:reason`, and `:stacktrace`.

    *Available since 1.7.0.*

  * `[:redix, :cluster, :discovery_wait]` - executed when a call had to wait
    for the initial topology discovery (only possible before the first
    topology fetch completes with `sync_connect: false`). Measurements are
    `:duration`. Metadata are `:cluster` and `:result`.

    *Available since 1.7.0.*

  * `[:redix, :cluster, :topology_change]` - executed every time the cluster
    topology is successfully fetched, **whether or not it changed**. Generally
    this is fired once per `:topology_refresh_interval`. It's also fired on
    refreshes caused by redirections. Handlers can use the `:changed` metadata
    field to count **changes** specifically (compared to uneventful
    refreshes). Measurements are `:duration` (the time spent fetching and
    applying the topology) and `:node_count`.

    Metadata are:

    * `:cluster` - the name of the cluster (the atom passed as `:name`).
    * `:changed` - `true` on the first successful fetch, or when the set of
      nodes, their roles, or the slot map differs from the last successful
      fetch. DNS address changes and pool member restarts do not count as
      topology changes. Replicas only count when `:read_from_replicas` is enabled.
      *This field is present since v1.9.1*.
    * `:nodes` - the list of node addresses (as `"host:port"` strings) for
      every node the cluster connects to.
    * `:node_info` - a list of maps with `:id`, `:host`, `:port`, and `:role`
      (`:primary` or `:replica`) for every node the cluster connects to.

    Node IDs keep the host returned by `CLUSTER SLOTS`, after `:address_mapper`
    runs.

  * `[:redix, :cluster, :failed_topology_refresh]` - executed when the cluster
    manager fails to refresh the topology (no reachable node). Measurements
    are `:duration`. Metadata are:

    * `:cluster` - the name of the cluster.
    * `:reason` - the error reason. This is `{:no_reachable_node, node_errors}`,
      where `node_errors` is a list of `{host, port, reason}` triples, one per
      node that was tried, in the order tried, so you can tell (for example) a
      wrong password from a network partition instead of a single opaque reason.

  * `[:redix, :cluster, :node_connection_failed]` - executed when the cluster
    manager fails to establish a connection to a specific node. There are no
    measurements. Metadata are:

    * `:cluster` - the name of the cluster.
    * `:address` - the node address (as a `"host:port"` string).
    * `:reason` - the error reason.
    * `:kind` - `:start_failed` if the connection could not be started, or
      `:parked` if the connection stopped with a semantic error (such as
      `NOAUTH` or `WRONGPASS`) and is left for the next topology refresh
      instead of being restarted.

  * `[:redix, :cluster, :node_connection_restarted]` - executed when a node
    connection went down for a non-semantic reason (a crash or a kill) and the
    cluster manager restarts it right away. There are no measurements.
    Metadata are:

    * `:cluster` - the name of the cluster.
    * `:address` - the node address (as a `"host:port"` string).
    * `:role` - `:primary` or `:replica`.
    * `:reason` - the exit reason of the old connection.

    *Available since 1.7.0.*

  * `[:redix, :cluster, :node_role_changed]` - executed when a topology refresh
    finds that a node changed role (typically after a failover) and its
    connections are restarted with the new role. There are no measurements.
    Metadata are:

    * `:cluster` - the name of the cluster.
    * `:address` - the node address (as a `"host:port"` string).
    * `:from` - the previous role (`:primary` or `:replica`).
    * `:to` - the new role.

    *Available since 1.7.0.*

  * `[:redix, :cluster, :redirection]` - executed when a command receives a
    `MOVED` or `ASK` redirection from a cluster node. There are no measurements.
    Metadata are:

    * `:cluster` - the name of the cluster.
    * `:type` - either `:moved` or `:ask`.
    * `:slot` - the hash slot being redirected.
    * `:target_address` - the target node address (as a `"host:port"` string).

More events might be added in the future and that won't be considered a breaking
change, so if you're writing a handler for Redix events be sure to ignore events
that are not known. All future Redix events will start with the `:redix` atom,
like the ones above.

A default handler that logs these events appropriately is provided, see
`attach_default_handler/0`. Otherwise, you can write your own handler to
instrument or log events, see the [Telemetry page](telemetry.html) in the docs.

# `attach_default_handler`

```elixir
@spec attach_default_handler() :: :ok | {:error, :already_exists}
```

Attaches the default Redix-provided Telemetry handler.

This function attaches a default Redix-provided handler that logs
(using Elixir's `Logger`) the following events:

  * `[:redix, :disconnection]` - logged at the `:error` level
  * `[:redix, :failed_connection]` - logged at the `:error` level
  * `[:redix, :connection]` - logged at the `:info` level if it's a
    reconnection, not logged if it's the first connection.
  * `[:redix, :cluster, :failed_topology_refresh]` - logged at the `:error` level
  * `[:redix, :cluster, :node_connection_failed]` - logged at the `:warning` level
  * `[:redix, :cluster, :node_connection_restarted]` - logged at the `:warning` level
  * `[:redix, :cluster, :node_role_changed]` - logged at the `:info` level
  * `[:redix, :cluster, :redirection]` - logged at the `:info` level

See the module documentation for more information. If you want to
attach your own handler, look at the [Telemetry page](telemetry.html)
in the documentation.

## Examples

    :ok = Redix.Telemetry.attach_default_handler()

---

*Consult [api-reference.md](api-reference.md) for complete listing*
