Skip to content

Commit 10ae833

Browse files
committed
fixup! fixup! fix(tracing): add gen_ai.request.messages.original_length attributes (#18608)
1 parent aa6d279 commit 10ae833

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

packages/core/src/tracing/anthropic-ai/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,7 @@ function extractRequestAttributes(args: unknown[], methodPath: string): Record<s
7676
*/
7777
function addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void {
7878
const messages = messagesFromParams(params);
79-
if (messages.length) {
80-
setMessagesAttribute(span, messages);
81-
} else if ('input' in params) {
82-
setMessagesAttribute(span, params.input);
83-
}
79+
setMessagesAttribute(span, messages);
8480

8581
if ('prompt' in params) {
8682
span.setAttributes({ [GEN_AI_PROMPT_ATTRIBUTE]: JSON.stringify(params.prompt) });

packages/core/src/tracing/anthropic-ai/utils.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,11 @@ export function shouldInstrument(methodPath: string): methodPath is AnthropicAiI
2020
* Set the messages and messages original length attributes.
2121
*/
2222
export function setMessagesAttribute(span: Span, messages: unknown): void {
23-
if (Array.isArray(messages)) {
24-
if (!messages.length) return;
23+
const length = Array.isArray(messages) ? messages.length : undefined;
24+
if (length !== 0) {
2525
span.setAttributes({
2626
[GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: getTruncatedJsonString(messages),
27-
[GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: messages.length,
28-
});
29-
} else if (messages) {
30-
span.setAttributes({
31-
[GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: getTruncatedJsonString(messages),
32-
[GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: undefined,
27+
[GEN_AI_REQUEST_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: length,
3328
});
3429
}
3530
}
@@ -55,11 +50,15 @@ export function handleResponseError(span: Span, response: AnthropicAiResponse):
5550
* Include the system prompt in the messages list, if available
5651
*/
5752
export function messagesFromParams(params: Record<string, unknown>): unknown[] {
58-
const { system, messages } = params;
53+
const { system, messages, input } = params;
5954

6055
const systemMessages = typeof system === 'string' ? [{ role: 'system', content: params.system }] : [];
6156

62-
const userMessages = Array.isArray(messages) ? messages : messages != null ? [messages] : [];
57+
const inputParamMessages = Array.isArray(input) ? input : input != null ? [input] : undefined;
58+
59+
const messagesParamMessages = Array.isArray(messages) ? messages : messages != null ? [messages] : [];
60+
61+
const userMessages = inputParamMessages ?? messagesParamMessages;
6362

6463
return [...systemMessages, ...userMessages];
6564
}

packages/core/test/lib/utils/anthropic-utils.test.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, it } from 'vitest';
2-
import { messagesFromParams, shouldInstrument } from '../../../src/tracing/anthropic-ai/utils';
2+
import { messagesFromParams, setMessagesAttribute, shouldInstrument } from '../../../src/tracing/anthropic-ai/utils';
3+
import type { Span } from '../../../src/types-hoist/span';
34

45
describe('anthropic-ai-utils', () => {
56
describe('shouldInstrument', () => {
@@ -25,6 +26,19 @@ describe('anthropic-ai-utils', () => {
2526
]);
2627
});
2728

29+
it('looks to params.input ahead of params.messages', () => {
30+
expect(
31+
messagesFromParams({
32+
input: [{ role: 'user', content: 'input' }],
33+
messages: [{ role: 'user', content: 'hello' }],
34+
system: 'You are a friendly robot awaiting a greeting.',
35+
}),
36+
).toStrictEqual([
37+
{ role: 'system', content: 'You are a friendly robot awaiting a greeting.' },
38+
{ role: 'user', content: 'input' },
39+
]);
40+
});
41+
2842
it('includes system message along with non-array messages', () => {
2943
expect(
3044
messagesFromParams({
@@ -53,4 +67,42 @@ describe('anthropic-ai-utils', () => {
5367
).toStrictEqual([{ role: 'user', content: 'hello' }]);
5468
});
5569
});
70+
71+
describe('setMessagesAtribute', () => {
72+
const mock = {
73+
attributes: {} as Record<string, any>,
74+
setAttributes(kv: Record<string, any>) {
75+
for (const [key, val] of Object.entries(kv)) {
76+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
77+
if (val === undefined) delete this.attributes[key];
78+
else this.attributes[key] = val;
79+
}
80+
},
81+
};
82+
const span = mock as unknown as Span;
83+
84+
it('sets length along with truncated value', () => {
85+
const content = 'A'.repeat(200_000);
86+
setMessagesAttribute(span, [{ role: 'user', content }]);
87+
const result = [{ role: 'user', content: 'A'.repeat(19972) }];
88+
expect(mock.attributes).toStrictEqual({
89+
"gen_ai.request.messages.original_length": 1,
90+
'gen_ai.request.messages': JSON.stringify(result),
91+
});
92+
});
93+
94+
it('removes length when setting new value ', () => {
95+
setMessagesAttribute(span, { content: 'hello, world' });
96+
expect(mock.attributes).toStrictEqual({
97+
'gen_ai.request.messages': '{"content":"hello, world"}',
98+
});
99+
});
100+
101+
it('ignores empty array', () => {
102+
setMessagesAttribute(span, []);
103+
expect(mock.attributes).toStrictEqual({
104+
'gen_ai.request.messages': '{"content":"hello, world"}',
105+
});
106+
});
107+
});
56108
});

0 commit comments

Comments
 (0)