From bc319d835ad7e1620bf93a0ee064b24ad3f2e693 Mon Sep 17 00:00:00 2001 From: Gal Kleinman Date: Thu, 24 Apr 2025 15:50:52 +0300 Subject: [PATCH 1/3] fix(traceloop-sdk): omit spans of non-traceloop instrumentations by default when using standalone processor --- packages/sample-app/src/sample_otel_sdk.ts | 5 +- .../traceloop-sdk/src/lib/tracing/index.ts | 11 ++-- .../src/lib/tracing/span-processor.ts | 60 ++++++++++++++++++- .../traceloop-sdk/src/lib/tracing/tracing.ts | 2 +- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/packages/sample-app/src/sample_otel_sdk.ts b/packages/sample-app/src/sample_otel_sdk.ts index 29232a95..37a0da1b 100644 --- a/packages/sample-app/src/sample_otel_sdk.ts +++ b/packages/sample-app/src/sample_otel_sdk.ts @@ -1,6 +1,6 @@ import { NodeSDK } from "@opentelemetry/sdk-node"; import { Resource } from "@opentelemetry/resources"; -import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; +import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"; import { createSpanProcessor, withTask, @@ -13,12 +13,13 @@ const traceloopSpanProcessor = createSpanProcessor({ apiKey: process.env.TRACELOOP_API_KEY, baseUrl: process.env.TRACELOOP_BASE_URL, disableBatch: true, + allowedInstrumentationLibraries: ["my-sample-app"], }); // Initialize the OpenTelemetry SDK with Traceloop's span processor const sdk = new NodeSDK({ resource: new Resource({ - [SemanticResourceAttributes.SERVICE_NAME]: "my-sample-app", + [ATTR_SERVICE_NAME]: "my-sample-app", }), spanProcessors: [traceloopSpanProcessor], }); diff --git a/packages/traceloop-sdk/src/lib/tracing/index.ts b/packages/traceloop-sdk/src/lib/tracing/index.ts index 3d425f0d..f66e6a09 100644 --- a/packages/traceloop-sdk/src/lib/tracing/index.ts +++ b/packages/traceloop-sdk/src/lib/tracing/index.ts @@ -4,7 +4,7 @@ import { baggageUtils } from "@opentelemetry/core"; import { context, diag } from "@opentelemetry/api"; import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto"; import { Resource } from "@opentelemetry/resources"; -import { SEMRESATTRS_SERVICE_NAME } from "@opentelemetry/semantic-conventions"; +import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"; import { Instrumentation } from "@opentelemetry/instrumentation"; import { InitializeOptions } from "../interfaces"; import { Telemetry } from "../telemetry/telemetry"; @@ -25,7 +25,10 @@ import { LangChainInstrumentation } from "@traceloop/instrumentation-langchain"; import { ChromaDBInstrumentation } from "@traceloop/instrumentation-chromadb"; import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant"; import { TogetherInstrumentation } from "@traceloop/instrumentation-together"; -import { createSpanProcessor } from "./span-processor"; +import { + ALL_INSTRUMENTATION_LIBRARIES, + createSpanProcessor, +} from "./span-processor"; let _sdk: NodeSDK; let _spanProcessor: SpanProcessor; @@ -268,6 +271,7 @@ export const startTracing = (options: InitializeOptions) => { disableBatch: options.disableBatch, exporter: traceExporter, headers, + allowedInstrumentationLibraries: ALL_INSTRUMENTATION_LIBRARIES, }); const spanProcessors: SpanProcessor[] = [_spanProcessor]; @@ -277,8 +281,7 @@ export const startTracing = (options: InitializeOptions) => { _sdk = new NodeSDK({ resource: new Resource({ - [SEMRESATTRS_SERVICE_NAME]: - options.appName || process.env.npm_package_name, + [ATTR_SERVICE_NAME]: options.appName || process.env.npm_package_name, }), spanProcessors, contextManager: options.contextManager, diff --git a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts index 7dc69cd3..f20da8eb 100644 --- a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts +++ b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts @@ -15,6 +15,9 @@ import { } from "./tracing"; import { SpanAttributes } from "@traceloop/ai-semantic-conventions"; +export const ALL_INSTRUMENTATION_LIBRARIES = "all" as const; +type AllInstrumentationLibraries = typeof ALL_INSTRUMENTATION_LIBRARIES; + export interface SpanProcessorOptions { /** * The API Key for sending traces data. Optional. @@ -44,6 +47,14 @@ export interface SpanProcessorOptions { * The headers to be sent with the traces data. Optional. */ headers?: Record; + + /** + * The instrumentation libraries to be allowed in the traces. Optional. + * Defaults to Traceloop instrumentation libraries. + * If set to ALL_INSTRUMENTATION_LIBRARIES, all instrumentation libraries will be allowed. + * If set to an array of instrumentation libraries, only traceloop instrumentation libraries and the specified instrumentation libraries will be allowed. + */ + allowedInstrumentationLibraries?: string[] | AllInstrumentationLibraries; } /** @@ -78,11 +89,40 @@ export const createSpanProcessor = ( const originalOnEnd = spanProcessor.onEnd.bind(spanProcessor); spanProcessor.onStart = onSpanStart; - spanProcessor.onEnd = onSpanEnd(originalOnEnd); + + if ( + options.allowedInstrumentationLibraries === ALL_INSTRUMENTATION_LIBRARIES + ) { + spanProcessor.onEnd = onSpanEnd(originalOnEnd); + } else { + const instrumentationLibraries = traceloopInstrumentationLibraries; + + if (options.allowedInstrumentationLibraries) { + instrumentationLibraries.push(...options.allowedInstrumentationLibraries); + } + + spanProcessor.onEnd = onSpanEnd(originalOnEnd, instrumentationLibraries); + } return spanProcessor; }; +export const traceloopInstrumentationLibraries = [ + "@traceloop/node-server-sdk", + "@traceloop/instrumentation-openai", + "@traceloop/instrumentation-langchain", + "@traceloop/instrumentation-chroma", + "@traceloop/instrumentation-anthropic", + "@traceloop/instrumentation-azure", + "@traceloop/instrumentation-llamaindex", + "@traceloop/instrumentation-vertexai", + "@traceloop/instrumentation-bedrock", + "@traceloop/instrumentation-cohere", + "@traceloop/instrumentation-pinecone", + "@traceloop/instrumentation-qdrant", + "@traceloop/instrumentation-together", +]; + /** * Handles span start event, enriching it with workflow and entity information */ @@ -119,8 +159,24 @@ const onSpanStart = (span: Span): void => { /** * Handles span end event, adapting attributes for Vercel AI compatibility */ -const onSpanEnd = (originalOnEnd: (span: ReadableSpan) => void) => { +const onSpanEnd = ( + originalOnEnd: (span: ReadableSpan) => void, + instrumentationLibraries?: string[], +) => { + console.log("instrumentation libraries", instrumentationLibraries); return (span: ReadableSpan): void => { + console.log( + "instrumentation library name", + span.instrumentationLibrary.name, + ); + if ( + instrumentationLibraries && + !instrumentationLibraries.includes(span.instrumentationLibrary.name) + ) { + console.log("skipping span", span.instrumentationLibrary.name); + return; + } + // Vercel AI Adapters const attributes = span.attributes; diff --git a/packages/traceloop-sdk/src/lib/tracing/tracing.ts b/packages/traceloop-sdk/src/lib/tracing/tracing.ts index 97813f05..ef91f010 100644 --- a/packages/traceloop-sdk/src/lib/tracing/tracing.ts +++ b/packages/traceloop-sdk/src/lib/tracing/tracing.ts @@ -1,7 +1,7 @@ import { trace, createContextKey } from "@opentelemetry/api"; import { Context } from "@opentelemetry/api/build/src/context/types"; -const TRACER_NAME = "traceloop.tracer"; +const TRACER_NAME = "@traceloop/node-server-sdk"; export const WORKFLOW_NAME_KEY = createContextKey("workflow_name"); export const ENTITY_NAME_KEY = createContextKey("entity_name"); export const ASSOCATION_PROPERTIES_KEY = createContextKey( From a03bf3074af43f823b13f3d5f215a3d77d71fe0e Mon Sep 17 00:00:00 2001 From: Gal Kleinman Date: Thu, 24 Apr 2025 15:53:10 +0300 Subject: [PATCH 2/3] remove console logs --- packages/traceloop-sdk/src/lib/tracing/span-processor.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts index f20da8eb..a0c32ee8 100644 --- a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts +++ b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts @@ -163,17 +163,11 @@ const onSpanEnd = ( originalOnEnd: (span: ReadableSpan) => void, instrumentationLibraries?: string[], ) => { - console.log("instrumentation libraries", instrumentationLibraries); return (span: ReadableSpan): void => { - console.log( - "instrumentation library name", - span.instrumentationLibrary.name, - ); if ( instrumentationLibraries && !instrumentationLibraries.includes(span.instrumentationLibrary.name) ) { - console.log("skipping span", span.instrumentationLibrary.name); return; } From b1b99d3ffe45a82ff096bb8dfe0f60fe766f45bb Mon Sep 17 00:00:00 2001 From: Gal Kleinman <33281963+galkleinman@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:58:13 +0300 Subject: [PATCH 3/3] Update packages/traceloop-sdk/src/lib/tracing/span-processor.ts Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --- packages/traceloop-sdk/src/lib/tracing/span-processor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts index a0c32ee8..02c483de 100644 --- a/packages/traceloop-sdk/src/lib/tracing/span-processor.ts +++ b/packages/traceloop-sdk/src/lib/tracing/span-processor.ts @@ -95,7 +95,7 @@ export const createSpanProcessor = ( ) { spanProcessor.onEnd = onSpanEnd(originalOnEnd); } else { - const instrumentationLibraries = traceloopInstrumentationLibraries; + const instrumentationLibraries = [...traceloopInstrumentationLibraries]; if (options.allowedInstrumentationLibraries) { instrumentationLibraries.push(...options.allowedInstrumentationLibraries);