first commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# instrumented
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`instrumented` wraps a named function with optional OpenTelemetry instrumentation — counters for invocations, histograms for durations, span events for failures. Instrumentation is **gated** behind the `TESTING_DOM_OTEL_ENABLED` environment variable, so production test runs pay zero overhead while CI or local profiling sessions can flip the flag on to surface hot-path data.
|
||||
|
||||
## Features
|
||||
|
||||
- Gated at import time via an environment variable check; no-op when disabled
|
||||
- Uses only `@opentelemetry/api` (no SDK dependency) — consumers wire the actual exporters at bootstrap
|
||||
- Preserves the wrapped function's signature and return type
|
||||
- Handles both sync and async functions, including rejection paths
|
||||
- Zero allocation overhead when gated off (returns the original function)
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { instrumented } from "@suaveplan/testing-dom/observability";
|
||||
|
||||
const render = instrumented("testing_dom.render", (tree: unknown) => {
|
||||
return reactRender(tree);
|
||||
});
|
||||
|
||||
render(<App />); // counter incremented, histogram timed — if enabled
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { instrumented } from "@suaveplan/testing-dom/observability";
|
||||
|
||||
class TestingHarness {
|
||||
public setup = instrumented("testing_dom.harness.setup", async () => {
|
||||
await this.loadFixtures();
|
||||
await this.mountApp();
|
||||
});
|
||||
public teardown = instrumented("testing_dom.harness.teardown", async () => {
|
||||
await this.unmountApp();
|
||||
});
|
||||
}
|
||||
|
||||
// Flag-off: `const harness = new TestingHarness(); await harness.setup();`
|
||||
// runs at the same cost as the unwrapped method.
|
||||
// Flag-on: every call emits a counter and a histogram observation.
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `instrumented<TFn>(name, fn): TFn`
|
||||
|
||||
- `name` — metric name suffix; the full metric becomes `testing_dom.<name>.count` / `duration_ms` / `errors`
|
||||
- `fn` — any function (sync or async)
|
||||
- Returns `TFn` — a function with the same signature, instrumented when enabled
|
||||
|
||||
### Environment gating
|
||||
|
||||
`TESTING_DOM_OTEL_ENABLED` must equal `"1"` / `"true"` at module-import time for instrumentation to activate.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The gate is evaluated once, at module import — flipping the env var mid-process has no effect. This avoids per-call environment reads in the hot path. When the gate is off, `instrumented` returns the original function reference unchanged, so V8 inlines as if the wrapper was never there. The `@opentelemetry/api` import is a marker package — it provides no-op tracers/meters when no SDK is registered, so even with the gate on, unconfigured environments pay only the cost of a no-op counter increment.
|
||||
Reference in New Issue
Block a user