# `Otel.Metrics.Aggregation`
[🔗](https://github.com/yangbancode/otel/blob/main/lib/otel/metrics/aggregation.ex#L1)

Aggregation behaviour and default instrument-to-aggregation
mapping (`metrics/sdk.md` §Aggregation L612-L860).

## Public API

| Callback | Role |
|---|---|
| `aggregate/4` | **SDK** (OTel API MUST) — record a measurement into an ETS-backed cell |
| `collect/3` | **SDK** (OTel API MUST) — emit datapoints for the configured temporality |

## References

- OTel Metrics SDK §Aggregation: `opentelemetry-specification/specification/metrics/sdk.md` L612-L860
- Built-in implementations: `Otel.Metrics.Aggregation.{Sum,LastValue,ExplicitBucketHistogram}`

# `agg_key`

```elixir
@type agg_key() ::
  {name :: String.t(), attributes :: %{required(String.t()) =&gt; primitive_any()}}
```

Per-stream-per-attribute-set aggregation key.

Used as the ETS key in the metrics table to identify a single
aggregation cell — combining the stream name and the
attribute set the cell aggregates over. Constructed at every
`aggregate/4` call site (e.g. `Otel.Metrics.Meter`) and at
exemplar reservoir lookups.

`InstrumentationScope` is not part of the key: minikube
hardcodes a single scope (project memory
`project_minikube_hardcode_decisions` § Follow-on #457), so
threading it through every cell key would be redundant. Apps
that share an instrument name across logical components
namespace via the name itself (e.g. `phoenix.requests` /
`ecto.requests`).

# `datapoint`

```elixir
@type datapoint() :: %{
  attributes: %{required(String.t()) =&gt; primitive_any()},
  value: term(),
  start_time: non_neg_integer(),
  time: non_neg_integer()
}
```

# `primitive`

```elixir
@type primitive() ::
  String.t() | {:bytes, binary()} | boolean() | integer() | float() | nil
```

# `primitive_any`

```elixir
@type primitive_any() ::
  primitive() | [primitive_any()] | %{required(String.t()) =&gt; primitive_any()}
```

# `stream_key`

```elixir
@type stream_key() :: String.t()
```

Stream-level identity used by `collect/3` callbacks — the
instrument's `name` (the prefix of `agg_key/0` minus
attributes).

# `aggregate`

```elixir
@callback aggregate(
  metrics_tab :: :ets.table(),
  key :: agg_key(),
  value :: number(),
  opts :: map()
) :: :ok
```

# `collect`

```elixir
@callback collect(
  metrics_tab :: :ets.table(),
  stream_key :: stream_key(),
  opts :: map()
) :: [datapoint()]
```

# `default_for`

```elixir
@spec default_for(kind :: Otel.Metrics.Instrument.kind()) :: module()
```

---

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