Skip to content

Commit c0c6b94

Browse files
authored
Merge branch 'main' into feat/langchain-callback-instrumentation
2 parents 6af4c33 + fabc504 commit c0c6b94

File tree

6 files changed

+81
-33
lines changed

6 files changed

+81
-33
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [0.16.2](https://github.com/traceloop/openllmetry-js/compare/v0.16.1...v0.16.2) (2025-08-17)
7+
8+
### Bug Fixes
9+
10+
- **sdk:** otel v1 resource backward compatibility ([#648](https://github.com/traceloop/openllmetry-js/issues/648)) ([0c21b36](https://github.com/traceloop/openllmetry-js/commit/0c21b3616ff6cbe4035158f2cc85764de0f34a7d))
11+
612
## [0.16.1](https://github.com/traceloop/openllmetry-js/compare/v0.16.0...v0.16.1) (2025-08-15)
713

814
### Bug Fixes

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
3-
"version": "0.16.1",
3+
"version": "0.16.2",
44
"packages": ["packages/*"],
55
"useNx": true
66
}

packages/traceloop-sdk/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [0.16.2](https://github.com/traceloop/openllmetry-js/compare/v0.16.1...v0.16.2) (2025-08-17)
7+
8+
### Bug Fixes
9+
10+
- **sdk:** otel v1 resource backward compatibility ([#648](https://github.com/traceloop/openllmetry-js/issues/648)) ([0c21b36](https://github.com/traceloop/openllmetry-js/commit/0c21b3616ff6cbe4035158f2cc85764de0f34a7d))
11+
612
## [0.16.1](https://github.com/traceloop/openllmetry-js/compare/v0.16.0...v0.16.1) (2025-08-15)
713

814
### Bug Fixes

packages/traceloop-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@traceloop/node-server-sdk",
3-
"version": "0.16.1",
3+
"version": "0.16.2",
44
"description": "Traceloop Software Development Kit (SDK) for Node.js",
55
"main": "dist/index.js",
66
"module": "dist/index.mjs",

packages/traceloop-sdk/src/lib/tracing/index.ts

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NodeSDK } from "@opentelemetry/sdk-node";
22
import { SpanProcessor } from "@opentelemetry/sdk-trace-node";
33
import { context, diag } from "@opentelemetry/api";
44
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
5-
import { resourceFromAttributes, Resource } from "@opentelemetry/resources";
5+
import { Resource } from "@opentelemetry/resources";
66
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
77
import { Instrumentation } from "@opentelemetry/instrumentation";
88
import { InitializeOptions } from "../interfaces";
@@ -305,35 +305,10 @@ export const startTracing = (options: InitializeOptions) => {
305305
spanProcessors.push(options.processor);
306306
}
307307

308-
// Create resource with proper detection and defensive handling for OTLP serialization
309-
const serviceName =
310-
options.appName || process.env.npm_package_name || "unknown-service";
311-
let resource: Resource;
312-
313-
try {
314-
// Create our custom resource with service name and let NodeSDK handle default detection
315-
resource = resourceFromAttributes({
316-
[ATTR_SERVICE_NAME]: serviceName,
317-
});
318-
319-
// Defensive check to prevent OTLP serialization errors
320-
if (!resource || typeof resource !== "object") {
321-
throw new Error("Invalid resource object");
322-
}
323-
324-
if (!resource.attributes || typeof resource.attributes !== "object") {
325-
throw new Error("Resource missing attributes");
326-
}
327-
} catch (error) {
328-
// Fallback: create a basic resource manually
329-
diag.warn(
330-
"Failed to create resource with resourceFromAttributes, using fallback",
331-
error,
332-
);
333-
resource = resourceFromAttributes({
334-
[ATTR_SERVICE_NAME]: serviceName,
335-
});
336-
}
308+
const resource = createResource({
309+
[ATTR_SERVICE_NAME]:
310+
options.appName || process.env.npm_package_name || "unknown_service",
311+
});
337312

338313
_sdk = new NodeSDK({
339314
resource,
@@ -376,3 +351,17 @@ export const shouldSendTraces = () => {
376351
export const forceFlush = async () => {
377352
await _spanProcessor.forceFlush();
378353
};
354+
355+
// Compatibility function for creating resources that works with both OTel v1.x and v2.x
356+
function createResource(attributes: Record<string, any>): Resource {
357+
// Import the resource module at runtime to handle both v1.x and v2.x
358+
const resourcesModule = require("@opentelemetry/resources");
359+
360+
// Try to use resourceFromAttributes if it exists (OTel v2.x)
361+
if (resourcesModule.resourceFromAttributes) {
362+
return resourcesModule.resourceFromAttributes(attributes);
363+
}
364+
365+
// Fallback to constructor for OTel v1.x
366+
return new resourcesModule.Resource(attributes);
367+
}

packages/traceloop-sdk/src/lib/tracing/span-processor.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,52 @@ const onSpanStart = (span: Span): void => {
157157
}
158158
};
159159

160+
/**
161+
* Ensures span compatibility between OTel v1.x and v2.x for OTLP transformer
162+
*/
163+
const ensureSpanCompatibility = (span: ReadableSpan): ReadableSpan => {
164+
const spanAny = span as any;
165+
166+
// If the span already has instrumentationLibrary, it's compatible (OTel v2.x)
167+
if (spanAny.instrumentationLibrary) {
168+
return span;
169+
}
170+
171+
// If it has instrumentationScope but no instrumentationLibrary (OTel v1.x),
172+
// add instrumentationLibrary as an alias to prevent OTLP transformer errors
173+
if (spanAny.instrumentationScope) {
174+
// Create a proxy that provides both properties
175+
return new Proxy(span, {
176+
get(target, prop) {
177+
if (prop === "instrumentationLibrary") {
178+
return (target as any).instrumentationScope;
179+
}
180+
return (target as any)[prop];
181+
},
182+
}) as ReadableSpan;
183+
}
184+
185+
// Fallback: add both properties with defaults
186+
return new Proxy(span, {
187+
get(target, prop) {
188+
if (
189+
prop === "instrumentationLibrary" ||
190+
prop === "instrumentationScope"
191+
) {
192+
return {
193+
name: "unknown",
194+
version: undefined,
195+
schemaUrl: undefined,
196+
};
197+
}
198+
return (target as any)[prop];
199+
},
200+
}) as ReadableSpan;
201+
};
202+
160203
/**
161204
* Handles span end event, adapting attributes for Vercel AI compatibility
205+
* and ensuring OTLP transformer compatibility
162206
*/
163207
const onSpanEnd = (
164208
originalOnEnd: (span: ReadableSpan) => void,
@@ -178,6 +222,9 @@ const onSpanEnd = (
178222
// Apply AI SDK transformations (if needed)
179223
transformAiSdkSpan(span);
180224

181-
originalOnEnd(span);
225+
// Ensure OTLP transformer compatibility
226+
const compatibleSpan = ensureSpanCompatibility(span);
227+
228+
originalOnEnd(compatibleSpan);
182229
};
183230
};

0 commit comments

Comments
 (0)