Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

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

## [0.9.3] — soak validation + test coverage (no runtime change)

### Tested

- Full-stack soak validation — 15 cases, leak-free and correct under load on a prod host + an
isolated VM. Observe: steady 20 min, edge-input, a real a3s-code agent, throughput (110k ev/60s),
memory-bound (256 Mi), restart ×8, idle + heartbeat, SIGTERM, concurrent collectors,
backpressure, connection-churn. Intervene: egress, file/exec, and SSL-content guards — plus all
three running alongside the collector.
- Lib line coverage 72% → **79.6%** (`cargo llvm-cov`): adversarial SNI/DNS parser tests, the
cgroup→pod parser, the full 14-provider SNI classifier, and the v0.9.2 writer-thread path.

## [0.9.2] — fix: output backpressure no longer stalls the event loop

### Fixed
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-observer"
version = "0.9.2"
version = "0.9.3"
edition = "2021"
license = "MIT"
description = "General-purpose, language-agnostic eBPF observability for AI agents (LLM calls, tools, files, network egress)."
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,19 @@ a3s-observer → NDJSON → OTel Collector (filelog → OTLP) → your bac

Rust + [Aya](https://aya-rs.dev). Validated on Linux 6.8.

## Tested

Soak-tested under sustained load — observe on a production host, intervene in an isolated VM:

| path | cases (all leak-free + correct under load) |
|---|---|
| **observe** | steady 20 min · edge-input · **a real a3s-code agent** · throughput 110k ev/60s · memory-bound (256 Mi) · restart ×8 · idle + heartbeat · SIGTERM · concurrent collectors · backpressure · connection-churn |
| **intervene** | egress · file/exec · SSL-content guards — and all three running alongside the collector |

Two robustness bugs surfaced and were fixed this way: NDJSON stdout pollution (v0.9.1) and an
output-backpressure event-loop stall (v0.9.2). Lib line coverage **79.6%** (`cargo llvm-cov`) —
the untrusted SNI / DNS / cgroup parsers and the full 14-provider classifier are unit-tested.

## Security

Privileged component — see [SECURITY.md](SECURITY.md) for the disclosure policy and how to
Expand Down
2 changes: 1 addition & 1 deletion a3s-observer-collector/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-observer-collector"
version = "0.9.2"
version = "0.9.3"
edition = "2021"
license = "MIT"
description = "a3s-observer collector: loads the eBPF probes and exports enriched events."
Expand Down
2 changes: 1 addition & 1 deletion a3s-observer-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-observer-common"
version = "0.9.2"
version = "0.9.3"
edition = "2021"
license = "MIT"
description = "Shared no_std types crossing the eBPF <-> userspace boundary for a3s-observer."
Expand Down
2 changes: 1 addition & 1 deletion a3s-observer-ebpf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "a3s-observer-ebpf"
version = "0.9.2"
version = "0.9.3"
edition = "2021"
license = "MIT"
publish = false
Expand Down
27 changes: 27 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,33 @@ mod tests {
c.classify(Some("bedrock-runtime.us-east-1.amazonaws.com"), ip),
Some(Provider::Bedrock)
);
assert_eq!(
c.classify(Some("generativelanguage.googleapis.com"), ip),
Some(Provider::Gemini)
);
assert_eq!(
c.classify(Some("api.cohere.ai"), ip),
Some(Provider::Cohere)
);
assert_eq!(c.classify(Some("api.x.ai"), ip), Some(Provider::XAi));
assert_eq!(c.classify(Some("api.groq.com"), ip), Some(Provider::Groq));
assert_eq!(
c.classify(Some("api.together.xyz"), ip),
Some(Provider::Together)
);
assert_eq!(
c.classify(Some("api.perplexity.ai"), ip),
Some(Provider::Perplexity)
);
assert_eq!(
c.classify(Some("api.fireworks.ai"), ip),
Some(Provider::Fireworks)
);
assert_eq!(
c.classify(Some("openrouter.ai"), ip),
Some(Provider::OpenRouter)
);
assert_eq!(c.classify(None, ip), None); // no SNI → unclassified
assert_eq!(c.classify(Some("example.com"), ip), None);
}

Expand Down
Loading