Skip to content

Commit bbf36bf

Browse files
RoyLinRoyLin
authored andcommitted
fix: operational logs to stderr (v0.9.1) — NDJSON stdout was polluted
Deep testing found the collector's tracing logs went to STDOUT, interleaved with the NDJSON event stream, so a consumer (jq / vector / OTel filelog) would choke on the INFO log lines. Logs now go to stderr (INFO by default); stdout is pure NDJSON. OTel json_parser skips non-JSON lines for the k8s interleaved-pod-log case. Deep test: all event types flow together, dropped=0 at ~110k events/60s, RSS flat (no leak), no panics. 0.9.0 -> 0.9.1.
1 parent 4927d2e commit bbf36bf

9 files changed

Lines changed: 31 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
All notable changes to a3s-observer will be documented in this file.
44

5+
## [0.9.1] — fix: operational logs to stderr (NDJSON stdout was polluted)
6+
7+
### Fixed
8+
9+
- **Logs now go to stderr** (were on stdout, interleaved with the NDJSON event stream) — found
10+
by deep testing: an NDJSON consumer (`jq` / vector / OTel `filelog`) would hit the `INFO …`
11+
log lines and fail. stdout is now pure NDJSON; the operational logs (startup, throughput, drop
12+
counter) are on stderr at INFO by default. The OTel sample's `json_parser` now also skips
13+
non-JSON lines (for the k8s pod log, where stdout+stderr interleave).
14+
15+
### Tested
16+
17+
- Deep test (sustained mixed workload): all event types flow together, **dropped=0** at ~110 k
18+
events/60 s, RSS flat (no leak), no panics.
19+
520
## [0.9.0] — file deletions (destructive actions)
621

722
### Added

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
edition = "2021"
55
license = "MIT"
66
description = "General-purpose, language-agnostic eBPF observability for AI agents (LLM calls, tools, files, network egress)."

a3s-observer-collector/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-collector"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
edition = "2021"
55
license = "MIT"
66
description = "a3s-observer collector: loads the eBPF probes and exports enriched events."

a3s-observer-collector/src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ async fn main() -> anyhow::Result<()> {
4545
}
4646
_ => {}
4747
}
48-
tracing_subscriber::fmt::init();
48+
// Logs go to STDERR so STDOUT stays pure NDJSON (the event stream a pipeline parses), at
49+
// INFO by default so the operational logs (throughput, drop counter) are actually visible.
50+
tracing_subscriber::fmt()
51+
.with_writer(std::io::stderr)
52+
.with_max_level(tracing::Level::INFO)
53+
.init();
4954

5055
let mut ebpf = Ebpf::load(aya::include_bytes_aligned!(concat!(
5156
env!("OUT_DIR"),

a3s-observer-common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-common"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
edition = "2021"
55
license = "MIT"
66
description = "Shared no_std types crossing the eBPF <-> userspace boundary for a3s-observer."

a3s-observer-ebpf/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "a3s-observer-ebpf"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
edition = "2021"
55
license = "MIT"
66
publish = false

deploy/daemonset.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ spec:
2525
terminationGracePeriodSeconds: 30 # the collector flushes a final report on SIGTERM
2626
containers:
2727
- name: a3s-observer
28-
image: 10.12.111.133:49164/a3s/observer:0.9.0 # mirror of ghcr.io/a3s-lab/observer:0.9.0
28+
image: 10.12.111.133:49164/a3s/observer:0.9.1 # mirror of ghcr.io/a3s-lab/observer:0.9.1
2929
securityContext:
3030
# eBPF load + tracepoint attach requires privileged. (Verified: a non-root
3131
# process with only CAP_BPF+CAP_PERFMON fails to attach — the tracefs tracepoint

deploy/otel-collector.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ receivers:
2828
include: [/var/log/a3s-observer.ndjson]
2929
operators:
3030
- type: json_parser # each line → structured attributes (identity/provider/event)
31+
if: 'body matches "^[{]"' # only parse NDJSON; skip any interleaved stderr log lines
3132
parse_from: body
3233

3334
processors:

0 commit comments

Comments
 (0)