Skip to content

refactor(otel): idiomatic abstractions, self-telemetry, SARIF SLO wiring#66

Merged
elasticdotventures merged 7 commits into
mainfrom
refactor/otel-idioms-and-synergies
May 2, 2026
Merged

refactor(otel): idiomatic abstractions, self-telemetry, SARIF SLO wiring#66
elasticdotventures merged 7 commits into
mainfrom
refactor/otel-idioms-and-synergies

Conversation

@elasticdotventures
Copy link
Copy Markdown
Member

Summary

Addresses non-obvious synergistic gaps by extracting shared OTLP abstractions into ledger-core, adding self-telemetry to rotel-visual, and wiring the previously orphan SARIF SLO evaluation into a production endpoint.

Changes

ledger-core::observability

  • TryFrom for OTelSeverityNumber: Maps OTLP severity ranges (1-24) canonically. Eliminates duplicated in rotel-visual.
  • otlp_json module: Shared OTLP JSON wire-format types (, , , ) for reuse across rotel-visual and ledgerr-host.
  • TryFrom bridge: bridges wire format to internal model.
  • LogShapeClassifier::with_builtin_rules(): Idiomatic constructor so callers don't hardcode operational rules.

rotel-visual

  • Uses new abstractions: Migrated to types, , .
  • Self-telemetry: with counters for logs/metrics/traces ingested, classified, and WebSocket connections.
  • GET /metrics: Returns self-telemetry snapshot JSON.
  • POST /rotel/evaluate: Wires — previously tested but never invoked in production code.
  • Error handling: and return instead of /.

Test Evidence

  • — 51 passed (4 new: severity mapping, OTLP deserialization, log record conversion, builtin rules)
  • — 51 passed
  • — 20 passed
  • — 12 passed (4 new: /metrics, /metrics increment, /rotel/evaluate pass, /rotel/evaluate SLO failure)

Checklist

  • Tests added/updated and passing
  • Idiomatic Rust patterns applied (TryFrom, configurable constructors, Result propagation)
  • Synergistic gaps closed (shared types, unused code wired, self-telemetry)
  • Conventional commit format followed

ledger-core::observability:
- Add TryFrom<u8> for OTelSeverityNumber (OTLP range 1-24) eliminating
  duplicated severity mapping in rotel-visual.
- Add otlp_json module with LogsRequest, LogRecord, AnyValue, Attribute
  wire-format types for shared OTLP JSON deserialization.
- Add TryFrom<&otlp_json::LogRecord> for OTelLogRecord bridge.
- Add LogShapeClassifier::with_builtin_rules() constructor so callers
  don't hardcode operational rules.

rotel-visual:
- Refactor to use new ledger-core abstractions: otlp_json types,
  OTelSeverityNumber::try_from(), LogShapeClassifier::with_builtin_rules().
- Add SurfaceMetrics with AtomicU64 counters for logs/metrics/traces
  ingested, classified, and WebSocket connections.
- Add GET /metrics endpoint returning self-telemetry snapshot.
- Add POST /rotel/evaluate endpoint wiring b00t-iface SARIF SLO
  evaluation (check_otel_logic_slo_as_sarif) — previously tested
  but never invoked in production code.
- Fix error handling: create_app() and run_server() return Result
  instead of unwrap/expect.
- Add b00t-iface dependency.

Tests:
- ledger-core: 4 new tests (severity mapping, OTLP deserialization,
  log record conversion, builtin rules)
- rotel-visual: 4 new tests (/metrics, /metrics increment, /rotel/evaluate
  success, /rotel/evaluate SLO failure detection)
- All crates pass: ledger-core 51, b00t-iface 51, ledgerr-host 20,
  rotel-visual 12
Copilot AI review requested due to automatic review settings May 2, 2026 14:58
Comment thread crates/rotel-visual/src/lib.rs Outdated
let replay = state.replay_buffer().await;
for batch in replay {
let msg = axum::extract::ws::Message::Text(
serde_json::to_string(&batch).unwrap().into()
Comment thread crates/rotel-visual/src/lib.rs Outdated
let replay = state.replay_buffer().await;
for batch in replay {
let msg = axum::extract::ws::Message::Text(
serde_json::to_string(&batch).unwrap().into()
Comment thread crates/rotel-visual/src/lib.rs Outdated
match rx.recv().await {
Ok(telemetry) => {
let msg = axum::extract::ws::Message::Text(
serde_json::to_string(&telemetry).unwrap().into()
Comment thread crates/rotel-visual/src/lib.rs Outdated
match rx.recv().await {
Ok(telemetry) => {
let msg = axum::extract::ws::Message::Text(
serde_json::to_string(&telemetry).unwrap().into()
Comment on lines +539 to +541
let status = if report.has_errors() {
axum::http::StatusCode::OK
} else {
Comment on lines +539 to +541
let status = if report.has_errors() {
axum::http::StatusCode::OK
} else {
Comment thread crates/rotel-visual/src/main.rs Outdated
@@ -0,0 +1,10 @@
use tracing_subscriber;
Comment thread crates/rotel-visual/src/main.rs Outdated
@@ -0,0 +1,10 @@
use tracing_subscriber;
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors OpenTelemetry support so shared OTLP/log-classification primitives live in ledger-core, while rotel-visual grows into a more complete OTLP-facing surface with self-telemetry and a production SARIF SLO evaluation endpoint.

Changes:

  • Extracts reusable OTLP severity and JSON wire-format abstractions into ledger-core::observability, plus a built-in log-shape classifier constructor.
  • Expands rotel-visual with OTLP ingest routes, self-telemetry counters, replay/broadcast plumbing, and a /rotel/evaluate SARIF endpoint.
  • Adds/updates integration tests and wires the crate as an explicit binary with new dependencies.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
crates/rotel-visual/tests/health_dashboard_tests.rs Adds endpoint and self-telemetry tests for the expanded rotel-visual surface.
crates/rotel-visual/src/main.rs Introduces the binary entrypoint and tracing initialization.
crates/rotel-visual/src/lib.rs Implements OTLP ingest handlers, websocket replay/broadcast, metrics snapshotting, dashboard updates, and SARIF evaluation routing.
crates/rotel-visual/Cargo.toml Declares the binary target and new crate dependencies needed for observability/SARIF work.
crates/ledger-core/src/observability.rs Adds shared OTLP severity conversion, OTLP JSON types, record conversion, and built-in classifier rules.
Cargo.lock Locks the newly added rotel-visual dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/rotel-visual/src/lib.rs Outdated
Comment thread crates/rotel-visual/src/lib.rs
Comment on lines +169 to +182
let response = app()
.clone()
.oneshot(
Request::builder()
.uri("/v1/logs")
.method("POST")
.header("content-type", "application/json")
.body(Body::from(body.to_string()))
.unwrap(),
)
.await
.unwrap();

assert_eq!(response.status(), StatusCode::ACCEPTED);
Comment on lines +408 to +412
let log = OTelLogRecord::new(
record.time_unix_nano.parse().unwrap_or(0),
severity,
body.clone(),
);
Comment on lines +530 to +537
let report = check_otel_logic_slo_as_sarif(
&mut registry,
&req.gate_name,
&req.expression,
req.log_shape_observed,
req.metric_observed,
req.slo_expected,
);
Comment thread crates/rotel-visual/src/lib.rs Outdated
Comment on lines +153 to +160
pub struct Resource {
pub attributes: Vec<Attribute>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScopeLogs {
#[serde(rename = "logRecords")]
pub log_records: Vec<LogRecord>,
Comment thread crates/rotel-visual/src/lib.rs Outdated
Comment on lines +342 to +346
let replay = state.replay_buffer().await;
for batch in replay {
let msg = axum::extract::ws::Message::Text(
serde_json::to_string(&batch).unwrap().into()
);
Comment thread crates/rotel-visual/src/lib.rs
Comment thread crates/ledger-core/src/observability.rs Outdated
elasticdotventures and others added 5 commits May 3, 2026 01:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
@elasticdotventures
Copy link
Copy Markdown
Member Author

chore(pr): superseded by #67

Rebased the stack onto feat/mdbook-rhai-mermaid-lib, carried the local mdbook-rhai-mermaid library export, and opened a fresh PR against main: #67.

Signed-off-by: Brian Horakh <35611074+elasticdotventures@users.noreply.github.com>
@elasticdotventures elasticdotventures merged commit 17577a3 into main May 2, 2026
1 check failed
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.

3 participants