# `instruments` — OTel counter for Altair UI requests _(no submodules)_ ## Purpose `instruments` owns the package's single OpenTelemetry counter, `graphql.ui.requests_total`, labelled with the constant `ui="altair"`. The counter name is deliberately identical to the GraphiQL sibling's so dashboards summing across both UIs can drop the `ui` label and add the two series. The `MeterProvider` is injectable — operators can hand in their own provider for in-process testing or rely on the OTel global the rest of the host has registered at boot. ## Features - Single counter — `graphql.ui.requests_total`. - Constant label preset: `{ ui: "altair" }`. - `recordRequest()` convenience captures the label internally so call sites never repeat the label literal (no drift risk). - Meter name pinned to `@suaveplan/api-graphql-ui-altair` for trace correlation. - Falls back to the OTel global `MeterProvider` when none is supplied. ## Usage: Basic ```ts import { createAltairInstruments } from "@suaveplan/api-graphql-ui-altair/instruments"; const inst = createAltairInstruments(); inst.recordRequest(); ``` ## Usage: Advanced ```ts import { MeterProvider } from "@opentelemetry/sdk-metrics"; import { createAltairInstruments } from "@suaveplan/api-graphql-ui-altair/instruments"; const meterProvider = new MeterProvider({ /* readers / exporters configured in the host */ }); const inst = createAltairInstruments({ meterProvider }); // Inside the HTML response handler: inst.recordRequest(); // graphql.ui.requests_total{ui="altair"} += 1 ``` ## API Reference - `createAltairInstruments(config?: AltairInstrumentsConfig): AltairInstruments`. - `AltairInstruments` — `{ meter, requestsTotal, recordRequest }`, frozen. - `GRAPHQL_UI_REQUESTS_COUNTER` — literal `"graphql.ui.requests_total"`. - `ALTAIR_UI_LABEL` — literal `"altair"`. - `ALTAIR_METER_NAME` — literal `"@suaveplan/api-graphql-ui-altair"`. ## Implementation Notes The counter description block documents the cross-package label contract so operators reading the OTel discovery endpoint understand why two packages emit the same metric name. The `Object.freeze` on the return record prevents accidental mutation downstream — the bundle is meant to be a singleton per host instance.