feat: discover NDJSON logs via message extraction - #34
Merged
Conversation
Per-file format detection routes NDJSON entries through a projected message line for Drain while samples keep the raw structured lines, per ADR 0006. Envelope requires ts, severity, and payload; anything less projects whole.
The word project reads as both verb and noun and its Chinese translations collide. Extraction is unambiguous.
STRRL
marked this pull request as ready for review
July 25, 2026 20:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The discovery pipeline treats every log file as plain text. Structured
JSON-lines logs get fed to Drain as raw JSON strings, which produces dirty,
low-value templates, and there is no way to keep the structured form for
investigation. ADR 0006 decided NDJSON storage with message extraction.
Solution
Per-file automatic format detection: NDJSON files are mined through an
extracted message line while pattern samples keep the raw structured entries.
Plain-text files flow through the existing path unchanged.
Major Changes
DetectFormat(a file is NDJSON only when every non-emptyline is a JSON object) and
Extract(envelope{ts, severity, payload}extracts from the payload; any other shape is extracted as a whole; message
from
message/msg/log/error, severity prefix from stringseverity/level, compact-JSON fallback)supporting a new shape means adding a fixture pair
TaggedLinecarries anoptional extracted line that Drain and template matching consume, while
samples and unmatched output keep the raw NDJSON lines
asserting raw-line preservation for both matched and unmatched entries
Note
Medium Risk
Changes core discovery input shaping and pattern matching for NDJSON files; behavior is well-tested but misclassification or extraction edge cases could shift templates for structured logs.
Overview
Discovery no longer treats every log file as plain text. Per-file format detection routes pure NDJSON (every non-empty line is a JSON object) through a new extraction path; mixed or plain files stay on the existing multiline text pipeline.
A new
pkg/ndjsonpackage implementsDetectFormatandExtractper ADR 0006: importer envelope{ts, severity, payload}mines from the payload; other shapes usemessage/msg/log/errorand stringseverity/level, with compact JSON fallback. Docs rename projection → extraction in CONTEXT and ADR 0006.TaggedLinegains optionalExtractedLineandDrainLine()so Drain, labeling samples, and template matching use extracted text whilesamples.logand unmatched output keep raw JSON lines. Builder template matching switches fromContenttoDrainLine(). Fixture-driven unit tests plus a mixed text/NDJSONDiscoverintegration test cover the behavior.Reviewed by Cursor Bugbot for commit 5bc9bd6. Bugbot is set up for automated code reviews on this repo. Configure here.