Conversation
📝 WalkthroughWalkthroughThe PR adds OTLP metrics export and mock collection, instruments WebSocket activity, makes direct-message queuing fallible, narrows analysis scopes, and standardizes Clippy expectations and panic handling across tests, generators, and build utilities. ChangesObservability and WebSocket behavior
Tooling configuration and lint-policy standardization
Estimated code review effort: 5 (Critical) | ~90+ minutes Sequence Diagram(s)sequenceDiagram
participant WebSocketClient
participant WSTestServer
participant WebSocketHub
participant OtlpCollector
participant OtlpMock
WebSocketClient->>WSTestServer: establish connection
WSTestServer->>WebSocketHub: accept and run connection
WebSocketHub->>OtlpCollector: export traces, logs, and metrics
OtlpCollector->>OtlpMock: relay telemetry
WebSocketClient->>WebSocketHub: send message
WebSocketHub->>OtlpMock: export inbound-message counter
WebSocketClient->>WebSocketHub: disconnect
WebSocketHub->>OtlpMock: export active-connections gauge
WSTestServer->>OtlpMock: retrieve and verify telemetry
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene Coverage |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| C# | Jul 12, 2026 4:04a.m. | Review ↗ | |
| C & C++ | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Docker | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Java | Jul 12, 2026 4:04a.m. | Review ↗ | |
| JavaScript | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Python | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Rust | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Secrets | Jul 12, 2026 4:04a.m. | Review ↗ | |
| Code coverage | Jul 12, 2026 4:26a.m. | Review ↗ |
Code Coverage Summary
| Language | Line Coverage (New Code) | Line Coverage (Overall) |
|---|---|---|
| Aggregate | 99.4% |
51.3% [▲ up 0.7% from main] |
| Python | - | 54.2% |
| Rust | 99.4% |
51.2% [▲ up 0.7% from main] |
➟ Additional coverage metrics may have been reported. See full coverage report ↗
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 12 |
| Duplication | 0 |
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
libs/otlp-mock/src/lib.rs (1)
253-282: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicate dual-encoding decode logic between
handle_tracesandhandle_metrics.
handle_metrics(Lines 258-281) repeats the sameis_protobufdetection + protobuf/JSON decode + response-encoding-echo pattern already inhandle_traces(Lines 213-241). Given this is a small, low-churn test-support crate, extracting a shared generic helper is optional but would reduce copy/paste drift if a third endpoint type is ever added.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libs/otlp-mock/src/lib.rs` around lines 253 - 282, Reduce the duplicated dual-encoding logic between handle_traces and handle_metrics by extracting and reusing a shared helper for content-type detection, protobuf/JSON decoding, and response encoding. Keep each handler responsible only for endpoint-specific request storage and use the helper for both existing endpoint types.libs/et-otlp/src/lib.rs (1)
100-129: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winGlobal providers are set before all fallible builds complete.
opentelemetry::global::set_tracer_provider(...)(Line 102) andset_meter_provider(...)(Line 119) run before the metric exporter build, log exporter build,EnvFilter::try_new, andset_global_defaultcalls that can still fail with?. If any of those later steps errors,initreturnsErr, but the tracer/meter providers have already been registered as process-wide globals and never get shut down (they aren't returned in anOtelHandles, so noshutdown()call is possible). In practice every current caller (ws-server,ws-wasi-runner, test helpers) treatsinit's error as fatal and exits shortly after, which limits exposure, but the leaked global registration is still an avoidable inconsistency and would bite any caller that retriesinitor continues after a soft failure.Consider building all exporters/providers first and only calling
set_tracer_provider/set_meter_provideronce every fallible step has succeeded, right beforeOk(OtelHandles { ... }).♻️ Sketch of reordering the global registration
let tracer_provider = SdkTracerProvider::builder() .with_batch_exporter(span_exporter) .with_resource(resource.clone()) .build(); - // Set the global tracer provider so direct `global::tracer(...)` spans (e.g. the ws hub's `ws.connect`) - // export too -- not just the `tracing`-subscriber spans routed through the layer below. - opentelemetry::global::set_tracer_provider(tracer_provider.clone()); - let otel_tracing_layer = OpenTelemetryLayer::new(tracer_provider.tracer(config.service_label.clone())); // Metrics ride the same OTLP/HTTP transport as spans and logs, posting to `<collector_url>/metrics`. let metric_endpoint = format!("{}/metrics", config.collector_url); let metric_exporter = MetricExporter::builder() .with_http() .with_protocol(protocol) .with_endpoint(metric_endpoint) .with_headers(headers.clone()) .build()?; let meter_provider = SdkMeterProvider::builder() .with_periodic_exporter(metric_exporter) .with_resource(resource.clone()) .build(); - opentelemetry::global::set_meter_provider(meter_provider.clone()); let log_directives = std::env::var(RUST_LOG).unwrap_or_else(|_| "info".to_string()); let env_filter = EnvFilter::try_new(log_directives)?; @@ set_global_default(subscriber)?; + + // Only register global providers once every fallible step above has succeeded. + opentelemetry::global::set_tracer_provider(tracer_provider.clone()); + opentelemetry::global::set_meter_provider(meter_provider.clone()); Ok(OtelHandles { tracer_provider, logger_provider, meter_provider, })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libs/et-otlp/src/lib.rs` around lines 100 - 129, Move the global provider registrations out of the early setup in init and place set_tracer_provider and set_meter_provider only after all fallible exporter construction, EnvFilter creation, and global subscriber setup have succeeded, immediately before returning Ok(OtelHandles { ... }). Keep the locally built providers available for layer construction and handle creation without registering process-wide globals on any error path.utilities/int-gen/src/openapi.rs (1)
47-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winStale wording in the lint justification: "expect calls" should read "unwrap calls."
The
#[expect(clippy::unwrap_used, ...)]reason at line 49 still says "the only way these expect calls fire is a serde_json bug", but the code below no longer uses.expect()— it uses.unwrap(). Leftover from before this refactor.✏️ Fix wording
- reason = "all conversions are between serde-derived types; the only way these expect calls fire is a serde_json bug" + reason = "all conversions are between serde-derived types; the only way these unwrap calls fire is a serde_json bug"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@utilities/int-gen/src/openapi.rs` around lines 47 - 50, Update the reason text on the clippy::unwrap_used #[expect] attribute to refer to “unwrap calls” instead of “expect calls,” leaving the lint configuration and conversion behavior unchanged.services/ws-modules/wasi-comm1/src/coverage.rs (1)
9-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate coverage-dump logic across modules.
This
dump()implementation is identical toservices/ws-modules/wasi-data1/src/coverage.rsexcept for the output filename. As per coding guidelines, shared low-dependency helpers should live in a shared test-support crate rather than being copy-pasted per module.♻️ Suggested consolidation
// et-test-helpers (or a shared coverage-support crate) pub fn dump_coverage(path: &str) { let mut coverage = Vec::new(); // SAFETY: single-threaded guest; capture_coverage reads the instrumented counters once at run() end. unsafe { minicov::capture_coverage(&mut coverage).unwrap(); } fs_err::write(path, coverage).unwrap(); }Then each module calls
dump_coverage("/cov/et_ws_wasi_comm1.profraw").🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/ws-modules/wasi-comm1/src/coverage.rs` around lines 9 - 16, Move the duplicated coverage-capture and file-writing logic from dump() into a shared low-dependency test-support or coverage-support helper named dump_coverage(path: &str). Update this module’s dump() to call dump_coverage with its existing output path, and apply the same reuse in the corresponding wasi-data1 coverage module.Source: Coding guidelines
services/ws-test-server/src/lib.rs (1)
108-137: 🚀 Performance & Scalability | 🔵 TrivialConsider a type alias for the repeated stream type.
tokio_tungstenite::WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>is spelled out three times acrossconnect_agent/next_payload. Apub type WsStream = ...alias would cut noise without behavior change.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/ws-test-server/src/lib.rs` around lines 108 - 137, Introduce a public type alias for the repeated WebSocket stream type, then update the signatures of connect_agent and next_payload to use the alias instead of the fully qualified type. Preserve all existing behavior and visibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@services/ws-modules/face-detection/src/test_face_detection.rs`:
- Around line 4-5: Replace the indexed assertions in the face-detection tests
with bounds-safe assertion patterns, covering filtered[0], filtered[1],
large[1], priors[0][0..3], and decoded[0..3]. Preserve the existing expected
values and ordering while avoiding indexing and slicing operations that trigger
clippy::indexing_slicing.
In `@services/ws-test-server/src/lib.rs`:
- Around line 84-106: Update connect_agent’s et-connect-ack wait loop to enforce
the same 5-second timeout used by next_payload. Wrap each stream.next().await
wait, preserve successful ack handling, and fail promptly with the existing
panic path when the timeout expires.
---
Nitpick comments:
In `@libs/et-otlp/src/lib.rs`:
- Around line 100-129: Move the global provider registrations out of the early
setup in init and place set_tracer_provider and set_meter_provider only after
all fallible exporter construction, EnvFilter creation, and global subscriber
setup have succeeded, immediately before returning Ok(OtelHandles { ... }). Keep
the locally built providers available for layer construction and handle creation
without registering process-wide globals on any error path.
In `@libs/otlp-mock/src/lib.rs`:
- Around line 253-282: Reduce the duplicated dual-encoding logic between
handle_traces and handle_metrics by extracting and reusing a shared helper for
content-type detection, protobuf/JSON decoding, and response encoding. Keep each
handler responsible only for endpoint-specific request storage and use the
helper for both existing endpoint types.
In `@services/ws-modules/wasi-comm1/src/coverage.rs`:
- Around line 9-16: Move the duplicated coverage-capture and file-writing logic
from dump() into a shared low-dependency test-support or coverage-support helper
named dump_coverage(path: &str). Update this module’s dump() to call
dump_coverage with its existing output path, and apply the same reuse in the
corresponding wasi-data1 coverage module.
In `@services/ws-test-server/src/lib.rs`:
- Around line 108-137: Introduce a public type alias for the repeated WebSocket
stream type, then update the signatures of connect_agent and next_payload to use
the alias instead of the fully qualified type. Preserve all existing behavior
and visibility.
In `@utilities/int-gen/src/openapi.rs`:
- Around line 47-50: Update the reason text on the clippy::unwrap_used #[expect]
attribute to refer to “unwrap calls” instead of “expect calls,” leaving the lint
configuration and conversion behavior unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ebcbb547-55e7-4ecd-b131-c760580da394
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (50)
.deepsource.toml.mise/config.coverage.toml.mise/config.tomlCargo.tomlconfig/clippy.tomllibs/edge-toolkit/src/config.rslibs/edge-toolkit/src/ws.rslibs/edge-toolkit/src/ws_server.rslibs/edge-toolkit/tests/config.rslibs/edge-toolkit/tests/http_pyodide.rslibs/edge-toolkit/tests/no_mise.rslibs/edge-toolkit/tests/npm_mod.rslibs/edge-toolkit/tests/pipx_site_packages.rslibs/edge-toolkit/tests/ws.rslibs/et-otlp/src/lib.rslibs/otlp-mock/Cargo.tomllibs/otlp-mock/src/lib.rslibs/otlp-mock/tests/metrics.rslibs/path/tests/find.rslibs/test-helpers/src/lib.rslibs/ws-runner-common/tests/config.rsservices/modules/tests/symlinks.rsservices/storage/tests/put.rsservices/ws-modules/face-detection/src/test_face_detection.rsservices/ws-modules/face-detection/tests/web.rsservices/ws-modules/har1/src/test_har1.rsservices/ws-modules/pydata1/pkg/et_ws_pydata1.jsservices/ws-modules/pyface1/pkg/et_ws_pyface1.jsservices/ws-modules/wasi-comm1/src/coverage.rsservices/ws-modules/wasi-data1/src/coverage.rsservices/ws-pyo3-runner/tests/modules.rsservices/ws-server/src/main.rsservices/ws-test-server/Cargo.tomlservices/ws-test-server/src/lib.rsservices/ws-test-server/tests/hub_forwarding.rsservices/ws-test-server/tests/otel.rsservices/ws-wasi-runner/src/main.rsservices/ws-wasi-runner/tests/modules.rsservices/ws-wasi-runner/tests/otel_propagation.rsservices/ws-wasi-runner/tests/vector_otlp_relay.rsservices/ws-web-runner/build.rsservices/ws-web-runner/tests/modules.rsservices/ws/src/lib.rsservices/ws/tests/config.rsutilities/cli/tests/module_package_json.rsutilities/cli/tests/scenario_generation.rsutilities/int-gen/src/lib.rsutilities/int-gen/src/openapi.rsutilities/int-gen/src/wit/messages.rsutilities/int-gen/src/wit/upstream.rs
💤 Files with no reviewable changes (7)
- utilities/cli/tests/scenario_generation.rs
- libs/edge-toolkit/tests/http_pyodide.rs
- libs/edge-toolkit/tests/pipx_site_packages.rs
- utilities/cli/tests/module_package_json.rs
- libs/path/tests/find.rs
- libs/edge-toolkit/tests/no_mise.rs
- libs/edge-toolkit/tests/npm_mod.rs
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
services/ws-test-server/tests/helpers.rs (1)
19-33: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winLet the scripted server task terminate when the client disconnects.
Dropping the
JoinHandledetaches a task that waits forever inpending(), retaining the WebSocket and task until the test runtime is torn down. Read from the socket until closure, or retain and abort the handle explicitly.Proposed cleanup
-use futures_util::SinkExt as _; +use futures_util::{SinkExt as _, StreamExt as _}; - std::future::pending::<()>().await; + while ws.next().await.is_some() {}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/ws-test-server/tests/helpers.rs` around lines 19 - 33, Update the scripted server task around the spawned WebSocket handler to stop waiting indefinitely in std::future::pending. After sending the frames, read from ws until the client closes the connection, allowing the task and socket to terminate naturally; alternatively, retain the JoinHandle and explicitly abort it during cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@services/ws-web-runner/build.rs`:
- Around line 17-22: Remove the crate-level clippy::unwrap_used expectation and
add narrowly scoped Windows-only #[expect] attributes to the link_mingw_shim and
run functions, preserving the existing justification. Leave unrelated
build-script code subject to the workspace lint.
---
Nitpick comments:
In `@services/ws-test-server/tests/helpers.rs`:
- Around line 19-33: Update the scripted server task around the spawned
WebSocket handler to stop waiting indefinitely in std::future::pending. After
sending the frames, read from ws until the client closes the connection,
allowing the task and socket to terminate naturally; alternatively, retain the
JoinHandle and explicitly abort it during cleanup.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1962d3c8-a20d-4778-a295-5ad8b8ee0c01
📒 Files selected for processing (7)
config/ast-grep/rules/no-mod-in-tests.yamlservices/ws-test-server/src/lib.rsservices/ws-test-server/tests/helpers.rsservices/ws-test-server/tests/hub_forwarding.rsservices/ws-web-runner/Cargo.tomlservices/ws-web-runner/build.rsservices/ws/src/lib.rs
✅ Files skipped from review due to trivial changes (1)
- services/ws-web-runner/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (2)
- services/ws-test-server/src/lib.rs
- services/ws/src/lib.rs
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Pull Request Overview
The PR successfully introduces OpenTelemetry metrics and crucial stability fixes for the WebSocket hub, specifically addressing a panic risk in direct messaging. While Codacy indicates the code is up to standards, two high-severity issues must be addressed: a missing service.name attribute in the telemetry initialization which will cause metric assertions to fail, and an undeclared variable in the pydata1 module that will lead to runtime errors.
There is also significant scope creep beyond 'Add metrics', including a workspace-wide refactor of test error handling logic. While this improves consistency, it should be noted as it expands the surface area of the review. Additionally, the new coverage scripts introduce a dependency on goawk, which may impact developer environments.
About this PR
- The coverage filter script in
.mise/config.coverage.tomlintroduces a hard dependency ongoawk, which may not be available in all developer or CI environments. Consider using a more common tool or documenting the requirement. - The PR scope significantly exceeds 'Add metrics'. It includes a workspace-wide refactor of test error handling (replacing
.expectwith.unwrapacross many files) and updates to linting/link-check tasks. Please ensure these secondary changes are intentional and correctly implemented across all affected services.
2 comments outside of the diff
services/ws-modules/pydata1/pkg/et_ws_pydata1.js
line 21🔴 HIGH RISK
Use of undeclared variablePYODIDE_CDN. Based on the file's constants, this appears to be a typo forPYODIDE_BASE_PATH.
line 11🟡 MEDIUM RISK
The return value of the Promise executor is ignored. Avoid returning the result ofresolve(). Use an explicit block for early exit to avoid confusion.
Test suggestions
- Verify OTLP mock correctly decodes and flattens Sum, Gauge, and Histogram metrics from both JSON and Protobuf payloads.
- Verify the hub increments the received message counter for every handled inbound WebSocket frame.
- Verify the hub updates the active connection gauge correctly on client connect and disconnect.
- Verify that sending a direct message to a non-existent agent returns an Invalid response and is logged without panicking.
- Verify end-to-end integration where traces, logs, and metrics from the hub are all successfully captured by the mock collector.
- Verify that
next_payloadcorrectly skips protocol-level frames likeet-connect-ackand control frames like Pings.
TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback
| .expect("build OTLP span exporter"); | ||
| .build()?; | ||
|
|
||
| let mut service_descriptors = vec![KeyValue::new("service.version", env!("CARGO_PKG_VERSION").to_string())]; |
There was a problem hiding this comment.
🔴 HIGH RISK
The service_label from the configuration should be added to service_descriptors as the service.name attribute. Without this, the mock collector's flatten_metrics and flatten_spans will fail to identify the service correctly, breaking tests in services/ws-test-server/tests/otel.rs.
| // export too -- not just the `tracing`-subscriber spans routed through the layer below. | ||
| opentelemetry::global::set_tracer_provider(tracer_provider.clone()); | ||
|
|
||
| let otel_tracing_layer = OpenTelemetryLayer::new(tracer_provider.tracer(config.service_label.clone())); |
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: Use the instrumentation library name (e.g. env!("CARGO_PKG_NAME")) instead of the service label as the tracer name. Service identity is already properly scoped via Resource attributes.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
services/ws-web-runner/build.rs (1)
34-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlign the expectation reason with the suppressed lint.
The “single call site” wording justifies
clippy::single_call_fn, but Line 34 suppressesclippy::unwrap_used. Keep the reason focused on why these Windows build-script unwraps assert invariants.As per coding guidelines: “Do not weaken or disable workspace Clippy lints without explicit operator permission; fix the code or use a narrowly scoped, justified
#[expect].”Proposed adjustment
- reason = "windows-gnu link setup: single call site, and unwraps assert build invariants" + reason = "Windows linker setup unwraps assert build-script invariants"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@services/ws-web-runner/build.rs` around lines 34 - 35, Update the reason attached to the clippy::unwrap_used expectation in the Windows GNU link setup to remove the “single call site” justification and focus solely on why these unwraps validate build invariants. Keep the narrowly scoped lint expectation and its existing suppression behavior unchanged.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@services/ws-web-runner/build.rs`:
- Around line 34-35: Update the reason attached to the clippy::unwrap_used
expectation in the Windows GNU link setup to remove the “single call site”
justification and focus solely on why these unwraps validate build invariants.
Keep the narrowly scoped lint expectation and its existing suppression behavior
unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c93be5b5-6e7b-4e72-9ae7-c8e26ca9244a
📒 Files selected for processing (2)
services/ws-web-runner/build.rsservices/ws/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- services/ws/src/lib.rs
Summary by CodeRabbit