Flush and Shutdown

Drain buffered telemetry safely in scripts, servers, workers, streams, and tests.

Neatlogs batches telemetry outside your application's request path. Ending a process does not guarantee that its final batch was sent. A flush waits for buffered logs and spans to be handed to the exporter; shutdown drains the SDK and closes SDK-owned resources.

Which call to use

RuntimeRequired lifecycle
Script or CLIFlush, then shut down in finally/defer before exiting.
Long-running serverDo not flush per request. Shut down once from the server's graceful-termination hook.
Reused serverless instanceAwait a bounded flush at the end of each invocation. Do not shut down after every invocation if the runtime may reuse the process.
Queue workerStop accepting work, await active jobs and streams, then shut down once.
Streaming callConsume, cancel, or close the stream first; then flush. Otherwise the span may still be active and contain only partial output.
Test processFlush before assertions that depend on exported data; shut down in suite teardown so no background work leaks into another test.

Use a deadline appropriate to your host. If the deadline expires, treat the result as possible telemetry loss; do not hold process termination indefinitely.

Python

try:
    run_application()
finally:
    neatlogs.flush(timeout_millis=10_000)
    neatlogs.shutdown(timeout_millis=10_000)

neatlogs.flush_all() drains every live Neatlogs client in the process, including secondary Client instances. It is scoped to Neatlogs-owned clients and does not flush a foreign or process-global OpenTelemetry provider. Use an individual client's flush() when you only want that client's pipeline.

TypeScript

try {
  await runApplication();
} finally {
  await flush();
  await shutdown();
}

flushAll() drains all registered Neatlogs clients. It does not flush or shut down a foreign/global tracer provider. shutdown() resets the default client so a later explicit init() can create a new SDK generation.

When an integration returns an AsyncIterable, ReadableStream, or other lazy stream, await its completion or cancellation before this block. Starting a stream without consuming it does not produce a completed response.

Go

shutdown, err := neatlogs.Init(ctx, cfg)
if err != nil {
    return err
}
defer func() {
    shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    _ = shutdown(shutdownCtx)
}()

neatlogs.Flush(ctx) drains the default provider without closing it. A secondary Client has its own Flush(ctx) and Shutdown(ctx). Go intentionally has no process-wide FlushAll: clients are explicit and their lifecycles remain independent.

On this page

Ask Neatlogs AI

Answers from the docs

How can I help?

Ask anything about instrumenting, tracing, or the Neatlogs dashboard.