debug while you are proving it works, and to Loki as the worked example.
Before you begin
- A place to run the collector (
otel/opentelemetry-collector-contrib—bearertokenauthand thetransformprocessor are contrib components, not in the core distribution). - A TLS certificate for the collector’s hostname. Lua refuses plain
http://endpoints, so the drain must reach it over HTTPS: either terminate TLS in the collector, as below, or put it behind a proxy that does and drop thetls:block. - A token you generate. It is shared state: the same value goes in the drain’s
Authorizationheader and in the collector’s environment.
The config
lua-otel-collector.yaml
What each piece is for
service.name already carries the agent’s name and service.instance.id its id, so nothing in the pipeline needs to construct them. A processor that overwrites service.name will collapse every agent into one service downstream.
Run it
Point a drain at it
lua.drain.test record. With the debug exporter in the pipeline it appears in the collector’s own output within a second or two:
lua drains status shows the drain healthy and the backlog draining.
Swap the exporter
The receiver, auth, and processors stay the same whatever is downstream. Replaceotlphttp/loki and the exporters: list in the pipeline:
- Loki
- Any OTLP backend
- Files, for a first look
If it isn’t working
The drain will not verify
The drain will not verify
Run the OTLP curl against the same URL from outside your network. A
401 means the token does not match LUA_DRAIN_TOKEN; remember the drain’s stored header value includes the Bearer prefix and the collector’s token does not. A connection failure usually means TLS: Lua refuses plain http://, and a self-signed certificate is refused as well.bearertokenauth is not a known extension
bearertokenauth is not a known extension
You are running the core distribution.
bearertokenauth and transform are contrib components: use otel/opentelemetry-collector-contrib.Records arrive but nothing reaches the backend
Records arrive but nothing reaches the backend
Keep
debug in the pipeline while you diagnose — it tells you whether the problem is before or after the batch processor. The collector’s own logs report exporter failures with the backend’s status code; sending_queue and retry_on_failure mean a brief backend outage is absorbed rather than lost.Memory grows under load
Memory grows under load
memory_limiter must be first in the processors list, before transform and batch. Behind it, sending_queue.queue_size bounds what the exporter holds. If the backend is persistently slower than the drain, the collector will refuse batches and Lua will retry them within its six-hour horizon — that is the intended backpressure path.Next steps
Grafana dashboard
Panels over what this pipeline produces.
OpenTelemetry
The drain side: wire shape, caps, and retry.
Event schema
The full OTLP field mapping.
Delivery guarantees
Retry, drops, and the heartbeat.

