import { HoistService, Span, FullSpanConfig } from '@xh/hoist/core'; /** * Client-side distributed tracing service for Hoist applications. * * Creates spans for user actions, fetch calls, and app bootstrap. Sends `traceparent` * headers on outgoing requests so server-side spans nest under client spans, producing * end-to-end traces from user interaction through server processing and back. * * Controlled by the `xhTraceConfig` soft config. When disabled (the default), spans are * still created and passed to wrapped functions but are flagged as unsampled and never * exported - callers can interact with the span without null checks. * * To support tracing from the earliest moments of app startup this service is installed * before any other, well before Config can be loaded. Spans created during that * window are marked with `sampled === null` (decision deferred) and held in a pending bucket. * Once config arrives, {@link noteConfigAvailable} the service walks the bucket, and applies * sampling rules per-trace. Outbound `traceparent` headers send `00` in the undetermined state * so server-side spans don't sample without a client decision. * * Completed spans are batched and exported to the Hoist server endpoint `xh/submitSpans`, * which relays them to the configured collector. */ export declare class TraceService extends HoistService { static instance: TraceService; /** Max spans to retain when pushes are failing - oldest are dropped beyond this. */ private static MAX_PENDING; /** Spans whose sampling has been decided and are queued for export. */ private _pending; /** Config. Will be loaded when available. */ private conf; /** Spans created before config available. */ private _preConfigSpans; initAsync(): Promise; /** Is tracing currently enabled? */ get enabled(): boolean; /** * Create a span wrapping an async operation. * Automatically handles timing, error recording, and export. * * @param config - span name string, or a SpanConfig with name and optional tags. * @param fn - the async function to wrap. */ withSpan(config: string | FullSpanConfig, fn: (span: Span) => Promise): Promise; /** * Create a new span. Always returns a span - when tracing is disabled the returned span * is flagged unsampled and will never be exported, so callers can interact with it safely. * * The `xh.source` tag defaults to `'hoist'` for spans whose name starts with `'xh.'` and * `'app'` otherwise. Callers may override all tag values, including setting to null to prevent * any default tag from being applied. * * Sampling rules from `xhTraceConfig.sampleRules` are evaluated against the span's tags * at creation time (head-based). Child spans inherit their parent's sampling decision. * Spans created before `xhTraceConfig` is loaded (during early app startup) are marked * `sampled === null` and parked in a pending bucket; {@link noteConfigAvailable} decides their * fate once config arrives. * * @param config - span name string, or a SpanConfig with name and optional tags. */ private createSpan; /** * Submit a completed span for export. Spans whose sampling is still undecided are held * for {@link noteConfigAvailable}; sampled spans are queued and flushed on a debounced timer. */ private exportSpan; /** * Flush the queue of pending spans to the server. * @internal - apps should generally allow this service to manage w/its internal debounce. */ pushPendingAsync(): Promise; /** * Called by {@link ConfigService} once `xhTraceConfig` has loaded. Applies sampling * decisions to all spans created during early startup and held in the pendingConfig * bucket. * * For each trace represented in the pending bucket: the root span (or oldest-known * ancestor) is evaluated against the sampling rules, and the decision is propagated * to every span in that trace. Sampled, ended spans are exported at this time. * * @internal - for framework use only. */ noteConfigAvailable(): void; private pushPendingBuffered; /** Flush all pending spans to the server. */ private pushPendingInternalAsync; /** Bound the pending buffer, silently dropping oldest spans (failed pushes are logged). */ private enforceCap; /** * Resolve a root-span sampling decision: a probabilistic decision from `sampleRules`. Rules * match on tag keys; the reserved key `name` matches the span's name (glob-capable, same * syntax as tag-value patterns). */ private computeSampled; private getSampleRate; /** For strings, simple glob matching: `*` = any, `foo*` = prefix, `*foo` = suffix, `*foo*` = contains. */ private matchesValue; private identityTags; }