//#region src/feature-flags.d.ts
/**
 * Feature flag evaluations, in the vocabulary OpenTelemetry already defined.
 *
 * A flagged rollout splits your traffic into two populations that share a
 * service name, a route and a version. Without the flag on the span there is no
 * way to ask the only question that matters during a rollout — is the new
 * branch slower, or failing more, than the old one — and the usual workaround
 * is to read it in the flag vendor's own dashboard, where the latency and the
 * errors are not.
 *
 * The specification covers this: `feature_flag.key`, `.result.value`,
 * `.result.variant`, `.result.reason`, `.provider.name`, `.context.id`, plus a
 * `feature_flag.evaluation` event. Emitting those means any backend can split
 * any metric by variant, with no vendor in the path.
 *
 * ## Attributes and events both
 *
 * Span attributes hold one flag: a second call overwrites the first. A request
 * that branched on three flags needs one event each, which is what the
 * `feature_flag.evaluation` event is for. Both are recorded — attributes so a
 * single-flag span is filterable without unpacking events, events so a
 * many-flag span keeps them all.
 *
 * ## Record what you branched on
 *
 * Record a flag where the code *reads* it, not where it is fetched. A flag
 * evaluated and ignored explains nothing; the value the request actually took a
 * branch on is the one that explains its behaviour.
 */
/** Canonical `feature_flag.*` attribute keys. */
declare const FEATURE_FLAG: {
  readonly KEY: "feature_flag.key";
  readonly RESULT_VALUE: "feature_flag.result.value";
  readonly RESULT_VARIANT: "feature_flag.result.variant";
  readonly RESULT_REASON: "feature_flag.result.reason";
  readonly PROVIDER_NAME: "feature_flag.provider.name";
  readonly CONTEXT_ID: "feature_flag.context.id";
  readonly SET_ID: "feature_flag.set.id";
  readonly VERSION: "feature_flag.version";
  /**
   * Why an evaluation failed. `feature_flag.evaluation.error.message` is the
   * deprecated spelling of this and is deliberately not emitted — writing both
   * would double the cardinality to no benefit.
   */
  readonly ERROR_MESSAGE: "feature_flag.error.message";
};
/** Canonical event name for one evaluation. */
declare const FEATURE_FLAG_EVALUATION_EVENT = "feature_flag.evaluation";
/**
 * Canonical `feature_flag.result.reason` values. The registry defines them in
 * lower snake case; OpenFeature and most SDKs report them upper-cased, and
 * forwarding that splits every group-by into two buckets meaning the same
 * thing.
 */
declare const FEATURE_FLAG_REASON: readonly ["static", "default", "targeting_match", "split", "cached", "disabled", "unknown", "stale", "error"];
interface FeatureFlagEvaluation {
  /** The flag's key, e.g. `new-checkout`. */
  key: string;
  /** The value the code branched on. Serialised if it is not a string. */
  value: unknown;
  /** Variant name, where the provider has one distinct from the value. */
  variant?: string;
  /**
   * Why this value. Case-normalised to the registry's spelling, so a provider
   * reporting `TARGETING_MATCH` and one reporting `targeting_match` land in the
   * same bucket.
   */
  reason?: string;
  /** The provider that answered, e.g. `posthog`, `launchdarkly`, `flagd`. */
  provider?: string;
  /** Identifier of the evaluation context — the user or account keyed on. */
  contextId?: string;
  /** Identifier of the flag set this flag belongs to. */
  setId?: string;
  /** Version of the flag definition that produced this value. */
  version?: string;
  /** Why the evaluation failed, when it did. */
  errorMessage?: string;
}
/** What an attribute can hold without being flattened to text. */
type FeatureFlagAttributeValue = string | number | boolean;
/**
 * The smallest thing that can carry an evaluation.
 *
 * `track` is the correlated-log seam a `TraceContext` provides, and it is the
 * only event seam offered: this repository emits events through the Logs API
 * model, and a `Span.addEvent` fallback is how that direction quietly becomes
 * optional. A caller holding a raw span supplies its own `track` — in the
 * browser, `emitEvent` from `autotel-web` is one.
 *
 * A sink with no `track` still records the attributes, which covers the common
 * single-flag span.
 */
interface FeatureFlagSink {
  setAttributes(attributes: Record<string, FeatureFlagAttributeValue>): void;
  track?(name: string, attributes?: Record<string, FeatureFlagAttributeValue>): void;
}
/** Canonical attributes for one evaluation. Absent fields are omitted. */
declare function featureFlagAttributes(evaluation: FeatureFlagEvaluation): Record<string, FeatureFlagAttributeValue>;
/**
 * Record a flag evaluation on `sink` — as attributes and as a
 * `feature_flag.evaluation` event.
 *
 * A missing sink is a no-op: instrumentation must never be the reason a branch
 * throws, and a flag read outside any span is a legitimate thing to do.
 */
declare function recordFeatureFlag(sink: FeatureFlagSink | undefined, evaluation: FeatureFlagEvaluation): void;
/**
 * The parts of an OpenFeature hook context this reads. Structurally typed on
 * purpose: matching the shape rather than importing `@openfeature/server-sdk`
 * keeps the SDK out of every bundle that imports a sibling of this module, and
 * works against the web SDK, the server SDK and the React one alike — they
 * agree on this shape and disagree on almost everything else.
 */
interface OpenFeatureHookContext {
  flagKey: string;
  defaultValue: unknown;
  context?: {
    targetingKey?: string;
  };
  providerMetadata?: {
    name?: string;
  };
  clientMetadata?: {
    name?: string;
  };
}
/** The evaluation result an OpenFeature hook receives. */
interface OpenFeatureEvaluationDetails {
  value: unknown;
  variant?: string;
  reason?: string;
}
/** Just enough of an OpenFeature hook to be registered as one. */
interface OpenFeatureHook {
  after?(hookContext: OpenFeatureHookContext, details: OpenFeatureEvaluationDetails): void;
  error?(hookContext: OpenFeatureHookContext, error: unknown): void;
}
interface OpenFeatureHookOptions {
  /**
   * Where to record. Defaults to the active span, which is what you want:
   * the span that branched on the flag is the one whose latency and errors the
   * flag explains.
   */
  getSpan?: () => FeatureFlagSink | undefined;
  /**
   * Where the evaluation event goes when the sink brings no `track` of its own.
   * Defaults to an OpenTelemetry log record. Injected for tests.
   */
  emitLogRecord?: (attributes: Record<string, FeatureFlagAttributeValue>) => void;
}
/**
 * An OpenFeature hook that records every evaluation under the canonical
 * `feature_flag.*` convention.
 *
 * This is the zero-config path: OpenFeature already sits between the
 * application and whichever flag vendor it uses, and it already fires on every
 * evaluation — which is exactly the moment worth recording, because it is the
 * moment the code branched.
 *
 * ```ts
 * import { OpenFeature } from '@openfeature/server-sdk';
 * import { autotelOpenFeatureHook } from 'autotel/feature-flags';
 *
 * OpenFeature.addHooks(autotelOpenFeatureHook());
 * ```
 *
 * A failed evaluation is still recorded, with the default value the code
 * actually used and `reason: 'ERROR'`. The default is what the request behaved
 * as; the failure is why.
 */
declare function autotelOpenFeatureHook(options?: OpenFeatureHookOptions): OpenFeatureHook;
//#endregion
export { FEATURE_FLAG, FEATURE_FLAG_EVALUATION_EVENT, FEATURE_FLAG_REASON, FeatureFlagAttributeValue, FeatureFlagEvaluation, FeatureFlagSink, OpenFeatureEvaluationDetails, OpenFeatureHook, OpenFeatureHookContext, OpenFeatureHookOptions, autotelOpenFeatureHook, featureFlagAttributes, recordFeatureFlag };