Skip to content

Commit 10f229d

Browse files
authored
Merge branch 'develop' into sig/consola-obj-keys
2 parents 282b963 + 0c3b071 commit 10f229d

10 files changed

Lines changed: 200 additions & 86 deletions

File tree

.cursor/commands/add_cdn_bundle.md

Lines changed: 0 additions & 35 deletions
This file was deleted.

.cursor/commands/bump_otel_instrumentations.md

Lines changed: 0 additions & 32 deletions
This file was deleted.

.cursor/commands/publish_release.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.cursor/rules/fetch-docs/bundle-size.mdc

Lines changed: 0 additions & 6 deletions
This file was deleted.

.cursor/rules/fetch-docs/tracing-in-browser.mdc

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { ChatAnthropic } from '@langchain/anthropic';
2+
import { RunnableLambda, RunnableSequence } from '@langchain/core/runnables';
3+
import { createLangChainCallbackHandler } from '@sentry/core';
4+
import * as Sentry from '@sentry/node';
5+
import express from 'express';
6+
7+
function startMockAnthropicServer() {
8+
const app = express();
9+
app.use(express.json());
10+
11+
app.post('/v1/messages', (req, res) => {
12+
res.json({
13+
id: 'msg_chain_test',
14+
type: 'message',
15+
role: 'assistant',
16+
content: [{ type: 'text', text: 'The weather is sunny.' }],
17+
model: req.body.model,
18+
stop_reason: 'end_turn',
19+
stop_sequence: null,
20+
usage: { input_tokens: 10, output_tokens: 5 },
21+
});
22+
});
23+
24+
return new Promise(resolve => {
25+
const server = app.listen(0, () => {
26+
resolve(server);
27+
});
28+
});
29+
}
30+
31+
async function run() {
32+
const server = await startMockAnthropicServer();
33+
const baseUrl = `http://localhost:${server.address().port}`;
34+
35+
await Sentry.startSpan({ op: 'function', name: 'main' }, async () => {
36+
const model = new ChatAnthropic({
37+
model: 'claude-3-5-sonnet-20241022',
38+
temperature: 0,
39+
maxTokens: 50,
40+
apiKey: 'mock-api-key',
41+
clientOptions: { baseURL: baseUrl },
42+
});
43+
44+
const formatStep = RunnableLambda.from(input => `Tell me about: ${input.topic}`).withConfig({
45+
runName: 'format_prompt',
46+
});
47+
48+
const parseStep = RunnableLambda.from(output => output.content[0].text).withConfig({
49+
runName: 'parse_output',
50+
});
51+
52+
const chain = RunnableSequence.from([formatStep, model, parseStep]);
53+
54+
const handler = createLangChainCallbackHandler();
55+
56+
await chain.invoke({ topic: 'weather' }, { callbacks: [handler] });
57+
});
58+
59+
await Sentry.flush(2000);
60+
server.close();
61+
}
62+
63+
run();

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,4 +376,41 @@ describe('LangChain integration', () => {
376376
});
377377
},
378378
);
379+
380+
createEsmAndCjsTests(__dirname, 'scenario-chain.mjs', 'instrument.mjs', (createRunner, test) => {
381+
test('uses runName for chain spans instead of unknown_chain', async () => {
382+
await createRunner()
383+
.ignore('event')
384+
.expect({
385+
transaction: {
386+
transaction: 'main',
387+
spans: expect.arrayContaining([
388+
expect.objectContaining({
389+
description: 'chain format_prompt',
390+
op: 'gen_ai.invoke_agent',
391+
origin: 'auto.ai.langchain',
392+
data: expect.objectContaining({
393+
'langchain.chain.name': 'format_prompt',
394+
}),
395+
}),
396+
expect.objectContaining({
397+
description: 'chain parse_output',
398+
op: 'gen_ai.invoke_agent',
399+
origin: 'auto.ai.langchain',
400+
data: expect.objectContaining({
401+
'langchain.chain.name': 'parse_output',
402+
}),
403+
}),
404+
expect.objectContaining({
405+
description: 'chat claude-3-5-sonnet-20241022',
406+
op: 'gen_ai.chat',
407+
origin: 'auto.ai.langchain',
408+
}),
409+
]),
410+
},
411+
})
412+
.start()
413+
.completed();
414+
});
415+
});
379416
});

packages/browser/AGENTS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Browser SDK
2+
3+
## Bundle Size
4+
5+
Bundle size is critical. Be mindful of imports and tree-shaking.
6+
7+
- [Bundle size documentation](https://develop.sentry.dev/sdk/platform-specifics/javascript-sdks/bundle-size.md)
8+
- [Browser tracing documentation](https://develop.sentry.dev/sdk/platform-specifics/javascript-sdks/browser-tracing.md)
9+
10+
## CDN Bundles
11+
12+
Use `/add-cdn-bundle` skill to create new CDN bundles.

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,17 @@ export function createLangChainCallbackHandler(options: LangChainOptions = {}):
184184
},
185185

186186
// Chain Start Handler
187-
handleChainStart(chain: { name?: string }, inputs: Record<string, unknown>, runId: string, _parentRunId?: string) {
188-
const chainName = chain.name || 'unknown_chain';
187+
handleChainStart(
188+
chain: { name?: string },
189+
inputs: Record<string, unknown>,
190+
runId: string,
191+
_parentRunId?: string,
192+
_tags?: string[],
193+
_metadata?: Record<string, unknown>,
194+
_runType?: string,
195+
runName?: string,
196+
) {
197+
const chainName = runName || chain.name || 'unknown_chain';
189198
const attributes: Record<string, SpanAttributeValue> = {
190199
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ai.langchain',
191200
'langchain.chain.name': chainName,

packages/nextjs/AGENTS.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Next.js SDK (`@sentry/nextjs`)
2+
3+
## Bundler Architecture: Webpack vs Turbopack
4+
5+
Next.js apps use **either webpack or turbopack** as their bundler. This fundamentally changes how Sentry instruments the application.
6+
7+
- **Webpack** — default bundler through Next.js 15
8+
- **Turbopack** — default bundler starting Next.js 16
9+
10+
Detection: `process.env.TURBOPACK` or `--turbo` CLI flag (see `src/config/util.ts:detectActiveBundler`).
11+
12+
### Webpack Path (Build-Time Wrapping)
13+
14+
Webpack builds use **loaders and templates** to wrap user code at compile time:
15+
16+
1. **Wrapping loader** (`src/config/loaders/wrappingLoader.ts`) identifies route handlers, API routes, pages, middleware, and server components by file path patterns
17+
2. **Templates** (`src/config/templates/`) inject Sentry instrumentation around each export — using Rollup internally to expand `export *` statements
18+
3. **Value injection loader** injects globals (`_sentryNextJsVersion`, route manifest, tunnel path, etc.)
19+
4. **SentryWebpackPlugin** handles sourcemap upload and release management
20+
21+
Template files and what they wrap:
22+
23+
- `pageWrapperTemplate.ts` — Pages Router pages (`getInitialProps`, `getStaticProps`, `getServerSideProps`)
24+
- `apiWrapperTemplate.ts` — Pages Router API routes
25+
- `routeHandlerWrapperTemplate.ts` — App Router route handlers (GET, POST, etc.)
26+
- `serverComponentWrapperTemplate.ts` — App Router server components, `generateMetadata`, `generateViewport`
27+
- `middlewareWrapperTemplate.ts` — Edge middleware
28+
29+
Config options that control wrapping: `autoInstrumentServerFunctions`, `autoInstrumentMiddleware`, `autoInstrumentAppDirectory`, `excludeServerRoutes`.
30+
31+
### Turbopack Path (No Build-Time Wrapping)
32+
33+
Turbopack does **NOT** use the wrapping loader or templates. There is no build-time function wrapping.
34+
35+
What turbopack **does** support:
36+
37+
- **Value injection** via Turbopack rules (`src/config/turbopack/`) — injects the same globals as webpack
38+
- **Module metadata injection** (`moduleMetadataInjectionLoader.ts`) — enables `thirdPartyErrorFilterIntegration` (requires Next.js 16+ and `_experimental.turbopackApplicationKey`)
39+
- **Native debug IDs** for sourcemaps (Next.js 15.6+)
40+
- **`runAfterProductionCompile` hook** (enabled by default) for sourcemap upload
41+
42+
What turbopack does **NOT** support:
43+
44+
- Build-time wrapping of route handlers, API routes, pages, server components, or middleware
45+
- `autoInstrumentServerFunctions`, `autoInstrumentMiddleware`, `autoInstrumentAppDirectory` — these are no-ops
46+
- `excludeServerRoutes` — no-op since routes aren't wrapped
47+
- React component name annotations
48+
- SentryWebpackPlugin (no webpack = no webpack plugin)
49+
50+
Instrumentation with turbopack relies on **Next.js's built-in telemetry/OpenTelemetry integration** and the `instrumentation.ts` hook rather than build-time code transformation.
51+
52+
## Config Flow
53+
54+
```
55+
withSentryConfig(nextConfig, sentryOptions)
56+
→ detect bundler (webpack or turbopack)
57+
→ webpack: constructWebpackConfigFunction() → loaders + plugins
58+
→ turbopack: constructTurbopackConfig() → value injection rules only
59+
→ set up runAfterProductionCompile hook (sourcemaps)
60+
```
61+
62+
Entry point: `src/config/withSentryConfig/index.ts`
63+
Routing logic: `src/config/withSentryConfig/getFinalConfigObject.ts`
64+
65+
## Key Directories
66+
67+
| Path | Purpose |
68+
| ------------------------------ | ------------------------------------------------------------ |
69+
| `src/config/webpack.ts` | Webpack-specific config (loaders, rules, plugins) |
70+
| `src/config/turbopack/` | Turbopack-specific config (value injection rules) |
71+
| `src/config/loaders/` | Webpack loaders (wrapping, value injection, module metadata) |
72+
| `src/config/templates/` | Wrapper templates used by wrapping loader (webpack only) |
73+
| `src/config/manifest/` | Route manifest generation for transaction grouping |
74+
| `src/config/withSentryConfig/` | Main `withSentryConfig` entry point and bundler routing |
75+
| `src/client/` | Client-side SDK (browser) |
76+
| `src/server/` | Server-side SDK (Node.js) |
77+
| `src/edge/` | Edge runtime SDK |

0 commit comments

Comments
 (0)