Skip to content

Commit 421b666

Browse files
committed
Fix async span closing
1 parent 6be6020 commit 421b666

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

.changeset/large-emus-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pydantic/logfire-api": patch
3+
---
4+
5+
Fix async parent span timing

examples/node/index.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,19 @@ logfire.span('Hello from Node.js, {next_player}', {
2020
}, {
2121
tags: ['example', 'example2']
2222
}, (span) => {
23-
span.end()
23+
console.log('Inside span callback');
24+
})
25+
26+
await logfire.span('parent span', {}, {}, async (_span) => {
27+
await new Promise((resolve) => setTimeout(resolve, 1000))
28+
logfire.info('nested span')
29+
await new Promise((resolve) => setTimeout(resolve, 1000))
30+
logfire.debug('another nested span')
31+
})
32+
33+
34+
logfire.span('parent sync span', {}, {}, (_span) => {
35+
logfire.info('nested span')
2436
})
2537

2638
if (process.env.TRIGGER_ERROR) {

packages/logfire-api/src/index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export interface LogOptions {
4343
tags?: string[]
4444
}
4545

46+
/**
47+
* Starts a new Span without setting it on context.
48+
* This method does NOT modify the current Context.
49+
* You need to manually call `span.end()` to finish the span.
50+
*/
4651
export function startSpan(
4752
msgTemplate: string,
4853
attributes: Record<string, unknown> = {},
@@ -66,6 +71,12 @@ export function startSpan(
6671
return span
6772
}
6873

74+
/**
75+
* Starts a new Span and calls the given function passing it the
76+
* created span as first argument.
77+
* Additionally the new span gets set in context and this context is activated within the execution of the function.
78+
* The span will be ended automatically after the function call.
79+
*/
6980
export function span<R>(
7081
msgTemplate: string,
7182
attributes: Record<string, unknown> = {},
@@ -86,7 +97,16 @@ export function span<R>(
8697
},
8798
(span: Span) => {
8899
const result = callback(span)
89-
span.end()
100+
101+
const asPromise = Promise.resolve(result)
102+
if (asPromise === result) {
103+
// eslint-disable-next-line no-void
104+
void asPromise.finally(() => {
105+
span.end()
106+
})
107+
} else {
108+
span.end()
109+
}
90110
return result
91111
}
92112
)

0 commit comments

Comments
 (0)