mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-24 23:48:42 +08:00
fix(core): Keep gen_ai.system next to gen_ai.provider.name for LangSmith
This commit is contained in:
@@ -103,6 +103,7 @@ describe('model request tracing wiring', () => {
|
||||
expect(requestSpans(spans)).toEqual([
|
||||
expect.objectContaining({
|
||||
attributes: expect.objectContaining({
|
||||
'gen_ai.system': 'anthropic',
|
||||
'gen_ai.provider.name': 'anthropic',
|
||||
'gen_ai.request.model': 'claude-sonnet-4-5',
|
||||
}),
|
||||
|
||||
@@ -49,7 +49,7 @@ it('records each HTTP attempt, with no payload or duplicate usage', async () =>
|
||||
.fn<typeof fetch>()
|
||||
.mockResolvedValueOnce(new Response('private error', { status: 500 }))
|
||||
.mockResolvedValueOnce(new Response('private output'));
|
||||
const fetcher = traceModelRequests(delegate, telemetry, 'google', 'test-model');
|
||||
const fetcher = traceModelRequests(delegate, telemetry, 'custom', 'test-model');
|
||||
const init = {
|
||||
method: 'POST',
|
||||
headers: { Authorization: 'private key' },
|
||||
@@ -64,7 +64,7 @@ it('records each HTTP attempt, with no payload or duplicate usage', async () =>
|
||||
'langsmith.traceable': 'true',
|
||||
'langsmith.metadata.thread_id': 'thread',
|
||||
'langsmith.metadata.evalRole': 'helper',
|
||||
'gen_ai.provider.name': 'gcp.gemini',
|
||||
'gen_ai.system': 'custom',
|
||||
'gen_ai.request.model': 'test-model',
|
||||
'http.response.status_code': 500,
|
||||
});
|
||||
@@ -95,6 +95,7 @@ it('keeps generic OpenTelemetry spans free of LangSmith attributes', async () =>
|
||||
{
|
||||
name: 'model.provider.request',
|
||||
attributes: {
|
||||
'gen_ai.system': 'custom',
|
||||
'gen_ai.request.model': 'model',
|
||||
'http.response.status_code': 200,
|
||||
},
|
||||
@@ -104,6 +105,16 @@ it('keeps generic OpenTelemetry spans free of LangSmith attributes', async () =>
|
||||
]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
['google', 'gcp.gemini'],
|
||||
['custom', undefined],
|
||||
] as const)('sends the spec provider name for the %s provider', async (provider, providerName) => {
|
||||
const { spans, telemetry } = fixture();
|
||||
const delegate = vi.fn<typeof fetch>().mockResolvedValue(new Response('ok'));
|
||||
await traceModelRequests(delegate, telemetry, provider, 'model')('url');
|
||||
expect(spans[0].attributes['gen_ai.provider.name']).toBe(providerName);
|
||||
});
|
||||
|
||||
it('records LangSmith request spans without optional metadata', async () => {
|
||||
const { spans, telemetry } = fixture();
|
||||
const delegate = vi.fn<typeof fetch>().mockResolvedValue(new Response('ok'));
|
||||
@@ -116,6 +127,7 @@ it('records LangSmith request spans without optional metadata', async () => {
|
||||
expect(spans[0]).toEqual({
|
||||
name: 'model.provider.request',
|
||||
attributes: {
|
||||
'gen_ai.system': 'custom',
|
||||
'gen_ai.request.model': 'model',
|
||||
'langsmith.traceable': 'true',
|
||||
'langsmith.span.kind': 'chain',
|
||||
|
||||
@@ -49,6 +49,7 @@ export function traceModelRequests(
|
||||
let span: Span | undefined;
|
||||
try {
|
||||
const attributes: Record<string, AttributeValue> = {
|
||||
'gen_ai.system': provider,
|
||||
...(providerName ? { [GEN_AI_ATTR.PROVIDER_NAME]: providerName } : {}),
|
||||
[GEN_AI_ATTR.REQUEST_MODEL]: model,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user