NDJSON is newline-delimited JSON: one complete JSON object per line. It is the default format, and the one to choose when your collector accepts it.
Everything the pipeline did survives as named fields. Parsed values stay parsed, enrichment stays attached, and normalised field names arrive as field names rather than being flattened into a message string.
destinations:
- type: tls
name: collector
params:
address: "collector.example.com:2514"
format: "ndjson"
framing: "lf"
ca_file: "C:\\ProgramData\\DPLens\\ca\\collector-ca.pem"
cache_max_bytes: "1073741824"
What a record looks like
Each line begins with the envelope — where the event came from and when — and then carries the event's fields:
{"source_id":"CORP-FS01","source_seq":50963,"time_event":"2026-09-14T18:55:21.155187300Z","time_collected":"2026-09-14T18:55:21.160Z","Channel":"Security","EventID":4624,"site":"london"}
| Field | Meaning |
|---|---|
source_id | Where the event originated. For a source on this machine, the machine's own name. For a syslog or NetFlow receiver, the device that sent it — taken from the message's own header where there is one, otherwise the sending address. |
source_seq | A sequence number within that origin, so gaps and duplicates are detectable downstream |
time_event | When the event happened, in UTC |
time_collected | When DPLens read it, in UTC |
Everything after that is your data: the event's own fields, plus anything your enrichment and normalisation stages added.
source_id is deliberately the origin, not the agent. Relayed events keep the identity of the device that produced them, so a firewall's events are attributed to the firewall rather than to the machine that forwarded them.
Framing
framing | How it works |
|---|---|
lf | One record per line, separated by a newline. The usual choice — it is what NDJSON means. |
octet-counted | Each record prefixed with its length, for collectors that prefer it |
Transport
Use tls where the collector supports it, tcp otherwise. UDP is available but gives up delivery entirely — see Choosing a destination.
Getting the field names you want
If your platform expects a particular schema, normalise at the agent rather than at search time: add a Parse stage and choose a schema and map, then use the remap rows to set, rename or drop individual fields. See Pipeline.
Doing it here costs a little CPU once per event, on the machine that produced it. Doing it at search time costs at every search, forever.
Checking it works
Watch Live stream with this destination selected. Because the stream shows the encoded bytes, you are reading exactly the JSON your collector receives — including which fields your masking rules rewrote.