@pingops/sdk 0.1.3 → 0.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/pingops.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;iBAyDgB,iBAAA,SACN;iBAGM,iBAAA;iBAIA,iBAAA;;;;;;iBAwGM,eAAA,CAAA,GAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgLzB;eACU;aACd,IAAI,QAAQ,KACrB,IAAI,QAAQ"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/pingops.ts"],"sourcesContent":[],"mappings":";;;;;AA+SA;AAOA;AAiCA;;;;;;;;;;;;iBArRgB,iBAAA,SACN;iBAGM,iBAAA;iBAIA,iBAAA;;;;;;iBAuGM,eAAA,CAAA,GAAmB;;;;iBA8HzB,gBAAA,CAAA;;;;iBAOA,eAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiCM;eACI;;aACd,IAAI,QAAQ,KACrB,QAAQ"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PingopsProcessorConfig } from "@pingops/otel";
2
- import { WrapHttpAttributes, WrapHttpAttributes as WrapHttpAttributes$1 } from "@pingops/core";
2
+ import { PingopsTraceAttributes, PingopsTraceAttributes as PingopsTraceAttributes$1 } from "@pingops/core";
3
3
 
4
4
  //#region src/pingops.d.ts
5
5
 
@@ -15,7 +15,7 @@ import { WrapHttpAttributes, WrapHttpAttributes as WrapHttpAttributes$1 } from "
15
15
  *
16
16
  * @param config - Configuration object, config file path, or config file wrapper
17
17
  * @param explicit - Whether this is an explicit call (default: true).
18
- * Set to false when called internally by wrapHttp auto-initialization.
18
+ * Set to false when called internally by startTrace auto-initialization.
19
19
  */
20
20
  declare function initializePingops(config: PingopsProcessorConfig, explicit?: boolean): void;
21
21
  declare function initializePingops(configFilePath: string, explicit?: boolean): void;
@@ -27,61 +27,46 @@ declare function initializePingops(config: {
27
27
  */
28
28
  declare function shutdownPingops(): Promise<void>;
29
29
  /**
30
- * Wraps a function to set attributes on HTTP spans created within the wrapped block.
31
- *
32
- * This function sets attributes (userId, sessionId, tags, metadata) in the OpenTelemetry
33
- * context, which are automatically propagated to all spans created within the wrapped function.
34
- *
35
- * Instrumentation behavior:
36
- * - If `initializePingops` was called: All HTTP requests are instrumented by default.
37
- * `wrapHttp` only adds attributes to spans created within the wrapped block.
38
- * - If `initializePingops` was NOT called: Only HTTP requests within `wrapHttp` blocks
39
- * are instrumented. Requests outside `wrapHttp` are not instrumented.
30
+ * Returns the trace ID of the currently active span, if any.
31
+ */
32
+ declare function getActiveTraceId(): string | undefined;
33
+ /**
34
+ * Returns the span ID of the currently active span, if any.
35
+ */
36
+ declare function getActiveSpanId(): string | undefined;
37
+ /**
38
+ * Starts a new trace using the PingOps tracer provider and runs the callback within that trace.
39
+ * Sets attributes (traceId, userId, sessionId, tags, metadata, etc.) in context so they are
40
+ * propagated to spans created within the callback.
40
41
  *
41
- * @param options - Options including attributes to propagate to spans
42
- * @param fn - Function to execute within the attribute context
43
- * @returns The result of the function
42
+ * @param options - Options including optional attributes and optional seed for deterministic traceId
43
+ * @param fn - Function to execute within the trace and attribute context
44
+ * @returns Promise resolving to the result of the function
44
45
  *
45
46
  * @example
46
47
  * ```typescript
47
- * import { wrapHttp } from '@pingops/sdk';
48
+ * import { startTrace, initializePingops } from '@pingops/sdk';
48
49
  *
49
- * // Scenario 1: initializePingops was called
50
50
  * initializePingops({ ... });
51
51
  *
52
- * // All HTTP requests are instrumented, but this block adds attributes
53
- * const result = await wrapHttp({
52
+ * const result = await startTrace({
54
53
  * attributes: {
55
54
  * userId: 'user-123',
56
55
  * sessionId: 'session-456',
57
56
  * tags: ['production', 'api'],
58
57
  * metadata: { environment: 'prod', version: '1.0.0' }
59
- * }
58
+ * },
59
+ * seed: 'request-123' // optional: deterministic traceId from this seed
60
60
  * }, async () => {
61
- * // This HTTP request will be instrumented AND have the attributes set above
62
61
  * const response = await fetch('https://api.example.com/users/123');
63
62
  * return response.json();
64
63
  * });
65
- *
66
- * // HTTP requests outside wrapHttp are still instrumented, just without the attributes
67
- * const otherResponse = await fetch('https://api.example.com/other');
68
- *
69
- * // Scenario 2: initializePingops was NOT called
70
- * // Only requests within wrapHttp are instrumented
71
- * await wrapHttp({
72
- * attributes: { userId: 'user-123' }
73
- * }, async () => {
74
- * // This request IS instrumented
75
- * return fetch('https://api.example.com/data');
76
- * });
77
- *
78
- * // This request is NOT instrumented (outside wrapHttp)
79
- * await fetch('https://api.example.com/other');
80
64
  * ```
81
65
  */
82
- declare function wrapHttp<T>(options: {
83
- attributes?: WrapHttpAttributes$1;
84
- }, fn: () => T | Promise<T>): T | Promise<T>;
66
+ declare function startTrace<T>(options: {
67
+ attributes?: PingopsTraceAttributes$1;
68
+ seed?: string;
69
+ }, fn: () => T | Promise<T>): Promise<T>;
85
70
  //#endregion
86
- export { type WrapHttpAttributes, initializePingops, shutdownPingops, wrapHttp };
71
+ export { type PingopsTraceAttributes, getActiveSpanId, getActiveTraceId, initializePingops, shutdownPingops, startTrace };
87
72
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/pingops.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;iBAyDgB,iBAAA,SACN;iBAGM,iBAAA;iBAIA,iBAAA;;;;;;iBAwGM,eAAA,CAAA,GAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgLzB;eACU;aACd,IAAI,QAAQ,KACrB,IAAI,QAAQ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/pingops.ts"],"sourcesContent":[],"mappings":";;;;;AA+SA;AAOA;AAiCA;;;;;;;;;;;;iBArRgB,iBAAA,SACN;iBAGM,iBAAA;iBAIA,iBAAA;;;;;;iBAuGM,eAAA,CAAA,GAAmB;;;;iBA8HzB,gBAAA,CAAA;;;;iBAOA,eAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiCM;eACI;;aACd,IAAI,QAAQ,KACrB,QAAQ"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as shutdownPingops, r as wrapHttp, t as initializePingops } from "./pingops-DlQdUQEU.mjs";
1
+ import { a as startTrace, i as shutdownPingops, n as getActiveTraceId, r as initializePingops, t as getActiveSpanId } from "./pingops-D4xrGLxy.mjs";
2
2
 
3
- export { initializePingops, shutdownPingops, wrapHttp };
3
+ export { getActiveSpanId, getActiveTraceId, initializePingops, shutdownPingops, startTrace };
@@ -1,3 +1,4 @@
1
+ let _opentelemetry_api = require("@opentelemetry/api");
1
2
  let _opentelemetry_sdk_node = require("@opentelemetry/sdk-node");
2
3
  let _opentelemetry_resources = require("@opentelemetry/resources");
3
4
  let _opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
@@ -67,25 +68,16 @@ let isSdkInitializedFlag$1 = false;
67
68
  function setSdkInitialized(initialized) {
68
69
  isSdkInitializedFlag$1 = initialized;
69
70
  }
70
- /**
71
- * Checks if global instrumentation is enabled.
72
- * This is used to determine instrumentation behavior:
73
- * - If true: all HTTP requests are instrumented
74
- * - If false: only requests within wrapHttp blocks are instrumented
75
- */
76
- function isGlobalInstrumentationEnabled() {
77
- return isSdkInitializedFlag$1;
78
- }
79
71
 
80
72
  //#endregion
81
73
  //#region src/pingops.ts
82
74
  /**
83
75
  * PingOps SDK singleton for manual instrumentation
84
76
  *
85
- * Provides initializePingops and shutdownPingops functions.
86
- * wrapHttp is available from @pingops/core and will auto-initialize
87
- * from environment variables if needed.
77
+ * Provides initializePingops, shutdownPingops, startTrace, getActiveTraceId,
78
+ * and getActiveSpanId. startTrace can auto-initialize from environment variables if needed.
88
79
  */
80
+ const TRACE_FLAG_SAMPLED = 1;
89
81
  const initLogger = (0, _pingops_core.createLogger)("[PingOps Initialize]");
90
82
  const logger = (0, _pingops_core.createLogger)("[PingOps Pingops]");
91
83
  let sdkInstance = null;
@@ -103,7 +95,7 @@ function initializePingops(config, explicit = true) {
103
95
  }
104
96
  const resource = (0, _opentelemetry_resources.resourceFromAttributes)({ [_opentelemetry_semantic_conventions.ATTR_SERVICE_NAME]: resolvedConfig.serviceName });
105
97
  const processor = new _pingops_otel.PingopsSpanProcessor(resolvedConfig);
106
- const instrumentations = (0, _pingops_otel.getInstrumentations)(isGlobalInstrumentationEnabled);
98
+ const instrumentations = (0, _pingops_otel.getInstrumentations)();
107
99
  const nodeSdk = new _opentelemetry_sdk_node.NodeSDK({
108
100
  resource,
109
101
  spanProcessors: [processor],
@@ -112,7 +104,7 @@ function initializePingops(config, explicit = true) {
112
104
  nodeSdk.start();
113
105
  sdkInstance = nodeSdk;
114
106
  isSdkInitializedFlag = true;
115
- setSdkInitialized(explicit);
107
+ setSdkInitialized(true);
116
108
  try {
117
109
  const isolatedProvider = new _opentelemetry_sdk_trace_node.NodeTracerProvider({
118
110
  resource,
@@ -224,68 +216,107 @@ async function ensureInitialized() {
224
216
  }
225
217
  }
226
218
  /**
227
- * Wraps a function to set attributes on HTTP spans created within the wrapped block.
228
- *
229
- * This function sets attributes (userId, sessionId, tags, metadata) in the OpenTelemetry
230
- * context, which are automatically propagated to all spans created within the wrapped function.
231
- *
232
- * Instrumentation behavior:
233
- * - If `initializePingops` was called: All HTTP requests are instrumented by default.
234
- * `wrapHttp` only adds attributes to spans created within the wrapped block.
235
- * - If `initializePingops` was NOT called: Only HTTP requests within `wrapHttp` blocks
236
- * are instrumented. Requests outside `wrapHttp` are not instrumented.
219
+ * Returns the trace ID of the currently active span, if any.
220
+ */
221
+ function getActiveTraceId() {
222
+ return _opentelemetry_api.trace.getActiveSpan()?.spanContext().traceId;
223
+ }
224
+ /**
225
+ * Returns the span ID of the currently active span, if any.
226
+ */
227
+ function getActiveSpanId() {
228
+ return _opentelemetry_api.trace.getActiveSpan()?.spanContext().spanId;
229
+ }
230
+ /**
231
+ * Starts a new trace using the PingOps tracer provider and runs the callback within that trace.
232
+ * Sets attributes (traceId, userId, sessionId, tags, metadata, etc.) in context so they are
233
+ * propagated to spans created within the callback.
237
234
  *
238
- * @param options - Options including attributes to propagate to spans
239
- * @param fn - Function to execute within the attribute context
240
- * @returns The result of the function
235
+ * @param options - Options including optional attributes and optional seed for deterministic traceId
236
+ * @param fn - Function to execute within the trace and attribute context
237
+ * @returns Promise resolving to the result of the function
241
238
  *
242
239
  * @example
243
240
  * ```typescript
244
- * import { wrapHttp } from '@pingops/sdk';
241
+ * import { startTrace, initializePingops } from '@pingops/sdk';
245
242
  *
246
- * // Scenario 1: initializePingops was called
247
243
  * initializePingops({ ... });
248
244
  *
249
- * // All HTTP requests are instrumented, but this block adds attributes
250
- * const result = await wrapHttp({
245
+ * const result = await startTrace({
251
246
  * attributes: {
252
247
  * userId: 'user-123',
253
248
  * sessionId: 'session-456',
254
249
  * tags: ['production', 'api'],
255
250
  * metadata: { environment: 'prod', version: '1.0.0' }
256
- * }
251
+ * },
252
+ * seed: 'request-123' // optional: deterministic traceId from this seed
257
253
  * }, async () => {
258
- * // This HTTP request will be instrumented AND have the attributes set above
259
254
  * const response = await fetch('https://api.example.com/users/123');
260
255
  * return response.json();
261
256
  * });
262
- *
263
- * // HTTP requests outside wrapHttp are still instrumented, just without the attributes
264
- * const otherResponse = await fetch('https://api.example.com/other');
265
- *
266
- * // Scenario 2: initializePingops was NOT called
267
- * // Only requests within wrapHttp are instrumented
268
- * await wrapHttp({
269
- * attributes: { userId: 'user-123' }
270
- * }, async () => {
271
- * // This request IS instrumented
272
- * return fetch('https://api.example.com/data');
273
- * });
274
- *
275
- * // This request is NOT instrumented (outside wrapHttp)
276
- * await fetch('https://api.example.com/other');
277
257
  * ```
278
258
  */
279
- function wrapHttp(options, fn) {
280
- return (0, _pingops_core.wrapHttp)({
281
- ...options,
282
- checkInitialized: isSdkInitialized,
283
- isGlobalInstrumentationEnabled,
284
- ensureInitialized
285
- }, fn);
259
+ async function startTrace(options, fn) {
260
+ if (!isSdkInitialized()) await ensureInitialized();
261
+ const traceId = options.attributes?.traceId ?? await (0, _pingops_core.createTraceId)(options?.seed);
262
+ const spanContext = {
263
+ traceId,
264
+ spanId: (0, _pingops_core.uint8ArrayToHex)(crypto.getRandomValues(new Uint8Array(8))),
265
+ traceFlags: TRACE_FLAG_SAMPLED
266
+ };
267
+ const activeContext = _opentelemetry_api.context.active();
268
+ const contextWithSpanContext = _opentelemetry_api.trace.setSpanContext(activeContext, spanContext);
269
+ const tracer = (0, _pingops_otel.getPingopsTracerProvider)().getTracer("pingops-sdk", "1.0.0");
270
+ return new Promise((resolve$1, reject) => {
271
+ tracer.startActiveSpan("pingops-trace", {}, contextWithSpanContext, (span) => {
272
+ let contextWithAttributes = _opentelemetry_api.context.active();
273
+ const attrs = options.attributes;
274
+ if (attrs) contextWithAttributes = setAttributesInContext(contextWithAttributes, attrs);
275
+ contextWithAttributes = contextWithAttributes.setValue(_pingops_core.PINGOPS_TRACE_ID, traceId);
276
+ const run = () => fn();
277
+ try {
278
+ const result = _opentelemetry_api.context.with(contextWithAttributes, run);
279
+ if (result instanceof Promise) result.then((v) => {
280
+ span.end();
281
+ resolve$1(v);
282
+ }).catch((err) => {
283
+ span.end();
284
+ reject(err instanceof Error ? err : new Error(String(err)));
285
+ });
286
+ else {
287
+ span.end();
288
+ resolve$1(result);
289
+ }
290
+ } catch (err) {
291
+ span.end();
292
+ reject(err instanceof Error ? err : new Error(String(err)));
293
+ }
294
+ });
295
+ });
296
+ }
297
+ function setAttributesInContext(ctx, attrs) {
298
+ if (attrs.userId !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_USER_ID, attrs.userId);
299
+ if (attrs.sessionId !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_SESSION_ID, attrs.sessionId);
300
+ if (attrs.tags !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_TAGS, attrs.tags);
301
+ if (attrs.metadata !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_METADATA, attrs.metadata);
302
+ if (attrs.captureRequestBody !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_CAPTURE_REQUEST_BODY, attrs.captureRequestBody);
303
+ if (attrs.captureResponseBody !== void 0) ctx = ctx.setValue(_pingops_core.PINGOPS_CAPTURE_RESPONSE_BODY, attrs.captureResponseBody);
304
+ return ctx;
286
305
  }
287
306
 
288
307
  //#endregion
308
+ Object.defineProperty(exports, 'getActiveSpanId', {
309
+ enumerable: true,
310
+ get: function () {
311
+ return getActiveSpanId;
312
+ }
313
+ });
314
+ Object.defineProperty(exports, 'getActiveTraceId', {
315
+ enumerable: true,
316
+ get: function () {
317
+ return getActiveTraceId;
318
+ }
319
+ });
289
320
  Object.defineProperty(exports, 'initializePingops', {
290
321
  enumerable: true,
291
322
  get: function () {
@@ -310,10 +341,10 @@ Object.defineProperty(exports, 'shutdownPingops', {
310
341
  return shutdownPingops;
311
342
  }
312
343
  });
313
- Object.defineProperty(exports, 'wrapHttp', {
344
+ Object.defineProperty(exports, 'startTrace', {
314
345
  enumerable: true,
315
346
  get: function () {
316
- return wrapHttp;
347
+ return startTrace;
317
348
  }
318
349
  });
319
- //# sourceMappingURL=pingops-Cb6UV5D8.cjs.map
350
+ //# sourceMappingURL=pingops-BBXegVtL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pingops-BBXegVtL.cjs","names":["isSdkInitializedFlag","ATTR_SERVICE_NAME","PingopsSpanProcessor","NodeSDK","NodeTracerProvider","trace","context","PINGOPS_TRACE_ID","PINGOPS_USER_ID","PINGOPS_SESSION_ID","PINGOPS_TAGS","PINGOPS_METADATA","PINGOPS_CAPTURE_REQUEST_BODY","PINGOPS_CAPTURE_RESPONSE_BODY"],"sources":["../src/config-loader.ts","../src/init-state.ts","../src/pingops.ts"],"sourcesContent":["/**\n * Configuration loader for reading PingOps config from JSON/YAML files\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { load as loadYaml } from \"js-yaml\";\nimport type { PingopsProcessorConfig } from \"@pingops/otel\";\n\n/**\n * Loads configuration from a JSON or YAML file\n *\n * @param filePath - Path to the config file (JSON or YAML)\n * @returns Parsed configuration object\n * @throws Error if file cannot be read or parsed\n */\nexport function loadConfigFromFile(\n filePath: string\n): Partial<PingopsProcessorConfig> {\n const resolvedPath = resolve(filePath);\n const fileContent = readFileSync(resolvedPath, \"utf-8\");\n\n const ext = resolvedPath.toLowerCase();\n if (ext.endsWith(\".yaml\") || ext.endsWith(\".yml\")) {\n return (loadYaml(fileContent) as Partial<PingopsProcessorConfig>) || {};\n } else if (ext.endsWith(\".json\")) {\n return JSON.parse(fileContent) as Partial<PingopsProcessorConfig>;\n } else {\n // Try to parse as JSON first, then YAML\n try {\n return JSON.parse(fileContent) as Partial<PingopsProcessorConfig>;\n } catch {\n return (loadYaml(fileContent) as Partial<PingopsProcessorConfig>) || {};\n }\n }\n}\n\n/**\n * Merges configuration from file and environment variables.\n * Environment variables take precedence over file config.\n *\n * @param fileConfig - Configuration loaded from file\n * @returns Merged configuration with env vars taking precedence\n */\nexport function mergeConfigWithEnv(\n fileConfig: Partial<PingopsProcessorConfig>\n): Partial<PingopsProcessorConfig> {\n const envConfig: Partial<PingopsProcessorConfig> = {};\n\n // Read from environment variables\n if (process.env.PINGOPS_API_KEY) {\n envConfig.apiKey = process.env.PINGOPS_API_KEY;\n }\n if (process.env.PINGOPS_BASE_URL) {\n envConfig.baseUrl = process.env.PINGOPS_BASE_URL;\n }\n if (process.env.PINGOPS_SERVICE_NAME) {\n envConfig.serviceName = process.env.PINGOPS_SERVICE_NAME;\n }\n if (process.env.PINGOPS_DEBUG) {\n envConfig.debug = process.env.PINGOPS_DEBUG === \"true\";\n }\n if (process.env.PINGOPS_BATCH_SIZE) {\n envConfig.batchSize = parseInt(process.env.PINGOPS_BATCH_SIZE, 10);\n }\n if (process.env.PINGOPS_BATCH_TIMEOUT) {\n envConfig.batchTimeout = parseInt(process.env.PINGOPS_BATCH_TIMEOUT, 10);\n }\n if (process.env.PINGOPS_EXPORT_MODE) {\n envConfig.exportMode = process.env.PINGOPS_EXPORT_MODE as\n | \"batched\"\n | \"immediate\";\n }\n\n // Merge: env vars override file config\n return {\n ...fileConfig,\n ...envConfig,\n };\n}\n","/**\n * Shared state for tracking SDK initialization\n * This module exists to avoid circular dependencies between pingops.ts and instrumentation.ts\n */\n\nlet isSdkInitializedFlag = false;\n\n/**\n * Returns whether the SDK has been initialized.\n */\nexport function isSdkInitialized(): boolean {\n return isSdkInitializedFlag;\n}\n\n/**\n * Sets the SDK initialization flag.\n * Called by initializePingops when the SDK is initialized.\n */\nexport function setSdkInitialized(initialized: boolean): void {\n isSdkInitializedFlag = initialized;\n}\n","/**\n * PingOps SDK singleton for manual instrumentation\n *\n * Provides initializePingops, shutdownPingops, startTrace, getActiveTraceId,\n * and getActiveSpanId. startTrace can auto-initialize from environment variables if needed.\n */\n\nimport { context, trace } from \"@opentelemetry/api\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport type { PingopsProcessorConfig } from \"@pingops/otel\";\nimport {\n setPingopsTracerProvider,\n shutdownTracerProvider,\n PingopsSpanProcessor,\n} from \"@pingops/otel\";\nimport {\n createLogger,\n createTraceId,\n uint8ArrayToHex,\n type PingopsTraceAttributes,\n} from \"@pingops/core\";\nimport {\n PINGOPS_TRACE_ID,\n PINGOPS_USER_ID,\n PINGOPS_SESSION_ID,\n PINGOPS_TAGS,\n PINGOPS_METADATA,\n PINGOPS_CAPTURE_REQUEST_BODY,\n PINGOPS_CAPTURE_RESPONSE_BODY,\n} from \"@pingops/core\";\nimport { loadConfigFromFile, mergeConfigWithEnv } from \"./config-loader\";\nimport { setSdkInitialized } from \"./init-state\";\nimport { getPingopsTracerProvider } from \"@pingops/otel\";\nimport { getInstrumentations } from \"@pingops/otel\";\n\nconst TRACE_FLAG_SAMPLED = 1;\n\nconst initLogger = createLogger(\"[PingOps Initialize]\");\nconst logger = createLogger(\"[PingOps Pingops]\");\n\nlet sdkInstance: NodeSDK | null = null;\nlet isSdkInitializedFlag = false;\n\n/**\n * Global state to track initialization\n */\nlet isInitialized = false;\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * Initializes PingOps SDK\n *\n * This function:\n * 1. Creates an OpenTelemetry NodeSDK instance\n * 2. Configures Resource with service.name\n * 3. Registers PingopsSpanProcessor\n * 4. Enables HTTP/fetch/GenAI instrumentation\n * 5. Starts the SDK\n *\n * @param config - Configuration object, config file path, or config file wrapper\n * @param explicit - Whether this is an explicit call (default: true).\n * Set to false when called internally by startTrace auto-initialization.\n */\nexport function initializePingops(\n config: PingopsProcessorConfig,\n explicit?: boolean\n): void;\nexport function initializePingops(\n configFilePath: string,\n explicit?: boolean\n): void;\nexport function initializePingops(\n config: { configFile: string },\n explicit?: boolean\n): void;\nexport function initializePingops(\n config:\n | PingopsProcessorConfig\n | string\n | {\n configFile: string;\n },\n explicit: boolean = true\n): void {\n void explicit; // Ignored: SDK always uses global instrumentation\n const resolvedConfig: PingopsProcessorConfig =\n typeof config === \"string\"\n ? resolveConfigFromFile(config)\n : \"configFile\" in config\n ? resolveConfigFromFile(config.configFile)\n : config;\n\n if (isSdkInitializedFlag) {\n if (resolvedConfig.debug) {\n initLogger.warn(\"[PingOps] SDK already initialized, skipping\");\n }\n return;\n }\n\n // Create resource with service name\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: resolvedConfig.serviceName,\n });\n\n const processor = new PingopsSpanProcessor(resolvedConfig);\n const instrumentations = getInstrumentations();\n\n // Node.js SDK\n const nodeSdk = new NodeSDK({\n resource,\n spanProcessors: [processor],\n instrumentations,\n });\n\n nodeSdk.start();\n sdkInstance = nodeSdk;\n\n // Mark SDK as initialized\n isSdkInitializedFlag = true;\n\n setSdkInitialized(true);\n\n // Initialize isolated TracerProvider for manual spans AFTER NodeSDK starts\n // This ensures manual spans created via startSpan are processed by the same processor\n // We register it after NodeSDK so it takes precedence as the global provider\n try {\n // In version 2.2.0, span processors are passed in the constructor\n const isolatedProvider = new NodeTracerProvider({\n resource,\n spanProcessors: [processor],\n });\n\n // Register the provider globally\n isolatedProvider.register();\n\n // Set it in global state\n setPingopsTracerProvider(isolatedProvider);\n } catch (error) {\n if (resolvedConfig.debug) {\n initLogger.error(\n \"[PingOps] Failed to create isolated TracerProvider:\",\n error instanceof Error ? error.message : String(error)\n );\n }\n // Continue without isolated provider - manual spans will use global provider\n }\n\n if (resolvedConfig.debug) {\n initLogger.info(\"[PingOps] SDK initialized\");\n }\n}\n\nfunction resolveConfigFromFile(configFilePath: string): PingopsProcessorConfig {\n const fileConfig = loadConfigFromFile(configFilePath);\n const mergedConfig = mergeConfigWithEnv(fileConfig);\n\n if (!mergedConfig.baseUrl || !mergedConfig.serviceName) {\n const missing = [\n !mergedConfig.baseUrl && \"baseUrl (or PINGOPS_BASE_URL)\",\n !mergedConfig.serviceName && \"serviceName (or PINGOPS_SERVICE_NAME)\",\n ].filter(Boolean);\n\n throw new Error(\n `initializePingops(configFile) requires ${missing.join(\" and \")}. ` +\n `Provide them in the config file or via environment variables.`\n );\n }\n\n return mergedConfig as PingopsProcessorConfig;\n}\n\n/**\n * Shuts down the SDK and flushes remaining spans\n */\nexport async function shutdownPingops(): Promise<void> {\n // Shutdown isolated TracerProvider first\n await shutdownTracerProvider();\n\n if (!sdkInstance) {\n return;\n }\n\n await sdkInstance.shutdown();\n sdkInstance = null;\n isSdkInitializedFlag = false;\n setSdkInitialized(false);\n}\n\n/**\n * Checks if the SDK is already initialized by checking if a NodeTracerProvider is available\n */\nfunction isSdkInitialized(): boolean {\n try {\n const provider = getPingopsTracerProvider();\n // If we have a NodeTracerProvider (not the default NoOpTracerProvider), SDK is initialized\n const initialized = provider instanceof NodeTracerProvider;\n logger.debug(\"Checked SDK initialization status\", {\n initialized,\n providerType: provider.constructor.name,\n });\n return initialized;\n } catch (error) {\n logger.debug(\"Error checking SDK initialization status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return false;\n }\n}\n\n/**\n * Auto-initializes the SDK from environment variables if not already initialized\n */\nasync function ensureInitialized(): Promise<void> {\n // Check if SDK is already initialized (e.g., by calling initializePingops directly)\n if (isSdkInitialized()) {\n logger.debug(\"SDK already initialized, skipping auto-initialization\");\n isInitialized = true;\n return;\n }\n\n if (isInitialized) {\n logger.debug(\"SDK initialization flag already set, skipping\");\n return;\n }\n\n // If initialization is in progress, wait for it\n if (initializationPromise) {\n logger.debug(\"SDK initialization already in progress, waiting...\");\n return initializationPromise;\n }\n\n // Start initialization\n logger.info(\"Starting SDK auto-initialization from environment variables\");\n initializationPromise = Promise.resolve().then(() => {\n const apiKey = process.env.PINGOPS_API_KEY;\n const baseUrl = process.env.PINGOPS_BASE_URL;\n const serviceName = process.env.PINGOPS_SERVICE_NAME;\n const debug = process.env.PINGOPS_DEBUG === \"true\";\n\n logger.debug(\"Reading environment variables\", {\n hasApiKey: !!apiKey,\n hasBaseUrl: !!baseUrl,\n hasServiceName: !!serviceName,\n debug,\n });\n\n if (!apiKey || !baseUrl || !serviceName) {\n const missing = [\n !apiKey && \"PINGOPS_API_KEY\",\n !baseUrl && \"PINGOPS_BASE_URL\",\n !serviceName && \"PINGOPS_SERVICE_NAME\",\n ].filter(Boolean);\n\n logger.error(\n \"Missing required environment variables for auto-initialization\",\n {\n missing,\n }\n );\n\n throw new Error(\n `PingOps SDK auto-initialization requires PINGOPS_API_KEY, PINGOPS_BASE_URL, and PINGOPS_SERVICE_NAME environment variables. Missing: ${missing.join(\", \")}`\n );\n }\n\n const config: PingopsProcessorConfig = {\n apiKey,\n baseUrl,\n serviceName,\n debug,\n };\n\n logger.info(\"Initializing SDK with config\", {\n baseUrl,\n serviceName,\n debug,\n });\n\n // Call initializePingops with explicit=false since this is auto-initialization\n initializePingops(config, false);\n isInitialized = true;\n\n logger.info(\"SDK auto-initialization completed successfully\");\n });\n\n try {\n await initializationPromise;\n } catch (error) {\n logger.error(\"SDK auto-initialization failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n initializationPromise = null;\n }\n}\n\n/**\n * Returns the trace ID of the currently active span, if any.\n */\nexport function getActiveTraceId(): string | undefined {\n return trace.getActiveSpan()?.spanContext().traceId;\n}\n\n/**\n * Returns the span ID of the currently active span, if any.\n */\nexport function getActiveSpanId(): string | undefined {\n return trace.getActiveSpan()?.spanContext().spanId;\n}\n\n/**\n * Starts a new trace using the PingOps tracer provider and runs the callback within that trace.\n * Sets attributes (traceId, userId, sessionId, tags, metadata, etc.) in context so they are\n * propagated to spans created within the callback.\n *\n * @param options - Options including optional attributes and optional seed for deterministic traceId\n * @param fn - Function to execute within the trace and attribute context\n * @returns Promise resolving to the result of the function\n *\n * @example\n * ```typescript\n * import { startTrace, initializePingops } from '@pingops/sdk';\n *\n * initializePingops({ ... });\n *\n * const result = await startTrace({\n * attributes: {\n * userId: 'user-123',\n * sessionId: 'session-456',\n * tags: ['production', 'api'],\n * metadata: { environment: 'prod', version: '1.0.0' }\n * },\n * seed: 'request-123' // optional: deterministic traceId from this seed\n * }, async () => {\n * const response = await fetch('https://api.example.com/users/123');\n * return response.json();\n * });\n * ```\n */\nexport async function startTrace<T>(\n options: { attributes?: PingopsTraceAttributes; seed?: string },\n fn: () => T | Promise<T>\n): Promise<T> {\n if (!isSdkInitialized()) {\n await ensureInitialized();\n }\n\n const traceId =\n options.attributes?.traceId ?? (await createTraceId(options?.seed));\n const parentSpanId = uint8ArrayToHex(\n crypto.getRandomValues(new Uint8Array(8))\n );\n\n const spanContext = {\n traceId,\n spanId: parentSpanId,\n traceFlags: TRACE_FLAG_SAMPLED,\n };\n\n const activeContext = context.active();\n const contextWithSpanContext = trace.setSpanContext(\n activeContext,\n spanContext\n );\n\n const tracer = getPingopsTracerProvider().getTracer(\"pingops-sdk\", \"1.0.0\");\n\n return new Promise((resolve, reject) => {\n tracer.startActiveSpan(\n \"pingops-trace\",\n {},\n contextWithSpanContext,\n (span) => {\n let contextWithAttributes = context.active();\n const attrs = options.attributes;\n if (attrs) {\n contextWithAttributes = setAttributesInContext(\n contextWithAttributes,\n attrs\n );\n }\n contextWithAttributes = contextWithAttributes.setValue(\n PINGOPS_TRACE_ID,\n traceId\n );\n\n const run = () => fn();\n\n try {\n const result = context.with(contextWithAttributes, run);\n if (result instanceof Promise) {\n result\n .then((v) => {\n span.end();\n resolve(v);\n })\n .catch((err) => {\n span.end();\n reject(err instanceof Error ? err : new Error(String(err)));\n });\n } else {\n span.end();\n resolve(result);\n }\n } catch (err) {\n span.end();\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n }\n );\n });\n}\n\nfunction setAttributesInContext(\n ctx: ReturnType<typeof context.active>,\n attrs: PingopsTraceAttributes\n): ReturnType<typeof context.active> {\n if (attrs.userId !== undefined) {\n ctx = ctx.setValue(PINGOPS_USER_ID, attrs.userId);\n }\n if (attrs.sessionId !== undefined) {\n ctx = ctx.setValue(PINGOPS_SESSION_ID, attrs.sessionId);\n }\n if (attrs.tags !== undefined) {\n ctx = ctx.setValue(PINGOPS_TAGS, attrs.tags);\n }\n if (attrs.metadata !== undefined) {\n ctx = ctx.setValue(PINGOPS_METADATA, attrs.metadata);\n }\n if (attrs.captureRequestBody !== undefined) {\n ctx = ctx.setValue(PINGOPS_CAPTURE_REQUEST_BODY, attrs.captureRequestBody);\n }\n if (attrs.captureResponseBody !== undefined) {\n ctx = ctx.setValue(\n PINGOPS_CAPTURE_RESPONSE_BODY,\n attrs.captureResponseBody\n );\n }\n return ctx;\n}\n"],"mappings":"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"}
@@ -1,9 +1,10 @@
1
+ import { context, trace } from "@opentelemetry/api";
1
2
  import { NodeSDK } from "@opentelemetry/sdk-node";
2
3
  import { resourceFromAttributes } from "@opentelemetry/resources";
3
4
  import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
4
5
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
5
6
  import { PingopsSpanProcessor, getInstrumentations, getPingopsTracerProvider, setPingopsTracerProvider, shutdownTracerProvider } from "@pingops/otel";
6
- import { createLogger, wrapHttp } from "@pingops/core";
7
+ import { PINGOPS_CAPTURE_REQUEST_BODY, PINGOPS_CAPTURE_RESPONSE_BODY, PINGOPS_METADATA, PINGOPS_SESSION_ID, PINGOPS_TAGS, PINGOPS_TRACE_ID, PINGOPS_USER_ID, createLogger, createTraceId, uint8ArrayToHex } from "@pingops/core";
7
8
  import { readFileSync } from "node:fs";
8
9
  import { resolve } from "node:path";
9
10
  import { load } from "js-yaml";
@@ -67,25 +68,16 @@ let isSdkInitializedFlag$1 = false;
67
68
  function setSdkInitialized(initialized) {
68
69
  isSdkInitializedFlag$1 = initialized;
69
70
  }
70
- /**
71
- * Checks if global instrumentation is enabled.
72
- * This is used to determine instrumentation behavior:
73
- * - If true: all HTTP requests are instrumented
74
- * - If false: only requests within wrapHttp blocks are instrumented
75
- */
76
- function isGlobalInstrumentationEnabled() {
77
- return isSdkInitializedFlag$1;
78
- }
79
71
 
80
72
  //#endregion
81
73
  //#region src/pingops.ts
82
74
  /**
83
75
  * PingOps SDK singleton for manual instrumentation
84
76
  *
85
- * Provides initializePingops and shutdownPingops functions.
86
- * wrapHttp is available from @pingops/core and will auto-initialize
87
- * from environment variables if needed.
77
+ * Provides initializePingops, shutdownPingops, startTrace, getActiveTraceId,
78
+ * and getActiveSpanId. startTrace can auto-initialize from environment variables if needed.
88
79
  */
80
+ const TRACE_FLAG_SAMPLED = 1;
89
81
  const initLogger = createLogger("[PingOps Initialize]");
90
82
  const logger = createLogger("[PingOps Pingops]");
91
83
  let sdkInstance = null;
@@ -103,7 +95,7 @@ function initializePingops(config, explicit = true) {
103
95
  }
104
96
  const resource = resourceFromAttributes({ [ATTR_SERVICE_NAME]: resolvedConfig.serviceName });
105
97
  const processor = new PingopsSpanProcessor(resolvedConfig);
106
- const instrumentations = getInstrumentations(isGlobalInstrumentationEnabled);
98
+ const instrumentations = getInstrumentations();
107
99
  const nodeSdk = new NodeSDK({
108
100
  resource,
109
101
  spanProcessors: [processor],
@@ -112,7 +104,7 @@ function initializePingops(config, explicit = true) {
112
104
  nodeSdk.start();
113
105
  sdkInstance = nodeSdk;
114
106
  isSdkInitializedFlag = true;
115
- setSdkInitialized(explicit);
107
+ setSdkInitialized(true);
116
108
  try {
117
109
  const isolatedProvider = new NodeTracerProvider({
118
110
  resource,
@@ -224,67 +216,94 @@ async function ensureInitialized() {
224
216
  }
225
217
  }
226
218
  /**
227
- * Wraps a function to set attributes on HTTP spans created within the wrapped block.
228
- *
229
- * This function sets attributes (userId, sessionId, tags, metadata) in the OpenTelemetry
230
- * context, which are automatically propagated to all spans created within the wrapped function.
231
- *
232
- * Instrumentation behavior:
233
- * - If `initializePingops` was called: All HTTP requests are instrumented by default.
234
- * `wrapHttp` only adds attributes to spans created within the wrapped block.
235
- * - If `initializePingops` was NOT called: Only HTTP requests within `wrapHttp` blocks
236
- * are instrumented. Requests outside `wrapHttp` are not instrumented.
219
+ * Returns the trace ID of the currently active span, if any.
220
+ */
221
+ function getActiveTraceId() {
222
+ return trace.getActiveSpan()?.spanContext().traceId;
223
+ }
224
+ /**
225
+ * Returns the span ID of the currently active span, if any.
226
+ */
227
+ function getActiveSpanId() {
228
+ return trace.getActiveSpan()?.spanContext().spanId;
229
+ }
230
+ /**
231
+ * Starts a new trace using the PingOps tracer provider and runs the callback within that trace.
232
+ * Sets attributes (traceId, userId, sessionId, tags, metadata, etc.) in context so they are
233
+ * propagated to spans created within the callback.
237
234
  *
238
- * @param options - Options including attributes to propagate to spans
239
- * @param fn - Function to execute within the attribute context
240
- * @returns The result of the function
235
+ * @param options - Options including optional attributes and optional seed for deterministic traceId
236
+ * @param fn - Function to execute within the trace and attribute context
237
+ * @returns Promise resolving to the result of the function
241
238
  *
242
239
  * @example
243
240
  * ```typescript
244
- * import { wrapHttp } from '@pingops/sdk';
241
+ * import { startTrace, initializePingops } from '@pingops/sdk';
245
242
  *
246
- * // Scenario 1: initializePingops was called
247
243
  * initializePingops({ ... });
248
244
  *
249
- * // All HTTP requests are instrumented, but this block adds attributes
250
- * const result = await wrapHttp({
245
+ * const result = await startTrace({
251
246
  * attributes: {
252
247
  * userId: 'user-123',
253
248
  * sessionId: 'session-456',
254
249
  * tags: ['production', 'api'],
255
250
  * metadata: { environment: 'prod', version: '1.0.0' }
256
- * }
251
+ * },
252
+ * seed: 'request-123' // optional: deterministic traceId from this seed
257
253
  * }, async () => {
258
- * // This HTTP request will be instrumented AND have the attributes set above
259
254
  * const response = await fetch('https://api.example.com/users/123');
260
255
  * return response.json();
261
256
  * });
262
- *
263
- * // HTTP requests outside wrapHttp are still instrumented, just without the attributes
264
- * const otherResponse = await fetch('https://api.example.com/other');
265
- *
266
- * // Scenario 2: initializePingops was NOT called
267
- * // Only requests within wrapHttp are instrumented
268
- * await wrapHttp({
269
- * attributes: { userId: 'user-123' }
270
- * }, async () => {
271
- * // This request IS instrumented
272
- * return fetch('https://api.example.com/data');
273
- * });
274
- *
275
- * // This request is NOT instrumented (outside wrapHttp)
276
- * await fetch('https://api.example.com/other');
277
257
  * ```
278
258
  */
279
- function wrapHttp$1(options, fn) {
280
- return wrapHttp({
281
- ...options,
282
- checkInitialized: isSdkInitialized,
283
- isGlobalInstrumentationEnabled,
284
- ensureInitialized
285
- }, fn);
259
+ async function startTrace(options, fn) {
260
+ if (!isSdkInitialized()) await ensureInitialized();
261
+ const traceId = options.attributes?.traceId ?? await createTraceId(options?.seed);
262
+ const spanContext = {
263
+ traceId,
264
+ spanId: uint8ArrayToHex(crypto.getRandomValues(new Uint8Array(8))),
265
+ traceFlags: TRACE_FLAG_SAMPLED
266
+ };
267
+ const activeContext = context.active();
268
+ const contextWithSpanContext = trace.setSpanContext(activeContext, spanContext);
269
+ const tracer = getPingopsTracerProvider().getTracer("pingops-sdk", "1.0.0");
270
+ return new Promise((resolve$1, reject) => {
271
+ tracer.startActiveSpan("pingops-trace", {}, contextWithSpanContext, (span) => {
272
+ let contextWithAttributes = context.active();
273
+ const attrs = options.attributes;
274
+ if (attrs) contextWithAttributes = setAttributesInContext(contextWithAttributes, attrs);
275
+ contextWithAttributes = contextWithAttributes.setValue(PINGOPS_TRACE_ID, traceId);
276
+ const run = () => fn();
277
+ try {
278
+ const result = context.with(contextWithAttributes, run);
279
+ if (result instanceof Promise) result.then((v) => {
280
+ span.end();
281
+ resolve$1(v);
282
+ }).catch((err) => {
283
+ span.end();
284
+ reject(err instanceof Error ? err : new Error(String(err)));
285
+ });
286
+ else {
287
+ span.end();
288
+ resolve$1(result);
289
+ }
290
+ } catch (err) {
291
+ span.end();
292
+ reject(err instanceof Error ? err : new Error(String(err)));
293
+ }
294
+ });
295
+ });
296
+ }
297
+ function setAttributesInContext(ctx, attrs) {
298
+ if (attrs.userId !== void 0) ctx = ctx.setValue(PINGOPS_USER_ID, attrs.userId);
299
+ if (attrs.sessionId !== void 0) ctx = ctx.setValue(PINGOPS_SESSION_ID, attrs.sessionId);
300
+ if (attrs.tags !== void 0) ctx = ctx.setValue(PINGOPS_TAGS, attrs.tags);
301
+ if (attrs.metadata !== void 0) ctx = ctx.setValue(PINGOPS_METADATA, attrs.metadata);
302
+ if (attrs.captureRequestBody !== void 0) ctx = ctx.setValue(PINGOPS_CAPTURE_REQUEST_BODY, attrs.captureRequestBody);
303
+ if (attrs.captureResponseBody !== void 0) ctx = ctx.setValue(PINGOPS_CAPTURE_RESPONSE_BODY, attrs.captureResponseBody);
304
+ return ctx;
286
305
  }
287
306
 
288
307
  //#endregion
289
- export { mergeConfigWithEnv as a, loadConfigFromFile as i, shutdownPingops as n, wrapHttp$1 as r, initializePingops as t };
290
- //# sourceMappingURL=pingops-DlQdUQEU.mjs.map
308
+ export { startTrace as a, shutdownPingops as i, getActiveTraceId as n, loadConfigFromFile as o, initializePingops as r, mergeConfigWithEnv as s, getActiveSpanId as t };
309
+ //# sourceMappingURL=pingops-D4xrGLxy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pingops-D4xrGLxy.mjs","names":["loadYaml","isSdkInitializedFlag"],"sources":["../src/config-loader.ts","../src/init-state.ts","../src/pingops.ts"],"sourcesContent":["/**\n * Configuration loader for reading PingOps config from JSON/YAML files\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { load as loadYaml } from \"js-yaml\";\nimport type { PingopsProcessorConfig } from \"@pingops/otel\";\n\n/**\n * Loads configuration from a JSON or YAML file\n *\n * @param filePath - Path to the config file (JSON or YAML)\n * @returns Parsed configuration object\n * @throws Error if file cannot be read or parsed\n */\nexport function loadConfigFromFile(\n filePath: string\n): Partial<PingopsProcessorConfig> {\n const resolvedPath = resolve(filePath);\n const fileContent = readFileSync(resolvedPath, \"utf-8\");\n\n const ext = resolvedPath.toLowerCase();\n if (ext.endsWith(\".yaml\") || ext.endsWith(\".yml\")) {\n return (loadYaml(fileContent) as Partial<PingopsProcessorConfig>) || {};\n } else if (ext.endsWith(\".json\")) {\n return JSON.parse(fileContent) as Partial<PingopsProcessorConfig>;\n } else {\n // Try to parse as JSON first, then YAML\n try {\n return JSON.parse(fileContent) as Partial<PingopsProcessorConfig>;\n } catch {\n return (loadYaml(fileContent) as Partial<PingopsProcessorConfig>) || {};\n }\n }\n}\n\n/**\n * Merges configuration from file and environment variables.\n * Environment variables take precedence over file config.\n *\n * @param fileConfig - Configuration loaded from file\n * @returns Merged configuration with env vars taking precedence\n */\nexport function mergeConfigWithEnv(\n fileConfig: Partial<PingopsProcessorConfig>\n): Partial<PingopsProcessorConfig> {\n const envConfig: Partial<PingopsProcessorConfig> = {};\n\n // Read from environment variables\n if (process.env.PINGOPS_API_KEY) {\n envConfig.apiKey = process.env.PINGOPS_API_KEY;\n }\n if (process.env.PINGOPS_BASE_URL) {\n envConfig.baseUrl = process.env.PINGOPS_BASE_URL;\n }\n if (process.env.PINGOPS_SERVICE_NAME) {\n envConfig.serviceName = process.env.PINGOPS_SERVICE_NAME;\n }\n if (process.env.PINGOPS_DEBUG) {\n envConfig.debug = process.env.PINGOPS_DEBUG === \"true\";\n }\n if (process.env.PINGOPS_BATCH_SIZE) {\n envConfig.batchSize = parseInt(process.env.PINGOPS_BATCH_SIZE, 10);\n }\n if (process.env.PINGOPS_BATCH_TIMEOUT) {\n envConfig.batchTimeout = parseInt(process.env.PINGOPS_BATCH_TIMEOUT, 10);\n }\n if (process.env.PINGOPS_EXPORT_MODE) {\n envConfig.exportMode = process.env.PINGOPS_EXPORT_MODE as\n | \"batched\"\n | \"immediate\";\n }\n\n // Merge: env vars override file config\n return {\n ...fileConfig,\n ...envConfig,\n };\n}\n","/**\n * Shared state for tracking SDK initialization\n * This module exists to avoid circular dependencies between pingops.ts and instrumentation.ts\n */\n\nlet isSdkInitializedFlag = false;\n\n/**\n * Returns whether the SDK has been initialized.\n */\nexport function isSdkInitialized(): boolean {\n return isSdkInitializedFlag;\n}\n\n/**\n * Sets the SDK initialization flag.\n * Called by initializePingops when the SDK is initialized.\n */\nexport function setSdkInitialized(initialized: boolean): void {\n isSdkInitializedFlag = initialized;\n}\n","/**\n * PingOps SDK singleton for manual instrumentation\n *\n * Provides initializePingops, shutdownPingops, startTrace, getActiveTraceId,\n * and getActiveSpanId. startTrace can auto-initialize from environment variables if needed.\n */\n\nimport { context, trace } from \"@opentelemetry/api\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport type { PingopsProcessorConfig } from \"@pingops/otel\";\nimport {\n setPingopsTracerProvider,\n shutdownTracerProvider,\n PingopsSpanProcessor,\n} from \"@pingops/otel\";\nimport {\n createLogger,\n createTraceId,\n uint8ArrayToHex,\n type PingopsTraceAttributes,\n} from \"@pingops/core\";\nimport {\n PINGOPS_TRACE_ID,\n PINGOPS_USER_ID,\n PINGOPS_SESSION_ID,\n PINGOPS_TAGS,\n PINGOPS_METADATA,\n PINGOPS_CAPTURE_REQUEST_BODY,\n PINGOPS_CAPTURE_RESPONSE_BODY,\n} from \"@pingops/core\";\nimport { loadConfigFromFile, mergeConfigWithEnv } from \"./config-loader\";\nimport { setSdkInitialized } from \"./init-state\";\nimport { getPingopsTracerProvider } from \"@pingops/otel\";\nimport { getInstrumentations } from \"@pingops/otel\";\n\nconst TRACE_FLAG_SAMPLED = 1;\n\nconst initLogger = createLogger(\"[PingOps Initialize]\");\nconst logger = createLogger(\"[PingOps Pingops]\");\n\nlet sdkInstance: NodeSDK | null = null;\nlet isSdkInitializedFlag = false;\n\n/**\n * Global state to track initialization\n */\nlet isInitialized = false;\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * Initializes PingOps SDK\n *\n * This function:\n * 1. Creates an OpenTelemetry NodeSDK instance\n * 2. Configures Resource with service.name\n * 3. Registers PingopsSpanProcessor\n * 4. Enables HTTP/fetch/GenAI instrumentation\n * 5. Starts the SDK\n *\n * @param config - Configuration object, config file path, or config file wrapper\n * @param explicit - Whether this is an explicit call (default: true).\n * Set to false when called internally by startTrace auto-initialization.\n */\nexport function initializePingops(\n config: PingopsProcessorConfig,\n explicit?: boolean\n): void;\nexport function initializePingops(\n configFilePath: string,\n explicit?: boolean\n): void;\nexport function initializePingops(\n config: { configFile: string },\n explicit?: boolean\n): void;\nexport function initializePingops(\n config:\n | PingopsProcessorConfig\n | string\n | {\n configFile: string;\n },\n explicit: boolean = true\n): void {\n void explicit; // Ignored: SDK always uses global instrumentation\n const resolvedConfig: PingopsProcessorConfig =\n typeof config === \"string\"\n ? resolveConfigFromFile(config)\n : \"configFile\" in config\n ? resolveConfigFromFile(config.configFile)\n : config;\n\n if (isSdkInitializedFlag) {\n if (resolvedConfig.debug) {\n initLogger.warn(\"[PingOps] SDK already initialized, skipping\");\n }\n return;\n }\n\n // Create resource with service name\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: resolvedConfig.serviceName,\n });\n\n const processor = new PingopsSpanProcessor(resolvedConfig);\n const instrumentations = getInstrumentations();\n\n // Node.js SDK\n const nodeSdk = new NodeSDK({\n resource,\n spanProcessors: [processor],\n instrumentations,\n });\n\n nodeSdk.start();\n sdkInstance = nodeSdk;\n\n // Mark SDK as initialized\n isSdkInitializedFlag = true;\n\n setSdkInitialized(true);\n\n // Initialize isolated TracerProvider for manual spans AFTER NodeSDK starts\n // This ensures manual spans created via startSpan are processed by the same processor\n // We register it after NodeSDK so it takes precedence as the global provider\n try {\n // In version 2.2.0, span processors are passed in the constructor\n const isolatedProvider = new NodeTracerProvider({\n resource,\n spanProcessors: [processor],\n });\n\n // Register the provider globally\n isolatedProvider.register();\n\n // Set it in global state\n setPingopsTracerProvider(isolatedProvider);\n } catch (error) {\n if (resolvedConfig.debug) {\n initLogger.error(\n \"[PingOps] Failed to create isolated TracerProvider:\",\n error instanceof Error ? error.message : String(error)\n );\n }\n // Continue without isolated provider - manual spans will use global provider\n }\n\n if (resolvedConfig.debug) {\n initLogger.info(\"[PingOps] SDK initialized\");\n }\n}\n\nfunction resolveConfigFromFile(configFilePath: string): PingopsProcessorConfig {\n const fileConfig = loadConfigFromFile(configFilePath);\n const mergedConfig = mergeConfigWithEnv(fileConfig);\n\n if (!mergedConfig.baseUrl || !mergedConfig.serviceName) {\n const missing = [\n !mergedConfig.baseUrl && \"baseUrl (or PINGOPS_BASE_URL)\",\n !mergedConfig.serviceName && \"serviceName (or PINGOPS_SERVICE_NAME)\",\n ].filter(Boolean);\n\n throw new Error(\n `initializePingops(configFile) requires ${missing.join(\" and \")}. ` +\n `Provide them in the config file or via environment variables.`\n );\n }\n\n return mergedConfig as PingopsProcessorConfig;\n}\n\n/**\n * Shuts down the SDK and flushes remaining spans\n */\nexport async function shutdownPingops(): Promise<void> {\n // Shutdown isolated TracerProvider first\n await shutdownTracerProvider();\n\n if (!sdkInstance) {\n return;\n }\n\n await sdkInstance.shutdown();\n sdkInstance = null;\n isSdkInitializedFlag = false;\n setSdkInitialized(false);\n}\n\n/**\n * Checks if the SDK is already initialized by checking if a NodeTracerProvider is available\n */\nfunction isSdkInitialized(): boolean {\n try {\n const provider = getPingopsTracerProvider();\n // If we have a NodeTracerProvider (not the default NoOpTracerProvider), SDK is initialized\n const initialized = provider instanceof NodeTracerProvider;\n logger.debug(\"Checked SDK initialization status\", {\n initialized,\n providerType: provider.constructor.name,\n });\n return initialized;\n } catch (error) {\n logger.debug(\"Error checking SDK initialization status\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return false;\n }\n}\n\n/**\n * Auto-initializes the SDK from environment variables if not already initialized\n */\nasync function ensureInitialized(): Promise<void> {\n // Check if SDK is already initialized (e.g., by calling initializePingops directly)\n if (isSdkInitialized()) {\n logger.debug(\"SDK already initialized, skipping auto-initialization\");\n isInitialized = true;\n return;\n }\n\n if (isInitialized) {\n logger.debug(\"SDK initialization flag already set, skipping\");\n return;\n }\n\n // If initialization is in progress, wait for it\n if (initializationPromise) {\n logger.debug(\"SDK initialization already in progress, waiting...\");\n return initializationPromise;\n }\n\n // Start initialization\n logger.info(\"Starting SDK auto-initialization from environment variables\");\n initializationPromise = Promise.resolve().then(() => {\n const apiKey = process.env.PINGOPS_API_KEY;\n const baseUrl = process.env.PINGOPS_BASE_URL;\n const serviceName = process.env.PINGOPS_SERVICE_NAME;\n const debug = process.env.PINGOPS_DEBUG === \"true\";\n\n logger.debug(\"Reading environment variables\", {\n hasApiKey: !!apiKey,\n hasBaseUrl: !!baseUrl,\n hasServiceName: !!serviceName,\n debug,\n });\n\n if (!apiKey || !baseUrl || !serviceName) {\n const missing = [\n !apiKey && \"PINGOPS_API_KEY\",\n !baseUrl && \"PINGOPS_BASE_URL\",\n !serviceName && \"PINGOPS_SERVICE_NAME\",\n ].filter(Boolean);\n\n logger.error(\n \"Missing required environment variables for auto-initialization\",\n {\n missing,\n }\n );\n\n throw new Error(\n `PingOps SDK auto-initialization requires PINGOPS_API_KEY, PINGOPS_BASE_URL, and PINGOPS_SERVICE_NAME environment variables. Missing: ${missing.join(\", \")}`\n );\n }\n\n const config: PingopsProcessorConfig = {\n apiKey,\n baseUrl,\n serviceName,\n debug,\n };\n\n logger.info(\"Initializing SDK with config\", {\n baseUrl,\n serviceName,\n debug,\n });\n\n // Call initializePingops with explicit=false since this is auto-initialization\n initializePingops(config, false);\n isInitialized = true;\n\n logger.info(\"SDK auto-initialization completed successfully\");\n });\n\n try {\n await initializationPromise;\n } catch (error) {\n logger.error(\"SDK auto-initialization failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n } finally {\n initializationPromise = null;\n }\n}\n\n/**\n * Returns the trace ID of the currently active span, if any.\n */\nexport function getActiveTraceId(): string | undefined {\n return trace.getActiveSpan()?.spanContext().traceId;\n}\n\n/**\n * Returns the span ID of the currently active span, if any.\n */\nexport function getActiveSpanId(): string | undefined {\n return trace.getActiveSpan()?.spanContext().spanId;\n}\n\n/**\n * Starts a new trace using the PingOps tracer provider and runs the callback within that trace.\n * Sets attributes (traceId, userId, sessionId, tags, metadata, etc.) in context so they are\n * propagated to spans created within the callback.\n *\n * @param options - Options including optional attributes and optional seed for deterministic traceId\n * @param fn - Function to execute within the trace and attribute context\n * @returns Promise resolving to the result of the function\n *\n * @example\n * ```typescript\n * import { startTrace, initializePingops } from '@pingops/sdk';\n *\n * initializePingops({ ... });\n *\n * const result = await startTrace({\n * attributes: {\n * userId: 'user-123',\n * sessionId: 'session-456',\n * tags: ['production', 'api'],\n * metadata: { environment: 'prod', version: '1.0.0' }\n * },\n * seed: 'request-123' // optional: deterministic traceId from this seed\n * }, async () => {\n * const response = await fetch('https://api.example.com/users/123');\n * return response.json();\n * });\n * ```\n */\nexport async function startTrace<T>(\n options: { attributes?: PingopsTraceAttributes; seed?: string },\n fn: () => T | Promise<T>\n): Promise<T> {\n if (!isSdkInitialized()) {\n await ensureInitialized();\n }\n\n const traceId =\n options.attributes?.traceId ?? (await createTraceId(options?.seed));\n const parentSpanId = uint8ArrayToHex(\n crypto.getRandomValues(new Uint8Array(8))\n );\n\n const spanContext = {\n traceId,\n spanId: parentSpanId,\n traceFlags: TRACE_FLAG_SAMPLED,\n };\n\n const activeContext = context.active();\n const contextWithSpanContext = trace.setSpanContext(\n activeContext,\n spanContext\n );\n\n const tracer = getPingopsTracerProvider().getTracer(\"pingops-sdk\", \"1.0.0\");\n\n return new Promise((resolve, reject) => {\n tracer.startActiveSpan(\n \"pingops-trace\",\n {},\n contextWithSpanContext,\n (span) => {\n let contextWithAttributes = context.active();\n const attrs = options.attributes;\n if (attrs) {\n contextWithAttributes = setAttributesInContext(\n contextWithAttributes,\n attrs\n );\n }\n contextWithAttributes = contextWithAttributes.setValue(\n PINGOPS_TRACE_ID,\n traceId\n );\n\n const run = () => fn();\n\n try {\n const result = context.with(contextWithAttributes, run);\n if (result instanceof Promise) {\n result\n .then((v) => {\n span.end();\n resolve(v);\n })\n .catch((err) => {\n span.end();\n reject(err instanceof Error ? err : new Error(String(err)));\n });\n } else {\n span.end();\n resolve(result);\n }\n } catch (err) {\n span.end();\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n }\n );\n });\n}\n\nfunction setAttributesInContext(\n ctx: ReturnType<typeof context.active>,\n attrs: PingopsTraceAttributes\n): ReturnType<typeof context.active> {\n if (attrs.userId !== undefined) {\n ctx = ctx.setValue(PINGOPS_USER_ID, attrs.userId);\n }\n if (attrs.sessionId !== undefined) {\n ctx = ctx.setValue(PINGOPS_SESSION_ID, attrs.sessionId);\n }\n if (attrs.tags !== undefined) {\n ctx = ctx.setValue(PINGOPS_TAGS, attrs.tags);\n }\n if (attrs.metadata !== undefined) {\n ctx = ctx.setValue(PINGOPS_METADATA, attrs.metadata);\n }\n if (attrs.captureRequestBody !== undefined) {\n ctx = ctx.setValue(PINGOPS_CAPTURE_REQUEST_BODY, attrs.captureRequestBody);\n }\n if (attrs.captureResponseBody !== undefined) {\n ctx = ctx.setValue(\n PINGOPS_CAPTURE_RESPONSE_BODY,\n attrs.captureResponseBody\n );\n }\n return ctx;\n}\n"],"mappings":"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"}