Skip to content

Commit f79ba78

Browse files
authored
Merge branch 'develop' into instrument-genai-google
2 parents da90c04 + d5f0ac3 commit f79ba78

File tree

115 files changed

+2474
-5887
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+2474
-5887
lines changed

.github/ISSUE_TEMPLATE/bug.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ body:
133133
description: Logs? Screenshots? Yes, please.
134134
validations:
135135
required: true
136+
- type: textarea
137+
id: additional
138+
attributes:
139+
label: Additional Context
140+
description:
141+
Add any other context here. Please keep the pre-filled text, which helps us manage issue prioritization.
142+
value: |-
143+
<sub>Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it.</sub>
144+
validations:
145+
required: false
136146
- type: markdown
137147
attributes:
138148
value: |-

.github/ISSUE_TEMPLATE/feature.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ body:
2323
Add a blender to Sentry.
2424
validations:
2525
required: true
26+
- type: textarea
27+
id: additional
28+
attributes:
29+
label: Additional Context
30+
description:
31+
Add any other context here. Please keep the pre-filled text, which helps us manage feature prioritization.
32+
value: |-
33+
<sub>Tip: React with 👍 to help prioritize this improvement. Please use comments to provide useful context, avoiding `+1` or `me too`, to help us triage it.</sub>
34+
validations:
35+
required: false
2636
- type: markdown
2737
attributes:
2838
value: |-

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
### Important Changes
88

9+
- **feat(node) Ensure `prismaIntegration` works with Prisma 5 ([#17595](https://github.com/getsentry/sentry-javascript/pull/17595))**
10+
11+
We used to require to pass in the v5 version of `@prisma/instrumentation` into `prismaIntegration({ prismaInstrumentation: new PrismaInstrumentation() })`, if you wanted to get full instrumentation for Prisma v5. However, it turns out this does not work on v10 of the SDK anymore, because `@prisma/instrumentation@5` requires OTEL v1.
12+
13+
With this release, we dropped the requirement to configure anything to get v5 support of Prisma. You do not need to configure anything in the integration anymore, and can remove the dependency on `@prisma/instrumentation@5` if you had it in your application. You only need to configure the `tracing` preview feature [according to our docs](https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/prisma/).
14+
915
- **feat(deps): Update OpenTelemetry dependencies ([#17558](https://github.com/getsentry/sentry-javascript/pull/17558))**
1016
- @opentelemetry/core bumped to ^2.1.0
1117
- @opentelemetry/context-async-hooks bumped to ^2.1.0
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as Sentry from '@sentry/cloudflare';
2+
import type { AnthropicAiClient } from '@sentry/core';
3+
import { MockAnthropic } from './mocks';
4+
5+
interface Env {
6+
SENTRY_DSN: string;
7+
}
8+
9+
const mockClient = new MockAnthropic({
10+
apiKey: 'mock-api-key',
11+
});
12+
13+
const client: AnthropicAiClient = Sentry.instrumentAnthropicAiClient(mockClient);
14+
15+
export default Sentry.withSentry(
16+
(env: Env) => ({
17+
dsn: env.SENTRY_DSN,
18+
tracesSampleRate: 1.0,
19+
}),
20+
{
21+
async fetch(_request, _env, _ctx) {
22+
const response = await client.messages?.create({
23+
model: 'claude-3-haiku-20240307',
24+
messages: [{ role: 'user', content: 'What is the capital of France?' }],
25+
temperature: 0.7,
26+
max_tokens: 100,
27+
});
28+
29+
return new Response(JSON.stringify(response));
30+
},
31+
},
32+
);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { AnthropicAiClient, AnthropicAiResponse } from '@sentry/core';
2+
3+
export class MockAnthropic implements AnthropicAiClient {
4+
public messages: {
5+
create: (...args: unknown[]) => Promise<AnthropicAiResponse>;
6+
countTokens: (...args: unknown[]) => Promise<AnthropicAiResponse>;
7+
};
8+
public models: {
9+
list: (...args: unknown[]) => Promise<AnthropicAiResponse>;
10+
get: (...args: unknown[]) => Promise<AnthropicAiResponse>;
11+
};
12+
public completions: {
13+
create: (...args: unknown[]) => Promise<AnthropicAiResponse>;
14+
};
15+
public apiKey: string;
16+
17+
public constructor(config: { apiKey: string }) {
18+
this.apiKey = config.apiKey;
19+
20+
// Main focus: messages.create functionality
21+
this.messages = {
22+
create: async (...args: unknown[]) => {
23+
const params = args[0] as { model: string; stream?: boolean };
24+
// Simulate processing time
25+
await new Promise(resolve => setTimeout(resolve, 10));
26+
27+
if (params.model === 'error-model') {
28+
const error = new Error('Model not found');
29+
(error as unknown as { status: number }).status = 404;
30+
(error as unknown as { headers: Record<string, string> }).headers = { 'x-request-id': 'mock-request-123' };
31+
throw error;
32+
}
33+
34+
return {
35+
id: 'msg_mock123',
36+
type: 'message',
37+
role: 'assistant',
38+
model: params.model,
39+
content: [
40+
{
41+
type: 'text',
42+
text: 'Hello from Anthropic mock!',
43+
},
44+
],
45+
stop_reason: 'end_turn',
46+
stop_sequence: null,
47+
usage: {
48+
input_tokens: 10,
49+
output_tokens: 15,
50+
cache_creation_input_tokens: 0,
51+
cache_read_input_tokens: 0,
52+
},
53+
};
54+
},
55+
countTokens: async (..._args: unknown[]) => ({ id: 'mock', type: 'model', model: 'mock', input_tokens: 0 }),
56+
};
57+
58+
// Minimal implementations for required interface compliance
59+
this.models = {
60+
list: async (..._args: unknown[]) => ({ id: 'mock', type: 'model', model: 'mock' }),
61+
get: async (..._args: unknown[]) => ({ id: 'mock', type: 'model', model: 'mock' }),
62+
};
63+
64+
this.completions = {
65+
create: async (..._args: unknown[]) => ({ id: 'mock', type: 'completion', model: 'mock' }),
66+
};
67+
}
68+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { expect, it } from 'vitest';
2+
import { createRunner } from '../../../runner';
3+
4+
// These tests are not exhaustive because the instrumentation is
5+
// already tested in the node integration tests and we merely
6+
// want to test that the instrumentation does not break in our
7+
// cloudflare SDK.
8+
9+
it('traces a basic message creation request', async () => {
10+
const runner = createRunner(__dirname)
11+
.ignore('event')
12+
.expect(envelope => {
13+
const transactionEvent = envelope[1]?.[0]?.[1] as any;
14+
15+
expect(transactionEvent.transaction).toBe('GET /');
16+
expect(transactionEvent.spans).toEqual(
17+
expect.arrayContaining([
18+
expect.objectContaining({
19+
data: expect.objectContaining({
20+
'gen_ai.operation.name': 'messages',
21+
'sentry.op': 'gen_ai.messages',
22+
'sentry.origin': 'auto.ai.anthropic',
23+
'gen_ai.system': 'anthropic',
24+
'gen_ai.request.model': 'claude-3-haiku-20240307',
25+
'gen_ai.request.temperature': 0.7,
26+
'gen_ai.response.model': 'claude-3-haiku-20240307',
27+
'gen_ai.response.id': 'msg_mock123',
28+
'gen_ai.usage.input_tokens': 10,
29+
'gen_ai.usage.output_tokens': 15,
30+
}),
31+
description: 'messages claude-3-haiku-20240307',
32+
op: 'gen_ai.messages',
33+
origin: 'auto.ai.anthropic',
34+
}),
35+
]),
36+
);
37+
})
38+
.start();
39+
await runner.makeRequest('get', '/');
40+
await runner.completed();
41+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "worker-name",
3+
"compatibility_date": "2025-06-17",
4+
"main": "index.ts",
5+
"compatibility_flags": ["nodejs_compat"],
6+
}

dev-packages/e2e-tests/test-applications/angular-20/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,17 @@
4444
"karma-coverage": "~2.2.0",
4545
"karma-jasmine": "~5.1.0",
4646
"karma-jasmine-html-reporter": "~2.1.0",
47-
"typescript": "~5.8.3"
47+
"typescript": "~5.9.0"
4848
},
4949
"volta": {
5050
"extends": "../../package.json"
51+
},
52+
"sentryTest": {
53+
"optionalVariants": [
54+
{
55+
"build-command": "pnpm test:build-canary",
56+
"label": "angular (canary)"
57+
}
58+
]
5159
}
5260
}

dev-packages/e2e-tests/test-applications/aws-serverless/tests/layer.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ test.describe('Lambda layer', () => {
160160
type: 'Error',
161161
value: 'test',
162162
mechanism: {
163-
type: 'auto.function.aws-serverless.otel',
163+
type: 'auto.function.aws_serverless.otel',
164164
handled: false,
165165
},
166166
}),
@@ -188,7 +188,7 @@ test.describe('Lambda layer', () => {
188188
type: 'Error',
189189
value: 'test esm',
190190
mechanism: {
191-
type: 'auto.function.aws-serverless.otel',
191+
type: 'auto.function.aws_serverless.otel',
192192
handled: false,
193193
},
194194
}),
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { NextResponse } from 'next/server';
2+
3+
export function middleware() {
4+
// Basic middleware to ensure that the build works with edge runtime
5+
return NextResponse.next();
6+
}

0 commit comments

Comments
 (0)