Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ Affected SDKs: All SDKs.
- `network.*` span attributes were aligned across SDKs.
- Legacy messaging (`messaging.*`) and database (`db.statement`, …) span attributes on the AMQP and Redis instrumentations were replaced by their current semantic-convention equivalents.
- The gen_ai cache token attributes `gen_ai.usage.cache_creation_input_tokens` and `gen_ai.usage.cache_read_input_tokens` were renamed to `gen_ai.usage.cache_creation.input_tokens` and `gen_ai.usage.cache_read.input_tokens`.
- The `gen_ai.system` span attribute was renamed to `gen_ai.provider.name` across all AI integrations.
- Span attributes now use the shared `@sentry/conventions` package under the hood.

If you reference these attributes in custom instrumentation, `beforeSendSpan`, dashboards, or alerts, update them to the new names.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { expect, it } from 'vitest';
import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
GEN_AI_RESPONSE_ID,
GEN_AI_RESPONSE_MODEL,
GEN_AI_RESPONSE_TEXT,
GEN_AI_SYSTEM,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -42,7 +42,7 @@ it('traces a basic message creation request with the anthropic SDK', async ({ si
attributes: {
'sentry.origin': { value: 'auto.ai.anthropic', type: 'string' },
'sentry.op': { value: 'gen_ai.chat', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'anthropic', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'anthropic', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'chat', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'claude-3-haiku-20240307', type: 'string' },
[GEN_AI_REQUEST_TEMPERATURE]: { value: 0.7, type: 'double' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {
GEN_AI_EMBEDDINGS_INPUT,
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
GEN_AI_REQUEST_TOP_P,
GEN_AI_RESPONSE_TEXT,
GEN_AI_SYSTEM,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -46,7 +46,7 @@ it('traces Google GenAI chat, generateContent, and embedContent calls', async ({
attributes: {
'sentry.origin': { value: 'auto.ai.google_genai', type: 'string' },
'sentry.op': { value: 'gen_ai.chat', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'google_genai', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'google_genai', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'chat', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'gemini-1.5-pro', type: 'string' },
// collect LLM input and outputs (default true)
Expand All @@ -70,7 +70,7 @@ it('traces Google GenAI chat, generateContent, and embedContent calls', async ({
attributes: {
'sentry.origin': { value: 'auto.ai.google_genai', type: 'string' },
'sentry.op': { value: 'gen_ai.generate_content', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'google_genai', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'google_genai', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'generate_content', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'gemini-1.5-flash', type: 'string' },
[GEN_AI_REQUEST_TEMPERATURE]: { value: 0.7, type: 'double' },
Expand Down Expand Up @@ -99,7 +99,7 @@ it('traces Google GenAI chat, generateContent, and embedContent calls', async ({
attributes: {
'sentry.origin': { value: 'auto.ai.google_genai', type: 'string' },
'sentry.op': { value: 'gen_ai.embeddings', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'google_genai', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'google_genai', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'embeddings', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'text-embedding-004', type: 'string' },
[GEN_AI_EMBEDDINGS_INPUT]: { value: 'Hello world', type: 'string' },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { expect, it } from 'vitest';
import {
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
GEN_AI_RESPONSE_FINISH_REASONS,
GEN_AI_RESPONSE_ID,
GEN_AI_RESPONSE_MODEL,
GEN_AI_SYSTEM,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
GEN_AI_USAGE_TOTAL_TOKENS,
Expand Down Expand Up @@ -42,7 +42,7 @@ it('traces a LangChain chat model invocation', async ({ signal }) => {
attributes: {
'sentry.origin': { value: 'auto.ai.langchain', type: 'string' },
'sentry.op': { value: 'gen_ai.chat', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'openai', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'openai', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'chat', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'gpt-3.5-turbo', type: 'string' },
[GEN_AI_REQUEST_TEMPERATURE]: { value: 0.7, type: 'double' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { expect, it } from 'vitest';
import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_MODEL,
GEN_AI_REQUEST_TEMPERATURE,
GEN_AI_RESPONSE_FINISH_REASONS,
GEN_AI_RESPONSE_ID,
GEN_AI_RESPONSE_MODEL,
GEN_AI_SYSTEM,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
Expand Down Expand Up @@ -42,7 +42,7 @@ it('traces a basic chat completion request with the openai SDK', async ({ signal
attributes: {
'sentry.origin': { value: 'auto.ai.openai', type: 'string' },
'sentry.op': { value: 'gen_ai.chat', type: 'string' },
[GEN_AI_SYSTEM]: { value: 'openai', type: 'string' },
[GEN_AI_PROVIDER_NAME]: { value: 'openai', type: 'string' },
[GEN_AI_OPERATION_NAME]: { value: 'chat', type: 'string' },
[GEN_AI_REQUEST_MODEL]: { value: 'gpt-3.5-turbo', type: 'string' },
[GEN_AI_REQUEST_TEMPERATURE]: { value: 0.7, type: 'double' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Deno.test('anthropic instrumentation: orchestrion @anthropic-ai/sdk:chat channel
const aiSpan = parent.spans?.find(s => s.op === 'gen_ai.chat');
assertExists(aiSpan, `expected a gen_ai.chat child span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`);
assertEquals(aiSpan!.description, 'chat claude-3-5-sonnet-latest');
assertEquals(aiSpan!.data?.['gen_ai.system'], 'anthropic');
assertEquals(aiSpan!.data?.['gen_ai.provider.name'], 'anthropic');
assertEquals(aiSpan!.data?.['gen_ai.operation.name'], 'chat');
assertEquals(aiSpan!.data?.['gen_ai.request.model'], 'claude-3-5-sonnet-latest');
assertEquals(aiSpan!.data?.['gen_ai.response.model'], 'claude-3-5-sonnet-20241022');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Deno.test('google-genai instrumentation: orchestrion @google/genai:generate-cont
`expected a gen_ai.generate_content child span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`,
);
assertEquals(aiSpan!.description, 'generate_content gemini-1.5-flash');
assertEquals(aiSpan!.data?.['gen_ai.system'], 'google_genai');
assertEquals(aiSpan!.data?.['gen_ai.provider.name'], 'google_genai');
assertEquals(aiSpan!.data?.['gen_ai.operation.name'], 'generate_content');
assertEquals(aiSpan!.data?.['gen_ai.request.model'], 'gemini-1.5-flash');
assertEquals(aiSpan!.data?.['gen_ai.response.model'], 'gemini-1.5-flash-002');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Deno.test('langchain instrumentation: orchestrion @langchain/openai:embedQuery c
const aiSpan = parent.spans?.find(s => s.op === 'gen_ai.embeddings');
assertExists(aiSpan, `expected a gen_ai.embeddings child span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`);
assertEquals(aiSpan!.description, 'embeddings text-embedding-3-small');
assertEquals(aiSpan!.data?.['gen_ai.system'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.provider.name'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.operation.name'], 'embeddings');
assertEquals(aiSpan!.data?.['gen_ai.request.model'], 'text-embedding-3-small');
assertEquals(aiSpan!.data?.['sentry.origin'], 'auto.ai.langchain');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Deno.test('openai instrumentation: orchestrion:openai:chat channel produces a ne
const aiSpan = parent.spans?.find(s => s.op === 'gen_ai.chat');
assertExists(aiSpan, `expected a gen_ai.chat child span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`);
assertEquals(aiSpan!.description, 'chat gpt-4o');
assertEquals(aiSpan!.data?.['gen_ai.system'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.provider.name'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.operation.name'], 'chat');
assertEquals(aiSpan!.data?.['gen_ai.request.model'], 'gpt-4o');
assertEquals(aiSpan!.data?.['gen_ai.response.model'], 'gpt-4o-2024-08-06');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Deno.test('vercel-ai instrumentation: orchestrion:ai:generateText channel produc
`expected a gen_ai.invoke_agent child span, got ops: ${parent.spans?.map(s => s.op).join(', ')}`,
);
assertEquals(aiSpan!.description, 'invoke_agent');
assertEquals(aiSpan!.data?.['gen_ai.system'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.provider.name'], 'openai');
assertEquals(aiSpan!.data?.['gen_ai.operation.name'], 'invoke_agent');
assertEquals(aiSpan!.data?.['gen_ai.request.model'], 'gpt-4o');
assertEquals(aiSpan!.data?.['vercel.ai.operationId'], 'ai.generateText');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('Instruments anthropic-ai automatically via orchestrion', async ({ baseURL
expect(chatSpan).toBeDefined();
expect(chatSpan?.attributes['sentry.op']?.value).toBe('gen_ai.chat');
expect(chatSpan?.attributes['sentry.origin']?.value).toBe('auto.ai.orchestrion.anthropic');
expect(chatSpan?.attributes['gen_ai.system']?.value).toBe('anthropic');
expect(chatSpan?.attributes['gen_ai.provider.name']?.value).toBe('anthropic');
expect(chatSpan?.attributes['gen_ai.request.model']?.value).toBe('claude-3-haiku-20240307');
expect(chatSpan?.attributes['gen_ai.usage.input_tokens']?.value).toBe(10);
expect(chatSpan?.attributes['gen_ai.usage.output_tokens']?.value).toBe(15);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('Instruments google-genai automatically via orchestrion', async ({ baseURL
expect(generateSpan).toBeDefined();
expect(generateSpan?.attributes['sentry.op']?.value).toBe('gen_ai.generate_content');
expect(generateSpan?.attributes['sentry.origin']?.value).toBe('auto.ai.orchestrion.google_genai');
expect(generateSpan?.attributes['gen_ai.system']?.value).toBe('google_genai');
expect(generateSpan?.attributes['gen_ai.provider.name']?.value).toBe('google_genai');
expect(generateSpan?.attributes['gen_ai.request.model']?.value).toBe('gemini-1.5-flash');
expect(generateSpan?.attributes['gen_ai.usage.input_tokens']?.value).toBe(8);
expect(generateSpan?.attributes['gen_ai.usage.output_tokens']?.value).toBe(12);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('Instruments openai automatically via orchestrion', async ({ baseURL }) =>
expect(chatSpan).toBeDefined();
expect(chatSpan?.attributes['sentry.op']?.value).toBe('gen_ai.chat');
expect(chatSpan?.attributes['sentry.origin']?.value).toBe('auto.ai.orchestrion.openai');
expect(chatSpan?.attributes['gen_ai.system']?.value).toBe('openai');
expect(chatSpan?.attributes['gen_ai.provider.name']?.value).toBe('openai');
expect(chatSpan?.attributes['gen_ai.request.model']?.value).toBe('gpt-3.5-turbo');
expect(chatSpan?.attributes['gen_ai.usage.input_tokens']?.value).toBe(10);
expect(chatSpan?.attributes['gen_ai.usage.output_tokens']?.value).toBe(15);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function assertBedrockSpans(transaction: TransactionEvent): void {
status: 'ok',
data: expect.objectContaining({
'sentry.origin': ORIGIN,
'gen_ai.system': 'aws.bedrock',
'gen_ai.provider.name': 'aws.bedrock',
'gen_ai.operation.name': 'chat',
'gen_ai.request.model': MODEL_ID,
'gen_ai.request.max_tokens': 100,
Expand All @@ -43,7 +43,7 @@ function assertBedrockSpans(transaction: TransactionEvent): void {
status: 'ok',
data: expect.objectContaining({
'sentry.origin': ORIGIN,
'gen_ai.system': 'aws.bedrock',
'gen_ai.provider.name': 'aws.bedrock',
'gen_ai.request.model': MODEL_ID,
'gen_ai.request.max_tokens': 100,
'gen_ai.request.temperature': 0.5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { afterAll, describe, expect } from 'vitest';
import {
GEN_AI_INPUT_MESSAGES,
GEN_AI_OPERATION_NAME,
GEN_AI_PROVIDER_NAME,
GEN_AI_REQUEST_AVAILABLE_TOOLS,
GEN_AI_REQUEST_MAX_TOKENS,
GEN_AI_REQUEST_MODEL,
Expand All @@ -12,7 +13,6 @@ import {
GEN_AI_RESPONSE_STREAMING,
GEN_AI_RESPONSE_TEXT,
GEN_AI_RESPONSE_TOOL_CALLS,
GEN_AI_SYSTEM,
GEN_AI_SYSTEM_INSTRUCTIONS,
GEN_AI_USAGE_INPUT_TOKENS,
GEN_AI_USAGE_OUTPUT_TOKENS,
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('Anthropic integration', () => {
expect(completionSpan!.attributes[GEN_AI_INPUT_MESSAGES].value).toBe(
'[{"role":"user","content":"What is the capital of France?"}]',
);
expect(completionSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(completionSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(completionSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS].value).toBe(10);
expect(completionSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS].value).toBe(15);
expect(completionSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS].value).toBe(25);
Expand Down Expand Up @@ -275,7 +275,7 @@ describe('Anthropic integration', () => {
expect(modelsSpan!.status).toBe('ok');
expect(modelsSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('models');
expect(modelsSpan!.attributes['sentry.op'].value).toBe('gen_ai.models');
expect(modelsSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(modelsSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(modelsSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');
expect(modelsSpan!.attributes[GEN_AI_RESPONSE_ID].value).toBe('claude-3-haiku-20240307');
expect(modelsSpan!.attributes[GEN_AI_RESPONSE_MODEL].value).toBe('claude-3-haiku-20240307');
Expand Down Expand Up @@ -327,7 +327,7 @@ describe('Anthropic integration', () => {
span => span.attributes[GEN_AI_RESPONSE_FINISH_REASONS]?.value === '["end_turn"]',
);
expect(detailedStreamSpan).toBeDefined();
expect(detailedStreamSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(detailedStreamSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(detailedStreamSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('chat');
expect(detailedStreamSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');
expect(detailedStreamSpan!.attributes[GEN_AI_RESPONSE_MODEL].value).toBe('claude-3-haiku-20240307');
Expand All @@ -341,7 +341,7 @@ describe('Anthropic integration', () => {
expect(messagesStreamSpan).toBeDefined();
expect(messagesStreamSpan!.name).toBe('chat claude-3-haiku-20240307');
expect(messagesStreamSpan!.status).toBe('ok');
expect(messagesStreamSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(messagesStreamSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(messagesStreamSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('chat');
expect(messagesStreamSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');
expect(messagesStreamSpan!.attributes[GEN_AI_RESPONSE_STREAMING].value).toBe(true);
Expand Down Expand Up @@ -624,7 +624,7 @@ describe('Anthropic integration', () => {
expect(truncatedSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('chat');
expect(truncatedSpan!.attributes['sentry.op'].value).toBe('gen_ai.chat');
expect(truncatedSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic');
expect(truncatedSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(truncatedSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(truncatedSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');

const smallMessageSpan = container.items.find(
Expand All @@ -636,7 +636,7 @@ describe('Anthropic integration', () => {
expect(smallMessageSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('chat');
expect(smallMessageSpan!.attributes['sentry.op'].value).toBe('gen_ai.chat');
expect(smallMessageSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic');
expect(smallMessageSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(smallMessageSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(smallMessageSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');
},
})
Expand Down Expand Up @@ -686,7 +686,7 @@ describe('Anthropic integration', () => {
expect(firstSpan!.attributes[GEN_AI_OPERATION_NAME].value).toBe('chat');
expect(firstSpan!.attributes['sentry.op'].value).toBe('gen_ai.chat');
expect(firstSpan!.attributes['sentry.origin'].value).toBe('auto.ai.orchestrion.anthropic');
expect(firstSpan!.attributes[GEN_AI_SYSTEM].value).toBe('anthropic');
expect(firstSpan!.attributes[GEN_AI_PROVIDER_NAME].value).toBe('anthropic');
expect(firstSpan!.attributes[GEN_AI_REQUEST_MODEL].value).toBe('claude-3-haiku-20240307');
},
})
Expand Down
Loading
Loading