elastic / elastic/apm-agent-nodejs

Exit spans created inside async functions are blocking subsequent span creations

Open
#4,560 0 comments 0 reactions 0 assignees View on GitHub
community triage
Dominant language
JavaScript
Stars
594
Forks
244
Avg merge
1d 8h
Merged PRs (30d)
16

Description

**Describe the bug**

When exit span is manually created inside async function, the following spans are not created.

The issue seems to be related to combination of creating exit span inside async function. If `exitSpan` option is removed from the span creation, subsequent spans are created normally. Or if the function is switched to synchronous function, then subsequent spans work as well.

Steps to reproduce the behavior:

I created a minimum example to reproduce the issue in [elastic-apm-exit-span-issue](https://github.com/tomirantanen/elastic-apm-exit-span-issue).

Here are the same code snippets as in the repository above.
**Not working:**
```js
const { setTimeout } = require("timers/promises");
const apm = require("elastic-apm-node").start({ serviceName: "example" });

const asyncFunction = async () => {
const span = apm.startSpan("First span", { exitSpan: true });
await setTimeout(5);
span.end();
};

const run = async () => {
apm.startTransaction("Not working transaction");
await asyncFunction();

const span = apm.startSpan("Second span"); // Span is not created.
console.log({ span }); // Span is null.
await setTimeout(5);
span?.end();
apm.endTransaction();
};

run();
```
**Working as expected:**
```js
const { setTimeout } = require("timers/promises");
const apm = require("elastic-apm-node").start({ serviceName: "example" });

const notAsyncFunction = () => {
const span = apm.startSpan("First span", { exitSpan: true });
span.end();
};

const run = async () => {
apm.startTransaction("Working transaction");
notAsyncFunction();

const span = apm.startSpan("Second span"); // Span is created normally.
console.log({ span });
await setTimeout(5);
span?.end();
apm.endTransaction();
};

run();
```

**Expected behavior**

I would expect any subsequent span creations work after creating exit span inside async function.

**Environment**

- OS: OS: macOS 15.4.
- Node.js version: 22.14.0
- APM Server version: 8.17.4
- Agent version: 4.11.2

**How are you starting the agent?**

- [x] Calling `agent.start()` directly (e.g. `require('elastic-apm-node').start(...)`)
- [ ] Requiring `elastic-apm-node/start` from within the source code
- [ ] Starting node with `-r elastic-apm-node/start`

**Additional context**

`package.json` dependencies:

Click to expand

```
"elastic-apm-node": "4.11.2"
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.