Skip to content

agent.flush() doesn't flush an ended span that is currently in span._encode() #2294

@trentm

Description

@trentm

Describe the bug

Currently the agent's API does not provide a way to know when an ended span has had a chance to be sent to agent._transport. On span.end(), the encoding of the span (span._encode()) is done asynchronously before the span object is sent to the transport (agent._transport.sendSpan(encodedSpanObject)). Currently a call to agent.flush([cb]) calls agent._transport.flush(cb), which only flushes objects already on the transport's queue.

For one, this is a pain for testing. The following does not suffice:

// ...
mySpan.end()
agent.flush(function () {
    // test that APM server got 'mySpan' here
})

The typical (poor) handling in tests is:

mySpan.end()
setTimeout(function () {
    agent.flush(function () {
        // test that APM server got 'mySpan' here
    })
}, SOME_DELAY)

where that $SOME_DELAY ms delay is a race.

Another use case is AWS lambda support. I suspect that a ending a span and then immediately completing the lambda handler function (using captureSpanStackTraces:true, spanFramesMinDuration:-1 to ensure longer span._encode() time) may result in that span not being flushed before the lambda container is frozen.

To Reproduce

TODO: A simple script repro. Also show a lambda repro.

Expected behavior

It would be helpful for testing and perhaps (to be demonstrated) required for lambda to have some programmatic way to wait for ended-and-currently-encoding spans to be flushed.

Additional context

A potential candidate here would be to extend the current agent.flush([cb]) to wait for these inflight encoding spans. Thinking out loud:

  • Add an Instrumentation.flush that handles this; and get Agent.flush to call that.
  • There would be some subtlety there to not starve waiting for span._encode()s that come in after agent.flush() was called.

Metadata

Metadata

Assignees

Labels

agent-nodejsMake available for APM Agents project planning.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions