Skip to main content

Background

Laminar span processor batches spans in memory before sending them to the backend. This is done to improve performance and reduce the number of network requests. However, there are cases when you need to flush spans immediately. Most often, this happens at the end of the program when you want to ensure that all spans are sent to the backend before the program exits.

When to use flush()

Do not use manual flushing in high-traffic web servers. If you put flush() in every API handler of a web server, it will severely degrade performance.

Automatic Flushing (Web Servers)

For long-running processes like Web Servers (Node.js, Python/FastAPI), the SDK empowers you with high-performance tracing by automatically batching and sending data in the background without blocking responses. You do not need to manually flush.

Manual Flushing (Scripts, CLI tools, Serverless)

Manual flushing (flush()) empowers you to guarantee data delivery in short-lived environments. In scenarios like CLI tools, scripts, or serverless functions, it ensures that your data is fully uploaded before the process terminates.

Flushing spans

You can flush spans manually using the Laminar.flush() method.
import { Laminar } from '@lmnr-ai/lmnr';

Laminar.initialize();

// your code here

// at the end of your script, when you are done tracing
await Laminar.flush(); // NOTE: don't forget to await
from lmnr import Laminar

Laminar.initialize()

# your code here

# at the end of your script, when you are done tracing
Laminar.flush()

Shutting down Laminar tracing

You can shut down Laminar tracing manually using the Laminar.shutdown() method.
import { Laminar } from '@lmnr-ai/lmnr';

Laminar.initialize();

// your code here

// at the end of your script, when you are done tracing.
// This will also flush any remaining spans.
await Laminar.shutdown(); // NOTE: don't forget to await

// IMPORTANT: you CAN re-initialize Laminar after shutting it down.
from lmnr import Laminar

Laminar.initialize()

# your code here

# at the end of your script, when you are done tracing
# This will also flush any remaining spans.
Laminar.shutdown()

# IMPORTANT: Laminar CANNOT be re-initialized after shutting it down inside
# the same process. For force flushing spans, refer to
# the section below on serverless functions.

Serverless functions and AWS Lambda

In Python, in order not to lose spans at the end of your Lambda or another serverless function, use Laminar.force_flush() to force flush the spans immediately.
# Inside your Lambda handler
from lmnr import Laminar

Laminar.initialize()

# your code here

Laminar.force_flush()

Technical explanation

In Python, Laminar.flush() is a synchronous function. However, the actual flush is done in a background daemon thread. This means that if the process exits before the flush is complete, the spans will be lost. This is a common failure scenario for serverless functions like AWS Lambda. This is NOT a problem in JavaScript, because the JavaScript OpenTelemetry SDK exposes shutdown() and flush() as asynchronous functions. Lambda will wait for the function to complete, as long as await is used on Laminar.shutdown() or Laminar.flush(). One possible way to avoid this issue is to completely shutdown Laminar at the end of your Lambda handler. This is because shutdown() is a synchronous function that blocks the main thread until the flush is complete. The problem with this approach is that if Lambda re-uses the same container for the next request, the Laminar SDK will not be usable again. Therefore, we expose Laminar.force_flush() as a way to force flush the spans and block on the flush operation until it is complete. Behind the scenes, this will shutdown and re-initialize OpenTelemetry SDKs, thus ensuring that the spans are flushed and the SDK is usable again.