/**
 * The `Tracer` module defines the low-level tracing model used by Effect to
 * describe and propagate spans. A span records the lifetime of an operation,
 * including its name, parent, attributes, links, annotations, sampling decision,
 * kind, and completion status.
 *
 * **Mental model**
 *
 * - `Tracer` is the backend interface responsible for creating spans
 * - `Span` values represent Effect-managed operations with mutable lifecycle
 *   hooks for ending spans and adding attributes, events, or links
 * - `ExternalSpan` represents trace context imported from another tracing
 *   system so Effect spans can be parented by or linked to external work
 * - `ParentSpan`, `Tracer`, and related context references control propagation,
 *   sampling, and trace-level filtering through the Effect context
 *
 * **Common tasks**
 *
 * - Implement a custom tracing backend with {@link make}
 * - Provide or inspect parent span context with {@link ParentSpan}
 * - Convert external trace identifiers into Effect span values with
 *   {@link externalSpan}
 * - Configure span metadata with {@link SpanOptions}, {@link SpanKind}, and
 *   {@link SpanLink}
 * - Disable propagation or adjust trace filtering with
 *   {@link DisablePropagation}, {@link CurrentTraceLevel}, and
 *   {@link MinimumTraceLevel}
 *
 * **Gotchas**
 *
 * - This module exposes the tracing data model and backend hooks; most
 *   application code should create spans through higher-level Effect APIs such
 *   as `Effect.withSpan`
 * - `ExternalSpan` only carries identity and metadata from another system; it
 *   does not have lifecycle methods like `Span`
 * - Propagation and sampling are context-dependent, so parent selection can be
 *   affected by disabled propagation, root span options, and trace-level
 *   thresholds
 *
 * @since 2.0.0
 */
import * as Context from "./Context.js";
import { constFalse } from "./Function.js";
import * as Option from "./Option.js";
const evaluate = "~effect/Effect/evaluate";
/**
 * Defines the string key for the parent-span context service.
 *
 * **When to use**
 *
 * Use when integrating lower-level tracing code that needs the raw context key
 * for parent span lookup.
 *
 * **Example** (Reading the parent span key)
 *
 * ```ts
 * import { Tracer } from "effect"
 *
 * // The key used to identify parent spans in the context
 * console.log(Tracer.ParentSpanKey) // "effect/Tracer/ParentSpan"
 * ```
 *
 * @category constants
 * @since 4.0.0
 */
export const ParentSpanKey = "effect/Tracer/ParentSpan";
/**
 * Context service containing the `Span` or `ExternalSpan` to use as the parent
 * of newly-created child spans.
 *
 * **Example** (Accessing the parent span)
 *
 * ```ts
 * import { Effect, Tracer } from "effect"
 *
 * // Access the parent span from the context
 * const program = Effect.gen(function*() {
 *   const parentSpan = yield* Effect.service(Tracer.ParentSpan)
 *   console.log(`Parent span: ${parentSpan.spanId}`)
 * })
 * ```
 *
 * @category services
 * @since 2.0.0
 */
export class ParentSpan extends /*#__PURE__*/Context.Service()(ParentSpanKey) {}
/**
 * Creates a `Tracer` value from a tracer implementation object.
 *
 * **When to use**
 *
 * Use to create a custom tracing backend value that Effect can use when
 * creating spans.
 *
 * **Details**
 *
 * `make` returns the supplied implementation object unchanged. The object must
 * satisfy the `Tracer` contract, including a `span` method that returns a
 * `Span`.
 *
 * @see {@link Span} for the span values returned by tracer implementations
 *
 * @category constructors
 * @since 2.0.0
 */
export const make = options => options;
/**
 * Creates an `ExternalSpan` from trace and span identifiers, defaulting
 * `sampled` to `true` and annotations to an empty context when they are not
 * provided.
 *
 * **Example** (Creating an external span)
 *
 * ```ts
 * import { Effect, Tracer } from "effect"
 *
 * // Create an external span from another tracing system
 * const span = Tracer.externalSpan({
 *   spanId: "span-abc-123",
 *   traceId: "trace-xyz-789",
 *   sampled: true
 * })
 *
 * // Use the external span as a parent
 * const program = Effect.succeed("Hello").pipe(
 *   Effect.withSpan("child-operation", { parent: span })
 * )
 * ```
 *
 * @category constructors
 * @since 2.0.0
 */
export const externalSpan = options => ({
  _tag: "ExternalSpan",
  spanId: options.spanId,
  traceId: options.traceId,
  sampled: options.sampled ?? true,
  annotations: options.annotations ?? Context.empty()
});
/**
 * Context reference for disabling trace propagation.
 *
 * **When to use**
 *
 * Use to prevent spans in a scope from propagating tracing context.
 *
 * **Details**
 *
 * When enabled on fiber or span annotations, new spans are created as
 * non-propagating no-op spans and disabled spans are skipped when deriving a
 * parent span.
 *
 * **Example** (Disabling span propagation)
 *
 * ```ts
 * import { Effect, Tracer } from "effect"
 *
 * // Disable span propagation for a specific effect
 * const program = Effect.gen(function*() {
 *   yield* Effect.log("This will not propagate parent span")
 * }).pipe(
 *   Effect.provideService(Tracer.DisablePropagation, true)
 * )
 * ```
 *
 * @category references
 * @since 3.12.0
 */
export const DisablePropagation = /*#__PURE__*/Context.Reference("effect/Tracer/DisablePropagation", {
  defaultValue: constFalse
});
/**
 * Context reference for controlling the current trace level for dynamic filtering.
 *
 * **When to use**
 *
 * Use to set the default trace level for spans in a scope when span options do
 * not provide `level`.
 *
 * **Details**
 *
 * The default value is `"Info"`. Span creation uses `options.level ??
 * CurrentTraceLevel` before applying `MinimumTraceLevel`.
 *
 * @see {@link MinimumTraceLevel} for the threshold that decides whether spans at that level are sampled
 *
 * @category references
 * @since 4.0.0
 */
export const CurrentTraceLevel = /*#__PURE__*/Context.Reference("effect/Tracer/CurrentTraceLevel", {
  defaultValue: () => "Info"
});
/**
 * Context reference for setting the minimum trace level threshold. Spans and their
 * descendants below this level will have their sampling decision forced to
 * false, preventing them from being exported.
 *
 * **When to use**
 *
 * Use to set the trace-level threshold that controls whether spans are sampled
 * by default.
 *
 * **Details**
 *
 * The default value is `"All"`. Span creation compares the span level from
 * `options.level ?? CurrentTraceLevel` against this threshold.
 *
 * **Gotchas**
 *
 * Explicit `options.sampled` bypasses threshold computation.
 *
 * @see {@link CurrentTraceLevel} for the default span level used when options do not specify one
 *
 * @category references
 * @since 4.0.0
 */
export const MinimumTraceLevel = /*#__PURE__*/Context.Reference("effect/Tracer/MinimumTraceLevel", {
  defaultValue: () => "All"
});
/**
 * Defines the string key for the active tracer context reference.
 *
 * **When to use**
 *
 * Use when integrating lower-level tracing code that needs the raw context key
 * for active tracer lookup.
 *
 * @category references
 * @since 4.0.0
 */
export const TracerKey = "effect/Tracer";
/**
 * Context reference for the active tracer service. By default it uses the
 * native tracer, which creates `NativeSpan` instances.
 *
 * **Example** (Accessing the current tracer)
 *
 * ```ts
 * import { Effect, Tracer } from "effect"
 *
 * // Access the current tracer from the context
 * const program = Effect.gen(function*() {
 *   const tracer = yield* Effect.service(Tracer.Tracer)
 *   console.log("Using current tracer")
 * })
 *
 * // Or use the built-in tracer effect
 * const tracerEffect = Effect.gen(function*() {
 *   const tracer = yield* Effect.tracer
 *   console.log("Current tracer obtained")
 * })
 * ```
 *
 * @category references
 * @since 2.0.0
 */
export const Tracer = /*#__PURE__*/Context.Reference(TracerKey, {
  defaultValue: () => make({
    span: options => new NativeSpan(options)
  })
});
/**
 * Default in-memory `Span` implementation used by the native tracer. It
 * generates span and trace identifiers, stores attributes, events, and links,
 * and records `Started` or `Ended` status.
 *
 * **Details**
 *
 * The constructor initializes the span with `Started` status, inherits the
 * parent trace id or generates a new one, and always generates a new span id.
 * Attributes, events, links, and status are then mutated through `Span` methods.
 *
 * @see {@link Span} for the interface implemented by native spans
 *
 * @category native tracer
 * @since 4.0.0
 */
export class NativeSpan {
  _tag = "Span";
  spanId;
  traceId = "native";
  sampled;
  name;
  parent;
  annotations;
  links;
  startTime;
  kind;
  status;
  attributes;
  events = [];
  constructor(options) {
    this.name = options.name;
    this.parent = options.parent;
    this.annotations = options.annotations;
    this.links = options.links;
    this.startTime = options.startTime;
    this.kind = options.kind;
    this.sampled = options.sampled;
    this.status = {
      _tag: "Started",
      startTime: options.startTime
    };
    this.attributes = new Map();
    this.traceId = Option.getOrUndefined(options.parent)?.traceId ?? randomHexString(32);
    this.spanId = randomHexString(16);
  }
  end(endTime, exit) {
    this.status = {
      _tag: "Ended",
      endTime,
      exit,
      startTime: this.status.startTime
    };
  }
  attribute(key, value) {
    this.attributes.set(key, value);
  }
  event(name, startTime, attributes) {
    this.events.push([name, startTime, attributes ?? {}]);
  }
  addLinks(links) {
    // oxlint-disable-next-line no-restricted-syntax
    this.links.push(...links);
  }
}
const randomHexString = /*#__PURE__*/function () {
  const characters = "abcdef0123456789";
  const charactersLength = characters.length;
  return function (length) {
    let result = "";
    for (let i = 0; i < length; i++) {
      result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
  };
}();
//# sourceMappingURL=Tracer.js.map