@pingops/otel 0.1.0 → 0.1.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/config-store.d.ts +26 -0
- package/dist/config-store.d.ts.map +1 -0
- package/dist/config-store.js +26 -0
- package/dist/config-store.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/instrumentations/http/http.d.ts +13 -0
- package/dist/instrumentations/http/http.d.ts.map +1 -0
- package/dist/instrumentations/{http.js → http/http.js} +6 -16
- package/dist/instrumentations/http/http.js.map +1 -0
- package/dist/instrumentations/http/pingops-http.d.ts +52 -0
- package/dist/instrumentations/http/pingops-http.d.ts.map +1 -0
- package/dist/instrumentations/http/pingops-http.js +381 -0
- package/dist/instrumentations/http/pingops-http.js.map +1 -0
- package/dist/instrumentations/index.d.ts.map +1 -1
- package/dist/instrumentations/index.js +6 -10
- package/dist/instrumentations/index.js.map +1 -1
- package/dist/instrumentations/undici/pingops-undici.d.ts +25 -0
- package/dist/instrumentations/undici/pingops-undici.d.ts.map +1 -0
- package/dist/instrumentations/undici/pingops-undici.js +568 -0
- package/dist/instrumentations/undici/pingops-undici.js.map +1 -0
- package/dist/instrumentations/undici/types.d.ts +106 -0
- package/dist/instrumentations/undici/types.d.ts.map +1 -0
- package/dist/instrumentations/undici/types.js +2 -0
- package/dist/instrumentations/undici/types.js.map +1 -0
- package/dist/instrumentations/{undici.d.ts → undici/undici.d.ts} +1 -1
- package/dist/instrumentations/undici/undici.d.ts.map +1 -0
- package/dist/instrumentations/{undici.js → undici/undici.js} +1 -13
- package/dist/instrumentations/undici/undici.js.map +1 -0
- package/dist/span-processor.d.ts.map +1 -1
- package/dist/span-processor.js +31 -21
- package/dist/span-processor.js.map +1 -1
- package/dist/tracer-provider.d.ts.map +1 -1
- package/dist/tracer-provider.js +22 -20
- package/dist/tracer-provider.js.map +1 -1
- package/package.json +7 -7
- package/dist/instrumentations/body-extractor.d.ts +0 -48
- package/dist/instrumentations/body-extractor.d.ts.map +0 -1
- package/dist/instrumentations/body-extractor.js +0 -361
- package/dist/instrumentations/body-extractor.js.map +0 -1
- package/dist/instrumentations/http.d.ts +0 -12
- package/dist/instrumentations/http.d.ts.map +0 -1
- package/dist/instrumentations/http.js.map +0 -1
- package/dist/instrumentations/undici.d.ts.map +0 -1
- package/dist/instrumentations/undici.js.map +0 -1
- package/dist/processor.d.ts +0 -82
- package/dist/processor.d.ts.map +0 -1
- package/dist/processor.js +0 -264
- package/dist/processor.js.map +0 -1
- package/dist/span-wrapper.d.ts +0 -60
- package/dist/span-wrapper.d.ts.map +0 -1
- package/dist/span-wrapper.js +0 -118
- package/dist/span-wrapper.js.map +0 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { InstrumentationConfig } from "@opentelemetry/instrumentation";
|
|
2
|
+
import type { Attributes, Span } from "@opentelemetry/api";
|
|
3
|
+
export interface UndiciRequest {
|
|
4
|
+
origin: string;
|
|
5
|
+
method: string;
|
|
6
|
+
path: string;
|
|
7
|
+
/**
|
|
8
|
+
* Serialized string of headers in the form `name: value\r\n` for v5
|
|
9
|
+
* Array of strings `[key1, value1, key2, value2]`, where values are
|
|
10
|
+
* `string | string[]` for v6
|
|
11
|
+
*/
|
|
12
|
+
headers: string | (string | string[])[];
|
|
13
|
+
/**
|
|
14
|
+
* Helper method to add headers (from v6)
|
|
15
|
+
*/
|
|
16
|
+
addHeader: (name: string, value: string) => void;
|
|
17
|
+
throwOnError: boolean;
|
|
18
|
+
completed: boolean;
|
|
19
|
+
aborted: boolean;
|
|
20
|
+
idempotent: boolean;
|
|
21
|
+
contentLength: number | null;
|
|
22
|
+
contentType: string | null;
|
|
23
|
+
body: any;
|
|
24
|
+
}
|
|
25
|
+
export interface UndiciResponse {
|
|
26
|
+
headers: Buffer[];
|
|
27
|
+
statusCode: number;
|
|
28
|
+
statusText: string;
|
|
29
|
+
}
|
|
30
|
+
export interface IgnoreRequestFunction<T = UndiciRequest> {
|
|
31
|
+
(request: T): boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface RequestHookFunction<T = UndiciRequest> {
|
|
34
|
+
(span: Span, request: T): void;
|
|
35
|
+
}
|
|
36
|
+
export interface ResponseHookFunction<RequestType = UndiciRequest, ResponseType = UndiciResponse> {
|
|
37
|
+
(span: Span, info: {
|
|
38
|
+
request: RequestType;
|
|
39
|
+
response: ResponseType;
|
|
40
|
+
}): void;
|
|
41
|
+
}
|
|
42
|
+
export interface StartSpanHookFunction<T = UndiciRequest> {
|
|
43
|
+
(request: T): Attributes;
|
|
44
|
+
}
|
|
45
|
+
export interface UndiciInstrumentationConfig<RequestType = UndiciRequest, ResponseType = UndiciResponse> extends InstrumentationConfig {
|
|
46
|
+
/** Not trace all outgoing requests that matched with custom function */
|
|
47
|
+
ignoreRequestHook?: IgnoreRequestFunction<RequestType>;
|
|
48
|
+
/** Function for adding custom attributes before request is handled */
|
|
49
|
+
requestHook?: RequestHookFunction<RequestType>;
|
|
50
|
+
/** Function called once response headers have been received */
|
|
51
|
+
responseHook?: ResponseHookFunction<RequestType, ResponseType>;
|
|
52
|
+
/** Function for adding custom attributes before a span is started */
|
|
53
|
+
startSpanHook?: StartSpanHookFunction<RequestType>;
|
|
54
|
+
/** Require parent to create span for outgoing requests */
|
|
55
|
+
requireParentforSpans?: boolean;
|
|
56
|
+
/** Map the following HTTP headers to span attributes. */
|
|
57
|
+
headersToSpanAttributes?: {
|
|
58
|
+
requestHeaders?: string[];
|
|
59
|
+
responseHeaders?: string[];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Maximum size of request body to capture in bytes
|
|
63
|
+
* @defaultValue 4096 (4 KB)
|
|
64
|
+
*/
|
|
65
|
+
maxRequestBodySize?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Maximum size of response body to capture in bytes
|
|
68
|
+
* @defaultValue 4096 (4 KB)
|
|
69
|
+
*/
|
|
70
|
+
maxResponseBodySize?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface ListenerRecord {
|
|
73
|
+
name: string;
|
|
74
|
+
unsubscribe: () => void;
|
|
75
|
+
}
|
|
76
|
+
export interface RequestMessage {
|
|
77
|
+
request: UndiciRequest;
|
|
78
|
+
}
|
|
79
|
+
export interface RequestHeadersMessage {
|
|
80
|
+
request: UndiciRequest;
|
|
81
|
+
socket: any;
|
|
82
|
+
}
|
|
83
|
+
export interface ResponseHeadersMessage {
|
|
84
|
+
request: UndiciRequest;
|
|
85
|
+
response: UndiciResponse;
|
|
86
|
+
}
|
|
87
|
+
export interface RequestTrailersMessage {
|
|
88
|
+
request: UndiciRequest;
|
|
89
|
+
response: UndiciResponse;
|
|
90
|
+
}
|
|
91
|
+
export interface RequestErrorMessage {
|
|
92
|
+
request: UndiciRequest;
|
|
93
|
+
error: Error;
|
|
94
|
+
}
|
|
95
|
+
export interface RequestBodyChunkSentMessage {
|
|
96
|
+
request: UndiciRequest;
|
|
97
|
+
chunk: Buffer;
|
|
98
|
+
}
|
|
99
|
+
export interface RequestBodySentMessage {
|
|
100
|
+
request: UndiciRequest;
|
|
101
|
+
}
|
|
102
|
+
export interface RequestBodyChunkReceivedMessage {
|
|
103
|
+
request: UndiciRequest;
|
|
104
|
+
chunk: Buffer;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/undici/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IACxC;;OAEG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,aAAa;IACtD,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,aAAa;IACpD,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB,CACnC,WAAW,GAAG,aAAa,EAC3B,YAAY,GAAG,cAAc;IAE7B,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,YAAY,CAAA;KAAE,GAAG,IAAI,CAAC;CAC5E;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,aAAa;IACtD,CAAC,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC;CAC1B;AAID,MAAM,WAAW,2BAA2B,CAC1C,WAAW,GAAG,aAAa,EAC3B,YAAY,GAAG,cAAc,CAC7B,SAAQ,qBAAqB;IAC7B,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;IACvD,sEAAsE;IACtE,WAAW,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,YAAY,CAAC,EAAE,oBAAoB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC/D,qEAAqE;IACrE,aAAa,CAAC,EAAE,qBAAqB,CAAC,WAAW,CAAC,CAAC;IACnD,0DAA0D;IAC1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,yDAAyD;IACzD,uBAAuB,CAAC,EAAE;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B,CAAC;IACF;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,aAAa,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/instrumentations/undici/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undici.d.ts","sourceRoot":"","sources":["../../../src/instrumentations/undici/undici.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAIzD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,8BAA8B,EAAE,MAAM,OAAO,GAC5C,qBAAqB,CAYvB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Undici instrumentation for OpenTelemetry
|
|
3
3
|
*/
|
|
4
|
-
import { UndiciInstrumentation } from "
|
|
4
|
+
import { UndiciInstrumentation } from "./pingops-undici";
|
|
5
5
|
import { context } from "@opentelemetry/api";
|
|
6
6
|
import { PINGOPS_HTTP_ENABLED } from "@pingops/core";
|
|
7
7
|
/**
|
|
@@ -21,18 +21,6 @@ export function createUndiciInstrumentation(isGlobalInstrumentationEnabled) {
|
|
|
21
21
|
// If global instrumentation is NOT enabled, only instrument when PINGOPS_HTTP_ENABLED is true
|
|
22
22
|
return context.active().getValue(PINGOPS_HTTP_ENABLED) !== true;
|
|
23
23
|
},
|
|
24
|
-
requestHook: (span, request) => {
|
|
25
|
-
const headers = request.headers;
|
|
26
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
27
|
-
span.setAttribute(`http.request.header.${key.toLowerCase()}`, Array.isArray(value) ? value.join(",") : String(value));
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
responseHook: (span, { response }) => {
|
|
31
|
-
const headers = response.headers;
|
|
32
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
33
|
-
span.setAttribute(`http.response.header.${key.toLowerCase()}`, Array.isArray(value) ? value.join(",") : String(value));
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
24
|
});
|
|
37
25
|
}
|
|
38
26
|
//# sourceMappingURL=undici.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undici.js","sourceRoot":"","sources":["../../../src/instrumentations/undici/undici.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,8BAA6C;IAE7C,OAAO,IAAI,qBAAqB,CAAC;QAC/B,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,GAAG,EAAE;YACtB,gEAAgE;YAChE,IAAI,8BAA8B,EAAE,EAAE,CAAC;gBACrC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,8FAA8F;YAC9F,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,KAAK,IAAI,CAAC;QAClE,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"span-processor.d.ts","sourceRoot":"","sources":["../src/span-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,IAAI,EACL,MAAM,+BAA+B,CAAC;AAMvC,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,oBAAoB,CAAC;AAS9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"span-processor.d.ts","sourceRoot":"","sources":["../src/span-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,IAAI,EACL,MAAM,+BAA+B,CAAC;AAMvC,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,oBAAoB,CAAC;AAS9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AA8DvD;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,aAAa;IACxD,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,MAAM,CAQZ;IAEF;;;;OAIG;gBACS,MAAM,EAAE,sBAAsB;IA2D1C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IA0BjD;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IA2F/B;;;;OAIG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAaxC;;;;OAIG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAYvC"}
|
package/dist/span-processor.js
CHANGED
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
import { BatchSpanProcessor, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base";
|
|
34
34
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
35
35
|
import { isSpanEligible, shouldCaptureSpan, createLogger, getPropagatedAttributesFromContext, extractSpanPayload, } from "@pingops/core";
|
|
36
|
-
|
|
36
|
+
import { setGlobalConfig } from "./config-store";
|
|
37
|
+
const logger = createLogger("[PingOps Processor]");
|
|
37
38
|
/**
|
|
38
39
|
* Creates a filtered span wrapper that applies header filtering to attributes
|
|
39
40
|
*
|
|
@@ -48,13 +49,14 @@ const log = createLogger("[PingOps Processor]");
|
|
|
48
49
|
*
|
|
49
50
|
* This allows us to filter headers before the span is serialized by OTLP exporter
|
|
50
51
|
*/
|
|
51
|
-
function createFilteredSpan(span, domainAllowList, globalHeadersAllowList, globalHeadersDenyList) {
|
|
52
|
+
function createFilteredSpan(span, domainAllowList, globalHeadersAllowList, globalHeadersDenyList, globalCaptureRequestBody, globalCaptureResponseBody) {
|
|
52
53
|
// Use extractSpanPayload to get filtered attributes
|
|
53
54
|
// This handles both domain-specific header rules and global header filtering
|
|
54
|
-
|
|
55
|
+
// as well as body capture filtering
|
|
56
|
+
const payload = extractSpanPayload(span, domainAllowList, globalHeadersAllowList, globalHeadersDenyList, globalCaptureRequestBody, globalCaptureResponseBody);
|
|
55
57
|
const filteredAttributes = (payload?.attributes ??
|
|
56
58
|
span.attributes);
|
|
57
|
-
|
|
59
|
+
logger.debug("Payload", { payload });
|
|
58
60
|
// Create a Proxy that intercepts 'attributes' access and forwards everything else
|
|
59
61
|
return new Proxy(span, {
|
|
60
62
|
get(target, prop) {
|
|
@@ -115,8 +117,16 @@ export class PingopsSpanProcessor {
|
|
|
115
117
|
headersDenyList: config.headersDenyList,
|
|
116
118
|
domainAllowList: config.domainAllowList,
|
|
117
119
|
domainDenyList: config.domainDenyList,
|
|
120
|
+
captureRequestBody: config.captureRequestBody,
|
|
121
|
+
captureResponseBody: config.captureResponseBody,
|
|
118
122
|
};
|
|
119
|
-
|
|
123
|
+
// Register global config for instrumentations to access
|
|
124
|
+
setGlobalConfig({
|
|
125
|
+
captureRequestBody: config.captureRequestBody,
|
|
126
|
+
captureResponseBody: config.captureResponseBody,
|
|
127
|
+
domainAllowList: config.domainAllowList,
|
|
128
|
+
});
|
|
129
|
+
logger.info("Initialized PingopsSpanProcessor", {
|
|
120
130
|
baseUrl: config.baseUrl,
|
|
121
131
|
exportMode,
|
|
122
132
|
batchSize: config.batchSize,
|
|
@@ -132,7 +142,7 @@ export class PingopsSpanProcessor {
|
|
|
132
142
|
*/
|
|
133
143
|
onStart(span, parentContext) {
|
|
134
144
|
const spanContext = span.spanContext();
|
|
135
|
-
|
|
145
|
+
logger.debug("Span started", {
|
|
136
146
|
spanName: span.name,
|
|
137
147
|
spanId: spanContext.spanId,
|
|
138
148
|
traceId: spanContext.traceId,
|
|
@@ -146,7 +156,7 @@ export class PingopsSpanProcessor {
|
|
|
146
156
|
span.setAttribute(key, value);
|
|
147
157
|
}
|
|
148
158
|
}
|
|
149
|
-
|
|
159
|
+
logger.debug("Set propagated attributes on span", {
|
|
150
160
|
spanName: span.name,
|
|
151
161
|
attributeKeys: Object.keys(propagatedAttributes),
|
|
152
162
|
});
|
|
@@ -164,7 +174,7 @@ export class PingopsSpanProcessor {
|
|
|
164
174
|
*/
|
|
165
175
|
onEnd(span) {
|
|
166
176
|
const spanContext = span.spanContext();
|
|
167
|
-
|
|
177
|
+
logger.debug("Span ended, processing", {
|
|
168
178
|
spanName: span.name,
|
|
169
179
|
spanId: spanContext.spanId,
|
|
170
180
|
traceId: spanContext.traceId,
|
|
@@ -173,7 +183,7 @@ export class PingopsSpanProcessor {
|
|
|
173
183
|
try {
|
|
174
184
|
// Step 1: Check if span is eligible (CLIENT + HTTP/GenAI attributes)
|
|
175
185
|
if (!isSpanEligible(span)) {
|
|
176
|
-
|
|
186
|
+
logger.debug("Span not eligible, skipping", {
|
|
177
187
|
spanName: span.name,
|
|
178
188
|
spanId: spanContext.spanId,
|
|
179
189
|
reason: "not CLIENT or missing HTTP/GenAI attributes",
|
|
@@ -187,7 +197,7 @@ export class PingopsSpanProcessor {
|
|
|
187
197
|
(attributes["server.address"]
|
|
188
198
|
? `https://${String(attributes["server.address"])}`
|
|
189
199
|
: "");
|
|
190
|
-
|
|
200
|
+
logger.debug("Extracted URL for domain filtering", {
|
|
191
201
|
spanName: span.name,
|
|
192
202
|
url,
|
|
193
203
|
hasHttpUrl: !!attributes["http.url"],
|
|
@@ -198,7 +208,7 @@ export class PingopsSpanProcessor {
|
|
|
198
208
|
if (url) {
|
|
199
209
|
const shouldCapture = shouldCaptureSpan(url, this.config.domainAllowList, this.config.domainDenyList);
|
|
200
210
|
if (!shouldCapture) {
|
|
201
|
-
|
|
211
|
+
logger.info("Span filtered out by domain rules", {
|
|
202
212
|
spanName: span.name,
|
|
203
213
|
spanId: spanContext.spanId,
|
|
204
214
|
url,
|
|
@@ -207,15 +217,15 @@ export class PingopsSpanProcessor {
|
|
|
207
217
|
}
|
|
208
218
|
}
|
|
209
219
|
else {
|
|
210
|
-
|
|
220
|
+
logger.debug("No URL found for domain filtering, proceeding", {
|
|
211
221
|
spanName: span.name,
|
|
212
222
|
});
|
|
213
223
|
}
|
|
214
224
|
// Step 4: Apply filtering (header filtering with domain-specific rules) by wrapping the span
|
|
215
|
-
const filteredSpan = createFilteredSpan(span, this.config.domainAllowList, this.config.headersAllowList, this.config.headersDenyList);
|
|
225
|
+
const filteredSpan = createFilteredSpan(span, this.config.domainAllowList, this.config.headersAllowList, this.config.headersDenyList, this.config.captureRequestBody, this.config.captureResponseBody);
|
|
216
226
|
// Step 5: Span passed all filters, pass filtered span to underlying processor for export
|
|
217
227
|
this.processor.onEnd(filteredSpan);
|
|
218
|
-
|
|
228
|
+
logger.info("Span passed all filters and queued for export", {
|
|
219
229
|
spanName: span.name,
|
|
220
230
|
spanId: spanContext.spanId,
|
|
221
231
|
traceId: spanContext.traceId,
|
|
@@ -225,7 +235,7 @@ export class PingopsSpanProcessor {
|
|
|
225
235
|
}
|
|
226
236
|
catch (error) {
|
|
227
237
|
// Defensive error handling - never crash the app
|
|
228
|
-
|
|
238
|
+
logger.error("Error processing span", {
|
|
229
239
|
spanName: span.name,
|
|
230
240
|
spanId: spanContext.spanId,
|
|
231
241
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -238,13 +248,13 @@ export class PingopsSpanProcessor {
|
|
|
238
248
|
* @returns Promise that resolves when all pending operations are complete
|
|
239
249
|
*/
|
|
240
250
|
async forceFlush() {
|
|
241
|
-
|
|
251
|
+
logger.info("Force flushing spans");
|
|
242
252
|
try {
|
|
243
253
|
await this.processor.forceFlush();
|
|
244
|
-
|
|
254
|
+
logger.info("Force flush complete");
|
|
245
255
|
}
|
|
246
256
|
catch (error) {
|
|
247
|
-
|
|
257
|
+
logger.error("Error during force flush", {
|
|
248
258
|
error: error instanceof Error ? error.message : String(error),
|
|
249
259
|
});
|
|
250
260
|
throw error;
|
|
@@ -256,13 +266,13 @@ export class PingopsSpanProcessor {
|
|
|
256
266
|
* @returns Promise that resolves when shutdown is complete
|
|
257
267
|
*/
|
|
258
268
|
async shutdown() {
|
|
259
|
-
|
|
269
|
+
logger.info("Shutting down processor");
|
|
260
270
|
try {
|
|
261
271
|
await this.processor.shutdown();
|
|
262
|
-
|
|
272
|
+
logger.info("Processor shutdown complete");
|
|
263
273
|
}
|
|
264
274
|
catch (error) {
|
|
265
|
-
|
|
275
|
+
logger.error("Error during processor shutdown", {
|
|
266
276
|
error: error instanceof Error ? error.message : String(error),
|
|
267
277
|
});
|
|
268
278
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"span-processor.js","sourceRoot":"","sources":["../src/span-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,OAAO,EACL,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACZ,kCAAkC,EAClC,kBAAkB,GACnB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"span-processor.js","sourceRoot":"","sources":["../src/span-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE5E,OAAO,EACL,cAAc,EACd,iBAAiB,EAEjB,YAAY,EACZ,kCAAkC,EAClC,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAEnD;;;;;;;;;;;;;GAaG;AACH,SAAS,kBAAkB,CACzB,IAAkB,EAClB,eAA8B,EAC9B,sBAAiC,EACjC,qBAAgC,EAChC,wBAAkC,EAClC,yBAAmC;IAEnC,oDAAoD;IACpD,6EAA6E;IAC7E,oCAAoC;IACpC,MAAM,OAAO,GAAG,kBAAkB,CAChC,IAAI,EACJ,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,CAC1B,CAAC;IACF,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,UAAU;QAC7C,IAAI,CAAC,UAAU,CAAe,CAAC;IACjC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAErC,kFAAkF;IAClF,OAAO,IAAI,KAAK,CAAC,IAAI,EAAE;QACrB,GAAG,CAAC,MAAM,EAAE,IAAI;YACd,oDAAoD;YACpD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1B,OAAO,kBAAkB,CAAC;YAC5B,CAAC;YACD,gEAAgE;YAChE,MAAM,KAAK,GAAI,MAAiD,CAC9D,IAAc,CACf,CAAC;YACF,gFAAgF;YAChF,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;gBAChC,OAAQ,KAAyC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,oBAAoB;IACvB,SAAS,CAAgB;IACzB,MAAM,CAQZ;IAEF;;;;OAIG;IACH,YAAY,MAA8B;QACxC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,SAAS,CAAC;QAElD,yCAAyC;QACzC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;QAElE,mDAAmD;QACnD,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;YACrC,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,YAAY;YAClC,OAAO,EAAE;gBACP,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;gBAC/C,cAAc,EAAE,kBAAkB;aACnC;YACD,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,mDAAmD;QACnD,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;YAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,GAAG,IAAI,kBAAkB,CAAC,QAAQ,EAAE;gBAChD,kBAAkB,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;gBAC1C,oBAAoB,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI;aAClD,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,MAAM,GAAG;YACZ,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK;YAC5B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;SAChD,CAAC;QAEF,wDAAwD;QACxD,eAAe,CAAC;YACd,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;YAC/C,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE;YAC9C,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU;YACV,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,kBAAkB,EAChB,CAAC,CAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;YAC/D,iBAAiB,EACf,CAAC,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;YAC7D,mBAAmB,EACjB,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC;YACjE,kBAAkB,EAChB,CAAC,CAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;SAChE,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAU,EAAE,aAAsB;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE;YAC3B,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;SAC7B,CAAC,CAAC;QAEH,sEAAsE;QACtE,MAAM,oBAAoB,GACxB,kCAAkC,CAAC,aAAa,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBAChE,4EAA4E;gBAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtD,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE;gBAChD,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;aACjD,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC9C,CAAC;IACD;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAkB;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE;YACrC,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,QAAQ,EAAE,IAAI,CAAC,IAAI;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,qEAAqE;YACrE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE;oBAC1C,QAAQ,EAAE,IAAI,CAAC,IAAI;oBACnB,MAAM,EAAE,WAAW,CAAC,MAAM;oBAC1B,MAAM,EAAE,6CAA6C;iBACtD,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,2CAA2C;YAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;YACnC,MAAM,GAAG,GACN,UAAU,CAAC,UAAU,CAAY;gBACjC,UAAU,CAAC,UAAU,CAAY;gBAClC,CAAC,UAAU,CAAC,gBAAgB,CAAC;oBAC3B,CAAC,CAAC,WAAW,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,EAAE;oBACnD,CAAC,CAAC,EAAE,CAAC,CAAC;YAEV,MAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE;gBACjD,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,GAAG;gBACH,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;gBACpC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;gBACpC,gBAAgB,EAAE,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC;aACjD,CAAC,CAAC;YAEH,iCAAiC;YACjC,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,aAAa,GAAG,iBAAiB,CACrC,GAAG,EACH,IAAI,CAAC,MAAM,CAAC,eAAe,EAC3B,IAAI,CAAC,MAAM,CAAC,cAAc,CAC3B,CAAC;gBAEF,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,MAAM,CAAC,IAAI,CAAC,mCAAmC,EAAE;wBAC/C,QAAQ,EAAE,IAAI,CAAC,IAAI;wBACnB,MAAM,EAAE,WAAW,CAAC,MAAM;wBAC1B,GAAG;qBACJ,CAAC,CAAC;oBACH,OAAO;gBACT,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,+CAA+C,EAAE;oBAC5D,QAAQ,EAAE,IAAI,CAAC,IAAI;iBACpB,CAAC,CAAC;YACL,CAAC;YAED,6FAA6F;YAC7F,MAAM,YAAY,GAAG,kBAAkB,CACrC,IAAI,EACJ,IAAI,CAAC,MAAM,CAAC,eAAe,EAC3B,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAC5B,IAAI,CAAC,MAAM,CAAC,eAAe,EAC3B,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAC9B,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAChC,CAAC;YAEF,yFAAyF;YACzF,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAEnC,MAAM,CAAC,IAAI,CAAC,+CAA+C,EAAE;gBAC3D,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;gBAC5B,GAAG;gBACH,kBAAkB,EAAE,CAAC,CAAC,CACpB,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAC5D;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,iDAAiD;YACjD,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE;gBACpC,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,MAAM,EAAE,WAAW,CAAC,MAAM;gBAC1B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,UAAU;QACrB,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE;gBACvC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,QAAQ;QACnB,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE;gBAC9C,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer-provider.d.ts","sourceRoot":"","sources":["../src/tracer-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA4EnE;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAC9B,IAAI,
|
|
1
|
+
{"version":3,"file":"tracer-provider.d.ts","sourceRoot":"","sources":["../src/tracer-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AA4EnE;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAC9B,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,CAezD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,cAAc,EAAE,aAAa,EAAE,EAC/B,WAAW,EAAE,MAAM,GAClB,IAAI,CA4BN;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,kBAAkB,GAAG,IAAI,CAG7D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6B5D"}
|
package/dist/tracer-provider.js
CHANGED
|
@@ -19,7 +19,7 @@ const PINGOPS_GLOBAL_SYMBOL = Symbol.for("pingops");
|
|
|
19
19
|
/**
|
|
20
20
|
* Logger instance for tracer provider
|
|
21
21
|
*/
|
|
22
|
-
const
|
|
22
|
+
const logger = createLogger("[PingOps TracerProvider]");
|
|
23
23
|
/**
|
|
24
24
|
* Creates initial global state
|
|
25
25
|
*/
|
|
@@ -37,11 +37,11 @@ function getGlobalState() {
|
|
|
37
37
|
const g = globalThis;
|
|
38
38
|
if (typeof g !== "object" || g === null) {
|
|
39
39
|
// Fallback if globalThis is not available
|
|
40
|
-
|
|
40
|
+
logger.warn("globalThis is not available, using fallback state");
|
|
41
41
|
return initialState;
|
|
42
42
|
}
|
|
43
43
|
if (!g[PINGOPS_GLOBAL_SYMBOL]) {
|
|
44
|
-
|
|
44
|
+
logger.debug("Creating new global state");
|
|
45
45
|
Object.defineProperty(g, PINGOPS_GLOBAL_SYMBOL, {
|
|
46
46
|
value: initialState,
|
|
47
47
|
writable: false, // lock the slot (not the contents)
|
|
@@ -50,12 +50,12 @@ function getGlobalState() {
|
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
|
-
|
|
53
|
+
logger.debug("Retrieved existing global state");
|
|
54
54
|
}
|
|
55
55
|
return g[PINGOPS_GLOBAL_SYMBOL];
|
|
56
56
|
}
|
|
57
57
|
catch (err) {
|
|
58
|
-
|
|
58
|
+
logger.error("Failed to access global state:", err instanceof Error ? err.message : String(err));
|
|
59
59
|
// Fallback on error
|
|
60
60
|
return initialState;
|
|
61
61
|
}
|
|
@@ -75,13 +75,15 @@ export function setPingopsTracerProvider(provider) {
|
|
|
75
75
|
const hadProvider = state.isolatedTracerProvider !== null;
|
|
76
76
|
state.isolatedTracerProvider = provider;
|
|
77
77
|
if (provider) {
|
|
78
|
-
|
|
78
|
+
logger.info("Set isolated TracerProvider", {
|
|
79
79
|
hadPrevious: hadProvider,
|
|
80
80
|
providerType: provider.constructor.name,
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
else {
|
|
84
|
-
|
|
84
|
+
logger.info("Cleared isolated TracerProvider", {
|
|
85
|
+
hadPrevious: hadProvider,
|
|
86
|
+
});
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
/**
|
|
@@ -96,13 +98,13 @@ export function setPingopsTracerProvider(provider) {
|
|
|
96
98
|
export function getPingopsTracerProvider() {
|
|
97
99
|
const { isolatedTracerProvider } = getGlobalState();
|
|
98
100
|
if (isolatedTracerProvider) {
|
|
99
|
-
|
|
101
|
+
logger.debug("Using isolated TracerProvider", {
|
|
100
102
|
providerType: isolatedTracerProvider.constructor.name,
|
|
101
103
|
});
|
|
102
104
|
return isolatedTracerProvider;
|
|
103
105
|
}
|
|
104
106
|
const globalProvider = trace.getTracerProvider();
|
|
105
|
-
|
|
107
|
+
logger.debug("Using global TracerProvider", {
|
|
106
108
|
providerType: globalProvider.constructor.name,
|
|
107
109
|
});
|
|
108
110
|
return globalProvider;
|
|
@@ -119,7 +121,7 @@ export function getPingopsTracerProvider() {
|
|
|
119
121
|
* @deprecated Use setPingopsTracerProvider instead
|
|
120
122
|
*/
|
|
121
123
|
export function initializeTracerProvider(spanProcessors, serviceName) {
|
|
122
|
-
|
|
124
|
+
logger.info("Initializing TracerProvider", {
|
|
123
125
|
serviceName,
|
|
124
126
|
spanProcessorCount: spanProcessors.length,
|
|
125
127
|
});
|
|
@@ -127,21 +129,21 @@ export function initializeTracerProvider(spanProcessors, serviceName) {
|
|
|
127
129
|
const resource = resourceFromAttributes({
|
|
128
130
|
[ATTR_SERVICE_NAME]: serviceName,
|
|
129
131
|
});
|
|
130
|
-
|
|
132
|
+
logger.debug("Created resource", { serviceName });
|
|
131
133
|
// In version 2.2.0, span processors are passed in the constructor
|
|
132
134
|
const tracerProvider = new NodeTracerProvider({
|
|
133
135
|
resource,
|
|
134
136
|
spanProcessors,
|
|
135
137
|
});
|
|
136
|
-
|
|
138
|
+
logger.debug("Created NodeTracerProvider", {
|
|
137
139
|
spanProcessorCount: spanProcessors.length,
|
|
138
140
|
});
|
|
139
141
|
// Register the provider globally
|
|
140
142
|
tracerProvider.register();
|
|
141
|
-
|
|
143
|
+
logger.info("Registered TracerProvider globally");
|
|
142
144
|
// Set it in global state
|
|
143
145
|
setPingopsTracerProvider(tracerProvider);
|
|
144
|
-
|
|
146
|
+
logger.info("TracerProvider initialization complete");
|
|
145
147
|
}
|
|
146
148
|
/**
|
|
147
149
|
* Gets the isolated TracerProvider instance
|
|
@@ -157,26 +159,26 @@ export function getTracerProvider() {
|
|
|
157
159
|
* Shuts down the TracerProvider and flushes remaining spans
|
|
158
160
|
*/
|
|
159
161
|
export async function shutdownTracerProvider() {
|
|
160
|
-
|
|
162
|
+
logger.info("Shutting down TracerProvider");
|
|
161
163
|
const provider = getPingopsTracerProvider();
|
|
162
164
|
// Check if provider has shutdown method (NodeTracerProvider and compatible providers)
|
|
163
165
|
const providerWithShutdown = provider;
|
|
164
166
|
if (providerWithShutdown &&
|
|
165
167
|
typeof providerWithShutdown.shutdown === "function") {
|
|
166
|
-
|
|
168
|
+
logger.debug("Calling provider.shutdown()");
|
|
167
169
|
try {
|
|
168
170
|
await providerWithShutdown.shutdown();
|
|
169
|
-
|
|
171
|
+
logger.info("TracerProvider shutdown complete");
|
|
170
172
|
}
|
|
171
173
|
catch (error) {
|
|
172
|
-
|
|
174
|
+
logger.error("Error during TracerProvider shutdown:", error instanceof Error ? error.message : String(error));
|
|
173
175
|
throw error;
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
178
|
else {
|
|
177
|
-
|
|
179
|
+
logger.warn("TracerProvider does not have shutdown method, skipping");
|
|
178
180
|
}
|
|
179
181
|
setPingopsTracerProvider(null);
|
|
180
|
-
|
|
182
|
+
logger.info("TracerProvider shutdown finished");
|
|
181
183
|
}
|
|
182
184
|
//# sourceMappingURL=tracer-provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer-provider.js","sourceRoot":"","sources":["../src/tracer-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,MAAM,qBAAqB,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAEpD;;GAEG;AACH,MAAM,
|
|
1
|
+
{"version":3,"file":"tracer-provider.js","sourceRoot":"","sources":["../src/tracer-provider.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pingops/otel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "OpenTelemetry SpanProcessor for PingOps",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@opentelemetry/api": "^1.9.0",
|
|
24
|
-
"@opentelemetry/
|
|
25
|
-
"@opentelemetry/sdk-trace-node": "^2.2.0",
|
|
26
|
-
"@opentelemetry/resources": "^2.2.0",
|
|
27
|
-
"@opentelemetry/semantic-conventions": "^1.38.0",
|
|
24
|
+
"@opentelemetry/core": "^2.2.0",
|
|
28
25
|
"@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
|
|
29
26
|
"@opentelemetry/instrumentation": "^0.208.0",
|
|
30
27
|
"@opentelemetry/instrumentation-http": "^0.208.0",
|
|
31
|
-
"@opentelemetry/
|
|
32
|
-
"@
|
|
28
|
+
"@opentelemetry/resources": "^2.2.0",
|
|
29
|
+
"@opentelemetry/sdk-trace-base": "^2.2.0",
|
|
30
|
+
"@opentelemetry/sdk-trace-node": "^2.2.0",
|
|
31
|
+
"@opentelemetry/semantic-conventions": "^1.38.0",
|
|
32
|
+
"@pingops/core": "0.1.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^20.11.0",
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilities for extracting HTTP request and response bodies
|
|
3
|
-
*
|
|
4
|
-
* Handles streaming bodies by buffering data from streams
|
|
5
|
-
*/
|
|
6
|
-
import type { IncomingMessage, ClientRequest } from 'http';
|
|
7
|
-
import type { Span } from '@opentelemetry/api';
|
|
8
|
-
/**
|
|
9
|
-
* Captures HTTP request body using event handlers
|
|
10
|
-
*
|
|
11
|
-
* Uses a PassThrough stream to capture data via events, while still needing to
|
|
12
|
-
* intercept write()/end() to feed data into the stream
|
|
13
|
-
*/
|
|
14
|
-
export declare function captureHttpRequestBody(span: Span, request: ClientRequest): void;
|
|
15
|
-
/**
|
|
16
|
-
* Extracts request body from HTTP ClientRequest (legacy function, kept for compatibility)
|
|
17
|
-
*/
|
|
18
|
-
export declare function extractHttpRequestBody(_request: ClientRequest | IncomingMessage): string | null;
|
|
19
|
-
/**
|
|
20
|
-
* Captures HTTP response body by listening to stream events
|
|
21
|
-
*/
|
|
22
|
-
export declare function captureHttpResponseBody(span: Span, response: IncomingMessage): void;
|
|
23
|
-
/**
|
|
24
|
-
* Extracts response body from HTTP IncomingMessage (legacy function, kept for compatibility)
|
|
25
|
-
*/
|
|
26
|
-
export declare function extractHttpResponseBody(_response: IncomingMessage): string | null;
|
|
27
|
-
/**
|
|
28
|
-
* Extracts request body from Undici request
|
|
29
|
-
*/
|
|
30
|
-
export declare function extractUndiciRequestBody(request: {
|
|
31
|
-
body?: unknown;
|
|
32
|
-
contentType?: string | null;
|
|
33
|
-
}): string | null;
|
|
34
|
-
/**
|
|
35
|
-
* Captures Undici response body by reading from the body stream
|
|
36
|
-
*/
|
|
37
|
-
export declare function captureUndiciResponseBody(span: Span, response: {
|
|
38
|
-
body?: any;
|
|
39
|
-
headers?: Buffer[] | Record<string, string | string[]>;
|
|
40
|
-
}): void;
|
|
41
|
-
/**
|
|
42
|
-
* Extracts response body from Undici response (legacy function, kept for compatibility)
|
|
43
|
-
*/
|
|
44
|
-
export declare function extractUndiciResponseBody(response: {
|
|
45
|
-
body?: unknown;
|
|
46
|
-
headers?: Buffer[] | Record<string, string | string[]>;
|
|
47
|
-
}): string | null;
|
|
48
|
-
//# sourceMappingURL=body-extractor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"body-extractor.d.ts","sourceRoot":"","sources":["../../src/instrumentations/body-extractor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAiF/C;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,aAAa,GACrB,IAAI,CAwEN;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,aAAa,GAAG,eAAe,GACxC,MAAM,GAAG,IAAI,CAGf;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,eAAe,GACxB,IAAI,CAiDN;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,eAAe,GACzB,MAAM,GAAG,IAAI,CAGf;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACvD,MAAM,GAAG,IAAI,CASf;AAgCD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE;IAAE,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,GAC/E,IAAI,CAiGN;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,GACnF,MAAM,GAAG,IAAI,CAUf"}
|