first commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# `otel/instruments`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
OpenTelemetry instrument bundle for `@suaveplan/api-plugin-notifications`.
|
||||
The module exposes a lazy, memoised factory that resolves a meter
|
||||
against the current global `MeterProvider` on first call and caches the
|
||||
resulting `Counter` instances for the lifetime of the process. A
|
||||
companion `resetNotificationsInstruments()` clears the cache so tests
|
||||
can install a fresh in-memory `MeterProvider` and re-resolve the meter
|
||||
against it deterministically.
|
||||
|
||||
## Features
|
||||
|
||||
- Six counters covering the entire production surface: notification
|
||||
create / read / delete, push send / fail, and device-token registry.
|
||||
- Single meter per process — the meter is created with the package
|
||||
name, so traces grouped by `service.namespace` keep notifications
|
||||
metrics separable from sibling plugins.
|
||||
- Reset helper for tests — the test suite installs a fresh
|
||||
`InMemoryMetricExporter` per file, resets the cache, and reads back
|
||||
cumulative metrics through `flushTestMetrics()` from
|
||||
`tests/setup/polyfills.ts`.
|
||||
- Counter attributes are caller-supplied. The route layer passes
|
||||
`{ platform: "ios" }` to `pushSentTotal.add(1, attrs)` and
|
||||
`{ reason: "BadDeviceToken" }` to `pushFailedTotal.add(1, attrs)`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { getNotificationsInstruments } from "@suaveplan/api-plugin-notifications";
|
||||
|
||||
const inst = getNotificationsInstruments();
|
||||
inst.notificationsCreatedTotal.add(1);
|
||||
inst.pushSentTotal.add(1, { platform: "ios" });
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
For test code that installs a fresh provider, reset the cache so the
|
||||
next call rebinds:
|
||||
|
||||
```ts
|
||||
import { metrics } from "@opentelemetry/api";
|
||||
import {
|
||||
AggregationTemporality,
|
||||
InMemoryMetricExporter,
|
||||
MeterProvider,
|
||||
} from "@opentelemetry/sdk-metrics";
|
||||
import {
|
||||
getNotificationsInstruments,
|
||||
resetNotificationsInstruments,
|
||||
} from "@suaveplan/api-plugin-notifications";
|
||||
|
||||
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
|
||||
const provider = new MeterProvider();
|
||||
metrics.setGlobalMeterProvider(provider);
|
||||
resetNotificationsInstruments();
|
||||
|
||||
const inst = getNotificationsInstruments();
|
||||
inst.pushFailedTotal.add(1, { reason: "BadDeviceToken" });
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `NotificationsInstruments` — readonly interface with six `Counter`
|
||||
fields.
|
||||
- `getNotificationsInstruments(): NotificationsInstruments` — lazy
|
||||
memoised factory. Idempotent within a session.
|
||||
- `resetNotificationsInstruments(): void` — drop the cache so the next
|
||||
factory call rebinds against the current global provider.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The lazy-bind pattern is required because the meter resolution copies
|
||||
the `MeterProvider` reference at meter-create time. If the bundle were
|
||||
created at module load, every test in the suite would share one meter
|
||||
bound to whatever provider happened to be installed first, defeating
|
||||
isolation. The cache resets between tests via the
|
||||
`afterEach(resetNotificationsInstruments)` hook in
|
||||
`instruments.test.ts`.
|
||||
Reference in New Issue
Block a user