first commit
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# otel
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Owns the OpenTelemetry instrument set for `@suaveplan/storage-cdn-rackspace`: counters (`reads_total`, `writes_total`, `deletes_total`, `purges_total`, `signed_urls_total`, `errors_total`, `range_fallback_total`), histograms (`op_duration_ms`, `io_bytes`), and a tracer scoped to `@suaveplan/storage-cdn-rackspace`. Every measurement carries `provider="rackspace"` and the configured `region` so dashboards can break Rackspace traffic down by region and aggregate across providers without losing detail.
|
||||
|
||||
## Features
|
||||
|
||||
- Lazy instrument construction so consumers can install a custom `MeterProvider` before the first operation runs.
|
||||
- `setRackspaceMeterProvider(provider)` override hook with auto-rebuild on next access.
|
||||
- `recordOp({ op, outcome, durationMs, region, bytes?, direction? })` emits the full observation set for one operation.
|
||||
- `recordRangeFallback(region)` increments the dedicated counter — surfaces origins that ignore Range.
|
||||
- `resetInstruments()` for test isolation.
|
||||
- Dedicated counters for CDN-specific operations (`purges_total`, `signed_urls_total`) so operators can monitor purge rate-limit pressure separately from storage IO.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { recordOp } from "@suaveplan/storage-cdn-rackspace";
|
||||
|
||||
recordOp({ op: "purge", outcome: "ok", durationMs: 42, region: "LON" });
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
resetInstruments,
|
||||
setRackspaceMeterProvider,
|
||||
recordOp,
|
||||
} from "@suaveplan/storage-cdn-rackspace";
|
||||
import { MeterProvider } from "@opentelemetry/sdk-metrics";
|
||||
|
||||
const provider = new MeterProvider({ readers: [periodicReader] });
|
||||
setRackspaceMeterProvider(provider);
|
||||
resetInstruments();
|
||||
recordOp({ op: "signUrl", outcome: "ok", durationMs: 1, region: "LON" });
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `setRackspaceMeterProvider(provider?): void`
|
||||
|
||||
Override or restore the meter provider. Calling this invalidates the cached instrument set so the next `getInstruments()` rebinds.
|
||||
|
||||
### `getInstruments(force?): RackspaceInstruments`
|
||||
|
||||
Returns the cached instrument bundle (`tracer`, `meter`, every counter and histogram). `force = true` rebuilds.
|
||||
|
||||
### `recordOp(input): void`
|
||||
|
||||
`input.outcome` decides which counter increments:
|
||||
|
||||
- `"ok"` + read-ish op → `reads_total`.
|
||||
- `"ok"` + `set`/`setPartial` → `writes_total`.
|
||||
- `"ok"` + `delete`/`clear` → `deletes_total`.
|
||||
- `"ok"` + `purge` → `purges_total`.
|
||||
- `"ok"` + `signUrl` → `signed_urls_total`.
|
||||
- anything else → `errors_total`.
|
||||
|
||||
Always records `op_duration_ms{op, outcome, provider, region}`. When `bytes` and `direction` are both provided, also records `io_bytes{op, direction, provider, region}`.
|
||||
|
||||
### `recordRangeFallback(region): void`
|
||||
|
||||
Increments `range_fallback_total{outcome="ok", provider="rackspace", region}`.
|
||||
|
||||
### `resetInstruments(): void`
|
||||
|
||||
Drops the cached bundle without changing the meter provider.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The cache is critical for hot-path performance. `setRackspaceMeterProvider` is the one path that intentionally invalidates the cache.
|
||||
- `provider="rackspace"` is hard-coded — every measurement from this package belongs to Rackspace by definition. Cross-provider dashboards aggregate on the `provider` attribute, so dropping it would defeat the family-wide observability.
|
||||
- `region` is sourced from the resolved configuration, not the operation argument, because operations don't take a region — the adapter is bound to one region per instance.
|
||||
- The tracer is acquired separately from the meter; no caching is required because `trace.getTracer` is idempotent.
|
||||
- `range_fallback_total` carries `outcome="ok"` only — the fallback path always succeeds (just less efficiently); upstream failures during fallback surface via `errors_total`.
|
||||
Reference in New Issue
Block a user