@sailfish-ai/sf-veritas 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contextManager-B1hI1vbB.cjs +1 -0
- package/dist/{contextManager-CZy0w11U.js → contextManager-CE9FcHd2.js} +55 -47
- package/dist/plugins/funcspanEsbuildPlugin.cjs +1 -1
- package/dist/plugins/funcspanEsbuildPlugin.mjs +1 -1
- package/dist/plugins/funcspanRollupPlugin.cjs +1 -1
- package/dist/plugins/funcspanRollupPlugin.mjs +1 -1
- package/dist/plugins/funcspanTscPlugin.cjs +1 -1
- package/dist/plugins/funcspanTscPlugin.mjs +1 -1
- package/dist/plugins/funcspanVitePlugin.cjs +1 -1
- package/dist/plugins/funcspanVitePlugin.mjs +1 -1
- package/dist/plugins/funcspanWebpackPlugin.cjs +1 -1
- package/dist/plugins/funcspanWebpackPlugin.mjs +1 -1
- package/dist/{runtimeConfig-ButdW4zP.js → runtimeConfig-B6ERoLRD.js} +279 -277
- package/dist/{runtimeConfig-C4_zc4Zg.cjs → runtimeConfig-BgTE3gmS.cjs} +4 -4
- package/dist/sf-veritas.cjs +27 -19
- package/dist/sf-veritas.mjs +1657 -612
- package/dist/types/baseTransmitter.d.ts +1 -0
- package/dist/types/constants.d.ts +6 -0
- package/dist/types/contextManager.d.ts +15 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/patches/asyncQueues/_stubs/bee-queue.d.ts +10 -0
- package/dist/types/patches/asyncQueues/_stubs/rabbitmq.d.ts +11 -0
- package/dist/types/patches/asyncQueues/_stubs/sqs.d.ts +9 -0
- package/dist/types/patches/asyncQueues/asyncQueueTracer.d.ts +127 -0
- package/dist/types/patches/asyncQueues/asyncQueues.bench.d.ts +1 -0
- package/dist/types/patches/asyncQueues/bullmq.d.ts +27 -0
- package/dist/types/patches/asyncQueues/bullmqPro.d.ts +3 -0
- package/dist/types/patches/asyncQueues/confluentKafkaJs.d.ts +3 -0
- package/dist/types/patches/asyncQueues/index.d.ts +15 -0
- package/dist/types/patches/asyncQueues/kafkajs.d.ts +7 -0
- package/dist/types/setupConfig.d.ts +3 -0
- package/dist/worker-pool-capture.cjs +1 -1
- package/dist/worker-pool-capture.mjs +1 -1
- package/dist/{workerPoolSpanCapture-BomWTMM2.js → workerPoolSpanCapture-B5AjE5B9.js} +115 -115
- package/dist/workerPoolSpanCapture-CVp5eCI6.cjs +83 -0
- package/package.json +2 -1
- package/dist/contextManager-qXvO_a5y.cjs +0 -1
- package/dist/workerPoolSpanCapture-BUFN_RMW.cjs +0 -83
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
* for a request (e.g., during stack trace or debugging).
|
|
4
4
|
*/
|
|
5
5
|
export declare const TRACE_HEADER = "x-sf3-rid";
|
|
6
|
+
/**
|
|
7
|
+
* Canonical header / metadata key for Sailfish trace propagation across any
|
|
8
|
+
* transport (HTTP, Kafka headers, Celery headers dict, BullMQ opts, etc).
|
|
9
|
+
* Use this constant everywhere a trace ID is written or read.
|
|
10
|
+
*/
|
|
11
|
+
export declare const HEADER_TRACING = "X-Sf3-Rid";
|
|
6
12
|
/**
|
|
7
13
|
* Outbound parent-trace header (mirrors Python's PARENT_SESSION_ID_HEADER).
|
|
8
14
|
* Carries the FULL inbound trace id (3 segments) so server-side code can
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "async_hooks";
|
|
2
2
|
type Store = Map<string, unknown>;
|
|
3
3
|
export declare const context: AsyncLocalStorage<Store>;
|
|
4
|
+
export declare const NONSESSION_APPLOGS = "nonsession-applogs";
|
|
4
5
|
export declare const DEFAULT_DOMAINS_TO_EXCLUDE: readonly ["identitytoolkit.googleapis.com", "t.co", "*.twitter.com", "*.gravatar.com", "*.googleapis.com", "*.amazonaws.com", "*.smooch.io", "*.zendesk.com"];
|
|
5
6
|
type Context = {
|
|
6
7
|
traceId?: string;
|
|
@@ -37,6 +38,20 @@ export declare class ContextManager {
|
|
|
37
38
|
runWithSession<T>(sessionId: string, fn: () => T): T;
|
|
38
39
|
/** Optional: clean up session context to avoid leaks in long-lived processes */
|
|
39
40
|
deleteSession(sessionId: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Run `fn` inside a new AsyncLocalStorage scope whose Context is a shallow
|
|
43
|
+
* merge of the current context and `overrides`. Used by queue-consumer
|
|
44
|
+
* wrappers so each message's handler has its own trace without leaking into
|
|
45
|
+
* sibling iterations.
|
|
46
|
+
*
|
|
47
|
+
* H1: Context holds `Set` fields (`handledExceptions`, `excludedDomains`,
|
|
48
|
+
* `supportedDomains`). A naïve shallow merge would propagate the SAME Set
|
|
49
|
+
* reference from parent to child — child mutations would write into the
|
|
50
|
+
* parent's Set, leaking state across consumer-message scopes and growing
|
|
51
|
+
* unbounded. Clone the Sets when entering a new scope so each child gets
|
|
52
|
+
* its own copy.
|
|
53
|
+
*/
|
|
54
|
+
runScoped<T>(overrides: Partial<Context>, fn: () => T): T;
|
|
40
55
|
getTraceId(): string | undefined;
|
|
41
56
|
getPageVisitUUID(): string | undefined;
|
|
42
57
|
setTraceId(traceId: string): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -7,3 +7,5 @@ export { transformFunctionSpans, transformFunctionSpansSync, setSkipTypeScriptPl
|
|
|
7
7
|
export { shouldEnableRuntimeHooks, isRuntimeModeEnabled, isProductionEnvironment } from "./runtime/runtimeConfig";
|
|
8
8
|
export { isAlreadyInstrumented } from "./runtime/instrumentationDetector";
|
|
9
9
|
export { initializeWorkerPoolPatching, isInitialized as isWorkerPoolInitialized } from "./patches/workerPool/index";
|
|
10
|
+
export { uninstallAsyncQueuePatches, isAsyncQueuePatchesInstalled, } from "./patches/asyncQueues/index";
|
|
11
|
+
export { _setAsyncQueueHopSpy } from "./patches/asyncQueues/asyncQueueTracer";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO(queue-tracing): bee-queue async-queue tracing patch.
|
|
3
|
+
*
|
|
4
|
+
* Placeholder. bee-queue is a lightweight Redis-backed queue similar to
|
|
5
|
+
* BullMQ but with a different API. Store the trace in `job.data._sf` or on
|
|
6
|
+
* a custom options field — see bullmq.ts for the pattern.
|
|
7
|
+
*
|
|
8
|
+
* See veritas/jsts-backend/CONTRIBUTING_QUEUES.md.
|
|
9
|
+
*/
|
|
10
|
+
export declare function patchBeeQueue(): "not-installed";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO(queue-tracing): RabbitMQ (amqplib) async-queue tracing patch.
|
|
3
|
+
*
|
|
4
|
+
* This is a placeholder. RabbitMQ messages have a `properties.headers` dict
|
|
5
|
+
* (amqplib) — the trace ID can go there. See the existing kafkajs.ts patch
|
|
6
|
+
* for the injection pattern.
|
|
7
|
+
*
|
|
8
|
+
* See veritas/jsts-backend/CONTRIBUTING_QUEUES.md for the step-by-step
|
|
9
|
+
* contributor guide on implementing this.
|
|
10
|
+
*/
|
|
11
|
+
export declare function patchRabbitMQ(): "not-installed";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO(queue-tracing): AWS SQS (@aws-sdk/client-sqs) async-queue tracing patch.
|
|
3
|
+
*
|
|
4
|
+
* Placeholder. SQS `SendMessageCommand` input has a `MessageAttributes` dict
|
|
5
|
+
* — inject the trace ID there; the consumer reads it via `ReceiveMessage`.
|
|
6
|
+
*
|
|
7
|
+
* See veritas/jsts-backend/CONTRIBUTING_QUEUES.md.
|
|
8
|
+
*/
|
|
9
|
+
export declare function patchSQS(): "not-installed";
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { NetworkHopTransmitter } from "../../networkHopTransmitter";
|
|
2
|
+
import { NetworkRequestData, NetworkRequestTransmitter } from "../../networkRequestTransmitter";
|
|
3
|
+
export declare const QUEUE_TRACE_HEADER = "X-Sf3-Rid";
|
|
4
|
+
/**
|
|
5
|
+
* Case-insensitive lookup of the Sailfish trace header (X-Sf3-Rid) in a
|
|
6
|
+
* headers object or array-of-{key,value} entries. Proxies (HAProxy, envoy,
|
|
7
|
+
* nginx) and some Kafka clients may normalize header case.
|
|
8
|
+
*/
|
|
9
|
+
export declare function findSailfishTraceHeaderValue(headers: unknown): unknown;
|
|
10
|
+
export interface QueueProducerContext {
|
|
11
|
+
/** Short library identifier, e.g. 'bullmq', 'kafkajs'. */
|
|
12
|
+
library: string;
|
|
13
|
+
/** Synthetic URI describing the destination, e.g. 'kafka://broker/topic'. */
|
|
14
|
+
queueUri: string;
|
|
15
|
+
/** The user-supplied message payload (used for body capture). */
|
|
16
|
+
messagePayload?: unknown;
|
|
17
|
+
/**
|
|
18
|
+
* HTTP-method-style label on the emitted hop. Defaults to ``ENQUEUE``.
|
|
19
|
+
* Useful overrides: ``ENQUEUE_TX`` for Kafka transactional producers so
|
|
20
|
+
* the UI can visually distinguish "pending until commit" from normal
|
|
21
|
+
* enqueue.
|
|
22
|
+
*/
|
|
23
|
+
method?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface QueueConsumerContext {
|
|
26
|
+
library: string;
|
|
27
|
+
queueUri: string;
|
|
28
|
+
messagePayload?: unknown;
|
|
29
|
+
/** Override the emitted hop method. Defaults to ``CONSUME``. Used by
|
|
30
|
+
* BullMQ stalled-recovery path to tag ``CONSUME_STALLED``. */
|
|
31
|
+
method?: string;
|
|
32
|
+
/** Trace ID extracted from the incoming message header (if present). */
|
|
33
|
+
incomingTraceId?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ProducerHandle {
|
|
36
|
+
/** Trace ID with the third UUID freshly rotated. Inject this into the message. */
|
|
37
|
+
readonly traceId: string;
|
|
38
|
+
/** Call when the enqueue call settles (success or error). */
|
|
39
|
+
hopEnd: (err?: Error | null) => void;
|
|
40
|
+
}
|
|
41
|
+
declare function getNetworkRequestTransmitter(): NetworkRequestTransmitter;
|
|
42
|
+
declare function getNetworkHopTransmitter(): NetworkHopTransmitter;
|
|
43
|
+
export declare function isValidTraceShape(trace: unknown): trace is string;
|
|
44
|
+
/**
|
|
45
|
+
* Rotate only the last segment (requestId) of a Sailfish trace triplet while
|
|
46
|
+
* preserving session + pageVisit. Exported so per-library consumer patches can
|
|
47
|
+
* rotate on retry/redelivery without emitting a producer hop.
|
|
48
|
+
*/
|
|
49
|
+
export declare function rotateTraceRequestId(trace: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Begin a producer span. Rotates the third UUID of the current trace, returns
|
|
52
|
+
* the new trace + a `hopEnd` callback.
|
|
53
|
+
*
|
|
54
|
+
* W1: snapshot the body string AT call time (rather than at `hopEnd` time) and
|
|
55
|
+
* extract every other ctx field we'll need into local variables before
|
|
56
|
+
* returning. The `hopEnd` closure must NOT close over `ctx`, otherwise
|
|
57
|
+
* `ctx.messagePayload` (potentially MB-sized) stays pinned in heap for the
|
|
58
|
+
* entire in-flight window of the user's `producer.send()`. Under producer
|
|
59
|
+
* backpressure (slow brokers, high concurrency) this multiplies memory
|
|
60
|
+
* residency by the number of in-flight enqueues.
|
|
61
|
+
*/
|
|
62
|
+
export declare function beginProducer(ctx: QueueProducerContext): ProducerHandle;
|
|
63
|
+
/**
|
|
64
|
+
* Wrap a consumer's handler so:
|
|
65
|
+
* 1. The handler runs inside a scoped AsyncLocalStorage context seeded with
|
|
66
|
+
* the incoming trace ID (so child work sees it).
|
|
67
|
+
* 2. An inbound NetworkRequest span is emitted whose duration spans the
|
|
68
|
+
* entire handler execution (success or error).
|
|
69
|
+
*/
|
|
70
|
+
export declare function wrapConsumerHandler<T>(ctx: QueueConsumerContext, handler: () => Promise<T> | T): Promise<T>;
|
|
71
|
+
export { getNetworkHopTransmitter, getNetworkRequestTransmitter };
|
|
72
|
+
/**
|
|
73
|
+
* W8: install a patched function onto a target prototype, returning whether
|
|
74
|
+
* the assignment succeeded. Customers who freeze library prototypes (security
|
|
75
|
+
* hardening, `Object.freeze(Queue.prototype)`) or other SDKs that install
|
|
76
|
+
* non-configurable properties on the same key would otherwise cause our
|
|
77
|
+
* assignment to throw TypeError in strict mode, aborting the entire installer
|
|
78
|
+
* mid-loop. We swallow the failure (logged under sfDebug) and let the rest
|
|
79
|
+
* of the patches in the same module continue.
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* Optional debug/QA hook: every hop the SDK is about to transmit is also
|
|
83
|
+
* passed to a spy callback (if registered) BEFORE the transmitter runs.
|
|
84
|
+
* Used by the QA test app to stream hop events to a browser UI in real time.
|
|
85
|
+
* Zero cost when no spy is registered.
|
|
86
|
+
*
|
|
87
|
+
* @internal — exposed publicly for QA tooling only. Not part of the
|
|
88
|
+
* stable customer-facing API.
|
|
89
|
+
*/
|
|
90
|
+
type HopSpy = (data: NetworkRequestData) => void;
|
|
91
|
+
export declare function _setAsyncQueueHopSpy(spy: HopSpy | null): void;
|
|
92
|
+
/**
|
|
93
|
+
* E3: use globally-keyed Symbols instead of string property names for our
|
|
94
|
+
* "this function/object has already been instrumented" markers. Other
|
|
95
|
+
* observability SDKs that happen to also use the string `__sfPatched`
|
|
96
|
+
* would otherwise see our marker on a function they wrapped and skip
|
|
97
|
+
* their own instrumentation, silently breaking their tracing. Symbols
|
|
98
|
+
* registered with the same key collide only across vendors that
|
|
99
|
+
* deliberately pick the same registry key.
|
|
100
|
+
*/
|
|
101
|
+
export declare const SF_PATCHED: unique symbol;
|
|
102
|
+
export declare const SF_INSTANCE_WRAPPED: unique symbol;
|
|
103
|
+
export declare function safeInstallPrototypeMethod(proto: any, key: string, patched: Function): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* W3: revert every prototype patch we've installed. Best-effort —
|
|
106
|
+
* individual restorations that throw (frozen prototype, non-configurable
|
|
107
|
+
* descriptor) are skipped. Returns the number of methods restored.
|
|
108
|
+
*
|
|
109
|
+
* After uninstall, `installAsyncQueuePatches()` may be called again to
|
|
110
|
+
* re-install. Customers should treat this as an emergency revert: if the
|
|
111
|
+
* SDK is responsible for an incident, uninstall in-process and redeploy
|
|
112
|
+
* later with `SF_DISABLE_QUEUE_PATCHES=true`.
|
|
113
|
+
*/
|
|
114
|
+
export declare function uninstallAllPrototypePatches(): number;
|
|
115
|
+
/**
|
|
116
|
+
* A1: run an instrumentation rewrite (compute a new args object, allocate
|
|
117
|
+
* tracking handles, etc.) and never let an exception in our code escape into
|
|
118
|
+
* the customer's call path. Returns the rewrite result on success, or
|
|
119
|
+
* `null` on failure (caller falls back to the user's original args, no
|
|
120
|
+
* hop emitted).
|
|
121
|
+
*
|
|
122
|
+
* Customer payloads can carry exotic shapes — Proxies with throwing traps,
|
|
123
|
+
* objects with throw-on-access getters, non-stringifiable Symbol keys —
|
|
124
|
+
* that make `{...x}` / `Buffer.from(x)` / `JSON.stringify(x)` throw. Our
|
|
125
|
+
* telemetry must absorb those failures, not propagate them.
|
|
126
|
+
*/
|
|
127
|
+
export declare function tryInstrumentationRewrite<T>(rewrite: () => T, context: string): T | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Shape we mutate. We don't depend on BullMQ's types to avoid a hard dep. */
|
|
2
|
+
interface MutableJobOpts {
|
|
3
|
+
sf?: {
|
|
4
|
+
rid?: string;
|
|
5
|
+
};
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* F9: queue-URI builder. For jobs we prefer (in order):
|
|
10
|
+
* 1. ``job.queueQualifiedName`` — BullMQ's prefix-aware canonical name
|
|
11
|
+
* (e.g. ``bull:my-queue``). Present on Worker side.
|
|
12
|
+
* 2. ``job.queueName`` — plain queue name.
|
|
13
|
+
* 3. ``worker.name`` or ``queue.name`` — fallback for edge cases.
|
|
14
|
+
*
|
|
15
|
+
* Callers pass whichever of these they have. We strip BullMQ's ``bull:``
|
|
16
|
+
* prefix if present since our URI already has a scheme.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildQueueUri(queueName: string | undefined, jobName: string | undefined): string;
|
|
19
|
+
/**
|
|
20
|
+
* Pick the best-available queue-name field from a Job or Worker-like
|
|
21
|
+
* object. Prefers qualified (prefix-aware) names.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pickQueueNameFromJob(job: any): string | undefined;
|
|
24
|
+
export declare function injectTraceIntoOpts(opts: MutableJobOpts | undefined, traceId: string): MutableJobOpts;
|
|
25
|
+
type PatchInstallResult = "installed" | "not-installed" | "failed";
|
|
26
|
+
export declare function patchBullmq(injectedBullmq?: unknown): PatchInstallResult;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type PatchResult = "installed" | "not-installed" | "failed";
|
|
2
|
+
type PatchInstaller = () => PatchResult;
|
|
3
|
+
export declare function installAsyncQueuePatches(): void;
|
|
4
|
+
export declare function isAsyncQueuePatchesInstalled(): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* W3: revert every async-queue prototype patch we've installed. Customers
|
|
7
|
+
* use this as an emergency revert when the SDK is implicated in an
|
|
8
|
+
* incident — restores library prototypes in-place and resets the
|
|
9
|
+
* `installed` guard so a later `installAsyncQueuePatches()` would
|
|
10
|
+
* install fresh. Returns the number of methods restored.
|
|
11
|
+
*/
|
|
12
|
+
export declare function uninstallAsyncQueuePatches(): number;
|
|
13
|
+
/** Internal — used by subsequent subtasks to register their patch. */
|
|
14
|
+
export declare function _registerAsyncQueuePatch(name: string, install: PatchInstaller, envDisableKey?: string): void;
|
|
15
|
+
export * from "./asyncQueueTracer";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type PatchInstallResult = "installed" | "not-installed" | "failed";
|
|
2
|
+
/**
|
|
3
|
+
* @param injectedKafkajs test hook — passes a kafkajs-shaped module so the
|
|
4
|
+
* vitest specs can avoid CJS require interop issues.
|
|
5
|
+
*/
|
|
6
|
+
export declare function patchKafkajs(injectedKafkajs?: unknown): PatchInstallResult;
|
|
7
|
+
export {};
|
|
@@ -156,7 +156,10 @@ declare class AppConfig {
|
|
|
156
156
|
captureResponseBody: boolean;
|
|
157
157
|
requestBodyLimitBytes: number;
|
|
158
158
|
responseBodyLimitBytes: number;
|
|
159
|
+
bullmqBulkAggregateMode: boolean;
|
|
159
160
|
retryOnClientError: "all" | "idempotent" | "none";
|
|
161
|
+
dataSensitivityLevel: string;
|
|
162
|
+
exceptionCaptureLocals: boolean;
|
|
160
163
|
private _serviceIdentificationReceived;
|
|
161
164
|
constructor(options: SetupOptions);
|
|
162
165
|
private getPackageVersion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./workerPoolSpanCapture-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./workerPoolSpanCapture-CVp5eCI6.cjs");exports.captureWorkerPoolOperation=e.captureWorkerPoolOperation;
|