Skip to content

Commit 252e521

Browse files
committed
updates
1 parent c025836 commit 252e521

5 files changed

Lines changed: 54 additions & 53 deletions

File tree

dev-packages/node-integration-tests/suites/tracing/langchain/test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,42 +444,42 @@ describe('LangChain integration', () => {
444444
// embedQuery span
445445
expect.objectContaining({
446446
data: expect.objectContaining({
447-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embed',
447+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
448448
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
449449
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
450450
[GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',
451451
[GEN_AI_REQUEST_MODEL_ATTRIBUTE]: 'text-embedding-3-small',
452452
[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE]: 1536,
453453
}),
454-
description: 'embed text-embedding-3-small',
454+
description: 'embeddings text-embedding-3-small',
455455
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
456456
origin: 'auto.ai.langchain',
457457
status: 'ok',
458458
}),
459459
// embedDocuments span
460460
expect.objectContaining({
461461
data: expect.objectContaining({
462-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embed_many',
462+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
463463
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
464464
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
465465
[GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',
466466
[GEN_AI_REQUEST_MODEL_ATTRIBUTE]: 'text-embedding-3-small',
467467
}),
468-
description: 'embed_many text-embedding-3-small',
468+
description: 'embeddings text-embedding-3-small',
469469
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
470470
origin: 'auto.ai.langchain',
471471
status: 'ok',
472472
}),
473473
// Error span
474474
expect.objectContaining({
475475
data: expect.objectContaining({
476-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embed',
476+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
477477
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
478478
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
479479
[GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',
480480
[GEN_AI_REQUEST_MODEL_ATTRIBUTE]: 'error-model',
481481
}),
482-
description: 'embed error-model',
482+
description: 'embeddings error-model',
483483
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
484484
origin: 'auto.ai.langchain',
485485
status: 'internal_error',
@@ -493,25 +493,25 @@ describe('LangChain integration', () => {
493493
// embedQuery span with input recorded
494494
expect.objectContaining({
495495
data: expect.objectContaining({
496-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embed',
496+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
497497
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
498498
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
499499
[GEN_AI_SYSTEM_ATTRIBUTE]: 'openai',
500500
[GEN_AI_REQUEST_MODEL_ATTRIBUTE]: 'text-embedding-3-small',
501501
[GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE]: 'Hello world',
502502
}),
503-
description: 'embed text-embedding-3-small',
503+
description: 'embeddings text-embedding-3-small',
504504
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
505505
origin: 'auto.ai.langchain',
506506
status: 'ok',
507507
}),
508508
// embedDocuments span with input recorded
509509
expect.objectContaining({
510510
data: expect.objectContaining({
511-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embed_many',
511+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
512512
[GEN_AI_EMBEDDINGS_INPUT_ATTRIBUTE]: JSON.stringify(['First document', 'Second document']),
513513
}),
514-
description: 'embed_many text-embedding-3-small',
514+
description: 'embeddings text-embedding-3-small',
515515
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
516516
origin: 'auto.ai.langchain',
517517
status: 'ok',

packages/core/src/tracing/langchain/embeddings.ts

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import { resolveAIRecordingOptions } from '../ai/utils';
1616
import { LANGCHAIN_ORIGIN } from './constants';
1717
import type { LangChainOptions } from './types';
1818

19-
type EmbeddingOperationName = 'embed' | 'embed_many';
20-
2119
/**
2220
* Infers the AI provider system name from the embedding class constructor name.
2321
*/
@@ -36,19 +34,16 @@ function inferSystemFromClassName(name: string): string | undefined {
3634
/**
3735
* Extracts span attributes from a LangChain embedding class instance.
3836
*/
39-
function extractEmbeddingAttributes(
40-
instance: unknown,
41-
operationName: EmbeddingOperationName,
42-
): Record<string, SpanAttributeValue> {
43-
const inst = (instance ?? {}) as Record<string, unknown>;
37+
function extractEmbeddingAttributes(instance: unknown): Record<string, SpanAttributeValue> {
38+
const embeddingsInstance = (instance ?? {}) as Record<string, unknown>;
4439

4540
const attributes: Record<string, SpanAttributeValue> = {
4641
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGCHAIN_ORIGIN,
4742
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
48-
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: operationName,
43+
[GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'embeddings',
4944
};
5045

51-
const modelName = inst.model ?? inst.modelName ?? 'unknown';
46+
const modelName = embeddingsInstance.model ?? embeddingsInstance.modelName ?? 'unknown';
5247
attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] = String(modelName);
5348

5449
const ctorName = (instance as { constructor?: { name?: string } }).constructor?.name ?? '';
@@ -57,14 +52,14 @@ function extractEmbeddingAttributes(
5752
attributes[GEN_AI_SYSTEM_ATTRIBUTE] = system;
5853
}
5954

60-
if (inst.dimensions != null) {
61-
const n = Number(inst.dimensions);
55+
if (embeddingsInstance.dimensions != null) {
56+
const n = Number(embeddingsInstance.dimensions);
6257
if (!Number.isNaN(n)) {
6358
attributes[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE] = n;
6459
}
6560
}
6661

67-
const encodingFormat = inst.encodingFormat ?? inst.encoding_format;
62+
const encodingFormat = embeddingsInstance.encodingFormat ?? embeddingsInstance.encoding_format;
6863
if (encodingFormat != null) {
6964
attributes[GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE] = String(encodingFormat);
7065
}
@@ -79,14 +74,13 @@ function extractEmbeddingAttributes(
7974
*/
8075
export function wrapEmbeddingMethod(
8176
originalMethod: (...args: unknown[]) => Promise<unknown>,
82-
operationName: EmbeddingOperationName,
8377
options: LangChainOptions = {},
8478
): (...args: unknown[]) => Promise<unknown> {
8579
const { recordInputs } = resolveAIRecordingOptions(options);
8680

8781
return new Proxy(originalMethod, {
8882
apply(target, thisArg, args: unknown[]): Promise<unknown> {
89-
const attributes = extractEmbeddingAttributes(thisArg, operationName);
83+
const attributes = extractEmbeddingAttributes(thisArg);
9084
const modelName = attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE] || 'unknown';
9185

9286
if (recordInputs) {
@@ -98,7 +92,7 @@ export function wrapEmbeddingMethod(
9892

9993
return startSpan(
10094
{
101-
name: `${operationName} ${modelName}`,
95+
name: `embeddings ${modelName}`,
10296
op: GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE,
10397
attributes,
10498
},
@@ -142,20 +136,18 @@ export function wrapEmbeddingMethod(
142136
* ```
143137
*/
144138
export function wrapLangChainEmbeddings<T extends object>(instance: T, options?: LangChainOptions): T {
145-
const inst = instance as Record<string, unknown>;
139+
const embeddingsInstance = instance as Record<string, unknown>;
146140

147-
if (typeof inst.embedQuery === 'function') {
148-
inst.embedQuery = wrapEmbeddingMethod(
149-
inst.embedQuery as (...args: unknown[]) => Promise<unknown>,
150-
'embed',
141+
if (typeof embeddingsInstance.embedQuery === 'function') {
142+
embeddingsInstance.embedQuery = wrapEmbeddingMethod(
143+
embeddingsInstance.embedQuery as (...args: unknown[]) => Promise<unknown>,
151144
options,
152145
);
153146
}
154147

155-
if (typeof inst.embedDocuments === 'function') {
156-
inst.embedDocuments = wrapEmbeddingMethod(
157-
inst.embedDocuments as (...args: unknown[]) => Promise<unknown>,
158-
'embed_many',
148+
if (typeof embeddingsInstance.embedDocuments === 'function') {
149+
embeddingsInstance.embedDocuments = wrapEmbeddingMethod(
150+
embeddingsInstance.embedDocuments as (...args: unknown[]) => Promise<unknown>,
159151
options,
160152
);
161153
}

packages/core/test/lib/tracing/langchain-embeddings.test.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ describe('wrapEmbeddingMethod', () => {
5050

5151
it('creates a span with correct attributes for embedQuery', async () => {
5252
const original = vi.fn().mockResolvedValue([0.1, 0.2, 0.3]);
53-
const wrapped = wrapEmbeddingMethod(original, 'embed');
53+
const wrapped = wrapEmbeddingMethod(original);
5454

5555
const instance = { constructor: { name: 'OpenAIEmbeddings' }, model: 'text-embedding-3-small', dimensions: 1536 };
5656
await wrapped.call(instance, 'Hello world');
5757

5858
expect(capturedSpanConfig).toBeDefined();
59-
expect(capturedSpanConfig!.name).toBe('embed text-embedding-3-small');
59+
expect(capturedSpanConfig!.name).toBe('embeddings text-embedding-3-small');
6060
expect(capturedSpanConfig!.op).toBe(GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE);
61-
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embed');
61+
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embeddings');
6262
expect(capturedSpanConfig!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE]).toBe('text-embedding-3-small');
6363
expect(capturedSpanConfig!.attributes[GEN_AI_SYSTEM_ATTRIBUTE]).toBe('openai');
6464
expect(capturedSpanConfig!.attributes[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE]).toBe(1536);
@@ -67,20 +67,20 @@ describe('wrapEmbeddingMethod', () => {
6767

6868
it('creates a span with correct attributes for embedDocuments', async () => {
6969
const original = vi.fn().mockResolvedValue([[0.1], [0.2]]);
70-
const wrapped = wrapEmbeddingMethod(original, 'embed_many');
70+
const wrapped = wrapEmbeddingMethod(original);
7171

7272
const instance = { constructor: { name: 'MistralAIEmbeddings' }, model: 'mistral-embed', encodingFormat: 'float' };
7373
await wrapped.call(instance, ['doc1', 'doc2']);
7474

75-
expect(capturedSpanConfig!.name).toBe('embed_many mistral-embed');
76-
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embed_many');
75+
expect(capturedSpanConfig!.name).toBe('embeddings mistral-embed');
76+
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embeddings');
7777
expect(capturedSpanConfig!.attributes[GEN_AI_SYSTEM_ATTRIBUTE]).toBe('mistralai');
7878
expect(capturedSpanConfig!.attributes[GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE]).toBe('float');
7979
});
8080

8181
it('records input when recordInputs is true (string)', async () => {
8282
const original = vi.fn().mockResolvedValue([0.1]);
83-
const wrapped = wrapEmbeddingMethod(original, 'embed', { recordInputs: true });
83+
const wrapped = wrapEmbeddingMethod(original, { recordInputs: true });
8484

8585
const instance = { constructor: { name: 'OpenAIEmbeddings' }, model: 'text-embedding-3-small' };
8686
await wrapped.call(instance, 'Hello world');
@@ -90,7 +90,7 @@ describe('wrapEmbeddingMethod', () => {
9090

9191
it('records input when recordInputs is true (array)', async () => {
9292
const original = vi.fn().mockResolvedValue([[0.1]]);
93-
const wrapped = wrapEmbeddingMethod(original, 'embed_many', { recordInputs: true });
93+
const wrapped = wrapEmbeddingMethod(original, { recordInputs: true });
9494

9595
const instance = { constructor: { name: 'OpenAIEmbeddings' }, model: 'text-embedding-3-small' };
9696
await wrapped.call(instance, ['doc1', 'doc2']);
@@ -101,7 +101,7 @@ describe('wrapEmbeddingMethod', () => {
101101
it('sets error status on failure', async () => {
102102
const error = new Error('API error');
103103
const original = vi.fn().mockRejectedValue(error);
104-
const wrapped = wrapEmbeddingMethod(original, 'embed');
104+
const wrapped = wrapEmbeddingMethod(original);
105105

106106
const instance = { constructor: { name: 'OpenAIEmbeddings' }, model: 'error-model' };
107107
await expect(wrapped.call(instance, 'test')).rejects.toThrow('API error');
@@ -124,7 +124,7 @@ describe('wrapEmbeddingMethod', () => {
124124
];
125125

126126
for (const { className, expected } of testCases) {
127-
const wrapped = wrapEmbeddingMethod(original, 'embed');
127+
const wrapped = wrapEmbeddingMethod(original);
128128
const instance = { constructor: { name: className }, model: 'test-model' };
129129
await wrapped.call(instance, 'test');
130130

@@ -134,11 +134,11 @@ describe('wrapEmbeddingMethod', () => {
134134

135135
it('handles missing instance properties gracefully', async () => {
136136
const original = vi.fn().mockResolvedValue([0.1]);
137-
const wrapped = wrapEmbeddingMethod(original, 'embed');
137+
const wrapped = wrapEmbeddingMethod(original);
138138

139139
await wrapped.call({}, 'test');
140140

141-
expect(capturedSpanConfig!.name).toBe('embed unknown');
141+
expect(capturedSpanConfig!.name).toBe('embeddings unknown');
142142
expect(capturedSpanConfig!.attributes[GEN_AI_REQUEST_MODEL_ATTRIBUTE]).toBe('unknown');
143143
expect(capturedSpanConfig!.attributes[GEN_AI_SYSTEM_ATTRIBUTE]).toBeUndefined();
144144
expect(capturedSpanConfig!.attributes[GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE]).toBeUndefined();
@@ -165,13 +165,10 @@ describe('wrapLangChainEmbeddings', () => {
165165
const wrapped = wrapLangChainEmbeddings(instance);
166166
expect(wrapped).toBe(instance); // Returns the same instance
167167

168-
// embedQuery should be wrapped
169168
await wrapped.embedQuery('test');
170-
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embed');
169+
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embeddings');
171170

172-
// embedDocuments should be wrapped
173171
await wrapped.embedDocuments(['doc1']);
174-
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embed_many');
172+
expect(capturedSpanConfig!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toBe('embeddings');
175173
});
176-
177174
});

packages/node/src/integrations/tracing/langchain/instrumentation.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,11 @@ export class SentryLangChainInstrumentation extends InstrumentationBase<LangChai
280280
// Duck-type detection already verified these are functions
281281
targetProto.embedQuery = wrapEmbeddingMethod(
282282
targetProto.embedQuery as (...args: unknown[]) => Promise<unknown>,
283-
'embed',
284283
options,
285284
);
286285

287286
targetProto.embedDocuments = wrapEmbeddingMethod(
288287
targetProto.embedDocuments as (...args: unknown[]) => Promise<unknown>,
289-
'embed_many',
290288
options,
291289
);
292290
}

yarn.lock

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5295,6 +5295,15 @@
52955295
"@langchain/langgraph-sdk" "~1.0.0"
52965296
uuid "^10.0.0"
52975297

5298+
"@langchain/openai@^0.5.0":
5299+
version "0.5.18"
5300+
resolved "https://registry.yarnpkg.com/@langchain/openai/-/openai-0.5.18.tgz#59ebbf48044d711ce9503d3b9854a3533cb54683"
5301+
integrity sha512-CX1kOTbT5xVFNdtLjnM0GIYNf+P7oMSu+dGCFxxWRa3dZwWiuyuBXCm+dToUGxDLnsHuV1bKBtIzrY1mLq/A1Q==
5302+
dependencies:
5303+
js-tiktoken "^1.0.12"
5304+
openai "^5.3.0"
5305+
zod "^3.25.32"
5306+
52985307
"@leichtgewicht/ip-codec@^2.0.1":
52995308
version "2.0.4"
53005309
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
@@ -23797,6 +23806,11 @@ openai@5.18.1:
2379723806
resolved "https://registry.yarnpkg.com/openai/-/openai-5.18.1.tgz#1c4884aefcada7ec684771e03c860c381f1902c1"
2379823807
integrity sha512-iXSOfLlOL+jgnFr5CGrB2SEZw5C92o1nrFW2SasoAXj4QxGhfeJPgg8zkX+vaCfX80cT6CWjgaGnq7z9XzbyRw==
2379923808

23809+
openai@^5.3.0:
23810+
version "5.23.2"
23811+
resolved "https://registry.yarnpkg.com/openai/-/openai-5.23.2.tgz#f13e2dc2ef6b88aab6a9b97cdc68d41a1d083c68"
23812+
integrity sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==
23813+
2380023814
opener@^1.5.2:
2380123815
version "1.5.2"
2380223816
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"

0 commit comments

Comments
 (0)