@respan/tracing 1.0.45 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
- # KeywordsAI Tracing SDK
1
+ # Respan Tracing SDK
2
2
 
3
- A lightweight OpenTelemetry-based tracing SDK for KeywordsAI, built with minimal dependencies and optional instrumentation support.
3
+ **[respan.ai](https://respan.ai)** | **[Documentation](https://docs.respan.ai)**
4
+
5
+ A lightweight OpenTelemetry-based tracing SDK for Respan, built with minimal dependencies and optional instrumentation support.
4
6
  Inspired by [Openllmetry](https://github.com/traceloop/openllmetry-js)
5
7
 
6
8
  ## Features
@@ -14,13 +16,13 @@ Inspired by [Openllmetry](https://github.com/traceloop/openllmetry-js)
14
16
  - **Span Management**: Full control over spans with `getClient()` API
15
17
  - **Multi-Processor Routing**: Route spans to multiple destinations
16
18
  - **Span Buffering**: Manual control over span export timing
17
- - **KeywordsAI Parameters**: Add customer identifiers and trace group identifiers
19
+ - **Respan Parameters**: Add customer identifiers and trace group identifiers
18
20
 
19
21
  ## Installation
20
22
 
21
23
  ### Core Package
22
24
  ```bash
23
- npm install @keywordsai/tracing
25
+ npm install @respan/tracing
24
26
  ```
25
27
 
26
28
  ### Optional Instrumentations
@@ -63,24 +65,24 @@ npm install @traceloop/instrumentation-vertexai
63
65
  ### Method 1: Dynamic Instrumentation (Recommended for Node.js)
64
66
 
65
67
  ```typescript
66
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
68
+ import { RespanTelemetry } from '@respan/tracing';
67
69
  import OpenAI from 'openai';
68
70
 
69
71
  // Initialize the SDK
70
- const keywordsAi = new KeywordsAITelemetry({
71
- apiKey: process.env.KEYWORDSAI_API_KEY,
72
- baseURL: process.env.KEYWORDSAI_BASE_URL,
72
+ const respan = new RespanTelemetry({
73
+ apiKey: process.env.RESPAN_API_KEY,
74
+ baseURL: process.env.RESPAN_BASE_URL,
73
75
  appName: 'my-app'
74
76
  });
75
77
 
76
78
  // Enable instrumentations you need
77
- await keywordsAi.enableInstrumentation('openai');
79
+ await respan.enableInstrumentation('openai');
78
80
 
79
81
  const openai = new OpenAI();
80
82
 
81
83
  // Use decorators to trace your functions
82
84
  const generateJoke = async () => {
83
- return await keywordsAi.withTask(
85
+ return await respan.withTask(
84
86
  { name: 'joke_generation' },
85
87
  async () => {
86
88
  const completion = await openai.chat.completions.create({
@@ -96,14 +98,14 @@ const generateJoke = async () => {
96
98
  ### Method 2: Manual Instrumentation (Recommended for Next.js)
97
99
 
98
100
  ```typescript
99
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
101
+ import { RespanTelemetry } from '@respan/tracing';
100
102
  import OpenAI from 'openai';
101
103
  import Anthropic from '@anthropic-ai/sdk';
102
104
 
103
105
  // Manual instrumentation - pass the actual imported modules
104
- const keywordsAi = new KeywordsAITelemetry({
105
- apiKey: process.env.KEYWORDSAI_API_KEY,
106
- baseURL: process.env.KEYWORDSAI_BASE_URL,
106
+ const respan = new RespanTelemetry({
107
+ apiKey: process.env.RESPAN_API_KEY,
108
+ baseURL: process.env.RESPAN_BASE_URL,
107
109
  appName: 'my-app',
108
110
  // Specify modules to instrument manually
109
111
  instrumentModules: {
@@ -114,7 +116,7 @@ const keywordsAi = new KeywordsAITelemetry({
114
116
  });
115
117
 
116
118
  // Wait for initialization (optional but recommended)
117
- await keywordsAi.initialize();
119
+ await respan.initialize();
118
120
 
119
121
  // Create clients - they will be automatically instrumented
120
122
  const openai = new OpenAI();
@@ -122,7 +124,7 @@ const anthropic = new Anthropic();
122
124
 
123
125
  // Use decorators to trace your functions
124
126
  const generateContent = async () => {
125
- return await keywordsAi.withWorkflow(
127
+ return await respan.withWorkflow(
126
128
  { name: 'content_generation', version: 1 },
127
129
  async () => {
128
130
  const result = await openai.chat.completions.create({
@@ -149,15 +151,15 @@ const generateContent = async () => {
149
151
 
150
152
  ## API Reference
151
153
 
152
- ### KeywordsAITelemetry
154
+ ### RespanTelemetry
153
155
 
154
156
  #### Constructor Options
155
157
 
156
158
  ```typescript
157
- interface KeywordsAIOptions {
159
+ interface RespanOptions {
158
160
  appName?: string; // App name for traces
159
- apiKey?: string; // KeywordsAI API key
160
- baseURL?: string; // KeywordsAI base URL
161
+ apiKey?: string; // Respan API key
162
+ baseURL?: string; // Respan base URL
161
163
  disableBatch?: boolean; // Disable batching for development
162
164
  logLevel?: "debug" | "info" | "warn" | "error";
163
165
  traceContent?: boolean; // Log prompts and completions
@@ -209,7 +211,7 @@ interface KeywordsAIOptions {
209
211
  #### withWorkflow
210
212
  Trace high-level workflows:
211
213
  ```typescript
212
- await keywordsAi.withWorkflow(
214
+ await respan.withWorkflow(
213
215
  { name: 'my_workflow', version: 1 },
214
216
  async () => {
215
217
  // Your workflow logic
@@ -220,7 +222,7 @@ await keywordsAi.withWorkflow(
220
222
  #### withTask
221
223
  Trace individual tasks:
222
224
  ```typescript
223
- await keywordsAi.withTask(
225
+ await respan.withTask(
224
226
  { name: 'my_task' },
225
227
  async () => {
226
228
  // Your task logic
@@ -231,7 +233,7 @@ await keywordsAi.withTask(
231
233
  #### withAgent
232
234
  Trace agent operations:
233
235
  ```typescript
234
- await keywordsAi.withAgent(
236
+ await respan.withAgent(
235
237
  { name: 'my_agent', associationProperties: { type: 'assistant' } },
236
238
  async () => {
237
239
  // Your agent logic
@@ -242,7 +244,7 @@ await keywordsAi.withAgent(
242
244
  #### withTool
243
245
  Trace tool usage:
244
246
  ```typescript
245
- await keywordsAi.withTool(
247
+ await respan.withTool(
246
248
  { name: 'my_tool' },
247
249
  async () => {
248
250
  // Your tool logic
@@ -271,9 +273,9 @@ interface DecoratorConfig {
271
273
  Get full control over your spans with the client API:
272
274
 
273
275
  ```typescript
274
- import { KeywordsAITelemetry, getClient } from '@keywordsai/tracing';
276
+ import { RespanTelemetry, getClient } from '@respan/tracing';
275
277
 
276
- const kai = new KeywordsAITelemetry({ apiKey: 'your-key' });
278
+ const kai = new RespanTelemetry({ apiKey: 'your-key' });
277
279
  await kai.initialize();
278
280
 
279
281
  await kai.withTask({ name: 'process_data' }, async () => {
@@ -284,9 +286,9 @@ await kai.withTask({ name: 'process_data' }, async () => {
284
286
  const spanId = client.getCurrentSpanId();
285
287
  console.log(`Trace: ${traceId}, Span: ${spanId}`);
286
288
 
287
- // Update span with KeywordsAI parameters
289
+ // Update span with Respan parameters
288
290
  client.updateCurrentSpan({
289
- keywordsaiParams: {
291
+ respanParams: {
290
292
  customerIdentifier: 'user-123',
291
293
  traceGroupIdentifier: 'data-pipeline',
292
294
  metadata: {
@@ -316,7 +318,7 @@ await kai.withTask({ name: 'process_data' }, async () => {
316
318
  **Available Client Methods:**
317
319
  - `getCurrentTraceId()` - Get the current trace ID
318
320
  - `getCurrentSpanId()` - Get the current span ID
319
- - `updateCurrentSpan(options)` - Update span attributes, name, status, or KeywordsAI params
321
+ - `updateCurrentSpan(options)` - Update span attributes, name, status, or Respan params
320
322
  - `addEvent(name, attributes?)` - Add an event to the current span
321
323
  - `recordException(exception)` - Record an exception on the current span
322
324
  - `isRecording()` - Check if the span is recording
@@ -328,11 +330,11 @@ await kai.withTask({ name: 'process_data' }, async () => {
328
330
  Route spans to different destinations based on processor names:
329
331
 
330
332
  ```typescript
331
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
333
+ import { RespanTelemetry } from '@respan/tracing';
332
334
 
333
- const kai = new KeywordsAITelemetry({ apiKey: 'your-key' });
335
+ const kai = new RespanTelemetry({ apiKey: 'your-key' });
334
336
 
335
- // Add a debug processor (in addition to default KeywordsAI processor)
337
+ // Add a debug processor (in addition to default Respan processor)
336
338
  kai.addProcessor({
337
339
  exporter: new YourCustomExporter(),
338
340
  name: 'debug',
@@ -359,7 +361,7 @@ await kai.withTask(
359
361
  await kai.withTask(
360
362
  { name: 'normal_task' },
361
363
  async () => {
362
- // This span goes to the default KeywordsAI processor
364
+ // This span goes to the default Respan processor
363
365
  }
364
366
  );
365
367
  ```
@@ -379,9 +381,9 @@ interface ProcessorConfig {
379
381
  Buffer spans and control when they're exported:
380
382
 
381
383
  ```typescript
382
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
384
+ import { RespanTelemetry } from '@respan/tracing';
383
385
 
384
- const kai = new KeywordsAITelemetry({ apiKey: 'your-key' });
386
+ const kai = new RespanTelemetry({ apiKey: 'your-key' });
385
387
  const manager = kai.getSpanBufferManager();
386
388
 
387
389
  // Create a buffer (spans won't be auto-exported)
@@ -407,7 +409,7 @@ const isSuccessful = true; // Your business logic
407
409
  const isPremiumUser = true; // Your business logic
408
410
 
409
411
  if (isSuccessful && isPremiumUser) {
410
- // Export to KeywordsAI
412
+ // Export to Respan
411
413
  await manager.processSpans(spans);
412
414
  } else {
413
415
  // Discard spans
@@ -428,18 +430,18 @@ if (isSuccessful && isPremiumUser) {
428
430
  - `getSpanCount()` - Get the number of buffered spans
429
431
  - `clearSpans()` - Discard all buffered spans without exporting
430
432
 
431
- ### KeywordsAI-Specific Parameters
433
+ ### Respan-Specific Parameters
432
434
 
433
435
  Add customer and trace group identifiers to your spans:
434
436
 
435
437
  ```typescript
436
- import { getClient } from '@keywordsai/tracing';
438
+ import { getClient } from '@respan/tracing';
437
439
 
438
440
  await kai.withWorkflow({ name: 'user_workflow' }, async () => {
439
441
  const client = getClient();
440
442
 
441
443
  client.updateCurrentSpan({
442
- keywordsaiParams: {
444
+ respanParams: {
443
445
  // Group traces by customer
444
446
  customerIdentifier: 'user-123',
445
447
 
@@ -518,7 +520,7 @@ Use manual instrumentation instead:
518
520
  await kai.enableInstrumentation('anthropic');
519
521
 
520
522
  // Use this:
521
- const kai = new KeywordsAITelemetry({
523
+ const kai = new RespanTelemetry({
522
524
  instrumentModules: {
523
525
  anthropic: Anthropic
524
526
  }
@@ -558,16 +560,16 @@ const kai = new KeywordsAITelemetry({
558
560
  ### Spans not showing up?
559
561
 
560
562
  1. Check that you're using decorators (`withTask`, `withWorkflow`, etc.)
561
- 2. Verify API key is set: `process.env.KEYWORDSAI_API_KEY`
563
+ 2. Verify API key is set: `process.env.RESPAN_API_KEY`
562
564
  3. Enable debug logging: `logLevel: 'debug'`
563
- 4. Check network requests to KeywordsAI endpoint
565
+ 4. Check network requests to Respan endpoint
564
566
 
565
567
  ## Environment Variables
566
568
 
567
- - `KEYWORDSAI_API_KEY`: Your KeywordsAI API key
568
- - `KEYWORDSAI_BASE_URL`: KeywordsAI base URL (default: https://api.keywordsai.co)
569
- - `KEYWORDSAI_APP_NAME`: Default app name
570
- - `KEYWORDSAI_TRACE_CONTENT`: Enable/disable content tracing (default: true)
569
+ - `RESPAN_API_KEY`: Your Respan API key
570
+ - `RESPAN_BASE_URL`: Respan base URL (default: https://api.respan.ai)
571
+ - `RESPAN_APP_NAME`: Default app name
572
+ - `RESPAN_TRACE_CONTENT`: Enable/disable content tracing (default: true)
571
573
 
572
574
  ## Provider-Specific Examples
573
575
 
@@ -575,11 +577,11 @@ const kai = new KeywordsAITelemetry({
575
577
 
576
578
  **Method 1: Dynamic Instrumentation (Simple)**
577
579
  ```typescript
578
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
580
+ import { RespanTelemetry } from '@respan/tracing';
579
581
  import OpenAI from 'openai';
580
582
 
581
- const kai = new KeywordsAITelemetry({
582
- apiKey: process.env.KEYWORDSAI_API_KEY,
583
+ const kai = new RespanTelemetry({
584
+ apiKey: process.env.RESPAN_API_KEY,
583
585
  appName: 'openai-app'
584
586
  });
585
587
 
@@ -599,11 +601,11 @@ await kai.withTask({ name: 'chat' }, async () => {
599
601
 
600
602
  **Method 2: Manual Instrumentation (Next.js/Webpack)**
601
603
  ```typescript
602
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
604
+ import { RespanTelemetry } from '@respan/tracing';
603
605
  import OpenAI from 'openai';
604
606
 
605
- const kai = new KeywordsAITelemetry({
606
- apiKey: process.env.KEYWORDSAI_API_KEY,
607
+ const kai = new RespanTelemetry({
608
+ apiKey: process.env.RESPAN_API_KEY,
607
609
  appName: 'openai-app',
608
610
  instrumentModules: {
609
611
  openAI: OpenAI // Pass the OpenAI class
@@ -626,12 +628,12 @@ await kai.withTask({ name: 'chat' }, async () => {
626
628
  ### Anthropic (Claude)
627
629
 
628
630
  ```typescript
629
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
631
+ import { RespanTelemetry } from '@respan/tracing';
630
632
  import Anthropic from '@anthropic-ai/sdk';
631
633
 
632
634
  // Initialize with Anthropic instrumentation
633
- const kai = new KeywordsAITelemetry({
634
- apiKey: process.env.KEYWORDSAI_API_KEY,
635
+ const kai = new RespanTelemetry({
636
+ apiKey: process.env.RESPAN_API_KEY,
635
637
  appName: 'anthropic-app',
636
638
  instrumentModules: {
637
639
  anthropic: Anthropic // Pass the Anthropic class
@@ -684,11 +686,11 @@ npm install @anthropic-ai/sdk @traceloop/instrumentation-anthropic
684
686
  ### Example 1: Full Workflow with Span Management
685
687
 
686
688
  ```typescript
687
- import { KeywordsAITelemetry, getClient } from '@keywordsai/tracing';
689
+ import { RespanTelemetry, getClient } from '@respan/tracing';
688
690
  import OpenAI from 'openai';
689
691
 
690
- const kai = new KeywordsAITelemetry({
691
- apiKey: process.env.KEYWORDSAI_API_KEY,
692
+ const kai = new RespanTelemetry({
693
+ apiKey: process.env.RESPAN_API_KEY,
692
694
  appName: 'my-app',
693
695
  resourceAttributes: {
694
696
  environment: 'production',
@@ -704,7 +706,7 @@ await kai.withWorkflow({ name: 'process_user_request', version: 1 }, async () =>
704
706
 
705
707
  // Set customer context
706
708
  client.updateCurrentSpan({
707
- keywordsaiParams: {
709
+ respanParams: {
708
710
  customerIdentifier: 'user-123',
709
711
  traceGroupIdentifier: 'onboarding'
710
712
  }
@@ -737,9 +739,9 @@ await kai.withWorkflow({ name: 'process_user_request', version: 1 }, async () =>
737
739
  ### Example 2: Backend Workflow with Span Buffering
738
740
 
739
741
  ```typescript
740
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
742
+ import { RespanTelemetry } from '@respan/tracing';
741
743
 
742
- const kai = new KeywordsAITelemetry({ apiKey: 'your-key' });
744
+ const kai = new RespanTelemetry({ apiKey: 'your-key' });
743
745
  const manager = kai.getSpanBufferManager();
744
746
 
745
747
  // Ingest workflow results from backend
@@ -781,10 +783,10 @@ async function ingestWorkflow(workflowResult: any, orgId: string) {
781
783
  ### Example 3: Multi-Destination Routing
782
784
 
783
785
  ```typescript
784
- import { KeywordsAITelemetry } from '@keywordsai/tracing';
786
+ import { RespanTelemetry } from '@respan/tracing';
785
787
  import { FileExporter, AnalyticsExporter } from './exporters';
786
788
 
787
- const kai = new KeywordsAITelemetry({ apiKey: 'your-key' });
789
+ const kai = new RespanTelemetry({ apiKey: 'your-key' });
788
790
 
789
791
  // Add debug file exporter
790
792
  kai.addProcessor({
@@ -799,10 +801,10 @@ kai.addProcessor({
799
801
  filter: (span) => !span.name.includes('test')
800
802
  });
801
803
 
802
- // Route to default KeywordsAI processor
804
+ // Route to default Respan processor
803
805
  await kai.withTask(
804
806
  { name: 'production_task' },
805
- async () => { /* goes to KeywordsAI */ }
807
+ async () => { /* goes to Respan */ }
806
808
  );
807
809
 
808
810
  // Route to debug processor
@@ -851,7 +853,7 @@ All new features are **backward compatible**. Existing code will continue to wor
851
853
 
852
854
  To use new features, simply import and use them:
853
855
  ```typescript
854
- import { getClient } from '@keywordsai/tracing'; // New in v1.1.0
856
+ import { getClient } from '@respan/tracing'; // New in v1.1.0
855
857
  ```
856
858
 
857
859
  ## License
@@ -1 +1,2 @@
1
1
  export * from "./span.js";
2
+ export * from "./propagation.js";
@@ -1,2 +1,3 @@
1
1
  export * from "./span.js";
2
+ export * from "./propagation.js";
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { RespanParams } from "@respan/respan-sdk";
2
+ /**
3
+ * Run a function within a context that propagates Respan attributes to all
4
+ * spans created within its scope.
5
+ *
6
+ * Attributes are merged into every span at creation time via
7
+ * `RespanCompositeProcessor.onStart()`. Nested calls merge attributes
8
+ * (inner wins). Metadata dicts are merged, not replaced.
9
+ *
10
+ * @param attrs - Respan attributes to propagate (customer_identifier,
11
+ * thread_identifier, metadata, prompt, environment, etc.)
12
+ * @param fn - The function to execute within the propagation scope
13
+ * @returns The result of `fn`
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * await propagateAttributes(
18
+ * { customer_identifier: "user_123", thread_identifier: "conv_abc" },
19
+ * async () => {
20
+ * await Runner.run(agent, "Hello");
21
+ * }
22
+ * );
23
+ * ```
24
+ */
25
+ export declare function propagateAttributes<T>(attrs: Partial<RespanParams>, fn: () => T): T;
@@ -0,0 +1,47 @@
1
+ import { context } from "@opentelemetry/api";
2
+ import { RESPAN_SPAN_ATTRIBUTES_MAP } from "@respan/respan-sdk";
3
+ import { PROPAGATED_ATTRIBUTES_KEY, getPropagatedAttributes, } from "../utils/context.js";
4
+ /**
5
+ * Run a function within a context that propagates Respan attributes to all
6
+ * spans created within its scope.
7
+ *
8
+ * Attributes are merged into every span at creation time via
9
+ * `RespanCompositeProcessor.onStart()`. Nested calls merge attributes
10
+ * (inner wins). Metadata dicts are merged, not replaced.
11
+ *
12
+ * @param attrs - Respan attributes to propagate (customer_identifier,
13
+ * thread_identifier, metadata, prompt, environment, etc.)
14
+ * @param fn - The function to execute within the propagation scope
15
+ * @returns The result of `fn`
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * await propagateAttributes(
20
+ * { customer_identifier: "user_123", thread_identifier: "conv_abc" },
21
+ * async () => {
22
+ * await Runner.run(agent, "Hello");
23
+ * }
24
+ * );
25
+ * ```
26
+ */
27
+ export function propagateAttributes(attrs, fn) {
28
+ // Merge with any already-active attributes (supports nesting)
29
+ const parent = getPropagatedAttributes() ?? {};
30
+ const merged = { ...parent };
31
+ for (const [key, value] of Object.entries(attrs)) {
32
+ if (!(key in RESPAN_SPAN_ATTRIBUTES_MAP)) {
33
+ console.warn(`[Respan] Ignoring unsupported attribute: ${key}`);
34
+ continue;
35
+ }
36
+ if (key === "metadata" && typeof value === "object" && value !== null) {
37
+ // Merge metadata dicts instead of replacing
38
+ merged.metadata = { ...(merged.metadata ?? {}), ...value };
39
+ }
40
+ else {
41
+ merged[key] = value;
42
+ }
43
+ }
44
+ const ctx = context.active().setValue(PROPAGATED_ATTRIBUTES_KEY, merged);
45
+ return context.with(ctx, fn);
46
+ }
47
+ //# sourceMappingURL=propagation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propagation.js","sourceRoot":"","sources":["../../src/contexts/propagation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA4B,EAC5B,EAAW;IAEX,8DAA8D;IAC9D,MAAM,MAAM,GAAG,uBAAuB,EAAE,IAAI,EAAE,CAAC;IAC/C,MAAM,MAAM,GAA0B,EAAE,GAAG,MAAM,EAAE,CAAC;IAEpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,CAAC,GAAG,IAAI,0BAA0B,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,4CAA4C,GAAG,EAAE,CAAC,CAAC;YAChE,SAAS;QACX,CAAC;QACD,IAAI,GAAG,KAAK,UAAU,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACtE,4CAA4C;YAC5C,MAAM,CAAC,QAAQ,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;QAC7D,CAAC;aAAM,CAAC;YACL,MAAc,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC,CAAC;IACzE,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC"}
@@ -1,5 +1,72 @@
1
1
  import { SpanAttributes } from "@traceloop/ai-semantic-conventions";
2
- import { getEntityPath } from "../utils/context.js";
2
+ import { RESPAN_SPAN_ATTRIBUTES_MAP, RespanSpanAttributes, RespanLogType, } from "@respan/respan-sdk";
3
+ import { getEntityPath, getPropagatedAttributes } from "../utils/context.js";
4
+ // ── OpenInference span enrichment ──────────────────────────────────────────
5
+ /** Map OI span kinds → Traceloop span kinds */
6
+ const OI_KIND_TO_TRACELOOP = {
7
+ LLM: RespanLogType.TASK,
8
+ CHAIN: RespanLogType.WORKFLOW,
9
+ TOOL: RespanLogType.TOOL,
10
+ AGENT: RespanLogType.AGENT,
11
+ EMBEDDING: RespanLogType.TASK,
12
+ RETRIEVER: RespanLogType.TASK,
13
+ RERANKER: RespanLogType.TASK,
14
+ GUARDRAIL: RespanLogType.TASK,
15
+ EVALUATOR: RespanLogType.TASK,
16
+ };
17
+ /** OI span kinds that imply an LLM request type */
18
+ const OI_LLM_REQUEST_KINDS = {
19
+ LLM: RespanLogType.CHAT,
20
+ EMBEDDING: RespanLogType.EMBEDDING,
21
+ };
22
+ /** Map OI span kinds → respan.entity.log_type values */
23
+ const OI_LOG_TYPE = {
24
+ LLM: RespanLogType.CHAT,
25
+ CHAIN: RespanLogType.WORKFLOW,
26
+ TOOL: RespanLogType.TOOL,
27
+ AGENT: RespanLogType.AGENT,
28
+ EMBEDDING: RespanLogType.EMBEDDING,
29
+ RETRIEVER: RespanLogType.TASK,
30
+ RERANKER: RespanLogType.TASK,
31
+ GUARDRAIL: RespanLogType.GUARDRAIL,
32
+ EVALUATOR: RespanLogType.TASK,
33
+ };
34
+ /**
35
+ * Build Traceloop/GenAI enrichment attributes for an OpenInference span.
36
+ * Returns only the attributes that need to be *added*; callers merge them
37
+ * on top of the original span attributes.
38
+ */
39
+ function getOIEnrichmentAttrs(span) {
40
+ const attrs = {};
41
+ const oiKind = String(span.attributes[RespanSpanAttributes.OPENINFERENCE_SPAN_KIND] ?? "");
42
+ if (OI_KIND_TO_TRACELOOP[oiKind]) {
43
+ attrs[SpanAttributes.TRACELOOP_SPAN_KIND] = OI_KIND_TO_TRACELOOP[oiKind];
44
+ }
45
+ if (OI_LLM_REQUEST_KINDS[oiKind]) {
46
+ attrs[RespanSpanAttributes.LLM_REQUEST_TYPE] = OI_LLM_REQUEST_KINDS[oiKind];
47
+ }
48
+ if (OI_LOG_TYPE[oiKind]) {
49
+ attrs[RespanSpanAttributes.RESPAN_LOG_TYPE] = OI_LOG_TYPE[oiKind];
50
+ }
51
+ // Bridge OI semantic attrs → Traceloop/GenAI equivalents
52
+ if (span.attributes["input.value"] !== undefined)
53
+ attrs[SpanAttributes.TRACELOOP_ENTITY_INPUT] = span.attributes["input.value"];
54
+ if (span.attributes["output.value"] !== undefined)
55
+ attrs[SpanAttributes.TRACELOOP_ENTITY_OUTPUT] = span.attributes["output.value"];
56
+ if (span.attributes["llm.model_name"] !== undefined)
57
+ attrs[RespanSpanAttributes.GEN_AI_REQUEST_MODEL] = span.attributes["llm.model_name"];
58
+ if (span.attributes["llm.token_count.prompt"] !== undefined)
59
+ attrs[RespanSpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS] = span.attributes["llm.token_count.prompt"];
60
+ if (span.attributes["llm.token_count.completion"] !== undefined)
61
+ attrs[RespanSpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS] = span.attributes["llm.token_count.completion"];
62
+ // Entity name / path
63
+ attrs[SpanAttributes.TRACELOOP_ENTITY_NAME] = span.name;
64
+ if (OI_KIND_TO_TRACELOOP[oiKind] !== "workflow") {
65
+ attrs[SpanAttributes.TRACELOOP_ENTITY_PATH] = span.name;
66
+ }
67
+ return attrs;
68
+ }
69
+ // ── Composite processor ────────────────────────────────────────────────────
3
70
  /**
4
71
  * Composite processor that combines filtering with multi-processor routing.
5
72
  *
@@ -28,6 +95,28 @@ export class RespanCompositeProcessor {
28
95
  // We need to cast to any to set attributes during onStart
29
96
  span.setAttribute(SpanAttributes.TRACELOOP_ENTITY_PATH, entityPath);
30
97
  }
98
+ // Apply propagated attributes (customer_identifier, thread_identifier, etc.)
99
+ const propagated = getPropagatedAttributes(parentContext);
100
+ if (propagated) {
101
+ for (const [key, value] of Object.entries(propagated)) {
102
+ if (value === undefined || value === null)
103
+ continue;
104
+ const attrKey = RESPAN_SPAN_ATTRIBUTES_MAP[key];
105
+ if (!attrKey)
106
+ continue;
107
+ if (key === "metadata" && typeof value === "object") {
108
+ for (const [mk, mv] of Object.entries(value)) {
109
+ span.setAttribute(`${RespanSpanAttributes.RESPAN_METADATA}.${mk}`, typeof mv === "string" ? mv : JSON.stringify(mv));
110
+ }
111
+ }
112
+ else if (key === "prompt" && typeof value === "object") {
113
+ span.setAttribute(attrKey, JSON.stringify(value));
114
+ }
115
+ else {
116
+ span.setAttribute(attrKey, value);
117
+ }
118
+ }
119
+ }
31
120
  // Forward to processor manager
32
121
  this._processorManager.onStart(span, parentContext);
33
122
  }
@@ -45,8 +134,8 @@ export class RespanCompositeProcessor {
45
134
  }
46
135
  // Check if this is an LLM instrumentation span (OpenAI, Anthropic, etc.)
47
136
  // These have gen_ai.* or llm.* attributes
48
- const isLLMSpan = span.attributes['gen_ai.system'] !== undefined ||
49
- span.attributes['llm.system'] !== undefined ||
137
+ const isLLMSpan = span.attributes[RespanSpanAttributes.GEN_AI_SYSTEM] !== undefined ||
138
+ span.attributes[RespanSpanAttributes.LLM_SYSTEM] !== undefined ||
50
139
  span.attributes['gen_ai.request.model'] !== undefined ||
51
140
  span.name.includes('anthropic.messages') ||
52
141
  span.name.includes('openai.chat') ||
@@ -81,6 +170,25 @@ export class RespanCompositeProcessor {
81
170
  // Route to processors
82
171
  this._processorManager.onEnd(span);
83
172
  }
173
+ else if (span.attributes[RespanSpanAttributes.OPENINFERENCE_SPAN_KIND] !== undefined) {
174
+ // OpenInference span — enrich with Traceloop/GenAI attrs, then route
175
+ console.debug(`[Respan Debug] Processing OpenInference span: ${span.name} (kind: ${span.attributes[RespanSpanAttributes.OPENINFERENCE_SPAN_KIND]})`);
176
+ const enrichmentAttrs = getOIEnrichmentAttrs(span);
177
+ const enrichedSpan = Object.create(Object.getPrototypeOf(span));
178
+ Object.assign(enrichedSpan, span);
179
+ Object.defineProperty(enrichedSpan, "attributes", {
180
+ value: { ...span.attributes, ...enrichmentAttrs },
181
+ writable: false,
182
+ configurable: true,
183
+ enumerable: true,
184
+ });
185
+ this._processorManager.onEnd(enrichedSpan);
186
+ }
187
+ else if (span.attributes[RespanSpanAttributes.RESPAN_LOG_TYPE] !== undefined) {
188
+ // Enriched Respan span (from an instrumentation plugin)
189
+ console.debug(`[Respan Debug] Processing enriched Respan span: ${span.name}`);
190
+ this._processorManager.onEnd(span);
191
+ }
84
192
  else {
85
193
  // This span has none of the above - it's pure auto-instrumentation noise (HTTP calls, etc.)
86
194
  console.debug(`[Respan Debug] Filtering out auto-instrumentation span: ${span.name}`);
@@ -1 +1 @@
1
- {"version":3,"file":"composite.js","sourceRoot":"","sources":["../../src/processor/composite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"composite.js","sourceRoot":"","sources":["../../src/processor/composite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Batch API result logging utilities.
3
+ *
4
+ * Logs OpenAI Batch API results as individual chat completion spans
5
+ * injected into the OTEL pipeline.
6
+ */
7
+ export interface BatchRequest {
8
+ custom_id: string;
9
+ body?: {
10
+ messages?: any[];
11
+ model?: string;
12
+ [key: string]: any;
13
+ };
14
+ [key: string]: any;
15
+ }
16
+ export interface BatchResult {
17
+ custom_id: string;
18
+ response?: {
19
+ status_code?: number;
20
+ body?: {
21
+ choices?: Array<{
22
+ message?: any;
23
+ [key: string]: any;
24
+ }>;
25
+ usage?: {
26
+ prompt_tokens?: number;
27
+ completion_tokens?: number;
28
+ };
29
+ model?: string;
30
+ created?: number;
31
+ [key: string]: any;
32
+ };
33
+ [key: string]: any;
34
+ };
35
+ [key: string]: any;
36
+ }
37
+ /**
38
+ * Log OpenAI Batch API results as individual chat completion spans.
39
+ *
40
+ * Trace linking (in priority order):
41
+ * 1. OTEL context — when called inside a `withTask` / `withWorkflow`,
42
+ * auto-links to the active trace.
43
+ * 2. Explicit `traceId` — for async batches where results arrive later.
44
+ * 3. Auto-generated — creates a new standalone trace.
45
+ */
46
+ export declare function logBatchResults(requests: BatchRequest[], results: BatchResult[], traceId?: string): void;
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Batch API result logging utilities.
3
+ *
4
+ * Logs OpenAI Batch API results as individual chat completion spans
5
+ * injected into the OTEL pipeline.
6
+ */
7
+ import { SpanAttributes } from "@traceloop/ai-semantic-conventions";
8
+ import { RespanSpanAttributes } from "@respan/respan-sdk";
9
+ import { buildReadableSpan, injectSpan, ensureSpanId } from "./spanFactory.js";
10
+ import { getClient } from "./client.js";
11
+ /**
12
+ * Log OpenAI Batch API results as individual chat completion spans.
13
+ *
14
+ * Trace linking (in priority order):
15
+ * 1. OTEL context — when called inside a `withTask` / `withWorkflow`,
16
+ * auto-links to the active trace.
17
+ * 2. Explicit `traceId` — for async batches where results arrive later.
18
+ * 3. Auto-generated — creates a new standalone trace.
19
+ */
20
+ export function logBatchResults(requests, results, traceId) {
21
+ const client = getClient();
22
+ // Resolve trace context: OTEL > explicit > auto-generated.
23
+ let otelTraceId = client.getCurrentTraceId();
24
+ let otelSpanId = client.getCurrentSpanId();
25
+ if (otelTraceId && /^0+$/.test(otelTraceId))
26
+ otelTraceId = undefined;
27
+ if (otelSpanId && /^0+$/.test(otelSpanId))
28
+ otelSpanId = undefined;
29
+ const resolvedTraceId = otelTraceId ?? traceId ?? undefined;
30
+ const parentSpanId = otelSpanId ?? undefined;
31
+ // Index requests by custom_id
32
+ const requestsById = new Map();
33
+ for (const req of requests) {
34
+ requestsById.set(req.custom_id, req.body ?? {});
35
+ }
36
+ // When no OTEL context, create a grouping span so completions are nested
37
+ let groupSpanId;
38
+ if (!otelSpanId) {
39
+ groupSpanId = ensureSpanId();
40
+ }
41
+ const completionTimestamps = [];
42
+ for (const result of results) {
43
+ const customId = result.custom_id ?? "";
44
+ const response = result.response ?? {};
45
+ const body = response.body ?? {};
46
+ const statusCode = response.status_code ?? 200;
47
+ const original = requestsById.get(customId) ?? {};
48
+ const messages = original.messages ?? [];
49
+ const choices = body.choices ?? [{}];
50
+ const output = choices[0]?.message ?? {};
51
+ const usage = body.usage ?? {};
52
+ // Extract timestamp
53
+ const created = body.created;
54
+ let endTimeIso;
55
+ if (created) {
56
+ const ts = new Date(created * 1000);
57
+ endTimeIso = ts.toISOString();
58
+ completionTimestamps.push(ts);
59
+ }
60
+ const model = body.model ?? original.model ?? "";
61
+ const span = buildReadableSpan({
62
+ name: `batch:${customId}`,
63
+ traceId: resolvedTraceId,
64
+ parentId: groupSpanId ?? parentSpanId,
65
+ endTimeIso,
66
+ attributes: {
67
+ "llm.request.type": "chat",
68
+ "gen_ai.request.model": model,
69
+ "gen_ai.usage.prompt_tokens": usage.prompt_tokens ?? 0,
70
+ "gen_ai.usage.completion_tokens": usage.completion_tokens ?? 0,
71
+ [SpanAttributes.TRACELOOP_ENTITY_INPUT]: JSON.stringify(messages),
72
+ [SpanAttributes.TRACELOOP_ENTITY_OUTPUT]: JSON.stringify(output),
73
+ [SpanAttributes.TRACELOOP_ENTITY_PATH]: "batch_results",
74
+ [SpanAttributes.TRACELOOP_SPAN_KIND]: "task",
75
+ [RespanSpanAttributes.RESPAN_LOG_TYPE]: "chat",
76
+ },
77
+ statusCode,
78
+ });
79
+ injectSpan(span);
80
+ }
81
+ // Create the grouping "batch_results" task span (when no OTEL context)
82
+ if (groupSpanId) {
83
+ let earliestIso;
84
+ let latestIso;
85
+ if (completionTimestamps.length > 0) {
86
+ completionTimestamps.sort((a, b) => a.getTime() - b.getTime());
87
+ earliestIso = completionTimestamps[0].toISOString();
88
+ latestIso =
89
+ completionTimestamps[completionTimestamps.length - 1].toISOString();
90
+ }
91
+ const parentSpan = buildReadableSpan({
92
+ name: "batch_results.task",
93
+ traceId: resolvedTraceId,
94
+ spanId: groupSpanId,
95
+ startTimeIso: earliestIso,
96
+ endTimeIso: latestIso,
97
+ attributes: {
98
+ [SpanAttributes.TRACELOOP_SPAN_KIND]: "task",
99
+ [SpanAttributes.TRACELOOP_ENTITY_NAME]: "batch_results",
100
+ [SpanAttributes.TRACELOOP_ENTITY_PATH]: "",
101
+ [RespanSpanAttributes.RESPAN_LOG_TYPE]: "task",
102
+ },
103
+ });
104
+ injectSpan(parentSpan);
105
+ }
106
+ }
107
+ //# sourceMappingURL=batchLogging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchLogging.js","sourceRoot":"","sources":["../../src/utils/batchLogging.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { Context } from "@opentelemetry/api";
2
+ import { RespanParams } from "@respan/respan-sdk";
2
3
  /**
3
4
  * Context Keys: Type-safe identifiers for storing values in OpenTelemetry context
4
5
  *
@@ -19,6 +20,11 @@ export declare const ASSOCIATION_PROPERTIES_KEY: symbol;
19
20
  * @returns The entity path string or undefined if not set
20
21
  */
21
22
  export declare const getEntityPath: (ctx?: Context) => string | undefined;
23
+ export declare const PROPAGATED_ATTRIBUTES_KEY: symbol;
24
+ /**
25
+ * Get propagated attributes from the given context.
26
+ */
27
+ export declare const getPropagatedAttributes: (ctx?: Context) => Partial<RespanParams> | undefined;
22
28
  /**
23
29
  * Determines whether trace content (input/output data) should be captured.
24
30
  * This can be controlled via environment variable for security/privacy.
@@ -32,6 +32,15 @@ export const getEntityPath = (ctx = context.active()) => {
32
32
  const workflowName = ctx.getValue(WORKFLOW_NAME_KEY);
33
33
  return workflowName;
34
34
  };
35
+ // Stores propagated Respan attributes (customer_identifier, thread_identifier, etc.)
36
+ // These are merged onto every span created within the context scope.
37
+ export const PROPAGATED_ATTRIBUTES_KEY = createContextKey("respan.propagated_attributes");
38
+ /**
39
+ * Get propagated attributes from the given context.
40
+ */
41
+ export const getPropagatedAttributes = (ctx = context.active()) => {
42
+ return ctx.getValue(PROPAGATED_ATTRIBUTES_KEY);
43
+ };
35
44
  /**
36
45
  * Determines whether trace content (input/output data) should be captured.
37
46
  * This can be controlled via environment variable for security/privacy.
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAW,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE;;;;;;;;GAQG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAC/C,cAAc,CAAC,uBAAuB,CACvC,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAC7C,cAAc,CAAC,qBAAqB,CACrC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CACxD,cAAc,CAAC,gCAAgC,CAChD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,EAAsB,EAAE;IAC1E,4DAA4D;IAC5D,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAuB,CAAC;IACvE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,2DAA2D;IAC3D,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAuB,CAAC;IAC3E,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAY,EAAE;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,OAAO,CAAC;AACtD,CAAC,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAW,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGpE;;;;;;;;GAQG;AAEH,gEAAgE;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAC/C,cAAc,CAAC,uBAAuB,CACvC,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAC7C,cAAc,CAAC,qBAAqB,CACrC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,0BAA0B,GAAG,gBAAgB,CACxD,cAAc,CAAC,gCAAgC,CAChD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,EAAsB,EAAE;IAC1E,4DAA4D;IAC5D,MAAM,UAAU,GAAG,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAuB,CAAC;IACvE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,2DAA2D;IAC3D,MAAM,YAAY,GAAG,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAuB,CAAC;IAC3E,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAEF,qFAAqF;AACrF,qEAAqE;AACrE,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CACvD,8BAA8B,CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,MAAe,OAAO,CAAC,MAAM,EAAE,EACI,EAAE;IACrC,OAAO,GAAG,CAAC,QAAQ,CAAC,yBAAyB,CAEhC,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAY,EAAE;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,OAAO,CAAC;AACtD,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export * from "./context.js";
2
2
  export * from "./span.js";
3
+ export * from "./spanFactory.js";
3
4
  export { startTracing, forceFlush, _resolveBaseURL } from "./tracing.js";
4
5
  export * from "./client.js";
5
6
  export * from "./spanBuffer.js";
@@ -1,5 +1,6 @@
1
1
  export * from "./context.js";
2
2
  export * from "./span.js";
3
+ export * from "./spanFactory.js";
3
4
  // Export tracing utils but avoid naming conflicts
4
5
  export { startTracing, forceFlush, _resolveBaseURL } from "./tracing.js";
5
6
  // Export client and span buffer
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAE1B,kDAAkD;AAClD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzE,gCAAgC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AAEjC,kDAAkD;AAClD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzE,gCAAgC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Shared utilities for constructing and injecting ReadableSpan objects.
3
+ *
4
+ * Used by the `Respan` unified entry point (e.g. `logBatchResults`) and
5
+ * instrumentation plugins to emit spans into the OTEL pipeline without
6
+ * going through a live tracer context.
7
+ */
8
+ import type { ReadableSpan } from "@opentelemetry/sdk-trace-base";
9
+ export declare function ensureTraceId(id?: string): string;
10
+ export declare function ensureSpanId(id?: string): string;
11
+ export declare function parseISOToHrTime(iso: string | undefined): [number, number] | null;
12
+ export interface BuildSpanOptions {
13
+ name: string;
14
+ traceId?: string;
15
+ spanId?: string;
16
+ parentId?: string;
17
+ startTimeIso?: string;
18
+ endTimeIso?: string;
19
+ startTimeHr?: [number, number] | null;
20
+ endTimeHr?: [number, number] | null;
21
+ attributes: Record<string, any>;
22
+ statusCode?: number;
23
+ errorMessage?: string;
24
+ /** Merge propagated attributes from context. Default: true (matches Python). */
25
+ mergePropagated?: boolean;
26
+ }
27
+ /**
28
+ * Construct a ReadableSpan-compatible object with explicit IDs and attributes.
29
+ */
30
+ export declare function buildReadableSpan(opts: BuildSpanOptions): ReadableSpan;
31
+ /**
32
+ * Push a ReadableSpan through the active TracerProvider's processor chain.
33
+ *
34
+ * Returns true on success, false if no processor is available.
35
+ */
36
+ export declare function injectSpan(span: ReadableSpan): boolean;
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Shared utilities for constructing and injecting ReadableSpan objects.
3
+ *
4
+ * Used by the `Respan` unified entry point (e.g. `logBatchResults`) and
5
+ * instrumentation plugins to emit spans into the OTEL pipeline without
6
+ * going through a live tracer context.
7
+ */
8
+ import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
9
+ import { hrTime, hrTimeDuration } from "@opentelemetry/core";
10
+ import { RESPAN_SPAN_ATTRIBUTES_MAP, RespanSpanAttributes } from "@respan/respan-sdk";
11
+ import { RESPAN_PACKAGE_NAME } from "../constants/index.js";
12
+ import { getPropagatedAttributes } from "./context.js";
13
+ // ── ID helpers ──────────────────────────────────────────────────────────────
14
+ function hashStringToHexId(s, length) {
15
+ let hash = 0;
16
+ for (let i = 0; i < s.length; i++) {
17
+ hash = ((hash << 5) - hash + s.charCodeAt(i)) | 0;
18
+ }
19
+ const hex = Math.abs(hash).toString(16).padStart(8, "0");
20
+ return (hex + hex + hex + hex).slice(0, length);
21
+ }
22
+ function generateHexId(length) {
23
+ return Array.from({ length }, () => Math.floor(Math.random() * 16).toString(16)).join("");
24
+ }
25
+ export function ensureTraceId(id) {
26
+ if (!id)
27
+ return generateHexId(32);
28
+ if (/^[0-9a-f]{32}$/i.test(id))
29
+ return id.toLowerCase();
30
+ return hashStringToHexId(id, 32);
31
+ }
32
+ export function ensureSpanId(id) {
33
+ if (!id)
34
+ return generateHexId(16);
35
+ if (/^[0-9a-f]{16}$/i.test(id))
36
+ return id.toLowerCase();
37
+ return hashStringToHexId(id, 16);
38
+ }
39
+ // ── Timestamp helpers ───────────────────────────────────────────────────────
40
+ export function parseISOToHrTime(iso) {
41
+ if (!iso)
42
+ return null;
43
+ try {
44
+ const ms = new Date(iso).getTime();
45
+ const secs = Math.floor(ms / 1000);
46
+ const nanos = (ms % 1000) * 1_000_000;
47
+ return [secs, nanos];
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ /**
54
+ * Construct a ReadableSpan-compatible object with explicit IDs and attributes.
55
+ */
56
+ export function buildReadableSpan(opts) {
57
+ const startTime = opts.startTimeHr ??
58
+ parseISOToHrTime(opts.startTimeIso) ??
59
+ hrTime();
60
+ const endTime = opts.endTimeHr ??
61
+ parseISOToHrTime(opts.endTimeIso) ??
62
+ hrTime();
63
+ const traceId = ensureTraceId(opts.traceId);
64
+ const spanId = ensureSpanId(opts.spanId);
65
+ const parentSpanId = opts.parentId
66
+ ? ensureSpanId(opts.parentId)
67
+ : undefined;
68
+ // Merge propagated attributes (customer_identifier, thread_id, etc.)
69
+ // Matches Python's merge_propagated=True default in build_readable_span()
70
+ const attrs = { ...opts.attributes };
71
+ if (opts.mergePropagated !== false) {
72
+ const propagated = getPropagatedAttributes();
73
+ if (propagated) {
74
+ for (const [key, value] of Object.entries(propagated)) {
75
+ if (value === undefined || value === null)
76
+ continue;
77
+ const attrKey = RESPAN_SPAN_ATTRIBUTES_MAP[key];
78
+ if (!attrKey)
79
+ continue;
80
+ // Only set if not already present (caller attrs take precedence)
81
+ if (attrs[attrKey] !== undefined)
82
+ continue;
83
+ if (key === "metadata" && typeof value === "object") {
84
+ for (const [mk, mv] of Object.entries(value)) {
85
+ const fullKey = `${RespanSpanAttributes.RESPAN_METADATA}.${mk}`;
86
+ if (attrs[fullKey] === undefined) {
87
+ attrs[fullKey] = typeof mv === "string" ? mv : JSON.stringify(mv);
88
+ }
89
+ }
90
+ }
91
+ else if (key === "prompt" && typeof value === "object") {
92
+ attrs[attrKey] = JSON.stringify(value);
93
+ }
94
+ else {
95
+ attrs[attrKey] = value;
96
+ }
97
+ }
98
+ }
99
+ }
100
+ const status = opts.errorMessage
101
+ ? { code: SpanStatusCode.ERROR, message: opts.errorMessage }
102
+ : opts.statusCode && opts.statusCode >= 400
103
+ ? { code: SpanStatusCode.ERROR, message: `HTTP ${opts.statusCode}` }
104
+ : { code: SpanStatusCode.OK, message: "" };
105
+ return {
106
+ name: opts.name,
107
+ kind: SpanKind.INTERNAL,
108
+ spanContext: () => ({
109
+ traceId,
110
+ spanId,
111
+ traceFlags: 1,
112
+ isRemote: false,
113
+ }),
114
+ parentSpanId,
115
+ startTime,
116
+ endTime,
117
+ duration: hrTimeDuration(startTime, endTime),
118
+ status,
119
+ attributes: attrs,
120
+ links: [],
121
+ events: [],
122
+ resource: { attributes: {} },
123
+ instrumentationLibrary: {
124
+ name: RESPAN_PACKAGE_NAME,
125
+ version: "1.0.0",
126
+ },
127
+ ended: true,
128
+ droppedAttributesCount: 0,
129
+ droppedEventsCount: 0,
130
+ droppedLinksCount: 0,
131
+ };
132
+ }
133
+ // ── Inject into OTEL pipeline ───────────────────────────────────────────────
134
+ /**
135
+ * Push a ReadableSpan through the active TracerProvider's processor chain.
136
+ *
137
+ * Returns true on success, false if no processor is available.
138
+ */
139
+ export function injectSpan(span) {
140
+ const tp = trace.getTracerProvider();
141
+ const processor = tp?.activeSpanProcessor ?? tp?._delegate?.activeSpanProcessor;
142
+ if (processor && typeof processor.onEnd === "function") {
143
+ processor.onEnd(span);
144
+ return true;
145
+ }
146
+ return false;
147
+ }
148
+ //# sourceMappingURL=spanFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spanFactory.js","sourceRoot":"","sources":["../../src/utils/spanFactory.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@respan/tracing",
3
3
  "type": "module",
4
- "version": "1.0.45",
5
- "description": "TypeScript support for Respan SDK",
4
+ "version": "1.1.1",
5
+ "description": "OpenTelemetry-based tracing SDK for LLM applications",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [