Skip to content

Commit f803fa7

Browse files
authored
Tracing: tag spans as failed if their runner fn fails (#91206)
This adds a dedicated attribute, `failed`, to a span representing if the procedure failed. It's then set if the runner function threw. Test Plan: Added an e2e test
1 parent 21b9f6b commit f803fa7

File tree

4 files changed

+51
-0
lines changed

4 files changed

+51
-0
lines changed

packages/next/src/trace/trace.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ export class Span {
133133
traceFn<T>(fn: (span: Span) => T): T {
134134
try {
135135
return fn(this)
136+
} catch (e) {
137+
this.attrs['failed'] = true
138+
throw e
136139
} finally {
137140
this.stop()
138141
}
@@ -141,6 +144,9 @@ export class Span {
141144
async traceAsyncFn<T>(fn: (span: Span) => T | Promise<T>): Promise<T> {
142145
try {
143146
return await fn(this)
147+
} catch (e) {
148+
this.attrs['failed'] = true
149+
throw e
144150
} finally {
145151
this.stop()
146152
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { nextTestSetup, isNextStart } from 'e2e-utils'
2+
import { join } from 'path'
3+
import { readFileSync } from 'fs'
4+
import type { TraceEvent } from 'next/dist/trace'
5+
6+
function parseTraceFile(tracePath: string): TraceEvent[] {
7+
const content = readFileSync(tracePath, 'utf8')
8+
const events: TraceEvent[] = []
9+
for (const line of content.trim().split('\n').filter(Boolean)) {
10+
events.push(...(JSON.parse(line) as TraceEvent[]))
11+
}
12+
return events
13+
}
14+
15+
describe('build-failed-trace', () => {
16+
if (!isNextStart) {
17+
return
18+
}
19+
20+
const { next } = nextTestSetup({
21+
files: __dirname,
22+
skipStart: true,
23+
skipDeployment: true,
24+
})
25+
26+
it('should mark the next-build span as failed when the build fails', async () => {
27+
const { exitCode } = await next.build()
28+
expect(exitCode).not.toBe(0)
29+
30+
const tracePath = join(next.testDir, '.next', 'trace')
31+
const events = parseTraceFile(tracePath)
32+
33+
const nextBuildEvent = events.find((e) => e.name === 'next-build')
34+
expect(nextBuildEvent).toBeDefined()
35+
expect(nextBuildEvent!.tags).toMatchObject({ failed: true })
36+
})
37+
})
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
redirects: async () => {
3+
throw new Error('intentional build failure for trace testing')
4+
},
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page() {
2+
return <p>hello world</p>
3+
}

0 commit comments

Comments
 (0)