@pingops/core 0.1.0 → 0.1.2
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/index.cjs +824 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +306 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +306 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +804 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +17 -5
- package/dist/context-keys.d.ts +0 -30
- package/dist/context-keys.d.ts.map +0 -1
- package/dist/context-keys.js +0 -31
- package/dist/context-keys.js.map +0 -1
- package/dist/filtering/domain-filter.d.ts +0 -9
- package/dist/filtering/domain-filter.d.ts.map +0 -1
- package/dist/filtering/domain-filter.js +0 -136
- package/dist/filtering/domain-filter.js.map +0 -1
- package/dist/filtering/header-filter.d.ts +0 -31
- package/dist/filtering/header-filter.d.ts.map +0 -1
- package/dist/filtering/header-filter.js +0 -187
- package/dist/filtering/header-filter.js.map +0 -1
- package/dist/filtering/span-filter.d.ts +0 -13
- package/dist/filtering/span-filter.d.ts.map +0 -1
- package/dist/filtering/span-filter.js +0 -46
- package/dist/filtering/span-filter.js.map +0 -1
- package/dist/index.d.ts +0 -13
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +0 -1
- package/dist/logger.d.ts +0 -21
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -36
- package/dist/logger.js.map +0 -1
- package/dist/transport/client.d.ts +0 -46
- package/dist/transport/client.d.ts.map +0 -1
- package/dist/transport/client.js +0 -110
- package/dist/transport/client.js.map +0 -1
- package/dist/types.d.ts +0 -34
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/dist/utils/context-extractor.d.ts +0 -13
- package/dist/utils/context-extractor.d.ts.map +0 -1
- package/dist/utils/context-extractor.js +0 -44
- package/dist/utils/context-extractor.js.map +0 -1
- package/dist/utils/span-extractor.d.ts +0 -10
- package/dist/utils/span-extractor.d.ts.map +0 -1
- package/dist/utils/span-extractor.js +0 -125
- package/dist/utils/span-extractor.js.map +0 -1
- package/dist/wrap-http.d.ts +0 -55
- package/dist/wrap-http.d.ts.map +0 -1
- package/dist/wrap-http.js +0 -129
- package/dist/wrap-http.js.map +0 -1
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Context } from "@opentelemetry/api";
|
|
2
|
+
import { ReadableSpan } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Shared type definitions for PingOps SDK
|
|
7
|
+
*/
|
|
8
|
+
interface DomainRule {
|
|
9
|
+
domain: string;
|
|
10
|
+
paths?: string[];
|
|
11
|
+
headersAllowList?: string[];
|
|
12
|
+
headersDenyList?: string[];
|
|
13
|
+
captureRequestBody?: boolean;
|
|
14
|
+
captureResponseBody?: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface SpanPayload {
|
|
17
|
+
traceId: string;
|
|
18
|
+
spanId: string;
|
|
19
|
+
parentSpanId?: string;
|
|
20
|
+
name: string;
|
|
21
|
+
kind: string;
|
|
22
|
+
startTime: string;
|
|
23
|
+
endTime: string;
|
|
24
|
+
duration: number;
|
|
25
|
+
attributes: Record<string, unknown>;
|
|
26
|
+
status: {
|
|
27
|
+
code: string;
|
|
28
|
+
message?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Attributes to propagate to HTTP spans
|
|
33
|
+
*/
|
|
34
|
+
interface WrapHttpAttributes {
|
|
35
|
+
userId?: string;
|
|
36
|
+
sessionId?: string;
|
|
37
|
+
tags?: string[];
|
|
38
|
+
metadata?: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to capture request body for HTTP spans in this context.
|
|
41
|
+
* Takes precedence over domain-specific rules and global config.
|
|
42
|
+
*/
|
|
43
|
+
captureRequestBody?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether to capture response body for HTTP spans in this context.
|
|
46
|
+
* Takes precedence over domain-specific rules and global config.
|
|
47
|
+
*/
|
|
48
|
+
captureResponseBody?: boolean;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/filtering/span-filter.d.ts
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a span is eligible for capture based on span kind and attributes.
|
|
54
|
+
* A span is eligible if:
|
|
55
|
+
* 1. span.kind === SpanKind.CLIENT
|
|
56
|
+
* 2. AND has HTTP attributes (http.method, http.url, or server.address)
|
|
57
|
+
* OR has GenAI attributes (gen_ai.system, gen_ai.operation.name)
|
|
58
|
+
*/
|
|
59
|
+
declare function isSpanEligible(span: ReadableSpan): boolean;
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/filtering/domain-filter.d.ts
|
|
62
|
+
/**
|
|
63
|
+
* Determines if a span should be captured based on domain rules
|
|
64
|
+
*/
|
|
65
|
+
declare function shouldCaptureSpan(url: string, domainAllowList?: DomainRule[], domainDenyList?: DomainRule[]): boolean;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/filtering/sensitive-headers.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* Sensitive header patterns and redaction configuration
|
|
70
|
+
*/
|
|
71
|
+
/**
|
|
72
|
+
* Default patterns for sensitive headers that should be redacted
|
|
73
|
+
* These are matched case-insensitively
|
|
74
|
+
*/
|
|
75
|
+
declare const DEFAULT_SENSITIVE_HEADER_PATTERNS: readonly ["authorization", "www-authenticate", "proxy-authenticate", "proxy-authorization", "x-auth-token", "x-api-key", "x-api-token", "x-access-token", "x-auth-user", "x-auth-password", "x-csrf-token", "x-xsrf-token", "api-key", "apikey", "api_key", "access-key", "accesskey", "access_key", "secret-key", "secretkey", "secret_key", "private-key", "privatekey", "private_key", "cookie", "set-cookie", "session-id", "sessionid", "session_id", "session-token", "sessiontoken", "session_token", "oauth-token", "oauth_token", "oauth2-token", "oauth2_token", "bearer", "x-amz-security-token", "x-amz-signature", "x-aws-access-key", "x-aws-secret-key", "x-aws-session-token", "x-password", "x-secret", "x-token", "x-jwt", "x-jwt-token", "x-refresh-token", "x-client-secret", "x-client-id", "x-user-token", "x-service-key"];
|
|
76
|
+
/**
|
|
77
|
+
* Redaction strategies for sensitive header values
|
|
78
|
+
*/
|
|
79
|
+
declare enum HeaderRedactionStrategy {
|
|
80
|
+
/**
|
|
81
|
+
* Replace the entire value with a fixed redaction string
|
|
82
|
+
*/
|
|
83
|
+
REPLACE = "replace",
|
|
84
|
+
/**
|
|
85
|
+
* Show only the first N characters, redact the rest
|
|
86
|
+
*/
|
|
87
|
+
PARTIAL = "partial",
|
|
88
|
+
/**
|
|
89
|
+
* Show only the last N characters, redact the rest
|
|
90
|
+
*/
|
|
91
|
+
PARTIAL_END = "partial_end",
|
|
92
|
+
/**
|
|
93
|
+
* Remove the header entirely (same as deny list)
|
|
94
|
+
*/
|
|
95
|
+
REMOVE = "remove",
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Configuration for header redaction
|
|
99
|
+
*/
|
|
100
|
+
interface HeaderRedactionConfig {
|
|
101
|
+
/**
|
|
102
|
+
* Patterns to match sensitive headers (case-insensitive)
|
|
103
|
+
* Defaults to DEFAULT_SENSITIVE_HEADER_PATTERNS if not provided
|
|
104
|
+
*/
|
|
105
|
+
sensitivePatterns?: readonly string[];
|
|
106
|
+
/**
|
|
107
|
+
* Redaction strategy to use
|
|
108
|
+
* @default HeaderRedactionStrategy.REPLACE
|
|
109
|
+
*/
|
|
110
|
+
strategy?: HeaderRedactionStrategy;
|
|
111
|
+
/**
|
|
112
|
+
* Redaction string used when strategy is REPLACE
|
|
113
|
+
* @default "[REDACTED]"
|
|
114
|
+
*/
|
|
115
|
+
redactionString?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Number of characters to show when strategy is PARTIAL or PARTIAL_END
|
|
118
|
+
* @default 4
|
|
119
|
+
*/
|
|
120
|
+
visibleChars?: number;
|
|
121
|
+
/**
|
|
122
|
+
* Whether to enable redaction
|
|
123
|
+
* @default true
|
|
124
|
+
*/
|
|
125
|
+
enabled?: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Default redaction configuration
|
|
129
|
+
*/
|
|
130
|
+
declare const DEFAULT_REDACTION_CONFIG: Required<HeaderRedactionConfig>;
|
|
131
|
+
/**
|
|
132
|
+
* Checks if a header name matches any sensitive pattern
|
|
133
|
+
* Uses case-insensitive matching with exact match, prefix/suffix, and substring matching
|
|
134
|
+
*
|
|
135
|
+
* @param headerName - The header name to check
|
|
136
|
+
* @param patterns - Array of patterns to match against (defaults to DEFAULT_SENSITIVE_HEADER_PATTERNS)
|
|
137
|
+
* @returns true if the header matches any sensitive pattern
|
|
138
|
+
*/
|
|
139
|
+
declare function isSensitiveHeader(headerName: string, patterns?: readonly string[]): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Redacts a header value based on the configuration
|
|
142
|
+
*/
|
|
143
|
+
declare function redactHeaderValue(value: string | string[] | undefined, config: Required<HeaderRedactionConfig>): string | string[] | undefined;
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/filtering/header-filter.d.ts
|
|
146
|
+
/**
|
|
147
|
+
* Filters headers based on allow/deny lists and applies redaction to sensitive headers
|
|
148
|
+
* - Deny list always wins (if header is in deny list, exclude it)
|
|
149
|
+
* - Allow list filters included headers (if specified, only include these)
|
|
150
|
+
* - Sensitive headers are redacted after filtering (if redaction is enabled)
|
|
151
|
+
* - Case-insensitive matching
|
|
152
|
+
*
|
|
153
|
+
* @param headers - Headers to filter
|
|
154
|
+
* @param headersAllowList - Optional allow list of header names to include
|
|
155
|
+
* @param headersDenyList - Optional deny list of header names to exclude
|
|
156
|
+
* @param redactionConfig - Optional configuration for header value redaction
|
|
157
|
+
* @returns Filtered and redacted headers
|
|
158
|
+
*/
|
|
159
|
+
declare function filterHeaders(headers: Record<string, string | string[] | undefined>, headersAllowList?: string[], headersDenyList?: string[], redactionConfig?: HeaderRedactionConfig): Record<string, string | string[] | undefined>;
|
|
160
|
+
/**
|
|
161
|
+
* Extracts and normalizes headers from OpenTelemetry span attributes
|
|
162
|
+
*
|
|
163
|
+
* Handles flat array format headers (e.g., 'http.request.header.0', 'http.request.header.1')
|
|
164
|
+
* and converts them to proper key-value objects.
|
|
165
|
+
*
|
|
166
|
+
* Some OpenTelemetry instrumentations store headers as flat arrays:
|
|
167
|
+
* - 'http.request.header.0': 'Content-Type'
|
|
168
|
+
* - 'http.request.header.1': 'application/json'
|
|
169
|
+
* - 'http.request.header.2': 'Authorization'
|
|
170
|
+
* - 'http.request.header.3': 'Bearer token'
|
|
171
|
+
*
|
|
172
|
+
* This function converts them to:
|
|
173
|
+
* - { 'Content-Type': 'application/json', 'Authorization': 'Bearer token' }
|
|
174
|
+
*/
|
|
175
|
+
declare function extractHeadersFromAttributes(attributes: Record<string, unknown>, headerPrefix: "http.request.header" | "http.response.header"): Record<string, string | string[] | undefined> | null;
|
|
176
|
+
/**
|
|
177
|
+
* Normalizes headers from various sources into a proper key-value object
|
|
178
|
+
*/
|
|
179
|
+
declare function normalizeHeaders(headers: unknown): Record<string, string | string[] | undefined>;
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/utils/span-extractor.d.ts
|
|
182
|
+
/**
|
|
183
|
+
* Extracts structured payload from a span
|
|
184
|
+
*/
|
|
185
|
+
declare function extractSpanPayload(span: ReadableSpan, domainAllowList?: DomainRule[], globalHeadersAllowList?: string[], globalHeadersDenyList?: string[], globalCaptureRequestBody?: boolean, globalCaptureResponseBody?: boolean, headerRedaction?: HeaderRedactionConfig): SpanPayload | null;
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/utils/context-extractor.d.ts
|
|
188
|
+
/**
|
|
189
|
+
* Extracts propagated attributes from the given context and returns them
|
|
190
|
+
* as span attributes that can be set on a span.
|
|
191
|
+
*
|
|
192
|
+
* @param parentContext - The OpenTelemetry context to extract attributes from
|
|
193
|
+
* @returns Record of attribute key-value pairs to set on spans
|
|
194
|
+
*/
|
|
195
|
+
declare function getPropagatedAttributesFromContext(parentContext: Context): Record<string, string | string[]>;
|
|
196
|
+
//#endregion
|
|
197
|
+
//#region src/logger.d.ts
|
|
198
|
+
/**
|
|
199
|
+
* Global logger utility for PingOps Core
|
|
200
|
+
*
|
|
201
|
+
* Provides consistent logging across all core components with support for
|
|
202
|
+
* different log levels and debug mode control via PINGOPS_DEBUG environment variable.
|
|
203
|
+
*/
|
|
204
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
205
|
+
interface Logger {
|
|
206
|
+
debug(message: string, ...args: unknown[]): void;
|
|
207
|
+
info(message: string, ...args: unknown[]): void;
|
|
208
|
+
warn(message: string, ...args: unknown[]): void;
|
|
209
|
+
error(message: string, ...args: unknown[]): void;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Creates a logger instance with a specific prefix
|
|
213
|
+
*
|
|
214
|
+
* @param prefix - Prefix to add to all log messages (e.g., '[PingOps Filter]')
|
|
215
|
+
* @returns Logger instance
|
|
216
|
+
*/
|
|
217
|
+
declare function createLogger(prefix: string): Logger;
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/context-keys.d.ts
|
|
220
|
+
/**
|
|
221
|
+
* OpenTelemetry context keys for PingOps
|
|
222
|
+
*/
|
|
223
|
+
/**
|
|
224
|
+
* Context key for enabling HTTP instrumentation.
|
|
225
|
+
* When set to true, HTTP requests will be automatically instrumented.
|
|
226
|
+
* This allows wrapHttp to control which HTTP calls are captured.
|
|
227
|
+
*/
|
|
228
|
+
declare const PINGOPS_HTTP_ENABLED: symbol;
|
|
229
|
+
/**
|
|
230
|
+
* Context key for user ID attribute.
|
|
231
|
+
* Used to propagate user identifier to all spans in the context.
|
|
232
|
+
*/
|
|
233
|
+
declare const PINGOPS_USER_ID: symbol;
|
|
234
|
+
/**
|
|
235
|
+
* Context key for session ID attribute.
|
|
236
|
+
* Used to propagate session identifier to all spans in the context.
|
|
237
|
+
*/
|
|
238
|
+
declare const PINGOPS_SESSION_ID: symbol;
|
|
239
|
+
/**
|
|
240
|
+
* Context key for tags attribute.
|
|
241
|
+
* Used to propagate tags array to all spans in the context.
|
|
242
|
+
*/
|
|
243
|
+
declare const PINGOPS_TAGS: symbol;
|
|
244
|
+
/**
|
|
245
|
+
* Context key for metadata attribute.
|
|
246
|
+
* Used to propagate metadata object to all spans in the context.
|
|
247
|
+
*/
|
|
248
|
+
declare const PINGOPS_METADATA: symbol;
|
|
249
|
+
/**
|
|
250
|
+
* Context key for capturing request body.
|
|
251
|
+
* When set, controls whether request bodies should be captured for HTTP spans.
|
|
252
|
+
* This allows wrapHttp to control body capture per-request.
|
|
253
|
+
*/
|
|
254
|
+
declare const PINGOPS_CAPTURE_REQUEST_BODY: symbol;
|
|
255
|
+
/**
|
|
256
|
+
* Context key for capturing response body.
|
|
257
|
+
* When set, controls whether response bodies should be captured for HTTP spans.
|
|
258
|
+
* This allows wrapHttp to control body capture per-request.
|
|
259
|
+
*/
|
|
260
|
+
declare const PINGOPS_CAPTURE_RESPONSE_BODY: symbol;
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/wrap-http.d.ts
|
|
263
|
+
/**
|
|
264
|
+
* Options for wrapHttp function
|
|
265
|
+
*/
|
|
266
|
+
interface WrapHttpOptions {
|
|
267
|
+
attributes?: WrapHttpAttributes;
|
|
268
|
+
/**
|
|
269
|
+
* Callback to check if SDK is initialized.
|
|
270
|
+
* Required to determine if global instrumentation is enabled.
|
|
271
|
+
*/
|
|
272
|
+
checkInitialized: () => boolean;
|
|
273
|
+
/**
|
|
274
|
+
* Callback to check if global instrumentation is enabled.
|
|
275
|
+
* Required to determine instrumentation behavior.
|
|
276
|
+
*/
|
|
277
|
+
isGlobalInstrumentationEnabled: () => boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Optional callback to ensure SDK is initialized (auto-initialization).
|
|
280
|
+
* If not provided, wrapHttp will try to auto-initialize from environment variables.
|
|
281
|
+
*/
|
|
282
|
+
ensureInitialized?: () => Promise<void>;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Wraps a function to set attributes on HTTP spans created within the wrapped block.
|
|
286
|
+
*
|
|
287
|
+
* This function sets attributes (userId, sessionId, tags, metadata) in the OpenTelemetry
|
|
288
|
+
* context, which are automatically propagated to all spans created within the wrapped function.
|
|
289
|
+
*
|
|
290
|
+
* Instrumentation behavior:
|
|
291
|
+
* - If `initializePingops` was called: All HTTP requests are instrumented by default.
|
|
292
|
+
* `wrapHttp` only adds attributes to spans created within the wrapped block.
|
|
293
|
+
* - If `initializePingops` was NOT called: Only HTTP requests within `wrapHttp` blocks
|
|
294
|
+
* are instrumented. Requests outside `wrapHttp` are not instrumented.
|
|
295
|
+
*
|
|
296
|
+
* Note: This is the low-level API. For a simpler API with automatic setup,
|
|
297
|
+
* use `wrapHttp` from `@pingops/sdk` instead.
|
|
298
|
+
*
|
|
299
|
+
* @param options - Options including attributes and required callbacks
|
|
300
|
+
* @param fn - Function to execute within the attribute context
|
|
301
|
+
* @returns The result of the function
|
|
302
|
+
*/
|
|
303
|
+
declare function wrapHttp<T>(options: WrapHttpOptions, fn: () => T | Promise<T>): T | Promise<T>;
|
|
304
|
+
//#endregion
|
|
305
|
+
export { DEFAULT_REDACTION_CONFIG, DEFAULT_SENSITIVE_HEADER_PATTERNS, DomainRule, HeaderRedactionConfig, HeaderRedactionStrategy, LogLevel, Logger, PINGOPS_CAPTURE_REQUEST_BODY, PINGOPS_CAPTURE_RESPONSE_BODY, PINGOPS_HTTP_ENABLED, PINGOPS_METADATA, PINGOPS_SESSION_ID, PINGOPS_TAGS, PINGOPS_USER_ID, SpanPayload, WrapHttpAttributes, WrapHttpOptions, createLogger, extractHeadersFromAttributes, extractSpanPayload, filterHeaders, getPropagatedAttributesFromContext, isSensitiveHeader, isSpanEligible, normalizeHeaders, redactHeaderValue, shouldCaptureSpan, wrapHttp };
|
|
306
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/filtering/span-filter.ts","../src/filtering/domain-filter.ts","../src/filtering/sensitive-headers.ts","../src/filtering/header-filter.ts","../src/utils/span-extractor.ts","../src/utils/context-extractor.ts","../src/logger.ts","../src/context-keys.ts","../src/wrap-http.ts"],"sourcesContent":[],"mappings":"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"}
|