Skip to content

feat: shared pkg/recordfmt export library + xtcp2client -format output#40

Merged
randomizedcoder merged 1 commit into
feat/output-formats-destinationsfrom
feat/recordfmt-shared-export
Jun 20, 2026
Merged

feat: shared pkg/recordfmt export library + xtcp2client -format output#40
randomizedcoder merged 1 commit into
feat/output-formats-destinationsfrom
feat/recordfmt-shared-export

Conversation

@randomizedcoder

Copy link
Copy Markdown
Owner

Extracts the record export/humanize code into a shared library used by both the daemon and xtcp2client, and gives the client real output.

Stacked on #38 (feat/output-formats-destinations). Merge #38 first; this then retargets to main. (It builds on the jsonl/csv/tsv/humanize code from #36/#38.)

pkg/recordfmt (new, pure)

  • humanize.goIPString/TCPStateName/CongestionAlgorithmName/TimestampRFC3339.
  • columns.go — reflection-derived Columns, SelectColumns, Header, Row.
  • marshal.go — per-record MarshalJSON/MarshalText/MarshalMsgPack/MarshalHumanizedJSON + format-name constants (single source of truth).
  • marshal_envelope.go — batch marshallers + pool-friendly AppendEnvelopeProtobufList.
  • Returns ([]byte, error); no prometheus/pools/logging — callers own those.

Daemon (pkg/xtcp)

marshallers.go / marshallers_text.go become thin wrappers that keep the registries, destBytesPool reuse for protobufList, and prometheus error counting, delegating to recordfmt. Adds a humanize marshaller (humanized JSONL) for parity. humanize.go + flat_record_row.go removed (moved). Behavior-preserving — existing daemon tests unchanged and green.

Client (cmd/xtcp2client)

Previously emitted nothing. Now: -format json|csv|tsv|humanize|null (+ -columns for csv/tsv); -json kept as a deprecated alias. A concurrency-safe recordPrinter formats each streamed record via recordfmt (csv/tsv header once).

Verification

  • nix build .#checks.x86_64-linux.golangci-lint .#test-go-unit .#test-pkg-xtcp .#test-cmd-xtcp2 .#test-cmd-xtcp2client all pass.
  • End-to-end against a live daemon: client json (valid per line), csv (l,172.16.50.219,SYN_SENT), humanize (readable JSON), null (empty); daemon -marshal humanize emits humanized JSONL.

Pairs with the docs in #39 (protobuf-formats).

🤖 Generated with Claude Code

…output

Extract the record formatting (json/jsonl/csv/tsv/humanize + protobufList/
text/msgpack) and humanizing (IPs, TCP state, congestion enum, timestamp) out
of pkg/xtcp into a new pure library, pkg/recordfmt, used by both the daemon and
the gRPC client so they format identically.

pkg/recordfmt:
- humanize.go, columns.go (reflection-derived columns + selection), marshal.go
  (per-record incl. MarshalHumanizedJSON), marshal_envelope.go (batch +
  pool-friendly AppendEnvelopeProtobufList). Pure: returns ([]byte, error), no
  prometheus/pool/logging — callers own those. Format-name constants are the
  single source of truth.

pkg/xtcp: marshallers.go / marshallers_text.go become thin wrappers that keep
the registries, destBytesPool reuse for protobufList, and prometheus error
counting, delegating byte production to recordfmt. New `humanize` marshaller
(humanized JSONL) for parity. humanize.go and flat_record_row.go removed
(moved). Existing daemon tests unchanged and green.

cmd/xtcp2client: now actually outputs records. New -format json|csv|tsv|
humanize|null (+ -columns for csv/tsv); -json kept as a deprecated alias. A
concurrency-safe recordPrinter writes via recordfmt, csv/tsv header once.

Verified end-to-end against a live daemon: each client -format prints real
humanized host sockets (172.16.50.219 / LISTEN / CUBIC); daemon -marshal
humanize emits humanized JSONL. nix lint + unit + cmd tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@randomizedcoder randomizedcoder merged commit 1ec1cec into feat/output-formats-destinations Jun 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant