@rootcat/node 0.0.0-stage → 0.1.0
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/LICENSE +202 -0
- package/README.md +213 -2
- package/dist/callsite.d.ts +109 -0
- package/dist/callsite.js +565 -0
- package/dist/callsite.js.map +1 -0
- package/dist/config.d.ts +75 -0
- package/dist/config.js +182 -0
- package/dist/config.js.map +1 -0
- package/dist/drizzle.d.ts +21 -0
- package/dist/drizzle.js +124 -0
- package/dist/drizzle.js.map +1 -0
- package/dist/esm.mjs +41 -0
- package/dist/esmhook.d.ts +12 -0
- package/dist/esmhook.js +84 -0
- package/dist/esmhook.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/intake.d.ts +40 -0
- package/dist/intake.js +164 -0
- package/dist/intake.js.map +1 -0
- package/dist/keys.d.ts +9 -0
- package/dist/keys.js +15 -0
- package/dist/keys.js.map +1 -0
- package/dist/notices.d.ts +2 -0
- package/dist/notices.js +21 -0
- package/dist/notices.js.map +1 -0
- package/dist/otlp.d.ts +75 -0
- package/dist/otlp.js +449 -0
- package/dist/otlp.js.map +1 -0
- package/dist/pg.d.ts +16 -0
- package/dist/pg.js +165 -0
- package/dist/pg.js.map +1 -0
- package/dist/pgpool.d.ts +13 -0
- package/dist/pgpool.js +85 -0
- package/dist/pgpool.js.map +1 -0
- package/dist/postgresjs.d.ts +33 -0
- package/dist/postgresjs.js +272 -0
- package/dist/postgresjs.js.map +1 -0
- package/dist/privacy.d.ts +38 -0
- package/dist/privacy.js +147 -0
- package/dist/privacy.js.map +1 -0
- package/dist/processor.d.ts +94 -0
- package/dist/processor.js +252 -0
- package/dist/processor.js.map +1 -0
- package/dist/register.d.ts +1 -0
- package/dist/register.js +12 -0
- package/dist/register.js.map +1 -0
- package/dist/sampler.d.ts +12 -0
- package/dist/sampler.js +52 -0
- package/dist/sampler.js.map +1 -0
- package/dist/sdk.d.ts +88 -0
- package/dist/sdk.js +305 -0
- package/dist/sdk.js.map +1 -0
- package/package.json +65 -4
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type Context } from '@opentelemetry/api';
|
|
2
|
+
import type { ReadableSpan, Span, SpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
3
|
+
import { type CallSiteLocation } from './callsite.js';
|
|
4
|
+
import { type StatementMode } from './privacy.js';
|
|
5
|
+
export { callSiteContextKey } from './keys.js';
|
|
6
|
+
/**
|
|
7
|
+
* CallSiteSampling is the gate every capture goes through: the
|
|
8
|
+
* processor's own and the entry wrappers' (pg, pg pool, Drizzle,
|
|
9
|
+
* postgres.js), so a capture is never paid for a span that will not be
|
|
10
|
+
* exported or that the one-in-N setting skips.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CallSiteSampling {
|
|
13
|
+
/** sample is the one-in-N setting; the benchmark changes it between blocks. */
|
|
14
|
+
sample: number;
|
|
15
|
+
/** ratio is the trace sampling share; the benchmark changes it between blocks. */
|
|
16
|
+
ratio: number;
|
|
17
|
+
private counter;
|
|
18
|
+
/** sample is ROOTCAT_CALLSITE_SAMPLE; ratio is ROOTCAT_SAMPLE. */
|
|
19
|
+
constructor(sample: number, ratio?: number);
|
|
20
|
+
/** take counts one occasion and reports whether it captures. */
|
|
21
|
+
take(): boolean;
|
|
22
|
+
/** on reports whether any capture happens at all. */
|
|
23
|
+
get on(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* carry is what an entry wrapper calls before the operation it wraps:
|
|
26
|
+
* it returns the context to run the operation in, or undefined to run
|
|
27
|
+
* it as it is. Under an unsampled span nothing happens. Outside any
|
|
28
|
+
* span with a ratio below 1, the trace decision is made here (the
|
|
29
|
+
* sampler follows it), and an unsampled operation captures nothing. A
|
|
30
|
+
* site already carried by an outer layer of the same operation stands,
|
|
31
|
+
* unless override (a capture that costs nothing, such as postgres.js's
|
|
32
|
+
* own origin, and names the operation more exactly). Otherwise, one
|
|
33
|
+
* occasion in N, capture() runs and its site is carried.
|
|
34
|
+
*/
|
|
35
|
+
carry(capture: () => CallSiteLocation | undefined, override?: boolean): Context | undefined;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* unsampled reports whether a span started under ctx would not be
|
|
39
|
+
* recorded (an unsampled parent, or a root an entry wrapper decided
|
|
40
|
+
* against): the drivers then run untouched, without even a
|
|
41
|
+
* non-recording span or a context of their own.
|
|
42
|
+
*/
|
|
43
|
+
export declare function unsampled(ctx: Context): boolean;
|
|
44
|
+
/** runCarried runs fn under the context carry returned, if any. */
|
|
45
|
+
export declare function runCarried<T>(ctx: Context | undefined, fn: () => T): T;
|
|
46
|
+
/** CallSiteProcessorOptions configures the processor. */
|
|
47
|
+
export interface CallSiteProcessorOptions {
|
|
48
|
+
/** sampling gates the captures; a number is the one-in-N setting. */
|
|
49
|
+
sampling: CallSiteSampling | number;
|
|
50
|
+
/** depth bounds the frames walked. */
|
|
51
|
+
depth: number;
|
|
52
|
+
/** statement is passed to the privacy rules. */
|
|
53
|
+
statement: StatementMode;
|
|
54
|
+
/** isApp decides which files are application code (tests override). */
|
|
55
|
+
isApp?: (file: string) => boolean;
|
|
56
|
+
/**
|
|
57
|
+
* above is the function a capture from the processor starts below (the
|
|
58
|
+
* SDK tracer's startSpan), so the walk skips the SDK's own frames.
|
|
59
|
+
*/
|
|
60
|
+
above?: Function;
|
|
61
|
+
}
|
|
62
|
+
/** Attribute keys written. */
|
|
63
|
+
export declare const codeFilepath = "code.filepath";
|
|
64
|
+
export declare const codeLineno = "code.lineno";
|
|
65
|
+
export declare const codeFunction = "code.function";
|
|
66
|
+
/**
|
|
67
|
+
* eligible reports whether a span is a client operation worth a call
|
|
68
|
+
* site: client and producer spans, anything carrying db.system, and the
|
|
69
|
+
* operation spans of the ORMs that start their work in application code.
|
|
70
|
+
*/
|
|
71
|
+
export declare function eligible(span: ReadableSpan): boolean;
|
|
72
|
+
/** CallSiteProcessor implements SpanProcessor. */
|
|
73
|
+
export declare class CallSiteProcessor implements SpanProcessor {
|
|
74
|
+
readonly sampling: CallSiteSampling;
|
|
75
|
+
private readonly depth;
|
|
76
|
+
private readonly statement;
|
|
77
|
+
private readonly isApp;
|
|
78
|
+
/** above is where a processor capture starts (the SDK tracer startSpan); set once the provider exists. */
|
|
79
|
+
above: Function | undefined;
|
|
80
|
+
private readonly sites;
|
|
81
|
+
/** captured counts spans given a call site (tests and the benchmark). */
|
|
82
|
+
captured: number;
|
|
83
|
+
constructor(options: CallSiteProcessorOptions);
|
|
84
|
+
onStart(span: Span, parentContext: Context): void;
|
|
85
|
+
/**
|
|
86
|
+
* locate takes a site already carried in the context or by the parent
|
|
87
|
+
* span (an entry wrapper paid for it, under the same gate), else, one
|
|
88
|
+
* occasion in N, captures the synchronous stack.
|
|
89
|
+
*/
|
|
90
|
+
private locate;
|
|
91
|
+
onEnd(span: ReadableSpan): void;
|
|
92
|
+
shutdown(): Promise<void>;
|
|
93
|
+
forceFlush(): Promise<void>;
|
|
94
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CallSiteProcessor = exports.codeFunction = exports.codeLineno = exports.codeFilepath = exports.CallSiteSampling = exports.callSiteContextKey = void 0;
|
|
4
|
+
exports.unsampled = unsampled;
|
|
5
|
+
exports.runCarried = runCarried;
|
|
6
|
+
exports.eligible = eligible;
|
|
7
|
+
// CallSiteProcessor: a span processor that, when a client span starts,
|
|
8
|
+
// records the application frame that caused it as code.filepath,
|
|
9
|
+
// code.lineno and code.function, and applies the privacy rules to the
|
|
10
|
+
// span's attributes at start and at end.
|
|
11
|
+
//
|
|
12
|
+
// Where the frame comes from, in order: the synchronous stack at span
|
|
13
|
+
// start (the usual case: the driver was called from application code);
|
|
14
|
+
// else a call site an entry wrapper stored in the active context (a pg
|
|
15
|
+
// pool hands queries to a client on nextTick, where the stack is the
|
|
16
|
+
// pool's); else the parent span's call site (an ORM's operation span
|
|
17
|
+
// started in application code, its driver span on a later tick).
|
|
18
|
+
const api_1 = require("@opentelemetry/api");
|
|
19
|
+
const callsite_js_1 = require("./callsite.js");
|
|
20
|
+
const keys_js_1 = require("./keys.js");
|
|
21
|
+
const privacy_js_1 = require("./privacy.js");
|
|
22
|
+
var keys_js_2 = require("./keys.js");
|
|
23
|
+
Object.defineProperty(exports, "callSiteContextKey", { enumerable: true, get: function () { return keys_js_2.callSiteContextKey; } });
|
|
24
|
+
/**
|
|
25
|
+
* CallSiteSampling is the gate every capture goes through: the
|
|
26
|
+
* processor's own and the entry wrappers' (pg, pg pool, Drizzle,
|
|
27
|
+
* postgres.js), so a capture is never paid for a span that will not be
|
|
28
|
+
* exported or that the one-in-N setting skips.
|
|
29
|
+
*/
|
|
30
|
+
class CallSiteSampling {
|
|
31
|
+
/** sample is the one-in-N setting; the benchmark changes it between blocks. */
|
|
32
|
+
sample;
|
|
33
|
+
/** ratio is the trace sampling share; the benchmark changes it between blocks. */
|
|
34
|
+
ratio;
|
|
35
|
+
counter = 0;
|
|
36
|
+
/** sample is ROOTCAT_CALLSITE_SAMPLE; ratio is ROOTCAT_SAMPLE. */
|
|
37
|
+
constructor(sample, ratio = 1) {
|
|
38
|
+
this.sample = Math.max(0, Math.floor(sample));
|
|
39
|
+
this.ratio = Math.min(1, Math.max(0, ratio));
|
|
40
|
+
}
|
|
41
|
+
/** take counts one occasion and reports whether it captures. */
|
|
42
|
+
take() {
|
|
43
|
+
if (this.sample === 0) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
this.counter++;
|
|
47
|
+
return this.counter % this.sample === 0;
|
|
48
|
+
}
|
|
49
|
+
/** on reports whether any capture happens at all. */
|
|
50
|
+
get on() {
|
|
51
|
+
return this.sample > 0;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* carry is what an entry wrapper calls before the operation it wraps:
|
|
55
|
+
* it returns the context to run the operation in, or undefined to run
|
|
56
|
+
* it as it is. Under an unsampled span nothing happens. Outside any
|
|
57
|
+
* span with a ratio below 1, the trace decision is made here (the
|
|
58
|
+
* sampler follows it), and an unsampled operation captures nothing. A
|
|
59
|
+
* site already carried by an outer layer of the same operation stands,
|
|
60
|
+
* unless override (a capture that costs nothing, such as postgres.js's
|
|
61
|
+
* own origin, and names the operation more exactly). Otherwise, one
|
|
62
|
+
* occasion in N, capture() runs and its site is carried.
|
|
63
|
+
*/
|
|
64
|
+
carry(capture, override = false) {
|
|
65
|
+
const active = api_1.context.active();
|
|
66
|
+
const span = api_1.trace.getSpanContext(active);
|
|
67
|
+
let ctx = active;
|
|
68
|
+
// A remote parent (an incoming traceparent) decides nothing: see the sampler.
|
|
69
|
+
if (span && api_1.trace.isSpanContextValid(span) && !span.isRemote) {
|
|
70
|
+
if ((span.traceFlags & api_1.TraceFlags.SAMPLED) === 0) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (this.ratio < 1 && active.getValue(keys_js_1.rootDecisionKey) === undefined) {
|
|
75
|
+
const decided = Math.random() < this.ratio;
|
|
76
|
+
ctx = ctx.setValue(keys_js_1.rootDecisionKey, decided);
|
|
77
|
+
if (!decided) {
|
|
78
|
+
return ctx;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (active.getValue(keys_js_1.rootDecisionKey) === false) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const existing = active.getValue(keys_js_1.callSiteContextKey) !== undefined;
|
|
85
|
+
if ((existing && !override) || (!existing && !this.take())) {
|
|
86
|
+
return ctx === active ? undefined : ctx;
|
|
87
|
+
}
|
|
88
|
+
const site = capture();
|
|
89
|
+
if (site) {
|
|
90
|
+
ctx = ctx.setValue(keys_js_1.callSiteContextKey, site);
|
|
91
|
+
}
|
|
92
|
+
return ctx === active ? undefined : ctx;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.CallSiteSampling = CallSiteSampling;
|
|
96
|
+
/**
|
|
97
|
+
* unsampled reports whether a span started under ctx would not be
|
|
98
|
+
* recorded (an unsampled parent, or a root an entry wrapper decided
|
|
99
|
+
* against): the drivers then run untouched, without even a
|
|
100
|
+
* non-recording span or a context of their own.
|
|
101
|
+
*/
|
|
102
|
+
function unsampled(ctx) {
|
|
103
|
+
const parent = api_1.trace.getSpanContext(ctx);
|
|
104
|
+
if (parent && api_1.trace.isSpanContextValid(parent) && !parent.isRemote) {
|
|
105
|
+
return (parent.traceFlags & api_1.TraceFlags.SAMPLED) === 0;
|
|
106
|
+
}
|
|
107
|
+
return ctx.getValue(keys_js_1.rootDecisionKey) === false;
|
|
108
|
+
}
|
|
109
|
+
/** runCarried runs fn under the context carry returned, if any. */
|
|
110
|
+
function runCarried(ctx, fn) {
|
|
111
|
+
return ctx ? api_1.context.with(ctx, fn) : fn();
|
|
112
|
+
}
|
|
113
|
+
/** Attribute keys written. */
|
|
114
|
+
exports.codeFilepath = 'code.filepath';
|
|
115
|
+
exports.codeLineno = 'code.lineno';
|
|
116
|
+
exports.codeFunction = 'code.function';
|
|
117
|
+
/**
|
|
118
|
+
* eligible reports whether a span is a client operation worth a call
|
|
119
|
+
* site: client and producer spans, anything carrying db.system, and the
|
|
120
|
+
* operation spans of the ORMs that start their work in application code.
|
|
121
|
+
*/
|
|
122
|
+
function eligible(span) {
|
|
123
|
+
if (!span.spanContext().traceFlags) {
|
|
124
|
+
return false; // not sampled: nothing will export it
|
|
125
|
+
}
|
|
126
|
+
if (span.kind === api_1.SpanKind.CLIENT || span.kind === api_1.SpanKind.PRODUCER) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
const attributes = span.attributes;
|
|
130
|
+
if (attributes['db.system'] !== undefined || attributes['db.system.name'] !== undefined) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return span.name.startsWith('drizzle.') || span.name.startsWith('prisma:client:');
|
|
134
|
+
}
|
|
135
|
+
/** CallSiteProcessor implements SpanProcessor. */
|
|
136
|
+
class CallSiteProcessor {
|
|
137
|
+
sampling;
|
|
138
|
+
depth;
|
|
139
|
+
statement;
|
|
140
|
+
isApp;
|
|
141
|
+
/** above is where a processor capture starts (the SDK tracer startSpan); set once the provider exists. */
|
|
142
|
+
above;
|
|
143
|
+
sites = new WeakMap();
|
|
144
|
+
/** captured counts spans given a call site (tests and the benchmark). */
|
|
145
|
+
captured = 0;
|
|
146
|
+
constructor(options) {
|
|
147
|
+
this.sampling = typeof options.sampling === 'number' ? new CallSiteSampling(options.sampling) : options.sampling;
|
|
148
|
+
this.depth = Math.max(1, Math.floor(options.depth));
|
|
149
|
+
this.statement = options.statement;
|
|
150
|
+
this.isApp = options.isApp ?? callsite_js_1.isAppFile;
|
|
151
|
+
this.above = options.above;
|
|
152
|
+
}
|
|
153
|
+
onStart(span, parentContext) {
|
|
154
|
+
try {
|
|
155
|
+
const changes = (0, privacy_js_1.scrubbed)(span.attributes, this.statement);
|
|
156
|
+
if (changes) {
|
|
157
|
+
span.setAttributes(changes);
|
|
158
|
+
}
|
|
159
|
+
if (!this.sampling.on || !eligible(span)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const site = this.locate(parentContext);
|
|
163
|
+
if (!site) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.sites.set(span, site);
|
|
167
|
+
this.captured++;
|
|
168
|
+
span.setAttribute(exports.codeFilepath, (0, callsite_js_1.displayPath)(site.file));
|
|
169
|
+
span.setAttribute(exports.codeLineno, site.line);
|
|
170
|
+
if (site.function !== '') {
|
|
171
|
+
span.setAttribute(exports.codeFunction, site.function);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// A call site is an extra; a failure to find one never reaches the app.
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* locate takes a site already carried in the context or by the parent
|
|
180
|
+
* span (an entry wrapper paid for it, under the same gate), else, one
|
|
181
|
+
* occasion in N, captures the synchronous stack.
|
|
182
|
+
*/
|
|
183
|
+
locate(parentContext) {
|
|
184
|
+
const carried = parentContext.getValue(keys_js_1.callSiteContextKey);
|
|
185
|
+
if (isLocation(carried)) {
|
|
186
|
+
return carried;
|
|
187
|
+
}
|
|
188
|
+
const parent = api_1.trace.getSpan(parentContext);
|
|
189
|
+
const inherited = parent ? this.sites.get(parent) : undefined;
|
|
190
|
+
if (inherited) {
|
|
191
|
+
return inherited;
|
|
192
|
+
}
|
|
193
|
+
if (!this.sampling.take()) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
return (0, callsite_js_1.captureCallSite)(this.depth, this.isApp, this.above);
|
|
197
|
+
}
|
|
198
|
+
onEnd(span) {
|
|
199
|
+
try {
|
|
200
|
+
// The span is ended; the exporter reads these same objects, so the
|
|
201
|
+
// rules hold for attributes and events set after the start as well.
|
|
202
|
+
const changes = (0, privacy_js_1.scrubbed)(span.attributes, this.statement);
|
|
203
|
+
if (changes) {
|
|
204
|
+
const attributes = span.attributes;
|
|
205
|
+
for (const [key, value] of Object.entries(changes)) {
|
|
206
|
+
attributes[key] = value;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
let exceptionMessage;
|
|
210
|
+
for (const event of span.events) {
|
|
211
|
+
const attributes = event.attributes;
|
|
212
|
+
const stack = attributes?.['exception.stacktrace'];
|
|
213
|
+
if (typeof stack === 'string') {
|
|
214
|
+
// A recorded exception's stack opens with its message line, which
|
|
215
|
+
// a database server may fill with the input that failed; the
|
|
216
|
+
// frames alone say where it happened.
|
|
217
|
+
attributes['exception.stacktrace'] = (0, privacy_js_1.framesOnly)(stack);
|
|
218
|
+
}
|
|
219
|
+
if (event.name === 'exception' && typeof attributes?.['exception.message'] === 'string') {
|
|
220
|
+
exceptionMessage = attributes['exception.message'];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// A database span's status message is the server's text, which can
|
|
224
|
+
// quote the input that failed; the instrumentation's own exception
|
|
225
|
+
// message (the pg one says only the class and SQLSTATE) stands in.
|
|
226
|
+
if (span.status.code === api_1.SpanStatusCode.ERROR && isDatabase(span.attributes) && span.status.message) {
|
|
227
|
+
span.status.message = exceptionMessage ?? 'database error';
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// never reaches the app
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
shutdown() {
|
|
235
|
+
return Promise.resolve();
|
|
236
|
+
}
|
|
237
|
+
forceFlush() {
|
|
238
|
+
return Promise.resolve();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
exports.CallSiteProcessor = CallSiteProcessor;
|
|
242
|
+
function isDatabase(attributes) {
|
|
243
|
+
return attributes['db.system'] !== undefined || attributes['db.system.name'] !== undefined;
|
|
244
|
+
}
|
|
245
|
+
function isLocation(value) {
|
|
246
|
+
if (!value || typeof value !== 'object') {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
const record = value;
|
|
250
|
+
return typeof record.file === 'string' && typeof record.line === 'number';
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processor.js","sourceRoot":"","sources":["../src/processor.ts"],"names":[],"mappings":";;;AAmGA,8BAMC;AAGD,gCAEC;AA6BD,4BAYC;AAvJD,uEAAuE;AACvE,iEAAiE;AACjE,sEAAsE;AACtE,yCAAyC;AACzC,EAAE;AACF,sEAAsE;AACtE,uEAAuE;AACvE,uEAAuE;AACvE,qEAAqE;AACrE,qEAAqE;AACrE,iEAAiE;AACjE,4CAAyH;AAEzH,+CAA+F;AAC/F,uCAAgE;AAChE,6CAAwE;AAExE,qCAA+C;AAAtC,6GAAA,kBAAkB,OAAA;AAE3B;;;;;GAKG;AACH,MAAa,gBAAgB;IAC3B,+EAA+E;IAC/E,MAAM,CAAS;IACf,kFAAkF;IAClF,KAAK,CAAS;IACN,OAAO,GAAG,CAAC,CAAC;IAEpB,kEAAkE;IAClE,YAAY,MAAc,EAAE,KAAK,GAAG,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,gEAAgE;IAChE,IAAI;QACF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,qDAAqD;IACrD,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAA2C,EAAE,QAAQ,GAAG,KAAK;QACjE,MAAM,MAAM,GAAG,aAAO,CAAC,MAAM,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,WAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,GAAG,GAAG,MAAM,CAAC;QACjB,8EAA8E;QAC9E,IAAI,IAAI,IAAI,WAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,gBAAU,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,yBAAe,CAAC,KAAK,SAAS,EAAE,CAAC;YAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YAC3C,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,yBAAe,EAAE,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;aAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,yBAAe,CAAC,KAAK,KAAK,EAAE,CAAC;YACtD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,4BAAkB,CAAC,KAAK,SAAS,CAAC;QACnE,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3D,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1C,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,IAAI,EAAE,CAAC;YACT,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,4BAAkB,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1C,CAAC;CACF;AAlED,4CAkEC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,GAAY;IACpC,MAAM,MAAM,GAAG,WAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,MAAM,IAAI,WAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnE,OAAO,CAAC,MAAM,CAAC,UAAU,GAAG,gBAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC,yBAAe,CAAC,KAAK,KAAK,CAAC;AACjD,CAAC;AAED,mEAAmE;AACnE,SAAgB,UAAU,CAAI,GAAwB,EAAE,EAAW;IACjE,OAAO,GAAG,CAAC,CAAC,CAAC,aAAO,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC5C,CAAC;AAmBD,8BAA8B;AACjB,QAAA,YAAY,GAAG,eAAe,CAAC;AAC/B,QAAA,UAAU,GAAG,aAAa,CAAC;AAC3B,QAAA,YAAY,GAAG,eAAe,CAAC;AAE5C;;;;GAIG;AACH,SAAgB,QAAQ,CAAC,IAAkB;IACzC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,CAAC,sCAAsC;IACtD,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,KAAK,cAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,cAAQ,CAAC,QAAQ,EAAE,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACnC,IAAI,UAAU,CAAC,WAAW,CAAC,KAAK,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC,KAAK,SAAS,EAAE,CAAC;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACpF,CAAC;AAED,kDAAkD;AAClD,MAAa,iBAAiB;IACnB,QAAQ,CAAmB;IACnB,KAAK,CAAS;IACd,SAAS,CAAgB;IACzB,KAAK,CAA4B;IAClD,0GAA0G;IAC1G,KAAK,CAAuB;IACX,KAAK,GAAG,IAAI,OAAO,EAA4B,CAAC;IACjE,yEAAyE;IACzE,QAAQ,GAAG,CAAC,CAAC;IAEb,YAAY,OAAiC;QAC3C,IAAI,CAAC,QAAQ,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;QACjH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,uBAAS,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC7B,CAAC;IAED,OAAO,CAAC,IAAU,EAAE,aAAsB;QACxC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAA,qBAAQ,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,YAAY,CAAC,oBAAY,EAAE,IAAA,yBAAW,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACxD,IAAI,CAAC,YAAY,CAAC,kBAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;gBACzB,IAAI,CAAC,YAAY,CAAC,oBAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,aAAsB;QACnC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,4BAAkB,CAAC,CAAC;QAC3D,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,WAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAA,6BAAe,EAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,IAAkB;QACtB,IAAI,CAAC;YACH,mEAAmE;YACnE,oEAAoE;YACpE,MAAM,OAAO,GAAG,IAAA,qBAAQ,EAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,UAAU,GAAG,IAAI,CAAC,UAAqC,CAAC;gBAC9D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnD,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,CAAC;YACH,CAAC;YACD,IAAI,gBAAoC,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAiD,CAAC;gBAC3E,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,sBAAsB,CAAC,CAAC;gBACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC9B,kEAAkE;oBAClE,6DAA6D;oBAC7D,sCAAsC;oBACtC,UAAW,CAAC,sBAAsB,CAAC,GAAG,IAAA,uBAAU,EAAC,KAAK,CAAC,CAAC;gBAC1D,CAAC;gBACD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,UAAU,EAAE,CAAC,mBAAmB,CAAC,KAAK,QAAQ,EAAE,CAAC;oBACxF,gBAAgB,GAAG,UAAU,CAAC,mBAAmB,CAAW,CAAC;gBAC/D,CAAC;YACH,CAAC;YACD,mEAAmE;YACnE,mEAAmE;YACnE,mEAAmE;YACnE,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,oBAAc,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnG,IAAI,CAAC,MAA+B,CAAC,OAAO,GAAG,gBAAgB,IAAI,gBAAgB,CAAC;YACvF,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,UAAU;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;CACF;AA5GD,8CA4GC;AAED,SAAS,UAAU,CAAC,UAAsB;IACxC,OAAO,UAAU,CAAC,WAAW,CAAC,KAAK,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC,KAAK,SAAS,CAAC;AAC7F,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,OAAO,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// The --require entry: starts tracing as a side effect of being loaded.
|
|
4
|
+
// NODE_OPTIONS="--require @rootcat/node"
|
|
5
|
+
// The module loader hooks thread runs the same preloads as the main
|
|
6
|
+
// thread; tracing belongs to the main thread only.
|
|
7
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
8
|
+
const sdk_js_1 = require("./sdk.js");
|
|
9
|
+
if (node_worker_threads_1.isMainThread) {
|
|
10
|
+
(0, sdk_js_1.start)();
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":";;AAAA,wEAAwE;AACxE,2CAA2C;AAC3C,oEAAoE;AACpE,mDAAmD;AACnD,6DAAmD;AACnD,qCAAiC;AAEjC,IAAI,kCAAY,EAAE,CAAC;IACjB,IAAA,cAAK,GAAE,CAAC;AACV,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Attributes, type Context, type Link, type SpanKind } from '@opentelemetry/api';
|
|
2
|
+
import { type Sampler, type SamplingResult } from '@opentelemetry/sdk-trace-base';
|
|
3
|
+
/** RootcatSampler is the ratio sampler that honours a wrapper's root decision. */
|
|
4
|
+
export declare class RootcatSampler implements Sampler {
|
|
5
|
+
readonly ratio: number;
|
|
6
|
+
private readonly inner;
|
|
7
|
+
constructor(ratio: number);
|
|
8
|
+
shouldSample(context: Context, traceId: string, spanName: string, spanKind: SpanKind, attributes: Attributes, links: Link[]): SamplingResult;
|
|
9
|
+
toString(): string;
|
|
10
|
+
}
|
|
11
|
+
/** rootcatSampler builds the sampler for a ratio between 0 and 1. */
|
|
12
|
+
export declare function rootcatSampler(ratio: number): Sampler;
|
package/dist/sampler.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RootcatSampler = void 0;
|
|
4
|
+
exports.rootcatSampler = rootcatSampler;
|
|
5
|
+
// The sampler: parent-based, with a trace-id ratio at the root
|
|
6
|
+
// (ROOTCAT_SAMPLE, 1 by default) and for a parent from outside the
|
|
7
|
+
// process, whose sampled flag is not trusted. A root span whose context carries a
|
|
8
|
+
// decision an entry wrapper already made (see CallSiteSampling.carry)
|
|
9
|
+
// follows it, so the wrapper's capture and the span's fate agree. A span
|
|
10
|
+
// the sampler refuses is never recording: no processor runs for it.
|
|
11
|
+
const api_1 = require("@opentelemetry/api");
|
|
12
|
+
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
13
|
+
const keys_js_1 = require("./keys.js");
|
|
14
|
+
const sampled = { decision: sdk_trace_base_1.SamplingDecision.RECORD_AND_SAMPLED };
|
|
15
|
+
const dropped = { decision: sdk_trace_base_1.SamplingDecision.NOT_RECORD };
|
|
16
|
+
/** RootcatSampler is the ratio sampler that honours a wrapper's root decision. */
|
|
17
|
+
class RootcatSampler {
|
|
18
|
+
ratio;
|
|
19
|
+
inner;
|
|
20
|
+
constructor(ratio) {
|
|
21
|
+
this.ratio = ratio;
|
|
22
|
+
// A parent from outside the process (an incoming traceparent) does not
|
|
23
|
+
// decide: anyone on the internet could otherwise force full tracing of
|
|
24
|
+
// their requests with the sampled flag, or hide them with 00. The
|
|
25
|
+
// ratio decides on the trace id, which the request keeps, so the trace
|
|
26
|
+
// still joins its caller's.
|
|
27
|
+
const root = ratio >= 1 ? new sdk_trace_base_1.AlwaysOnSampler() : new sdk_trace_base_1.TraceIdRatioBasedSampler(ratio);
|
|
28
|
+
this.inner = new sdk_trace_base_1.ParentBasedSampler({ root, remoteParentSampled: root, remoteParentNotSampled: root });
|
|
29
|
+
}
|
|
30
|
+
shouldSample(context, traceId, spanName, spanKind, attributes, links) {
|
|
31
|
+
const parent = api_1.trace.getSpanContext(context);
|
|
32
|
+
if (!parent || !api_1.trace.isSpanContextValid(parent) || parent.isRemote) {
|
|
33
|
+
const decided = context.getValue(keys_js_1.rootDecisionKey);
|
|
34
|
+
if (decided === true) {
|
|
35
|
+
return sampled;
|
|
36
|
+
}
|
|
37
|
+
if (decided === false) {
|
|
38
|
+
return dropped;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return this.inner.shouldSample(context, traceId, spanName, spanKind, attributes, links);
|
|
42
|
+
}
|
|
43
|
+
toString() {
|
|
44
|
+
return `RootcatSampler(${this.ratio})`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.RootcatSampler = RootcatSampler;
|
|
48
|
+
/** rootcatSampler builds the sampler for a ratio between 0 and 1. */
|
|
49
|
+
function rootcatSampler(ratio) {
|
|
50
|
+
return new RootcatSampler(ratio);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=sampler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sampler.js","sourceRoot":"","sources":["../src/sampler.ts"],"names":[],"mappings":";;;AA+CA,wCAEC;AAjDD,+DAA+D;AAC/D,mEAAmE;AACnE,kFAAkF;AAClF,sEAAsE;AACtE,yEAAyE;AACzE,oEAAoE;AACpE,4CAAoG;AACpG,kEAAmK;AACnK,uCAA4C;AAE5C,MAAM,OAAO,GAAmB,EAAE,QAAQ,EAAE,iCAAgB,CAAC,kBAAkB,EAAE,CAAC;AAClF,MAAM,OAAO,GAAmB,EAAE,QAAQ,EAAE,iCAAgB,CAAC,UAAU,EAAE,CAAC;AAE1E,kFAAkF;AAClF,MAAa,cAAc;IAGJ;IAFJ,KAAK,CAAU;IAEhC,YAAqB,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;QAChC,uEAAuE;QACvE,uEAAuE;QACvE,kEAAkE;QAClE,uEAAuE;QACvE,4BAA4B;QAC5B,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,gCAAe,EAAE,CAAC,CAAC,CAAC,IAAI,yCAAwB,CAAC,KAAK,CAAC,CAAC;QACtF,IAAI,CAAC,KAAK,GAAG,IAAI,mCAAkB,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,YAAY,CAAC,OAAgB,EAAE,OAAe,EAAE,QAAgB,EAAE,QAAkB,EAAE,UAAsB,EAAE,KAAa;QACzH,MAAM,MAAM,GAAG,WAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,IAAI,CAAC,WAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpE,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,yBAAe,CAAC,CAAC;YAClD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;gBACtB,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IAC1F,CAAC;IAED,QAAQ;QACN,OAAO,kBAAkB,IAAI,CAAC,KAAK,GAAG,CAAC;IACzC,CAAC;CACF;AA9BD,wCA8BC;AAED,qEAAqE;AACrE,SAAgB,cAAc,CAAC,KAAa;IAC1C,OAAO,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC"}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type Instrumentation } from '@opentelemetry/instrumentation';
|
|
2
|
+
import { type Sampler, type SpanExporter, type SpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
3
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
4
|
+
import { type Config } from './config.js';
|
|
5
|
+
import { type ESMHook } from './esmhook.js';
|
|
6
|
+
import { CallSiteProcessor, CallSiteSampling } from './processor.js';
|
|
7
|
+
/**
|
|
8
|
+
* Exporter bounds, fixed: sized for a loopback intake that takes 1 MiB
|
|
9
|
+
* per request (512 protobuf spans are a few hundred KiB) and four
|
|
10
|
+
* uploads per sender. The queue holds 4096 ended spans; past that the
|
|
11
|
+
* newest are dropped, and the drop is reported once on stderr.
|
|
12
|
+
*/
|
|
13
|
+
export declare const exporterTimeoutMillis = 2000;
|
|
14
|
+
export declare const exporterConcurrency = 2;
|
|
15
|
+
export declare const batchMaxQueueSize = 4096;
|
|
16
|
+
export declare const batchMaxExportSize = 512;
|
|
17
|
+
export declare const batchDelayMillis = 10000;
|
|
18
|
+
/**
|
|
19
|
+
* spanLimits bound every span, so a batch of them can be split into
|
|
20
|
+
* requests the agent accepts and nothing the application records (a
|
|
21
|
+
* statement from any driver, an exception stack) grows without bound:
|
|
22
|
+
* each attribute value at most 4 KiB, 64 attributes, 8 events of 8
|
|
23
|
+
* attributes. The largest possible span then encodes to about half a MiB.
|
|
24
|
+
*/
|
|
25
|
+
export declare const spanLimits: {
|
|
26
|
+
attributeValueLengthLimit: number;
|
|
27
|
+
attributeCountLimit: number;
|
|
28
|
+
eventCountLimit: number;
|
|
29
|
+
attributePerEventCountLimit: number;
|
|
30
|
+
linkCountLimit: number;
|
|
31
|
+
attributePerLinkCountLimit: number;
|
|
32
|
+
};
|
|
33
|
+
/** signalFlushMillis bounds the flush attempted on SIGTERM and SIGINT. */
|
|
34
|
+
export declare const signalFlushMillis = 2000;
|
|
35
|
+
/** Started is a running SDK. */
|
|
36
|
+
export interface Started {
|
|
37
|
+
config: Config;
|
|
38
|
+
provider: NodeTracerProvider;
|
|
39
|
+
callSites: CallSiteProcessor;
|
|
40
|
+
/** esmHook says whether the module loader hook is registered. */
|
|
41
|
+
esmHook: ESMHook;
|
|
42
|
+
/** instrumentations are the ones registered (the benchmark disables and enables them). */
|
|
43
|
+
instrumentations: Instrumentation[];
|
|
44
|
+
/** shutdown flushes and stops; it resolves within the exporter timeout. */
|
|
45
|
+
shutdown(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
/** StartOptions override the environment (tests). */
|
|
48
|
+
export interface StartOptions {
|
|
49
|
+
env?: NodeJS.ProcessEnv;
|
|
50
|
+
cwd?: string;
|
|
51
|
+
/** spanProcessors replace the exporting processor (tests pass an in-memory one). */
|
|
52
|
+
spanProcessors?: SpanProcessor[];
|
|
53
|
+
/** exporter replaces the OTLP exporter behind the batching processor. */
|
|
54
|
+
exporter?: SpanExporter;
|
|
55
|
+
/** sampler replaces the default sampler. */
|
|
56
|
+
sampler?: Sampler;
|
|
57
|
+
/** esmHook false skips the module loader hook (the benchmark measures its cost). */
|
|
58
|
+
esmHook?: boolean;
|
|
59
|
+
/** instrumentations replace the curated set (tests). */
|
|
60
|
+
instrumentations?: Instrumentation[];
|
|
61
|
+
/** hooks installs the exit and signal handlers; default true. */
|
|
62
|
+
hooks?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** instrumentationNames are the names ROOTCAT_DISABLE accepts. */
|
|
65
|
+
export declare const instrumentationNames: readonly ["http", "undici", "pg", "postgres", "drizzle", "mysql2", "mongodb", "ioredis", "redis", "prisma"];
|
|
66
|
+
/** redisStatement records the command name and the argument count only. */
|
|
67
|
+
export declare function redisStatement(command: string, args: unknown[]): string;
|
|
68
|
+
/**
|
|
69
|
+
* curatedInstrumentations builds the instrumentation set the config
|
|
70
|
+
* allows; sampling is the call-site gate they share with the processor.
|
|
71
|
+
*/
|
|
72
|
+
export declare function curatedInstrumentations(config: Config, sampling?: CallSiteSampling): Instrumentation[];
|
|
73
|
+
/**
|
|
74
|
+
* prismaInstrumentation loads @prisma/instrumentation from the application
|
|
75
|
+
* when the application has it (Prisma ships it beside its client, and its
|
|
76
|
+
* version must match the client's), and nothing otherwise.
|
|
77
|
+
*/
|
|
78
|
+
export declare function prismaInstrumentation(cwd: string): Instrumentation | undefined;
|
|
79
|
+
/** current returns the running SDK, if any. */
|
|
80
|
+
export declare function current(): Started | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* start reads the configuration and starts the SDK once per process. A
|
|
83
|
+
* later call (the import line and NODE_OPTIONS both, or a second copy of
|
|
84
|
+
* the package) returns the first result. It never throws.
|
|
85
|
+
*/
|
|
86
|
+
export declare function start(options?: StartOptions): Started | undefined;
|
|
87
|
+
/** otlpExporter builds the package's OTLP/HTTP protobuf exporter (see otlp.ts). */
|
|
88
|
+
export declare function otlpExporter(url: string): SpanExporter;
|