/**
 * Standard metric names emitted by the dispatcher.
 *
 * The user-supplied `onMetric(name, value, tags)` callback is vendor-neutral —
 * pipe to Prometheus, OpenTelemetry, statsd, or just append to a log file.
 */

export const METRIC_OP_DURATION_MS = 'shade_files_op_duration_ms';
export const METRIC_OP_TOTAL = 'shade_files_op_total';
export const METRIC_BYTES_IN = 'shade_files_bytes_in';
export const METRIC_BYTES_OUT = 'shade_files_bytes_out';
export const METRIC_IDEMPOTENCY_HIT_TOTAL = 'shade_files_idempotency_hit_total';
export const METRIC_IDEMPOTENCY_CONFLICT_TOTAL = 'shade_files_idempotency_conflict_total';
export const METRIC_RATE_LIMIT_REJECT_TOTAL = 'shade_files_rate_limit_reject_total';
export const METRIC_FINGERPRINT_REJECT_TOTAL = 'shade_files_fingerprint_reject_total';
export const METRIC_SIGNATURE_REJECT_TOTAL = 'shade_files_signature_reject_total';

/** Tags attached to every metric event. */
export type MetricTags = Record<string, string | number | boolean>;

/** User-supplied metric sink. Synchronous to keep hot-path fast. */
export type MetricSink = (name: string, value: number, tags: MetricTags) => void;

/** No-op sink used when the user doesn't supply one. */
export const NOOP_METRIC_SINK: MetricSink = () => undefined;
