@respan/tracing 1.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +860 -0
  3. package/dist/constants/index.d.ts +8 -0
  4. package/dist/constants/index.js +9 -0
  5. package/dist/constants/index.js.map +1 -0
  6. package/dist/contexts/index.d.ts +1 -0
  7. package/dist/contexts/index.js +2 -0
  8. package/dist/contexts/index.js.map +1 -0
  9. package/dist/contexts/span.d.ts +9 -0
  10. package/dist/contexts/span.js +39 -0
  11. package/dist/contexts/span.js.map +1 -0
  12. package/dist/decorators/base.d.ts +32 -0
  13. package/dist/decorators/base.js +242 -0
  14. package/dist/decorators/base.js.map +1 -0
  15. package/dist/decorators/index.d.ts +1 -0
  16. package/dist/decorators/index.js +2 -0
  17. package/dist/decorators/index.js.map +1 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.js +8 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/instrumentation/index.d.ts +2 -0
  22. package/dist/instrumentation/index.js +3 -0
  23. package/dist/instrumentation/index.js.map +1 -0
  24. package/dist/instrumentation/loader.d.ts +5 -0
  25. package/dist/instrumentation/loader.js +104 -0
  26. package/dist/instrumentation/loader.js.map +1 -0
  27. package/dist/instrumentation/manager.d.ts +29 -0
  28. package/dist/instrumentation/manager.js +564 -0
  29. package/dist/instrumentation/manager.js.map +1 -0
  30. package/dist/main.d.ts +162 -0
  31. package/dist/main.js +212 -0
  32. package/dist/main.js.map +1 -0
  33. package/dist/processor/composite.d.ts +29 -0
  34. package/dist/processor/composite.js +106 -0
  35. package/dist/processor/composite.js.map +1 -0
  36. package/dist/processor/filtering.d.ts +19 -0
  37. package/dist/processor/filtering.js +78 -0
  38. package/dist/processor/filtering.js.map +1 -0
  39. package/dist/processor/index.d.ts +3 -0
  40. package/dist/processor/index.js +4 -0
  41. package/dist/processor/index.js.map +1 -0
  42. package/dist/processor/manager.d.ts +61 -0
  43. package/dist/processor/manager.js +111 -0
  44. package/dist/processor/manager.js.map +1 -0
  45. package/dist/types/clientTypes.d.ts +188 -0
  46. package/dist/types/clientTypes.js +22 -0
  47. package/dist/types/clientTypes.js.map +1 -0
  48. package/dist/types/decoratorTypes.d.ts +6 -0
  49. package/dist/types/decoratorTypes.js +2 -0
  50. package/dist/types/decoratorTypes.js.map +1 -0
  51. package/dist/types/index.d.ts +3 -0
  52. package/dist/types/index.js +4 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/types/instrumentationTypes.d.ts +25 -0
  55. package/dist/types/instrumentationTypes.js +82 -0
  56. package/dist/types/instrumentationTypes.js.map +1 -0
  57. package/dist/utils/client.d.ts +168 -0
  58. package/dist/utils/client.js +151 -0
  59. package/dist/utils/client.js.map +1 -0
  60. package/dist/utils/context.d.ts +28 -0
  61. package/dist/utils/context.js +44 -0
  62. package/dist/utils/context.js.map +1 -0
  63. package/dist/utils/index.d.ts +5 -0
  64. package/dist/utils/index.js +8 -0
  65. package/dist/utils/index.js.map +1 -0
  66. package/dist/utils/span.d.ts +65 -0
  67. package/dist/utils/span.js +269 -0
  68. package/dist/utils/span.js.map +1 -0
  69. package/dist/utils/spanBuffer.d.ts +94 -0
  70. package/dist/utils/spanBuffer.js +147 -0
  71. package/dist/utils/spanBuffer.js.map +1 -0
  72. package/dist/utils/tracing.d.ts +31 -0
  73. package/dist/utils/tracing.js +239 -0
  74. package/dist/utils/tracing.js.map +1 -0
  75. package/package.json +72 -0
package/dist/main.d.ts ADDED
@@ -0,0 +1,162 @@
1
+ import { WithFunctionType } from "./types/decoratorTypes.js";
2
+ import { RespanOptions, ProcessorConfig } from "./types/clientTypes.js";
3
+ import { withRespanSpanAttributes } from "./contexts/span.js";
4
+ /**
5
+ * Respan client for trace management and instrumentation.
6
+ * This class provides an interface for initializing and managing OpenTelemetry-based tracing
7
+ * for various AI/ML services and frameworks.
8
+ *
9
+ * ## Instrumentation Management
10
+ *
11
+ * ### Automatic Discovery (Default)
12
+ * By default, Respan will attempt to load all available instrumentations automatically:
13
+ * ```typescript
14
+ * const respan = new RespanTelemetry({
15
+ * apiKey: 'your-api-key',
16
+ * logLevel: 'info' // Shows what gets loaded successfully
17
+ * });
18
+ * ```
19
+ *
20
+ * ### Manual Instrumentation (Next.js/Webpack environments)
21
+ * For environments where dynamic imports don't work properly:
22
+ * ```typescript
23
+ * import OpenAI from 'openai';
24
+ * import Anthropic from '@anthropic-ai/sdk';
25
+ *
26
+ * const respan = new RespanTelemetry({
27
+ * apiKey: 'your-api-key',
28
+ * instrumentModules: {
29
+ * openAI: OpenAI,
30
+ * anthropic: Anthropic
31
+ * }
32
+ * });
33
+ * ```
34
+ *
35
+ * ### Disable Specific Instrumentations
36
+ * Block instrumentations you don't want to use:
37
+ * ```typescript
38
+ * const respan = new RespanTelemetry({
39
+ * apiKey: 'your-api-key',
40
+ * disabledInstrumentations: ['bedrock', 'chromaDB', 'qdrant']
41
+ * });
42
+ * ```
43
+ *
44
+ * ### Available Instrumentations (consistent camelCase naming)
45
+ * - `openAI` - OpenAI API instrumentation
46
+ * - `anthropic` - Anthropic API instrumentation
47
+ * - `azureOpenAI` - Azure OpenAI instrumentation
48
+ * - `cohere` - Cohere API instrumentation
49
+ * - `bedrock` - AWS Bedrock instrumentation
50
+ * - `googleVertexAI` - Google Vertex AI instrumentation
51
+ * - `googleAIPlatform` - Google AI Platform instrumentation
52
+ * - `pinecone` - Pinecone vector database instrumentation
53
+ * - `together` - Together AI instrumentation
54
+ * - `langChain` - LangChain framework instrumentation
55
+ * - `llamaIndex` - LlamaIndex framework instrumentation
56
+ * - `chromaDB` - ChromaDB vector database instrumentation
57
+ * - `qdrant` - Qdrant vector database instrumentation
58
+ *
59
+ * ### Debugging Instrumentation Loading
60
+ * Set `logLevel: 'info'` or `logLevel: 'debug'` to see:
61
+ * - Which instrumentations loaded successfully
62
+ * - Which ones failed and installation instructions
63
+ * - Which ones were disabled by configuration
64
+ */
65
+ export declare class RespanTelemetry {
66
+ private options;
67
+ private initialized;
68
+ private initializing;
69
+ constructor(options: RespanOptions);
70
+ private _initialize;
71
+ /**
72
+ * Manually initialize tracing. This is useful if you want to ensure
73
+ * tracing is fully initialized before proceeding.
74
+ */
75
+ initialize(): Promise<void>;
76
+ /**
77
+ * Check if tracing has been initialized
78
+ */
79
+ isInitialized(): boolean;
80
+ withTask: WithFunctionType;
81
+ withWorkflow: WithFunctionType;
82
+ withAgent: WithFunctionType;
83
+ withTool: WithFunctionType;
84
+ withRespanSpanAttributes: typeof withRespanSpanAttributes;
85
+ /**
86
+ * Enable instrumentation for a specific provider
87
+ * @param name - The name of the instrumentation (e.g., 'openai', 'anthropic')
88
+ */
89
+ enableInstrumentation(name: string): Promise<void>;
90
+ /**
91
+ * Enable multiple instrumentations
92
+ * @param names - Array of instrumentation names
93
+ */
94
+ enableInstrumentations(names: string[]): Promise<void>;
95
+ /**
96
+ * Flush and shutdown tracing
97
+ */
98
+ shutdown(): Promise<void>;
99
+ /**
100
+ * Add a processor for routing spans to different destinations.
101
+ *
102
+ * Note: A default processor is automatically configured to send spans to Respan.
103
+ * You only need to call this method if you want to route spans to additional destinations.
104
+ *
105
+ * @param config - Processor configuration
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Add debug processor (in addition to default Respan processor)
110
+ * respan.addProcessor({
111
+ * exporter: new FileExporter("./debug.json"),
112
+ * name: "debug"
113
+ * });
114
+ *
115
+ * // Route specific spans to debug processor
116
+ * await respan.withTask(
117
+ * { name: "my_task", processors: "debug" },
118
+ * async () => { ... }
119
+ * );
120
+ *
121
+ * // Spans without processors attribute go to default Respan processor
122
+ * await respan.withTask(
123
+ * { name: "normal_task" },
124
+ * async () => { ... } // <- Goes to default processor
125
+ * );
126
+ * ```
127
+ */
128
+ addProcessor(config: ProcessorConfig): void;
129
+ /**
130
+ * Get the client API for span management.
131
+ * Provides methods to update spans, add events, record exceptions, etc.
132
+ *
133
+ * @returns The Respan client instance
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const client = respan.getClient();
138
+ * const traceId = client.getCurrentTraceId();
139
+ * client.updateCurrentSpan({
140
+ * respanParams: {
141
+ * customerIdentifier: "user-123"
142
+ * }
143
+ * });
144
+ * ```
145
+ */
146
+ getClient(): import("./utils/client.js").RespanClient;
147
+ /**
148
+ * Get the span buffer manager for manual span control.
149
+ *
150
+ * @returns The span buffer manager
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * const manager = respan.getSpanBufferManager();
155
+ * const buffer = manager.createBuffer("trace-123");
156
+ * buffer.createSpan("step1", { status: "completed" });
157
+ * const spans = buffer.getAllSpans();
158
+ * await manager.processSpans(spans);
159
+ * ```
160
+ */
161
+ getSpanBufferManager(): import("./utils/spanBuffer.js").SpanBufferManager;
162
+ }
package/dist/main.js ADDED
@@ -0,0 +1,212 @@
1
+ import { withTask, withWorkflow, withAgent, withTool } from "./decorators/index.js";
2
+ import { withRespanSpanAttributes } from "./contexts/span.js";
3
+ import { startTracing, forceFlush, addProcessorToSDK } from "./utils/tracing.js";
4
+ import { enableInstrumentation } from "./instrumentation/index.js";
5
+ import { getClient as getClientAPI } from "./utils/client.js";
6
+ import { getSpanBufferManager } from "./utils/spanBuffer.js";
7
+ /**
8
+ * Respan client for trace management and instrumentation.
9
+ * This class provides an interface for initializing and managing OpenTelemetry-based tracing
10
+ * for various AI/ML services and frameworks.
11
+ *
12
+ * ## Instrumentation Management
13
+ *
14
+ * ### Automatic Discovery (Default)
15
+ * By default, Respan will attempt to load all available instrumentations automatically:
16
+ * ```typescript
17
+ * const respan = new RespanTelemetry({
18
+ * apiKey: 'your-api-key',
19
+ * logLevel: 'info' // Shows what gets loaded successfully
20
+ * });
21
+ * ```
22
+ *
23
+ * ### Manual Instrumentation (Next.js/Webpack environments)
24
+ * For environments where dynamic imports don't work properly:
25
+ * ```typescript
26
+ * import OpenAI from 'openai';
27
+ * import Anthropic from '@anthropic-ai/sdk';
28
+ *
29
+ * const respan = new RespanTelemetry({
30
+ * apiKey: 'your-api-key',
31
+ * instrumentModules: {
32
+ * openAI: OpenAI,
33
+ * anthropic: Anthropic
34
+ * }
35
+ * });
36
+ * ```
37
+ *
38
+ * ### Disable Specific Instrumentations
39
+ * Block instrumentations you don't want to use:
40
+ * ```typescript
41
+ * const respan = new RespanTelemetry({
42
+ * apiKey: 'your-api-key',
43
+ * disabledInstrumentations: ['bedrock', 'chromaDB', 'qdrant']
44
+ * });
45
+ * ```
46
+ *
47
+ * ### Available Instrumentations (consistent camelCase naming)
48
+ * - `openAI` - OpenAI API instrumentation
49
+ * - `anthropic` - Anthropic API instrumentation
50
+ * - `azureOpenAI` - Azure OpenAI instrumentation
51
+ * - `cohere` - Cohere API instrumentation
52
+ * - `bedrock` - AWS Bedrock instrumentation
53
+ * - `googleVertexAI` - Google Vertex AI instrumentation
54
+ * - `googleAIPlatform` - Google AI Platform instrumentation
55
+ * - `pinecone` - Pinecone vector database instrumentation
56
+ * - `together` - Together AI instrumentation
57
+ * - `langChain` - LangChain framework instrumentation
58
+ * - `llamaIndex` - LlamaIndex framework instrumentation
59
+ * - `chromaDB` - ChromaDB vector database instrumentation
60
+ * - `qdrant` - Qdrant vector database instrumentation
61
+ *
62
+ * ### Debugging Instrumentation Loading
63
+ * Set `logLevel: 'info'` or `logLevel: 'debug'` to see:
64
+ * - Which instrumentations loaded successfully
65
+ * - Which ones failed and installation instructions
66
+ * - Which ones were disabled by configuration
67
+ */
68
+ export class RespanTelemetry {
69
+ options;
70
+ initialized = false;
71
+ initializing = false;
72
+ constructor(options) {
73
+ this.options = {
74
+ appName: options.appName || process.env.RESPAN_APP_NAME || "default",
75
+ disableBatch: options.disableBatch || false,
76
+ baseURL: options.baseURL || process.env.RESPAN_BASE_URL || "https://api.respan.co",
77
+ apiKey: options.apiKey || process.env.RESPAN_API_KEY || "",
78
+ instrumentModules: options.instrumentModules || {},
79
+ disabledInstrumentations: options.disabledInstrumentations || [],
80
+ tracingEnabled: options.tracingEnabled !== false,
81
+ traceContent: options.traceContent !== false,
82
+ logLevel: options.logLevel || "error",
83
+ silenceInitializationMessage: options.silenceInitializationMessage || false,
84
+ };
85
+ // Don't auto-initialize - let user call initialize() explicitly
86
+ // This prevents timing issues and double initialization
87
+ }
88
+ async _initialize() {
89
+ if (this.initialized || this.initializing) {
90
+ return;
91
+ }
92
+ this.initializing = true;
93
+ try {
94
+ await startTracing(this.options);
95
+ this.initialized = true;
96
+ }
97
+ catch (error) {
98
+ console.error("Failed to initialize Respan tracing:", error);
99
+ }
100
+ finally {
101
+ this.initializing = false;
102
+ }
103
+ }
104
+ /**
105
+ * Manually initialize tracing. This is useful if you want to ensure
106
+ * tracing is fully initialized before proceeding.
107
+ */
108
+ async initialize() {
109
+ await this._initialize();
110
+ }
111
+ /**
112
+ * Check if tracing has been initialized
113
+ */
114
+ isInitialized() {
115
+ return this.initialized;
116
+ }
117
+ withTask = withTask;
118
+ withWorkflow = withWorkflow;
119
+ withAgent = withAgent;
120
+ withTool = withTool;
121
+ withRespanSpanAttributes = withRespanSpanAttributes;
122
+ /**
123
+ * Enable instrumentation for a specific provider
124
+ * @param name - The name of the instrumentation (e.g., 'openai', 'anthropic')
125
+ */
126
+ async enableInstrumentation(name) {
127
+ await enableInstrumentation(name);
128
+ }
129
+ /**
130
+ * Enable multiple instrumentations
131
+ * @param names - Array of instrumentation names
132
+ */
133
+ async enableInstrumentations(names) {
134
+ await Promise.all(names.map(name => enableInstrumentation(name)));
135
+ }
136
+ /**
137
+ * Flush and shutdown tracing
138
+ */
139
+ async shutdown() {
140
+ await forceFlush();
141
+ }
142
+ /**
143
+ * Add a processor for routing spans to different destinations.
144
+ *
145
+ * Note: A default processor is automatically configured to send spans to Respan.
146
+ * You only need to call this method if you want to route spans to additional destinations.
147
+ *
148
+ * @param config - Processor configuration
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // Add debug processor (in addition to default Respan processor)
153
+ * respan.addProcessor({
154
+ * exporter: new FileExporter("./debug.json"),
155
+ * name: "debug"
156
+ * });
157
+ *
158
+ * // Route specific spans to debug processor
159
+ * await respan.withTask(
160
+ * { name: "my_task", processors: "debug" },
161
+ * async () => { ... }
162
+ * );
163
+ *
164
+ * // Spans without processors attribute go to default Respan processor
165
+ * await respan.withTask(
166
+ * { name: "normal_task" },
167
+ * async () => { ... } // <- Goes to default processor
168
+ * );
169
+ * ```
170
+ */
171
+ addProcessor(config) {
172
+ addProcessorToSDK(config);
173
+ }
174
+ /**
175
+ * Get the client API for span management.
176
+ * Provides methods to update spans, add events, record exceptions, etc.
177
+ *
178
+ * @returns The Respan client instance
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const client = respan.getClient();
183
+ * const traceId = client.getCurrentTraceId();
184
+ * client.updateCurrentSpan({
185
+ * respanParams: {
186
+ * customerIdentifier: "user-123"
187
+ * }
188
+ * });
189
+ * ```
190
+ */
191
+ getClient() {
192
+ return getClientAPI();
193
+ }
194
+ /**
195
+ * Get the span buffer manager for manual span control.
196
+ *
197
+ * @returns The span buffer manager
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const manager = respan.getSpanBufferManager();
202
+ * const buffer = manager.createBuffer("trace-123");
203
+ * buffer.createSpan("step1", { status: "completed" });
204
+ * const spans = buffer.getAllSpans();
205
+ * await manager.processSpans(spans);
206
+ * ```
207
+ */
208
+ getSpanBufferManager() {
209
+ return getSpanBufferManager();
210
+ }
211
+ }
212
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { Context } from "@opentelemetry/api";
2
+ import { SpanProcessor, ReadableSpan } from "@opentelemetry/sdk-trace-base";
3
+ import { MultiProcessorManager } from "./manager.js";
4
+ /**
5
+ * Composite processor that combines filtering with multi-processor routing.
6
+ *
7
+ * Flow:
8
+ * 1. Filter spans (keep only user-decorated spans and their children)
9
+ * 2. Apply postprocess callback if configured
10
+ * 3. Route filtered spans to appropriate processors
11
+ *
12
+ * This ensures only meaningful spans are routed to processors.
13
+ */
14
+ export declare class RespanCompositeProcessor implements SpanProcessor {
15
+ private readonly _processorManager;
16
+ private readonly _postprocessCallback?;
17
+ constructor(processorManager: MultiProcessorManager, postprocessCallback?: (span: ReadableSpan) => void);
18
+ onStart(span: ReadableSpan, parentContext: Context): void;
19
+ onEnd(span: ReadableSpan): void;
20
+ shutdown(): Promise<void>;
21
+ forceFlush(): Promise<void>;
22
+ /**
23
+ * Get the entity path from context
24
+ */
25
+ /**
26
+ * Get the processor manager (for adding new processors)
27
+ */
28
+ getProcessorManager(): MultiProcessorManager;
29
+ }
@@ -0,0 +1,106 @@
1
+ import { SpanAttributes } from "@traceloop/ai-semantic-conventions";
2
+ import { getEntityPath } from "../utils/context.js";
3
+ /**
4
+ * Composite processor that combines filtering with multi-processor routing.
5
+ *
6
+ * Flow:
7
+ * 1. Filter spans (keep only user-decorated spans and their children)
8
+ * 2. Apply postprocess callback if configured
9
+ * 3. Route filtered spans to appropriate processors
10
+ *
11
+ * This ensures only meaningful spans are routed to processors.
12
+ */
13
+ export class RespanCompositeProcessor {
14
+ _processorManager;
15
+ _postprocessCallback;
16
+ constructor(processorManager, postprocessCallback) {
17
+ this._processorManager = processorManager;
18
+ this._postprocessCallback = postprocessCallback;
19
+ }
20
+ onStart(span, parentContext) {
21
+ // Check if this span is being created within an entity context
22
+ // If so, add the entityPath attribute so it gets preserved by our filtering
23
+ const entityPath = getEntityPath(parentContext);
24
+ if (entityPath && !span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND]) {
25
+ // This is an auto-instrumentation span within an entity context
26
+ // Add the entityPath attribute so it doesn't get filtered out
27
+ console.debug(`[Respan Debug] Adding entityPath to auto-instrumentation span: ${span.name} (entityPath: ${entityPath})`);
28
+ // We need to cast to any to set attributes during onStart
29
+ span.setAttribute(SpanAttributes.TRACELOOP_ENTITY_PATH, entityPath);
30
+ }
31
+ // Forward to processor manager
32
+ this._processorManager.onStart(span, parentContext);
33
+ }
34
+ onEnd(span) {
35
+ const spanKind = span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND];
36
+ const entityPath = span.attributes[SpanAttributes.TRACELOOP_ENTITY_PATH];
37
+ // Apply postprocess callback if provided
38
+ if (this._postprocessCallback) {
39
+ try {
40
+ this._postprocessCallback(span);
41
+ }
42
+ catch (error) {
43
+ console.error("[Respan] Error in span postprocess callback:", error);
44
+ }
45
+ }
46
+ // Check if this is an LLM instrumentation span (OpenAI, Anthropic, etc.)
47
+ // These have gen_ai.* or llm.* attributes
48
+ const isLLMSpan = span.attributes['gen_ai.system'] !== undefined ||
49
+ span.attributes['llm.system'] !== undefined ||
50
+ span.attributes['gen_ai.request.model'] !== undefined ||
51
+ span.name.includes('anthropic.messages') ||
52
+ span.name.includes('openai.chat') ||
53
+ span.name.includes('chat.completions');
54
+ // Filter: only process spans that are user-decorated, within entity context, or LLM calls
55
+ if (spanKind) {
56
+ // This is a user-decorated span (withWorkflow, withTask, etc.) - make it a root span
57
+ console.debug(`[Respan Debug] Processing user-decorated span as root: ${span.name} (kind: ${spanKind})`);
58
+ // Create a wrapper that makes the span appear as a root span
59
+ const rootSpan = Object.create(Object.getPrototypeOf(span));
60
+ Object.assign(rootSpan, span);
61
+ // Override the parentSpanId to make it a root span
62
+ Object.defineProperty(rootSpan, 'parentSpanId', {
63
+ value: undefined,
64
+ writable: false,
65
+ configurable: true,
66
+ enumerable: true
67
+ });
68
+ // Route to processors
69
+ this._processorManager.onEnd(rootSpan);
70
+ }
71
+ else if (entityPath && entityPath !== "") {
72
+ // This span doesn't have a kind but has entityPath - it's a child span within a withEntity context
73
+ // Keep it as a normal child span (preserve parent relationships)
74
+ console.debug(`[Respan Debug] Processing child span within entity context: ${span.name} (entityPath: ${entityPath})`);
75
+ // Route to processors
76
+ this._processorManager.onEnd(span);
77
+ }
78
+ else if (isLLMSpan) {
79
+ // This is an LLM instrumentation span - keep it!
80
+ console.debug(`[Respan Debug] Processing LLM instrumentation span: ${span.name}`);
81
+ // Route to processors
82
+ this._processorManager.onEnd(span);
83
+ }
84
+ else {
85
+ // This span has none of the above - it's pure auto-instrumentation noise (HTTP calls, etc.)
86
+ console.debug(`[Respan Debug] Filtering out auto-instrumentation span: ${span.name}`);
87
+ }
88
+ }
89
+ async shutdown() {
90
+ await this._processorManager.shutdown();
91
+ }
92
+ async forceFlush() {
93
+ await this._processorManager.forceFlush();
94
+ }
95
+ /**
96
+ * Get the entity path from context
97
+ */
98
+ // Removed - now using imported getEntityPath function
99
+ /**
100
+ * Get the processor manager (for adding new processors)
101
+ */
102
+ getProcessorManager() {
103
+ return this._processorManager;
104
+ }
105
+ }
106
+ //# sourceMappingURL=composite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composite.js","sourceRoot":"","sources":["../../src/processor/composite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Context } from "@opentelemetry/api";
2
+ import { SpanProcessor, ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
3
+ /**
4
+ * Custom span processor that implements intelligent span filtering:
5
+ * 1. User-decorated spans (withEntity) become root spans (no parent hierarchy)
6
+ * 2. Auto-instrumentation spans within withEntity context get entityPath and are preserved
7
+ * 3. Pure auto-instrumentation spans (no context) are filtered out
8
+ *
9
+ * This eliminates noise while preserving useful spans like OpenAI/HTTP calls within user workflows.
10
+ */
11
+ export declare class RespanFilteringSpanProcessor implements SpanProcessor {
12
+ private readonly _spanProcessor;
13
+ private readonly _postprocessCallback?;
14
+ constructor(exporter: SpanExporter, postprocessCallback?: (span: ReadableSpan) => void);
15
+ onStart(span: ReadableSpan, parentContext: Context): void;
16
+ onEnd(span: ReadableSpan): void;
17
+ shutdown(): Promise<void>;
18
+ forceFlush(): Promise<void>;
19
+ }
@@ -0,0 +1,78 @@
1
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
2
+ import { SpanAttributes } from "@traceloop/ai-semantic-conventions";
3
+ import { getEntityPath } from "../utils/context.js";
4
+ /**
5
+ * Custom span processor that implements intelligent span filtering:
6
+ * 1. User-decorated spans (withEntity) become root spans (no parent hierarchy)
7
+ * 2. Auto-instrumentation spans within withEntity context get entityPath and are preserved
8
+ * 3. Pure auto-instrumentation spans (no context) are filtered out
9
+ *
10
+ * This eliminates noise while preserving useful spans like OpenAI/HTTP calls within user workflows.
11
+ */
12
+ export class RespanFilteringSpanProcessor {
13
+ _spanProcessor;
14
+ _postprocessCallback;
15
+ constructor(exporter, postprocessCallback) {
16
+ this._spanProcessor = new BatchSpanProcessor(exporter);
17
+ this._postprocessCallback = postprocessCallback;
18
+ }
19
+ onStart(span, parentContext) {
20
+ // Check if this span is being created within an entity context
21
+ // If so, add the entityPath attribute so it gets preserved by our filtering
22
+ const entityPath = getEntityPath(parentContext);
23
+ if (entityPath && !span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND]) {
24
+ // This is an auto-instrumentation span within an entity context
25
+ // Add the entityPath attribute so it doesn't get filtered out
26
+ console.debug(`[Respan Debug] Adding entityPath to auto-instrumentation span: ${span.name} (entityPath: ${entityPath})`);
27
+ // We need to cast to any to set attributes during onStart
28
+ span.setAttribute(SpanAttributes.TRACELOOP_ENTITY_PATH, entityPath);
29
+ }
30
+ // Always call onStart for all spans to maintain proper span lifecycle
31
+ this._spanProcessor.onStart(span, parentContext);
32
+ }
33
+ onEnd(span) {
34
+ const spanKind = span.attributes[SpanAttributes.TRACELOOP_SPAN_KIND];
35
+ const entityPath = span.attributes[SpanAttributes.TRACELOOP_ENTITY_PATH];
36
+ // Apply postprocess callback if provided
37
+ if (this._postprocessCallback) {
38
+ try {
39
+ this._postprocessCallback(span);
40
+ }
41
+ catch (error) {
42
+ console.error("[Respan] Error in span postprocess callback:", error);
43
+ }
44
+ }
45
+ if (spanKind) {
46
+ // This is a user-decorated span (withWorkflow, withTask, etc.) - make it a root span
47
+ console.debug(`[Respan Debug] Sending user-decorated span as root: ${span.name} (kind: ${spanKind})`);
48
+ // Create a wrapper that makes the span appear as a root span
49
+ const rootSpan = Object.create(Object.getPrototypeOf(span));
50
+ Object.assign(rootSpan, span);
51
+ // Override the parentSpanId to make it a root span
52
+ Object.defineProperty(rootSpan, 'parentSpanId', {
53
+ value: undefined,
54
+ writable: false,
55
+ configurable: true,
56
+ enumerable: true
57
+ });
58
+ this._spanProcessor.onEnd(rootSpan);
59
+ }
60
+ else if (entityPath && entityPath !== "") {
61
+ // This span doesn't have a kind but has entityPath - it's a child span within a withEntity context
62
+ // Keep it as a normal child span (preserve parent relationships)
63
+ console.debug(`[Respan Debug] Sending child span within entity context: ${span.name} (entityPath: ${entityPath})`);
64
+ this._spanProcessor.onEnd(span);
65
+ }
66
+ else {
67
+ // This span has neither kind nor entityPath - it's pure auto-instrumentation noise
68
+ console.debug(`[Respan Debug] Filtering out auto-instrumentation span: ${span.name} (no TRACELOOP_SPAN_KIND or entityPath)`);
69
+ }
70
+ }
71
+ shutdown() {
72
+ return this._spanProcessor.shutdown();
73
+ }
74
+ forceFlush() {
75
+ return this._spanProcessor.forceFlush();
76
+ }
77
+ }
78
+ //# sourceMappingURL=filtering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filtering.js","sourceRoot":"","sources":["../../src/processor/filtering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './filtering.js';
2
+ export * from './manager.js';
3
+ export * from './composite.js';
@@ -0,0 +1,4 @@
1
+ export * from './filtering.js';
2
+ export * from './manager.js';
3
+ export * from './composite.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/processor/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}