feat(core-shared): MetricsProtocol + BindContext.metrics? field
This commit is contained in:
@@ -5,6 +5,7 @@ import type {
|
|||||||
EventBusProtocol,
|
EventBusProtocol,
|
||||||
RealtimeBroadcasterProtocol,
|
RealtimeBroadcasterProtocol,
|
||||||
RealtimeRegistryProtocol,
|
RealtimeRegistryProtocol,
|
||||||
|
MetricsProtocol,
|
||||||
} from "./bind-protocols";
|
} from "./bind-protocols";
|
||||||
|
|
||||||
/** Always-present fields. Feature binders rely on these unconditionally. */
|
/** Always-present fields. Feature binders rely on these unconditionally. */
|
||||||
@@ -15,21 +16,26 @@ type BindContextBase = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional cross-cutting deps. Generics let the app aggregator narrow the
|
* Optional cross-cutting deps. Generics let the app aggregator narrow the
|
||||||
* shape to full interfaces (`IEventBus`, `IRealtimeBroadcaster`, etc.); feature
|
* shape to full interfaces (`IEventBus`, `IRealtimeBroadcaster`, `IMetrics`,
|
||||||
* binders see only the protocol surface, which is enough for the methods they
|
* etc.); feature binders see only the protocol surface, which is enough for
|
||||||
* call. When an optional core package is absent the corresponding generic
|
* the methods they call. When an optional core package is absent the
|
||||||
* defaults to its protocol type, and `ctx.bus` / `ctx.realtime` are undefined
|
* corresponding generic defaults to its protocol type, and `ctx.bus` /
|
||||||
* at runtime.
|
* `ctx.realtime` / `ctx.metrics` are undefined at runtime.
|
||||||
|
*
|
||||||
|
* The 4th generic `Metrics` defaults to `MetricsProtocol` so existing call
|
||||||
|
* sites that pass 3 explicit args remain backward-compatible.
|
||||||
*/
|
*/
|
||||||
export type BindContext<
|
export type BindContext<
|
||||||
Bus extends EventBusProtocol = EventBusProtocol,
|
Bus extends EventBusProtocol = EventBusProtocol,
|
||||||
Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
|
Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
|
||||||
RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
|
RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
|
||||||
|
Metrics extends MetricsProtocol = MetricsProtocol,
|
||||||
> = BindContextBase & {
|
> = BindContextBase & {
|
||||||
bus?: Bus;
|
bus?: Bus;
|
||||||
queue?: IJobQueue;
|
queue?: IJobQueue;
|
||||||
realtime?: Realtime;
|
realtime?: Realtime;
|
||||||
realtimeRegistry?: RealtimeReg;
|
realtimeRegistry?: RealtimeReg;
|
||||||
|
metrics?: Metrics;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Production binders also receive the resolved Payload config. */
|
/** Production binders also receive the resolved Payload config. */
|
||||||
@@ -37,6 +43,7 @@ export type BindProductionContext<
|
|||||||
Bus extends EventBusProtocol = EventBusProtocol,
|
Bus extends EventBusProtocol = EventBusProtocol,
|
||||||
Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
|
Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
|
||||||
RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
|
RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
|
||||||
> = BindContext<Bus, Realtime, RealtimeReg> & {
|
Metrics extends MetricsProtocol = MetricsProtocol,
|
||||||
|
> = BindContext<Bus, Realtime, RealtimeReg, Metrics> & {
|
||||||
config: SanitizedConfig;
|
config: SanitizedConfig;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Minimal protocol surfaces used by feature binders to interact with optional
|
* Minimal protocol surfaces used by feature binders to interact with optional
|
||||||
* cross-cutting infrastructure (event bus, realtime broadcaster, realtime
|
* cross-cutting infrastructure (event bus, realtime broadcaster, realtime
|
||||||
* handler registry). Lives in `core-shared` so `BindContext` can reference
|
* handler registry, metrics). Lives in `core-shared` so `BindContext` can
|
||||||
* these unconditionally — features depend on `core-shared`, never on the
|
* reference these unconditionally — features depend on `core-shared`, never
|
||||||
* optional packages directly.
|
* on the optional packages directly.
|
||||||
*
|
*
|
||||||
* The optional packages' full interfaces (`IEventBus`, `IRealtimeBroadcaster`,
|
* The optional packages' full interfaces (`IEventBus`, `IRealtimeBroadcaster`,
|
||||||
* `IRealtimeHandlerRegistry`) `extends` these — typechecks fail if a refactor
|
* `IRealtimeHandlerRegistry`, `IMetrics`) `extends` these — typechecks fail if
|
||||||
* narrows the protocol surface in a way the full interface would lose.
|
* a refactor narrows the protocol surface in a way the full interface would lose.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export type EventBusProtocol = {
|
export type EventBusProtocol = {
|
||||||
@@ -31,3 +31,26 @@ export type RealtimeRegistryProtocol = {
|
|||||||
registerChannel(descriptor: unknown): void;
|
registerChannel(descriptor: unknown): void;
|
||||||
listChannels(): unknown[];
|
listChannels(): unknown[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal metrics protocol surface. `IMetrics` in `core-shared/instrumentation`
|
||||||
|
* extends this — typechecks fail if `IMetrics` is narrowed below this surface.
|
||||||
|
* Feature binders that receive `ctx.metrics` see only this protocol type.
|
||||||
|
*/
|
||||||
|
export type MetricsProtocol = {
|
||||||
|
counter(
|
||||||
|
name: string,
|
||||||
|
value?: number,
|
||||||
|
attributes?: Record<string, string | number | boolean>,
|
||||||
|
): void;
|
||||||
|
histogram(
|
||||||
|
name: string,
|
||||||
|
value: number,
|
||||||
|
attributes?: Record<string, string | number | boolean>,
|
||||||
|
): void;
|
||||||
|
gauge(
|
||||||
|
name: string,
|
||||||
|
value: number,
|
||||||
|
attributes?: Record<string, string | number | boolean>,
|
||||||
|
): void;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
|
import type { MetricsProtocol } from "../di/bind-protocols";
|
||||||
|
|
||||||
export type MetricAttributeValue = string | number | boolean;
|
export type MetricAttributeValue = string | number | boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vendor-neutral metrics signal interface. Mirrors the pattern of ITracer / ILogger.
|
* Vendor-neutral metrics signal interface. Mirrors the pattern of ITracer / ILogger.
|
||||||
* Three impls: NoopMetrics (noop), OtelMetrics (OTel API), RecordingMetrics (core-testing).
|
* Three impls: NoopMetrics (noop), OtelMetrics (OTel API), RecordingMetrics (core-testing).
|
||||||
*
|
*
|
||||||
|
* Extends MetricsProtocol from `core-shared/di/bind-protocols` so the type
|
||||||
|
* system enforces structural compatibility — narrowing IMetrics below the
|
||||||
|
* protocol surface causes a typecheck error.
|
||||||
|
*
|
||||||
* gauge() limitation: uses UpDownCounter under the hood, which accumulates deltas.
|
* gauge() limitation: uses UpDownCounter under the hood, which accumulates deltas.
|
||||||
* True "set to absolute value" semantics require ObservableGauge with a callback —
|
* True "set to absolute value" semantics require ObservableGauge with a callback —
|
||||||
* deferred to a v2 interface when the first true-gauge use case lands.
|
* deferred to a v2 interface when the first true-gauge use case lands.
|
||||||
*/
|
*/
|
||||||
export interface IMetrics {
|
export interface IMetrics extends MetricsProtocol {
|
||||||
/** Monotonic counter. Use for event counts (signups, errors, requests). */
|
/** Monotonic counter. Use for event counts (signups, errors, requests). */
|
||||||
counter(
|
counter(
|
||||||
name: string,
|
name: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user