Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# `instruments`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Lazily resolves the OpenTelemetry instruments (`Counter`, `Histogram`)
|
||||
the plugin emits from its production paths. The bundle is built on
|
||||
first call and cached; tests call `resetTenantPluginInstruments` after
|
||||
installing a fresh `MeterProvider` so subsequent calls rebind to the
|
||||
test exporter. This pattern lets the package work seamlessly in
|
||||
production (where the global provider is the OTel SDK) and under test
|
||||
(where the global provider is an `InMemoryMetricExporter`).
|
||||
|
||||
## Features
|
||||
|
||||
- Four instruments: `resolutionsTotal` (counter),
|
||||
`resolutionDurationMs` (histogram), `cacheTotal` (counter),
|
||||
`managementOpsTotal` (counter).
|
||||
- Lazy initialisation — the meter is resolved on first call so test
|
||||
polyfills installed before the package loads bind correctly.
|
||||
- `resetTenantPluginInstruments` clears the cache so a re-bind is
|
||||
forced; primarily useful in test setup hooks.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { getTenantPluginInstruments } from "@suaveplan/api-plugin-tenant";
|
||||
|
||||
const instruments = getTenantPluginInstruments();
|
||||
instruments.resolutionsTotal.add(1, { outcome: "resolved", strategy: "header" });
|
||||
instruments.resolutionDurationMs.record(12.4, { strategy: "header" });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
getTenantPluginInstruments,
|
||||
resetTenantPluginInstruments,
|
||||
} from "@suaveplan/api-plugin-tenant";
|
||||
import { metrics } from "@opentelemetry/api";
|
||||
import { InMemoryMetricExporter, MeterProvider, PeriodicExportingMetricReader, AggregationTemporality } from "@opentelemetry/sdk-metrics";
|
||||
|
||||
// In test setup before the package's other modules load:
|
||||
const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
|
||||
const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 60_000 });
|
||||
const provider = new MeterProvider({ readers: [reader] });
|
||||
metrics.setGlobalMeterProvider(provider);
|
||||
resetTenantPluginInstruments();
|
||||
|
||||
// Later — assert the counters that were emitted:
|
||||
await provider.forceFlush();
|
||||
const collected = exporter.getMetrics();
|
||||
const resolutions = collected[0]?.scopeMetrics[0]?.metrics.find(
|
||||
(m) => m.descriptor.name === "tenant_plugin.resolutions_total"
|
||||
);
|
||||
console.assert(resolutions !== undefined);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interface TenantPluginInstruments` — `{ resolutionsTotal: Counter,
|
||||
resolutionDurationMs: Histogram, cacheTotal: Counter,
|
||||
managementOpsTotal: Counter }`.
|
||||
- `function getTenantPluginInstruments(): TenantPluginInstruments` —
|
||||
returns the cached bundle, building it on first call.
|
||||
- `function resetTenantPluginInstruments(): void` — drops the cache.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The lazy pattern is essential — calling `metrics.getMeter("...")` at
|
||||
module top-level binds to whichever `MeterProvider` was installed at
|
||||
import time. Because Vitest's `setupFiles` run before `src/` modules
|
||||
import, installing the in-memory provider there guarantees the test
|
||||
bundle binds correctly. Production callers that install their OTel SDK
|
||||
late (e.g. behind a feature flag) call `resetTenantPluginInstruments`
|
||||
once the SDK is up so the plugin rebinds. The instrument names use
|
||||
`tenant_plugin.` rather than `tenant.` so dashboards can cleanly
|
||||
distinguish the plugin's emissions from the underlying
|
||||
`@suaveplan/api-tenant` library's instruments (if any are added later).
|
||||
Reference in New Issue
Block a user