@pingops/core 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.
Files changed (45) hide show
  1. package/dist/context-keys.d.ts +30 -0
  2. package/dist/context-keys.d.ts.map +1 -0
  3. package/dist/context-keys.js +31 -0
  4. package/dist/context-keys.js.map +1 -0
  5. package/dist/filtering/domain-filter.d.ts +9 -0
  6. package/dist/filtering/domain-filter.d.ts.map +1 -0
  7. package/dist/filtering/domain-filter.js +136 -0
  8. package/dist/filtering/domain-filter.js.map +1 -0
  9. package/dist/filtering/header-filter.d.ts +31 -0
  10. package/dist/filtering/header-filter.d.ts.map +1 -0
  11. package/dist/filtering/header-filter.js +187 -0
  12. package/dist/filtering/header-filter.js.map +1 -0
  13. package/dist/filtering/span-filter.d.ts +13 -0
  14. package/dist/filtering/span-filter.d.ts.map +1 -0
  15. package/dist/filtering/span-filter.js +46 -0
  16. package/dist/filtering/span-filter.js.map +1 -0
  17. package/dist/index.d.ts +13 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +13 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/logger.d.ts +21 -0
  22. package/dist/logger.d.ts.map +1 -0
  23. package/dist/logger.js +36 -0
  24. package/dist/logger.js.map +1 -0
  25. package/dist/transport/client.d.ts +46 -0
  26. package/dist/transport/client.d.ts.map +1 -0
  27. package/dist/transport/client.js +110 -0
  28. package/dist/transport/client.js.map +1 -0
  29. package/dist/types.d.ts +34 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +5 -0
  32. package/dist/types.js.map +1 -0
  33. package/dist/utils/context-extractor.d.ts +13 -0
  34. package/dist/utils/context-extractor.d.ts.map +1 -0
  35. package/dist/utils/context-extractor.js +44 -0
  36. package/dist/utils/context-extractor.js.map +1 -0
  37. package/dist/utils/span-extractor.d.ts +10 -0
  38. package/dist/utils/span-extractor.d.ts.map +1 -0
  39. package/dist/utils/span-extractor.js +125 -0
  40. package/dist/utils/span-extractor.js.map +1 -0
  41. package/dist/wrap-http.d.ts +55 -0
  42. package/dist/wrap-http.d.ts.map +1 -0
  43. package/dist/wrap-http.js +129 -0
  44. package/dist/wrap-http.js.map +1 -0
  45. package/package.json +34 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * OpenTelemetry context keys for PingOps
3
+ */
4
+ /**
5
+ * Context key for enabling HTTP instrumentation.
6
+ * When set to true, HTTP requests will be automatically instrumented.
7
+ * This allows wrapHttp to control which HTTP calls are captured.
8
+ */
9
+ export declare const PINGOPS_HTTP_ENABLED: symbol;
10
+ /**
11
+ * Context key for user ID attribute.
12
+ * Used to propagate user identifier to all spans in the context.
13
+ */
14
+ export declare const PINGOPS_USER_ID: symbol;
15
+ /**
16
+ * Context key for session ID attribute.
17
+ * Used to propagate session identifier to all spans in the context.
18
+ */
19
+ export declare const PINGOPS_SESSION_ID: symbol;
20
+ /**
21
+ * Context key for tags attribute.
22
+ * Used to propagate tags array to all spans in the context.
23
+ */
24
+ export declare const PINGOPS_TAGS: symbol;
25
+ /**
26
+ * Context key for metadata attribute.
27
+ * Used to propagate metadata object to all spans in the context.
28
+ */
29
+ export declare const PINGOPS_METADATA: symbol;
30
+ //# sourceMappingURL=context-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-keys.d.ts","sourceRoot":"","sources":["../src/context-keys.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAA2C,CAAC;AAE7E;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAsC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAyC,CAAC;AAEzE;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAmC,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAuC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * OpenTelemetry context keys for PingOps
3
+ */
4
+ import { createContextKey } from "@opentelemetry/api";
5
+ /**
6
+ * Context key for enabling HTTP instrumentation.
7
+ * When set to true, HTTP requests will be automatically instrumented.
8
+ * This allows wrapHttp to control which HTTP calls are captured.
9
+ */
10
+ export const PINGOPS_HTTP_ENABLED = createContextKey("pingops-http-enabled");
11
+ /**
12
+ * Context key for user ID attribute.
13
+ * Used to propagate user identifier to all spans in the context.
14
+ */
15
+ export const PINGOPS_USER_ID = createContextKey("pingops-user-id");
16
+ /**
17
+ * Context key for session ID attribute.
18
+ * Used to propagate session identifier to all spans in the context.
19
+ */
20
+ export const PINGOPS_SESSION_ID = createContextKey("pingops-session-id");
21
+ /**
22
+ * Context key for tags attribute.
23
+ * Used to propagate tags array to all spans in the context.
24
+ */
25
+ export const PINGOPS_TAGS = createContextKey("pingops-tags");
26
+ /**
27
+ * Context key for metadata attribute.
28
+ * Used to propagate metadata object to all spans in the context.
29
+ */
30
+ export const PINGOPS_METADATA = createContextKey("pingops-metadata");
31
+ //# sourceMappingURL=context-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-keys.js","sourceRoot":"","sources":["../src/context-keys.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;AAE7E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;AAEnE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC;AAE7D;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Domain filtering logic - applies allow/deny list rules
3
+ */
4
+ import type { DomainRule } from "../types";
5
+ /**
6
+ * Determines if a span should be captured based on domain rules
7
+ */
8
+ export declare function shouldCaptureSpan(url: string, domainAllowList?: DomainRule[], domainDenyList?: DomainRule[]): boolean;
9
+ //# sourceMappingURL=domain-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-filter.d.ts","sourceRoot":"","sources":["../../src/filtering/domain-filter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AA6D3C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,eAAe,CAAC,EAAE,UAAU,EAAE,EAC9B,cAAc,CAAC,EAAE,UAAU,EAAE,GAC5B,OAAO,CAkFT"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Domain filtering logic - applies allow/deny list rules
3
+ */
4
+ import { createLogger } from "../logger";
5
+ const log = createLogger("[PingOps DomainFilter]");
6
+ /**
7
+ * Extracts domain from a URL
8
+ */
9
+ function extractDomain(url) {
10
+ try {
11
+ const urlObj = new URL(url);
12
+ const domain = urlObj.hostname;
13
+ log.debug("Extracted domain from URL", { url, domain });
14
+ return domain;
15
+ }
16
+ catch {
17
+ // If URL parsing fails, try to extract domain from string
18
+ const match = url.match(/^(?:https?:\/\/)?([^/]+)/);
19
+ const domain = match ? match[1] : "";
20
+ log.debug("Extracted domain from URL (fallback)", { url, domain });
21
+ return domain;
22
+ }
23
+ }
24
+ /**
25
+ * Checks if a domain matches a rule (exact or suffix match)
26
+ */
27
+ function domainMatches(domain, ruleDomain) {
28
+ // Exact match
29
+ if (domain === ruleDomain) {
30
+ log.debug("Domain exact match", { domain, ruleDomain });
31
+ return true;
32
+ }
33
+ // Suffix match (e.g., .github.com matches api.github.com)
34
+ if (ruleDomain.startsWith(".")) {
35
+ const matches = domain.endsWith(ruleDomain) || domain === ruleDomain.slice(1);
36
+ log.debug("Domain suffix match check", { domain, ruleDomain, matches });
37
+ return matches;
38
+ }
39
+ log.debug("Domain does not match", { domain, ruleDomain });
40
+ return false;
41
+ }
42
+ /**
43
+ * Checks if a path matches any of the allowed paths (prefix match)
44
+ */
45
+ function pathMatches(path, allowedPaths) {
46
+ if (!allowedPaths || allowedPaths.length === 0) {
47
+ log.debug("No path restrictions, all paths match", { path });
48
+ return true; // No path restrictions means all paths match
49
+ }
50
+ const matches = allowedPaths.some((allowedPath) => path.startsWith(allowedPath));
51
+ log.debug("Path match check", { path, allowedPaths, matches });
52
+ return matches;
53
+ }
54
+ /**
55
+ * Determines if a span should be captured based on domain rules
56
+ */
57
+ export function shouldCaptureSpan(url, domainAllowList, domainDenyList) {
58
+ log.debug("Checking domain filter rules", {
59
+ url,
60
+ hasAllowList: !!domainAllowList && domainAllowList.length > 0,
61
+ hasDenyList: !!domainDenyList && domainDenyList.length > 0,
62
+ allowListCount: domainAllowList?.length || 0,
63
+ denyListCount: domainDenyList?.length || 0,
64
+ });
65
+ const domain = extractDomain(url);
66
+ // Extract path from URL
67
+ let path = "/";
68
+ try {
69
+ const urlObj = new URL(url);
70
+ path = urlObj.pathname;
71
+ }
72
+ catch {
73
+ // If URL parsing fails, try to extract path from string
74
+ const pathMatch = url.match(/^(?:https?:\/\/)?[^/]+(\/.*)?$/);
75
+ path = pathMatch && pathMatch[1] ? pathMatch[1] : "/";
76
+ }
77
+ log.debug("Extracted domain and path", { url, domain, path });
78
+ // Deny list is evaluated first - if domain is denied, don't capture
79
+ if (domainDenyList) {
80
+ for (const rule of domainDenyList) {
81
+ if (domainMatches(domain, rule.domain)) {
82
+ log.info("Domain denied by deny list", {
83
+ domain,
84
+ ruleDomain: rule.domain,
85
+ url,
86
+ });
87
+ return false;
88
+ }
89
+ }
90
+ log.debug("Domain passed deny list check", { domain });
91
+ }
92
+ // If no allow list, capture all (except denied)
93
+ if (!domainAllowList || domainAllowList.length === 0) {
94
+ log.debug("No allow list configured, capturing span", { domain, url });
95
+ return true;
96
+ }
97
+ // Check if domain matches any allow list rule
98
+ for (const rule of domainAllowList) {
99
+ if (domainMatches(domain, rule.domain)) {
100
+ // If paths are specified, check path match
101
+ if (rule.paths && rule.paths.length > 0) {
102
+ const pathMatch = pathMatches(path, rule.paths);
103
+ if (pathMatch) {
104
+ log.info("Domain and path allowed by allow list", {
105
+ domain,
106
+ ruleDomain: rule.domain,
107
+ path,
108
+ allowedPaths: rule.paths,
109
+ url,
110
+ });
111
+ return true;
112
+ }
113
+ else {
114
+ log.debug("Domain allowed but path not matched", {
115
+ domain,
116
+ ruleDomain: rule.domain,
117
+ path,
118
+ allowedPaths: rule.paths,
119
+ });
120
+ }
121
+ }
122
+ else {
123
+ log.info("Domain allowed by allow list", {
124
+ domain,
125
+ ruleDomain: rule.domain,
126
+ url,
127
+ });
128
+ return true;
129
+ }
130
+ }
131
+ }
132
+ // Domain not in allow list
133
+ log.info("Domain not in allow list, filtering out", { domain, url });
134
+ return false;
135
+ }
136
+ //# sourceMappingURL=domain-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-filter.js","sourceRoot":"","sources":["../../src/filtering/domain-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Header filtering logic - applies allow/deny list rules
3
+ */
4
+ /**
5
+ * Filters headers based on allow/deny lists
6
+ * - Deny list always wins (if header is in deny list, exclude it)
7
+ * - Allow list filters included headers (if specified, only include these)
8
+ * - Case-insensitive matching
9
+ */
10
+ export declare function filterHeaders(headers: Record<string, string | string[] | undefined>, headersAllowList?: string[], headersDenyList?: string[]): Record<string, string | string[] | undefined>;
11
+ /**
12
+ * Extracts and normalizes headers from OpenTelemetry span attributes
13
+ *
14
+ * Handles flat array format headers (e.g., 'http.request.header.0', 'http.request.header.1')
15
+ * and converts them to proper key-value objects.
16
+ *
17
+ * Some OpenTelemetry instrumentations store headers as flat arrays:
18
+ * - 'http.request.header.0': 'Content-Type'
19
+ * - 'http.request.header.1': 'application/json'
20
+ * - 'http.request.header.2': 'Authorization'
21
+ * - 'http.request.header.3': 'Bearer token'
22
+ *
23
+ * This function converts them to:
24
+ * - { 'Content-Type': 'application/json', 'Authorization': 'Bearer token' }
25
+ */
26
+ export declare function extractHeadersFromAttributes(attributes: Record<string, unknown>, headerPrefix: "http.request.header" | "http.response.header"): Record<string, string | string[] | undefined> | null;
27
+ /**
28
+ * Normalizes headers from various sources into a proper key-value object
29
+ */
30
+ export declare function normalizeHeaders(headers: unknown): Record<string, string | string[] | undefined>;
31
+ //# sourceMappingURL=header-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-filter.d.ts","sourceRoot":"","sources":["../../src/filtering/header-filter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,EACtD,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAkD/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,YAAY,EAAE,qBAAqB,GAAG,sBAAsB,GAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAyDtD;AAgBD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAqD/C"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Header filtering logic - applies allow/deny list rules
3
+ */
4
+ import { createLogger } from "../logger";
5
+ const log = createLogger("[PingOps HeaderFilter]");
6
+ /**
7
+ * Normalizes header name to lowercase for case-insensitive matching
8
+ */
9
+ function normalizeHeaderName(name) {
10
+ return name.toLowerCase();
11
+ }
12
+ /**
13
+ * Filters headers based on allow/deny lists
14
+ * - Deny list always wins (if header is in deny list, exclude it)
15
+ * - Allow list filters included headers (if specified, only include these)
16
+ * - Case-insensitive matching
17
+ */
18
+ export function filterHeaders(headers, headersAllowList, headersDenyList) {
19
+ const originalCount = Object.keys(headers).length;
20
+ log.debug("Filtering headers", {
21
+ originalHeaderCount: originalCount,
22
+ hasAllowList: !!headersAllowList && headersAllowList.length > 0,
23
+ hasDenyList: !!headersDenyList && headersDenyList.length > 0,
24
+ allowListCount: headersAllowList?.length || 0,
25
+ denyListCount: headersDenyList?.length || 0,
26
+ });
27
+ const normalizedDenyList = headersDenyList?.map(normalizeHeaderName) ?? [];
28
+ const normalizedAllowList = headersAllowList?.map(normalizeHeaderName) ?? [];
29
+ const filtered = {};
30
+ const deniedHeaders = [];
31
+ const excludedHeaders = [];
32
+ for (const [name, value] of Object.entries(headers)) {
33
+ const normalizedName = normalizeHeaderName(name);
34
+ // Deny list always wins
35
+ if (normalizedDenyList.includes(normalizedName)) {
36
+ deniedHeaders.push(name);
37
+ log.debug("Header denied by deny list", { headerName: name });
38
+ continue;
39
+ }
40
+ // If allow list exists, only include headers in the list
41
+ if (normalizedAllowList.length > 0) {
42
+ if (!normalizedAllowList.includes(normalizedName)) {
43
+ excludedHeaders.push(name);
44
+ log.debug("Header excluded (not in allow list)", { headerName: name });
45
+ continue;
46
+ }
47
+ }
48
+ filtered[name] = value;
49
+ }
50
+ const filteredCount = Object.keys(filtered).length;
51
+ log.info("Header filtering complete", {
52
+ originalCount,
53
+ filteredCount,
54
+ deniedCount: deniedHeaders.length,
55
+ excludedCount: excludedHeaders.length,
56
+ deniedHeaders: deniedHeaders.length > 0 ? deniedHeaders : undefined,
57
+ excludedHeaders: excludedHeaders.length > 0 ? excludedHeaders : undefined,
58
+ });
59
+ return filtered;
60
+ }
61
+ /**
62
+ * Extracts and normalizes headers from OpenTelemetry span attributes
63
+ *
64
+ * Handles flat array format headers (e.g., 'http.request.header.0', 'http.request.header.1')
65
+ * and converts them to proper key-value objects.
66
+ *
67
+ * Some OpenTelemetry instrumentations store headers as flat arrays:
68
+ * - 'http.request.header.0': 'Content-Type'
69
+ * - 'http.request.header.1': 'application/json'
70
+ * - 'http.request.header.2': 'Authorization'
71
+ * - 'http.request.header.3': 'Bearer token'
72
+ *
73
+ * This function converts them to:
74
+ * - { 'Content-Type': 'application/json', 'Authorization': 'Bearer token' }
75
+ */
76
+ export function extractHeadersFromAttributes(attributes, headerPrefix) {
77
+ const headerMap = {};
78
+ const headerKeys = [];
79
+ // Find all keys matching the pattern (e.g., 'http.request.header.0', 'http.request.header.1', etc.)
80
+ for (const key in attributes) {
81
+ if (key.startsWith(`${headerPrefix}.`) && key !== headerPrefix) {
82
+ const match = key.match(new RegExp(`^${headerPrefix}\\.(\\d+)$`));
83
+ if (match) {
84
+ const index = parseInt(match[1], 10);
85
+ headerKeys.push(index);
86
+ }
87
+ }
88
+ }
89
+ // If no flat array headers found, return null
90
+ if (headerKeys.length === 0) {
91
+ return null;
92
+ }
93
+ // Sort indices to process in order
94
+ headerKeys.sort((a, b) => a - b);
95
+ // Convert flat array to key-value pairs
96
+ // Even indices are header names, odd indices are header values
97
+ for (let i = 0; i < headerKeys.length; i += 2) {
98
+ const nameIndex = headerKeys[i];
99
+ const valueIndex = headerKeys[i + 1];
100
+ if (valueIndex !== undefined) {
101
+ const nameKey = `${headerPrefix}.${nameIndex}`;
102
+ const valueKey = `${headerPrefix}.${valueIndex}`;
103
+ const headerName = attributes[nameKey];
104
+ const headerValue = attributes[valueKey];
105
+ if (headerName && headerValue !== undefined) {
106
+ // Handle multiple values for the same header name (case-insensitive)
107
+ const normalizedName = headerName.toLowerCase();
108
+ const existingKey = Object.keys(headerMap).find((k) => k.toLowerCase() === normalizedName);
109
+ if (existingKey) {
110
+ const existing = headerMap[existingKey];
111
+ headerMap[existingKey] = Array.isArray(existing)
112
+ ? [...existing, headerValue]
113
+ : [existing, headerValue];
114
+ }
115
+ else {
116
+ // Use original case for the first occurrence
117
+ headerMap[headerName] = headerValue;
118
+ }
119
+ }
120
+ }
121
+ }
122
+ return Object.keys(headerMap).length > 0 ? headerMap : null;
123
+ }
124
+ /**
125
+ * Type guard to check if value is a Headers-like object
126
+ */
127
+ function isHeadersLike(headers) {
128
+ return (typeof headers === "object" &&
129
+ headers !== null &&
130
+ "entries" in headers &&
131
+ typeof headers.entries === "function");
132
+ }
133
+ /**
134
+ * Normalizes headers from various sources into a proper key-value object
135
+ */
136
+ export function normalizeHeaders(headers) {
137
+ const result = {};
138
+ if (!headers) {
139
+ return result;
140
+ }
141
+ try {
142
+ // Handle Headers object (from fetch/undici)
143
+ if (isHeadersLike(headers)) {
144
+ for (const [key, value] of headers.entries()) {
145
+ // Headers can have multiple values for the same key
146
+ if (result[key]) {
147
+ // Convert to array if not already
148
+ const existing = result[key];
149
+ result[key] = Array.isArray(existing)
150
+ ? [...existing, value]
151
+ : [existing, value];
152
+ }
153
+ else {
154
+ result[key] = value;
155
+ }
156
+ }
157
+ return result;
158
+ }
159
+ // Handle plain object
160
+ if (typeof headers === "object" && !Array.isArray(headers)) {
161
+ for (const [key, value] of Object.entries(headers)) {
162
+ // Skip numeric keys (array-like objects)
163
+ if (!/^\d+$/.test(key)) {
164
+ result[key] = value;
165
+ }
166
+ }
167
+ return result;
168
+ }
169
+ // Handle array (shouldn't happen, but handle gracefully)
170
+ if (Array.isArray(headers)) {
171
+ // Try to reconstruct from array pairs
172
+ for (let i = 0; i < headers.length; i += 2) {
173
+ if (i + 1 < headers.length) {
174
+ const key = String(headers[i]);
175
+ const value = headers[i + 1];
176
+ result[key] = value;
177
+ }
178
+ }
179
+ return result;
180
+ }
181
+ }
182
+ catch {
183
+ // Fail silently - return empty object
184
+ }
185
+ return result;
186
+ }
187
+ //# sourceMappingURL=header-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-filter.js","sourceRoot":"","sources":["../../src/filtering/header-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Span filtering logic - determines if a span is eligible for capture
3
+ */
4
+ import type { ReadableSpan } from "@opentelemetry/sdk-trace-base";
5
+ /**
6
+ * Checks if a span is eligible for capture based on span kind and attributes.
7
+ * A span is eligible if:
8
+ * 1. span.kind === SpanKind.CLIENT
9
+ * 2. AND has HTTP attributes (http.method, http.url, or server.address)
10
+ * OR has GenAI attributes (gen_ai.system, gen_ai.operation.name)
11
+ */
12
+ export declare function isSpanEligible(span: ReadableSpan): boolean;
13
+ //# sourceMappingURL=span-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-filter.d.ts","sourceRoot":"","sources":["../../src/filtering/span-filter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAKlE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAqC1D"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Span filtering logic - determines if a span is eligible for capture
3
+ */
4
+ import { SpanKind } from "@opentelemetry/api";
5
+ import { createLogger } from "../logger";
6
+ const log = createLogger("[PingOps SpanFilter]");
7
+ /**
8
+ * Checks if a span is eligible for capture based on span kind and attributes.
9
+ * A span is eligible if:
10
+ * 1. span.kind === SpanKind.CLIENT
11
+ * 2. AND has HTTP attributes (http.method, http.url, or server.address)
12
+ * OR has GenAI attributes (gen_ai.system, gen_ai.operation.name)
13
+ */
14
+ export function isSpanEligible(span) {
15
+ log.debug("Checking span eligibility", {
16
+ spanName: span.name,
17
+ spanKind: span.kind,
18
+ spanId: span.spanContext().spanId,
19
+ traceId: span.spanContext().traceId,
20
+ });
21
+ // Must be a CLIENT span (outgoing request)
22
+ if (span.kind !== SpanKind.CLIENT) {
23
+ log.debug("Span not eligible: not CLIENT kind", {
24
+ spanName: span.name,
25
+ spanKind: span.kind,
26
+ });
27
+ return false;
28
+ }
29
+ const attributes = span.attributes;
30
+ // Check for HTTP attributes
31
+ const hasHttpMethod = attributes["http.method"] !== undefined;
32
+ const hasHttpUrl = attributes["http.url"] !== undefined;
33
+ const hasServerAddress = attributes["server.address"] !== undefined;
34
+ const isEligible = hasHttpMethod || hasHttpUrl || hasServerAddress;
35
+ log.debug("Span eligibility check result", {
36
+ spanName: span.name,
37
+ isEligible,
38
+ httpAttributes: {
39
+ hasMethod: hasHttpMethod,
40
+ hasUrl: hasHttpUrl,
41
+ hasServerAddress,
42
+ },
43
+ });
44
+ return isEligible;
45
+ }
46
+ //# sourceMappingURL=span-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-filter.js","sourceRoot":"","sources":["../../src/filtering/span-filter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,GAAG,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE;QACrC,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM;QACjC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO;KACpC,CAAC,CAAC;IAEH,2CAA2C;IAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClC,GAAG,CAAC,KAAK,CAAC,oCAAoC,EAAE;YAC9C,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,QAAQ,EAAE,IAAI,CAAC,IAAI;SACpB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IAEnC,4BAA4B;IAC5B,MAAM,aAAa,GAAG,UAAU,CAAC,aAAa,CAAC,KAAK,SAAS,CAAC;IAC9D,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;IACxD,MAAM,gBAAgB,GAAG,UAAU,CAAC,gBAAgB,CAAC,KAAK,SAAS,CAAC;IAEpE,MAAM,UAAU,GAAG,aAAa,IAAI,UAAU,IAAI,gBAAgB,CAAC;IAEnE,GAAG,CAAC,KAAK,CAAC,+BAA+B,EAAE;QACzC,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,UAAU;QACV,cAAc,EAAE;YACd,SAAS,EAAE,aAAa;YACxB,MAAM,EAAE,UAAU;YAClB,gBAAgB;SACjB;KACF,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @pingops/core - Internal shared utilities
3
+ */
4
+ export * from "./types";
5
+ export * from "./filtering/span-filter";
6
+ export * from "./filtering/domain-filter";
7
+ export * from "./filtering/header-filter";
8
+ export * from "./utils/span-extractor";
9
+ export * from "./utils/context-extractor";
10
+ export * from "./logger";
11
+ export * from "./context-keys";
12
+ export * from "./wrap-http";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @pingops/core - Internal shared utilities
3
+ */
4
+ export * from "./types";
5
+ export * from "./filtering/span-filter";
6
+ export * from "./filtering/domain-filter";
7
+ export * from "./filtering/header-filter";
8
+ export * from "./utils/span-extractor";
9
+ export * from "./utils/context-extractor";
10
+ export * from "./logger";
11
+ export * from "./context-keys";
12
+ export * from "./wrap-http";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Global logger utility for PingOps Core
3
+ *
4
+ * Provides consistent logging across all core components with support for
5
+ * different log levels and debug mode control via PINGOPS_DEBUG environment variable.
6
+ */
7
+ export type LogLevel = "debug" | "info" | "warn" | "error";
8
+ export interface Logger {
9
+ debug(message: string, ...args: unknown[]): void;
10
+ info(message: string, ...args: unknown[]): void;
11
+ warn(message: string, ...args: unknown[]): void;
12
+ error(message: string, ...args: unknown[]): void;
13
+ }
14
+ /**
15
+ * Creates a logger instance with a specific prefix
16
+ *
17
+ * @param prefix - Prefix to add to all log messages (e.g., '[PingOps Filter]')
18
+ * @returns Logger instance
19
+ */
20
+ export declare function createLogger(prefix: string): Logger;
21
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwBnD"}
package/dist/logger.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Global logger utility for PingOps Core
3
+ *
4
+ * Provides consistent logging across all core components with support for
5
+ * different log levels and debug mode control via PINGOPS_DEBUG environment variable.
6
+ */
7
+ /**
8
+ * Creates a logger instance with a specific prefix
9
+ *
10
+ * @param prefix - Prefix to add to all log messages (e.g., '[PingOps Filter]')
11
+ * @returns Logger instance
12
+ */
13
+ export function createLogger(prefix) {
14
+ const isDebugEnabled = process.env.PINGOPS_DEBUG === "true";
15
+ const formatMessage = (level, message) => {
16
+ const timestamp = new Date().toISOString();
17
+ return `[${timestamp}] ${prefix} [${level.toUpperCase()}] ${message}`;
18
+ };
19
+ return {
20
+ debug(message, ...args) {
21
+ if (isDebugEnabled) {
22
+ console.debug(formatMessage("debug", message), ...args);
23
+ }
24
+ },
25
+ info(message, ...args) {
26
+ console.log(formatMessage("info", message), ...args);
27
+ },
28
+ warn(message, ...args) {
29
+ console.warn(formatMessage("warn", message), ...args);
30
+ },
31
+ error(message, ...args) {
32
+ console.error(formatMessage("error", message), ...args);
33
+ },
34
+ };
35
+ }
36
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,MAAM,CAAC;IAE5D,MAAM,aAAa,GAAG,CAAC,KAAe,EAAE,OAAe,EAAU,EAAE;QACjE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,OAAO,IAAI,SAAS,KAAK,MAAM,KAAK,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;IACxE,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;YACvC,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;YACtC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,OAAe,EAAE,GAAG,IAAe;YACtC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACxD,CAAC;QACD,KAAK,CAAC,OAAe,EAAE,GAAG,IAAe;YACvC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC"}