Skip to content

Implement metrics & observability#213

Merged
leynos merged 10 commits intomainfrom
codex/implement-metrics-and-observability-feature
Jul 24, 2025
Merged

Implement metrics & observability#213
leynos merged 10 commits intomainfrom
codex/implement-metrics-and-observability-feature

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jul 22, 2025

Summary

  • integrate metrics instrumentation with metrics crate
  • expose Prometheus example in docs
  • add Prometheus recorder example in hardening guide
  • track active connections, frames processed and errors
  • implement metrics unit test and cucumber scenario
  • mark roadmap tasks complete

Testing

  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-targets --all-features
  • mdformat-all docs/**/*.md README.md

https://chatgpt.com/codex/tasks/task_e_687edb587d988322812c4a1cf95d88ec

Summary by Sourcery

Implement metrics instrumentation and observability by adding a dedicated metrics module, recording active connections, processed frames, and errors via the metrics crate, integrating a Prometheus exporter with examples, updating documentation, and adding corresponding tests.

New Features:

  • Instrument active connections, frame processing (inbound/outbound), and error counts using the metrics crate
  • Provide a Prometheus exporter integration with code examples in the hardening guide and maturity documentation

Enhancements:

  • Add a metrics module with helper functions and export metric constants
  • Update the project roadmap and documentation to include metrics and observability sections

Build:

  • Include metrics, metrics-exporter-prometheus, metrics-util, and cucumber dependencies and enable a cucumber test harness in Cargo.toml

Documentation:

  • Add Prometheus recorder usage examples to the hardening guide and capability maturity docs

Tests:

  • Add unit tests using a debugging recorder to verify frame and error metrics
  • Introduce cucumber scenarios and feature files for end-to-end metrics validation

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Jul 22, 2025

Reviewer's Guide

This PR integrates the metrics crate by introducing a dedicated metrics module, adding instrumentation for active connections, frame processing, and errors, updating Cargo dependencies and feature flags, enriching documentation with observability examples, and adding both unit and cucumber tests to verify metric emissions.

Entity relationship diagram for metrics counters and gauges

erDiagram
    CONNECTIONS_ACTIVE ||--o{ FRAMES_PROCESSED : tracks
    CONNECTIONS_ACTIVE {
        string name
        float value
    }
    FRAMES_PROCESSED {
        string name
        int value
        string direction
    }
    ERRORS_TOTAL {
        string name
        int value
    }
    CONNECTIONS_ACTIVE ||--o{ ERRORS_TOTAL : tracks
Loading

Class diagram for the new metrics module and helpers

classDiagram
    class Direction {
        +Inbound
        +Outbound
        +as_str() str
    }
    class metrics {
        <<module>>
        +CONNECTIONS_ACTIVE: &str
        +FRAMES_PROCESSED: &str
        +ERRORS_TOTAL: &str
        +inc_connections()
        +dec_connections()
        +inc_frames(direction: Direction)
        +inc_errors()
    }
    metrics --> Direction
Loading

File-Level Changes

Change Details Files
Extend documentation with metrics and observability sections
  • Add metrics instrumentation example to hardening guide
  • Augment philosophy docs with Prometheus recorder snippet
  • Mark metrics & observability tasks as completed in roadmap
docs/hardening-wireframe-a-guide-to-production-resilience.md
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
docs/roadmap.md
Introduce metrics module and instrumentation in core logic
  • Create src/metrics.rs with metric names and helper functions
  • Instrument connection establishment/drop to track active connections
  • Instrument frame processing and errors in connection and app modules
  • Export metrics symbols from lib.rs
src/metrics.rs
src/connection.rs
src/app.rs
src/lib.rs
Update dependencies and feature flags for metrics and testing
  • Add metrics and metrics-exporter-prometheus to Cargo.toml
  • Enable cucumber and metrics-util in dev-dependencies
  • Configure test harness for cucumber
Cargo.toml
wireframe_testing/Cargo.toml
Add unit and integration tests for metrics emission
  • Implement unit test using metrics_util DebuggingRecorder
  • Add cucumber tests and feature file to validate exporter output
tests/metrics.rs
tests/cucumber.rs
tests/steps/mod.rs
tests/features/metrics.feature

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 22, 2025

Summary by CodeRabbit

  • New Features

    • Introduced metrics collection and Prometheus integration, including tracking of active connections, processed frames (inbound/outbound), and error totals.
    • Added a public metrics module with helper functions and constants for observability.
  • Documentation

    • Expanded production hardening guide with a section on metrics and observability, including integration examples and a metrics entity–relationship diagram.
    • Updated roadmap to mark metrics and observability as complete.
  • Bug Fixes

    • Suppressed dead code warnings in documentation examples and test helpers.
  • Tests

    • Added unit tests to verify correct metric increments for frames and errors.
  • Chores

    • Updated Rust toolchain version.
    • Added and updated dependencies to support metrics functionality.

Walkthrough

Introduce a metrics subsystem to the codebase by adding a new metrics module, integrating metric collection calls throughout the application and connection logic, and exposing relevant metrics at the crate root. Update documentation to reflect metrics support, provide usage guidance, and mark observability tasks as complete. Add tests to verify metric recording.

Changes

File(s) Change Summary
Cargo.toml, wireframe_testing/Cargo.toml Add metrics, metrics-exporter-prometheus, and metrics-util dependencies; introduce a "metrics" feature as default.
src/metrics.rs Add new metrics module: constants, Direction enum, and metric helper functions with feature gating and documentation.
src/lib.rs Publicly expose metrics module and re-export metric constants, enum, and functions at crate root.
src/app.rs, src/connection.rs Insert metric increment calls for frames, errors, and connections throughout application and connection handling logic.
docs/hardening-wireframe-a-guide-to-production-resilience.md, docs/roadmap.md, docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md Update documentation to describe metrics feature, integration, and completion of observability roadmap items.
tests/metrics.rs Add unit tests to verify metric increments and correct recording using a local metrics recorder.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant WireframeApp
    participant Metrics

    Client->>WireframeApp: Send Frame
    WireframeApp->>Metrics: inc_frames(Inbound)
    alt Deserialization fails
        WireframeApp->>Metrics: inc_deser_errors()
    else Handler error
        WireframeApp->>Metrics: inc_handler_errors()
    end
    WireframeApp->>Client: Send Response
Loading
sequenceDiagram
    participant Connection
    participant Metrics

    Note over Connection: On connection creation
    Connection->>Metrics: inc_connections()

    Note over Connection: On connection drop
    Connection->>Metrics: dec_connections()

    Note over Connection: On outbound frame
    Connection->>Metrics: inc_frames(Outbound)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~45 minutes

Possibly related PRs

Poem

Metrics now tick and gauges climb,
Observability in rhythm, keeping time.
Frames and errors, counted with care,
Connections tracked—no state unaware.
Prometheus can now peer inside,
With tests and docs standing beside.
Wireframe’s insight, metrics supplied!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b607d09 and 6f71257.

📒 Files selected for processing (3)
  • Cargo.toml (2 hunks)
  • src/server.rs (1 hunks)
  • tests/metrics.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/server.rs
  • tests/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/server.rs
  • tests/metrics.rs
Cargo.toml

📄 CodeRabbit Inference Engine (AGENTS.md)

Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

Files:

  • Cargo.toml
🔇 Additional comments (9)
src/server.rs (1)

469-472: LGTM! Properly addresses coding guidelines.

The addition of the documentation comment and replacement of #[allow] with #[expect] with a clear reason correctly follows the coding guidelines and addresses previous review feedback.

tests/metrics.rs (5)

1-5: Excellent module documentation.

The module-level documentation clearly explains the purpose and approach, satisfying the coding guideline requirement for //! comments.


7-12: Well-designed helper function.

The function name accurately reflects its dual return value, and the documentation clearly explains its testing purpose. This addresses previous feedback effectively.


14-30: Comprehensive outbound frame test.

The test properly validates the metric name, direction label, and counter value increment. The isolated recorder approach ensures test reliability.


32-48: Thorough inbound frame validation.

The test correctly mirrors the outbound test structure whilst validating the "inbound" direction label specifically. The comprehensive assertion checks all relevant metric properties.


50-63: Robust error metric test.

The test properly validates error counter increments with appropriate assertions. The focused approach on counter value validation ensures the metric is functioning correctly.

Cargo.toml (3)

18-19: Appropriate metrics dependencies added.

The optional dependencies for metrics and metrics-exporter-prometheus with the "http-listener" feature properly support the metrics functionality whilst maintaining optional inclusion.


30-31: Correct dev dependencies for testing.

Adding metrics-util and metrics-exporter-prometheus as dev dependencies enables comprehensive testing of the metrics functionality without bloating production builds.


34-35: Well-structured feature configuration.

The "metrics" feature properly gates the optional dependencies and its inclusion in defaults ensures metrics are available by default whilst allowing opt-out when needed.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/implement-metrics-and-observability-feature

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.

  • Consider gating all metric calls (and the metrics dependency) behind a Cargo feature (e.g. “metrics”) so users can opt out of pulling in the crate and runtime overhead.
  • The Prometheus recorder example is duplicated in multiple docs—extract it to a single snippet (for example in the metrics module docs) and reference it in both guides to avoid drift.
  • You’ve added tests for outbound frames and active connections, but consider adding a test or Cucumber scenario for inbound-frame metrics and error counters to cover the other instrumented paths.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider gating all metric calls (and the `metrics` dependency) behind a Cargo feature (e.g. “metrics”) so users can opt out of pulling in the crate and runtime overhead.
- The Prometheus recorder example is duplicated in multiple docs—extract it to a single snippet (for example in the `metrics` module docs) and reference it in both guides to avoid drift.
- You’ve added tests for outbound frames and active connections, but consider adding a test or Cucumber scenario for inbound-frame metrics and error counters to cover the other instrumented paths.

## Individual Comments

### Comment 1
<location> `src/app.rs:657` </location>
<code_context>
         let (env, _) = match self.parse_envelope(frame) {
             Ok(result) => {
                 *deser_failures = 0;
+                crate::metrics::inc_frames(crate::metrics::Direction::Inbound);
                 result
             }
</code_context>

<issue_to_address>
Metrics increment is only on successful envelope parsing.

To track all inbound frames, increment the metric before parse_envelope; otherwise, only successfully parsed frames are counted.
</issue_to_address>

### Comment 2
<location> `src/app.rs:663` </location>
<code_context>
             Err(e) => {
                 *deser_failures += 1;
                 tracing::warn!(error = ?e, "failed to deserialize message");
+                crate::metrics::inc_errors();
                 if *deser_failures >= MAX_DESER_FAILURES {
                     return Err(io::Error::new(
</code_context>

<issue_to_address>
Error metric is incremented for deserialization failures and handler errors.

Consider using separate counters or labels to differentiate between deserialization failures and handler errors for more precise error metrics.

Suggested implementation:

```rust
                crate::metrics::inc_deser_errors();

```

```rust
                        crate::metrics::inc_handler_errors();

```

```rust
                    crate::metrics::inc_handler_errors();

```

You will need to implement the new functions `inc_deser_errors()` and `inc_handler_errors()` in your `crate::metrics` module. If you prefer to use a single function with a label, adjust the calls accordingly (e.g., `inc_errors("deserialization")` and `inc_errors("handler")`), and update the metrics module to support labeled error counting.
</issue_to_address>

### Comment 3
<location> `tests/metrics.rs:6` </location>
<code_context>
+use wireframe::{connection::ConnectionActor, push::PushQueues};
+
+#[tokio::test]
+async fn outbound_frame_metric_increments() {
+    let recorder = DebuggingRecorder::new();
+    let snapshotter = recorder.snapshotter();
+    recorder.install().expect("install");
+
+    let (queues, handle) = PushQueues::<u8>::bounded(1, 1);
+    handle.push_high_priority(1).await.unwrap();
+    let token = CancellationToken::new();
+    let mut actor: ConnectionActor<_, ()> = ConnectionActor::new(queues, handle, None, token);
+    let mut out = Vec::new();
+    actor.run(&mut out).await.unwrap();
+
+    let metrics = snapshotter.snapshot().into_vec();
+    let found = metrics
+        .iter()
+        .any(|(k, ..)| k.key().name() == wireframe::metrics::FRAMES_PROCESSED);
+    assert!(found, "frames_processed metric not recorded");
+}
</code_context>

<issue_to_address>
Missing tests for inbound frame and error metrics.

Please add tests to verify that inbound frame and error metrics are also recorded, ensuring full coverage of the metrics functionality.

Suggested implementation:

```rust
#[tokio::test]
async fn outbound_frame_metric_increments() {
    let recorder = DebuggingRecorder::new();
    let snapshotter = recorder.snapshotter();
    recorder.install().expect("install");

    let (queues, handle) = PushQueues::<u8>::bounded(1, 1);
    handle.push_high_priority(1).await.unwrap();
    let token = CancellationToken::new();
    let mut actor: ConnectionActor<_, ()> = ConnectionActor::new(queues, handle, None, token);
    let mut out = Vec::new();
    actor.run(&mut out).await.unwrap();

    let metrics = snapshotter.snapshot().into_vec();
    let found = metrics
        .iter()
        .any(|(k, ..)| k.key().name() == wireframe::metrics::FRAMES_PROCESSED);
    assert!(found, "frames_processed metric not recorded");
}

#[tokio::test]
async fn inbound_frame_metric_increments() {
    let recorder = DebuggingRecorder::new();
    let snapshotter = recorder.snapshotter();
    recorder.install().expect("install");

    let (queues, handle) = PushQueues::<u8>::bounded(1, 1);
    // Simulate inbound frame by pushing to the inbound queue if available
    queues.inbound().send(2).await.unwrap();
    let token = CancellationToken::new();
    let mut actor: ConnectionActor<_, ()> = ConnectionActor::new(queues, handle, None, token);
    let mut out = Vec::new();
    actor.run(&mut out).await.ok();

    let metrics = snapshotter.snapshot().into_vec();
    let found = metrics
        .iter()
        .any(|(k, ..)| k.key().name() == wireframe::metrics::INBOUND_FRAMES_PROCESSED);
    assert!(found, "inbound_frames_processed metric not recorded");
}

#[tokio::test]
async fn error_metric_increments() {
    let recorder = DebuggingRecorder::new();
    let snapshotter = recorder.snapshotter();
    recorder.install().expect("install");

    let (queues, handle) = PushQueues::<u8>::bounded(1, 1);
    // Simulate an error by dropping the handle before running the actor
    drop(handle);
    let token = CancellationToken::new();
    let mut actor: ConnectionActor<_, ()> = ConnectionActor::new(queues, /* handle is dropped */ Default::default(), None, token);
    let mut out = Vec::new();
    // This should result in an error metric being recorded
    let _ = actor.run(&mut out).await;

    let metrics = snapshotter.snapshot().into_vec();
    let found = metrics
        .iter()
        .any(|(k, ..)| k.key().name() == wireframe::metrics::FRAME_ERRORS);
    assert!(found, "frame_errors metric not recorded");
}

```

- If the actual metric names for inbound frames and errors differ from `INBOUND_FRAMES_PROCESSED` and `FRAME_ERRORS`, replace them with the correct constants from `wireframe::metrics`.
- If the `queues.inbound()` or error simulation does not match your actual API, adjust the test logic to properly trigger inbound frame processing and error conditions in your implementation.
</issue_to_address>

### Comment 4
<location> `tests/cucumber.rs:1` </location>
<code_context>
+use cucumber::World as _;
+
+#[derive(Debug, Default, cucumber::World)]
</code_context>

<issue_to_address>
Consider replacing the Cucumber test harness with a simple Rust test file for metrics validation.

Here you pull in a whole Cucumber test harness (and its boilerplate) just to verify a handful of metrics. You can keep the same coverage with a single Rust test file, no extra dependency or `features/` folder needed.

For example, replace the entire `cucumber::World` setup with something like this in `tests/metrics.rs`:

```rust
// tests/metrics.rs

use metrics_exporter_prometheus::{PrometheusBuilder, PrometheusHandle};
use your_crate::record_some_metrics; // <-- your metric logic

#[tokio::test]
async fn basic_metric_export() {
    // Install a Prometheus exporter handle
    let handle: PrometheusHandle = PrometheusBuilder::new()
        .with_family("my_counter", "counter")
        .install()
        .expect("failed to install exporter");

    // Call the code under test
    record_some_metrics();

    // Grab the rendered output
    let output = handle.render();

    // Assert that your metric shows up
    assert!(
        output.contains("my_counter"),
        "expected `my_counter` in Prometheus output, got:\n{}",
        output
    );
}
```

Steps to migrate:

1. Delete the new `main.rs` cucumber harness + `features/` folder.
2. Create `tests/metrics.rs` as shown above.
3. For each scenario in your old `.feature` files, write one `#[test]` or `#[tokio::test]` that:
   - Installs a `PrometheusHandle`
   - Invokes the behavior under test
   - Renders and asserts on the output string.

This keeps all your metric‐validation logic, removes the Cucumber dependency, and slims down your CI setup dramatically.
</issue_to_address>

### Comment 5
<location> `tests/features/metrics.feature:1` </location>
<code_context>
+Feature: metrics exporter
+  Scenario: active connections metric recorded
+    Given a metrics recorder
</code_context>

<issue_to_address>
Consider replacing the Cucumber scenario with a simple Rust test using assertions for the same coverage.

Here’s a simpler, zero-dependency way to get the exact same coverage in a plain Rust test. You can keep the `.feature` file for docs if you want, but move your “active connections” check into an assertion-based test:

```rust
// tests/metrics.rs
use my_crate::metrics::{MetricsRecorder, run_connection};

#[test]
fn active_connections_metric_recorded() {
    // arrange
    let recorder = MetricsRecorder::new();

    // act
    run_connection(&recorder, /* no frames */ &[]);

    // assert
    let output = recorder.scrape();  
    assert!(
        output.contains("active_connections"),
        "metrics output did not include `active_connections` gauge; got:\n{}",
        output
    );
}
```

Actionable steps:
1. Create (or update) `tests/metrics.rs` with the snippet above.
2. Remove your Cucumber runner / glue code for this one scenario.
3. Run `cargo test -- --nocapture` and confirm identical behavior.
</issue_to_address>

### Comment 6
<location> `tests/steps/mod.rs:8` </location>
<code_context>
+use crate::MetricsWorld;
+
+#[given("a metrics recorder")]
+fn metrics_recorder(world: &mut MetricsWorld) {
+    let handle = metrics_exporter_prometheus::PrometheusBuilder::new()
+        .install_recorder()
</code_context>

<issue_to_address>
Consider combining the recorder setup and connection run steps into a single helper or inlining them to eliminate unnecessary indirection and fields.

```markdown
You can collapse the “given” + exporter‐in‐world indirection and the “when” step into a single helper on `MetricsWorld`, or even inline the recorder into the “when” step. That removes the extra `exporter` field and simplifies maintenance, while keeping your scenario semantics.

Example 1: add a helper method on `MetricsWorld`  

```rust
impl MetricsWorld {
    /// Installs a Prometheus recorder, runs a no‐frame connection,
    /// does upkeep, and captures the rendered output.
    pub async fn record_active_connections(&mut self) {
        let handle = metrics_exporter_prometheus::PrometheusBuilder::new()
            .install_recorder()
            .expect("recorder install");
        let (queues, handle2) = PushQueues::<u8>::bounded(1, 1);
        let token = CancellationToken::new();
        let mut actor = ConnectionActor::new(queues, handle2, None, token);

        let mut out = Vec::new();
        actor.run(&mut out).await.unwrap();
        handle.run_upkeep();
        self.output = Some(handle.render());
    }
}
```

Then the step defs become:

```rust
#[when("a connection runs with no frames")]
async fn run_connection(world: &mut MetricsWorld) {
    world.record_active_connections().await;
}

#[then("the exporter output includes active connections gauge")]
fn check_output(world: &mut MetricsWorld) {
    let out = world.output.as_ref().unwrap();
    assert!(out.contains("wireframe_connections_active"), "{out}");
}
```

Example 2: inline everything in the “when” step

```rust
#[when("a connection runs with no frames")]
async fn run_connection(world: &mut MetricsWorld) {
    let handle = metrics_exporter_prometheus::PrometheusBuilder::new()
        .install_recorder().unwrap();
    let (queues, handle2) = PushQueues::<u8>::bounded(1, 1);
    let token = CancellationToken::new();
    let mut actor = ConnectionActor::new(queues, handle2, None, token);

    let mut out = Vec::new();
    actor.run(&mut out).await.unwrap();
    handle.run_upkeep();
    world.output = Some(handle.render());
}
```

Either approach keeps the same behavior but drops the extra `#[given]` indirection and the `exporter` field from your world, reducing boilerplate and future maintenance cost.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/app.rs Outdated
Comment thread src/app.rs Outdated
Comment thread tests/metrics.rs Outdated
Comment thread tests/cucumber.rs Outdated
Comment thread tests/features/metrics.feature Outdated
Comment thread tests/steps/mod.rs Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🔭 Outside diff range comments (2)
tests/cucumber.rs (1)

1-13: Address missing dependency and add required module documentation.

The build failure indicates metrics_exporter_prometheus is not available as a dependency. Add it to Cargo.toml under [dev-dependencies] since it's used in tests.

Additionally, this file violates the coding guideline requiring every module to begin with a //! doc comment explaining the module's purpose and utility.

+//! Cucumber test infrastructure for metrics validation.
+//!
+//! Defines the test world and main test runner for behaviour-driven
+//! testing of metrics recording and exporting functionality.
+
 use cucumber::World as _;

Also ensure metrics-exporter-prometheus is added to Cargo.toml:

[dev-dependencies]
metrics-exporter-prometheus = "0.x.x"  # Use appropriate version
tests/steps/mod.rs (1)

1-33: Add required module documentation and resolve dependency.

This file lacks the mandatory module-level doc comment and has the same dependency issue as the previous file.

+//! Cucumber step definitions for metrics testing.
+//!
+//! Implements Given-When-Then steps to validate metrics recording
+//! and Prometheus export functionality in integration tests.
+
 use cucumber::{given, then, when};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6429b57 and 11b7c6e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • Cargo.toml (2 hunks)
  • docs/hardening-wireframe-a-guide-to-production-resilience.md (1 hunks)
  • docs/roadmap.md (1 hunks)
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (1 hunks)
  • src/app.rs (2 hunks)
  • src/connection.rs (3 hunks)
  • src/lib.rs (2 hunks)
  • src/metrics.rs (1 hunks)
  • tests/cucumber.rs (1 hunks)
  • tests/features/metrics.feature (1 hunks)
  • tests/metrics.rs (1 hunks)
  • tests/steps/mod.rs (1 hunks)
  • wireframe_testing/Cargo.toml (1 hunks)
📓 Path-based instructions (4)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/lib.rs
  • tests/metrics.rs
  • src/connection.rs
  • tests/steps/mod.rs
  • tests/cucumber.rs
  • src/app.rs
  • src/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/lib.rs
  • tests/metrics.rs
  • src/connection.rs
  • tests/steps/mod.rs
  • tests/cucumber.rs
  • src/app.rs
  • src/metrics.rs
Cargo.toml

📄 CodeRabbit Inference Engine (AGENTS.md)

Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

Files:

  • Cargo.toml
🧬 Code Graph Analysis (3)
src/connection.rs (1)
src/metrics.rs (4)
  • inc_connections (34-34)
  • dec_connections (37-37)
  • inc_frames (40-42)
  • inc_errors (45-45)
tests/steps/mod.rs (3)
src/connection.rs (3)
  • new (30-34)
  • new (139-152)
  • new (511-520)
tests/connection_actor.rs (1)
  • queues (24-24)
src/push.rs (1)
  • bounded (288-291)
src/app.rs (1)
src/metrics.rs (2)
  • inc_frames (40-42)
  • inc_errors (45-45)
🪛 LanguageTool
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

[uncategorized] ~289-~289: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...usBuilder` can install a global recorder so external systems may scrape the values....

(COMMA_COMPOUND_SENTENCE_2)

🪛 GitHub Check: build-test
tests/steps/mod.rs

[failure] 9-9:
failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus

tests/cucumber.rs

[failure] 5-5:
failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus

🪛 GitHub Actions: CI
tests/steps/mod.rs

[error] 9-9: Rust compiler error E0433: failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus.

🧰 Additional context used
📓 Path-based instructions (4)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/roadmap.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/lib.rs
  • tests/metrics.rs
  • src/connection.rs
  • tests/steps/mod.rs
  • tests/cucumber.rs
  • src/app.rs
  • src/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/lib.rs
  • tests/metrics.rs
  • src/connection.rs
  • tests/steps/mod.rs
  • tests/cucumber.rs
  • src/app.rs
  • src/metrics.rs
Cargo.toml

📄 CodeRabbit Inference Engine (AGENTS.md)

Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

Files:

  • Cargo.toml
🧬 Code Graph Analysis (3)
src/connection.rs (1)
src/metrics.rs (4)
  • inc_connections (34-34)
  • dec_connections (37-37)
  • inc_frames (40-42)
  • inc_errors (45-45)
tests/steps/mod.rs (3)
src/connection.rs (3)
  • new (30-34)
  • new (139-152)
  • new (511-520)
tests/connection_actor.rs (1)
  • queues (24-24)
src/push.rs (1)
  • bounded (288-291)
src/app.rs (1)
src/metrics.rs (2)
  • inc_frames (40-42)
  • inc_errors (45-45)
🪛 LanguageTool
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

[uncategorized] ~289-~289: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...usBuilder` can install a global recorder so external systems may scrape the values....

(COMMA_COMPOUND_SENTENCE_2)

🪛 GitHub Check: build-test
tests/steps/mod.rs

[failure] 9-9:
failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus

tests/cucumber.rs

[failure] 5-5:
failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus

🪛 GitHub Actions: CI
tests/steps/mod.rs

[error] 9-9: Rust compiler error E0433: failed to resolve: use of unresolved module or unlinked crate metrics_exporter_prometheus.

🔇 Additional comments (25)
wireframe_testing/Cargo.toml (1)

14-14: LGTM: Dependency addition supports metrics testing.

The metrics-util dependency addition is appropriate for supporting the new metrics testing functionality.

docs/roadmap.md (1)

153-159: LGTM: Roadmap accurately reflects completed metrics work.

The marking of metrics and observability tasks as complete correctly reflects the implementation of metrics throughout the codebase, including the new metrics module, instrumentation, and Prometheus integration guide.

src/lib.rs (2)

15-15: LGTM: Metrics module properly exposed.

The addition of the metrics module follows the established pattern for public module exposure.


26-26: LGTM: Key metrics items appropriately re-exported.

Re-exporting CONNECTIONS_ACTIVE, Direction, ERRORS_TOTAL, and FRAMES_PROCESSED at the crate root provides convenient access to the most commonly used metrics components.

tests/features/metrics.feature (1)

1-6: LGTM: Well-structured Cucumber feature test.

The metrics exporter feature test follows proper Gherkin syntax and provides focused validation of active connections gauge recording. The Given-When-Then structure clearly defines the test scenario.

docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (2)

288-299: LGTM: Excellent metrics integration documentation.

The addition clearly explains metrics emission using the metrics crate and provides a practical code example for Prometheus integration. The content fits well within the observability section and enhances the documentation's completeness.


289-289: Add comma for proper compound sentence structure.

The sentence requires a comma before "so" when connecting two independent clauses.

-install a global recorder so external systems may scrape the values. The
+install a global recorder, so external systems may scrape the values. The

Likely an incorrect or invalid review comment.

Cargo.toml (3)

18-19: LGTM! Clean metrics dependency integration.

The metrics crate addition and optional Prometheus exporter with appropriate feature flags support the observability requirements effectively.


30-31: Appropriate testing dependencies added.

The cucumber and metrics-util additions support comprehensive testing of the metrics functionality.


39-41: Correct cucumber test configuration.

Disabling the test harness for cucumber tests follows standard practice for BDD testing frameworks.

docs/hardening-wireframe-a-guide-to-production-resilience.md (1)

350-366: Excellent addition to the hardening guide.

This section logically extends the production resilience theme by covering observability requirements. The Prometheus integration example is concise and demonstrates the essential setup clearly. The documentation maintains consistency with the existing guide's tone and technical depth.

src/app.rs (3)

657-657: Proper inbound frame tracking.

Correctly increments the inbound frames metric upon successful deserialization, providing visibility into message processing throughput.


663-663: Appropriate error tracking on deserialization failures.

Captures deserialization errors in the metrics, essential for monitoring data quality issues and potential attacks.


684-684: Comprehensive error instrumentation.

Error metrics cover all failure scenarios: response sending, handler execution, and missing routes. This provides complete visibility into application-level errors.

Also applies to: 689-689, 694-694

tests/metrics.rs (1)

5-23: Well-structured metrics integration test.

This test effectively validates outbound frame metric tracking by using the debugging recorder, exercising the connection actor with actual frame processing, and verifying the metric presence. The focused approach ensures the test validates the specific metrics integration without unnecessary complexity.

src/connection.rs (5)

32-32: Proper connection lifecycle tracking.

Correctly increments the active connections metric on connection creation, complementing the existing atomic counter.


39-41: Clean connection cleanup tracking.

The drop implementation properly decrements both the atomic counter and metrics gauge, ensuring accurate connection state tracking.


329-329: Accurate outbound frame tracking from push queues.

Correctly instruments frame processing from push queues with the Outbound direction label, providing visibility into pushed message throughput.


430-430: Complete outbound frame instrumentation.

Tracks frames from response streams alongside push queue frames, ensuring comprehensive outbound message visibility.


437-437: Appropriate error tracking on protocol failures.

Captures protocol errors in metrics, providing visibility into application-level issues during response stream processing.

tests/steps/mod.rs (1)

15-26: Well-structured test step implementation.

The async step correctly:

  • Creates bounded push queues with appropriate capacity
  • Instantiates ConnectionActor with proper parameters
  • Runs the actor and captures metrics output
  • Handles the optional exporter gracefully
src/metrics.rs (4)

1-5: Excellent module documentation.

The module doc comment clearly explains the purpose and references the metrics crate documentation. This meets the coding guideline requirements perfectly.


8-13: Well-defined metric constants with clear documentation.

The metric names follow Prometheus naming conventions and include descriptive doc comments. The consistent wireframe_ prefix ensures no namespace conflicts.


15-31: Clean Direction enum implementation.

The enum provides clear semantics for frame processing direction with:

  • Appropriate derive traits (Clone, Copy)
  • Clear variant documentation
  • Private as_str() method for consistent string representation
  • Simple match implementation

33-45: Well-designed helper functions.

The metric helper functions provide a clean API that:

  • Encapsulate the metrics crate complexity
  • Use appropriate metric types (gauge for connections, counter for frames/errors)
  • Include direction labelling for frame metrics
  • Follow consistent naming patterns

Comment thread tests/cucumber.rs Outdated
Comment thread tests/steps/mod.rs Outdated
Comment thread tests/steps/mod.rs Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
tests/metrics.rs (1)

23-51: Tests for inbound frames and errors are now implemented.

The missing test coverage mentioned in previous reviews has been addressed. The current implementation is superior to the suggested approach, using proper metric isolation rather than complex actor setups.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 11b7c6e and cd5becd.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml (2 hunks)
  • docs/hardening-wireframe-a-guide-to-production-resilience.md (1 hunks)
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (1 hunks)
  • src/app.rs (3 hunks)
  • src/connection.rs (3 hunks)
  • src/metrics.rs (1 hunks)
  • tests/metrics.rs (1 hunks)
📓 Path-based instructions (4)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/app.rs
  • tests/metrics.rs
  • src/metrics.rs
  • src/connection.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/app.rs
  • tests/metrics.rs
  • src/metrics.rs
  • src/connection.rs
Cargo.toml

📄 CodeRabbit Inference Engine (AGENTS.md)

Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

Files:

  • Cargo.toml
🧬 Code Graph Analysis (3)
src/app.rs (1)
src/metrics.rs (6)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_deser_errors (71-71)
  • inc_deser_errors (74-74)
  • inc_handler_errors (78-78)
  • inc_handler_errors (81-81)
tests/metrics.rs (1)
src/metrics.rs (4)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_deser_errors (71-71)
  • inc_deser_errors (74-74)
src/connection.rs (1)
src/metrics.rs (8)
  • inc_connections (48-48)
  • inc_connections (51-51)
  • dec_connections (55-55)
  • dec_connections (58-58)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_handler_errors (78-78)
  • inc_handler_errors (81-81)
🪛 LanguageTool
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

[uncategorized] ~290-~290: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...rumentation is gated behind this feature so users can opt out if metrics are unnece...

(COMMA_COMPOUND_SENTENCE_2)

🪛 GitHub Check: build-test
tests/metrics.rs

[warning] 30-30:
Diff in /home/runner/work/wireframe/wireframe/tests/metrics.rs

🪛 GitHub Actions: CI
tests/metrics.rs

[warning] 30-30: cargo fmt formatting check failed. Diff detected in code formatting at line 30.

🧰 Additional context used
📓 Path-based instructions (4)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/app.rs
  • tests/metrics.rs
  • src/metrics.rs
  • src/connection.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/app.rs
  • tests/metrics.rs
  • src/metrics.rs
  • src/connection.rs
Cargo.toml

📄 CodeRabbit Inference Engine (AGENTS.md)

Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

Files:

  • Cargo.toml
🧬 Code Graph Analysis (3)
src/app.rs (1)
src/metrics.rs (6)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_deser_errors (71-71)
  • inc_deser_errors (74-74)
  • inc_handler_errors (78-78)
  • inc_handler_errors (81-81)
tests/metrics.rs (1)
src/metrics.rs (4)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_deser_errors (71-71)
  • inc_deser_errors (74-74)
src/connection.rs (1)
src/metrics.rs (8)
  • inc_connections (48-48)
  • inc_connections (51-51)
  • dec_connections (55-55)
  • dec_connections (58-58)
  • inc_frames (62-64)
  • inc_frames (67-67)
  • inc_handler_errors (78-78)
  • inc_handler_errors (81-81)
🪛 LanguageTool
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

[uncategorized] ~290-~290: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...rumentation is gated behind this feature so users can opt out if metrics are unnece...

(COMMA_COMPOUND_SENTENCE_2)

🪛 GitHub Check: build-test
tests/metrics.rs

[warning] 30-30:
Diff in /home/runner/work/wireframe/wireframe/tests/metrics.rs

🪛 GitHub Actions: CI
tests/metrics.rs

[warning] 30-30: cargo fmt formatting check failed. Diff detected in code formatting at line 30.

🔇 Additional comments (16)
docs/hardening-wireframe-a-guide-to-production-resilience.md (1)

350-355: Excellent addition of observability guidance.

The new metrics section appropriately emphasises operational visibility and correctly references the optional feature gating. The content aligns well with the production resilience theme of this document.

src/app.rs (3)

654-654: Correct placement of inbound frame metric.

The metric increment is positioned properly before envelope parsing to capture all inbound frames, addressing the concern from previous reviews about only counting successfully parsed frames.


663-663: Appropriate error categorisation for deserialization failures.

The use of inc_deser_errors() correctly differentiates deserialization failures from handler errors, implementing the suggestion from previous reviews for more precise error metrics.


684-684: Consistent handler error tracking across failure scenarios.

All handler-related error conditions (send failures, handler errors, and missing handlers) are consistently tracked using inc_handler_errors(), providing comprehensive coverage of handler-related issues.

Also applies to: 689-689, 694-694

Cargo.toml (2)

33-34: Well-structured metrics feature configuration.

The feature definition properly includes both required dependencies and setting it as default provides good ergonomics whilst maintaining the ability to opt out.


18-19: Approve metrics dependencies

Confirmed that metrics = "0.24" pulls in v0.24.2 and metrics-exporter-prometheus = "0.17" pulls in v0.17.2. No known security advisories affect these crates. Merge as is.

src/connection.rs (3)

32-32: Excellent integration with RAII connection tracking.

The metrics calls are properly integrated with the existing ActiveConnection RAII pattern, ensuring accurate connection count tracking that automatically handles cleanup on drop.

Also applies to: 39-41


329-329: Consistent outbound frame tracking.

Both push queue frames and response stream frames are properly tracked with the outbound direction label, providing comprehensive coverage of outbound frame metrics.

Also applies to: 430-430


437-437: Appropriate protocol error tracking.

The handler error metric is correctly incremented for protocol errors in the response stream, maintaining consistency with error categorisation across the codebase.

tests/metrics.rs (3)

3-7: Well-structured helper function.

The helper function properly encapsulates the recorder setup logic, promoting code reuse across tests.


9-21: Solid test implementation for outbound frame metrics.

The test correctly isolates metric recording and validates the presence of the expected metric.


39-51: Error metrics test is properly implemented.

The test correctly validates that deserialization error metrics are recorded.

src/metrics.rs (4)

1-17: Excellent module documentation with practical example.

The module documentation clearly explains the purpose, feature gating behaviour, and includes a helpful Prometheus integration example.


21-26: Well-defined metric constants following Prometheus conventions.

The metric name constants are appropriately named and documented, following standard Prometheus naming patterns.


28-44: Direction enum is well-designed and implemented.

The enum properly represents frame processing directions with appropriate derives and a clean string conversion method.


46-81: Excellent feature-gated metrics implementation.

The helper functions are properly implemented with appropriate feature gating, providing no-op versions when metrics are disabled. The use of gauge for connections and counters for frames/errors is correct.

Comment thread docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md Outdated
Comment thread tests/metrics.rs
Comment on lines +23 to +37
#[test]
fn inbound_frame_metric_increments() {
let (snapshotter, recorder) = snapshotter();
metrics::with_local_recorder(&recorder, || {
wireframe::metrics::inc_frames(wireframe::metrics::Direction::Inbound);
});

let metrics = snapshotter.snapshot().into_vec();
let found = metrics.iter().any(|(k, _, _, v)| {
k.key().name() == wireframe::metrics::FRAMES_PROCESSED
&& k.key().labels().any(|l| l.key() == "direction" && l.value() == "inbound")
&& matches!(v, DebugValue::Counter(c) if *c > 0)
});
assert!(found, "inbound frames metric not recorded");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix formatting issue in the inbound frame test.

The test logic is comprehensive and correctly validates metric name, labels, and counter value. However, there's a formatting issue that must be resolved.

Apply this diff to fix the formatting:

-    let found = metrics.iter().any(|(k, _, _, v)| {
+    let found = metrics
+        .iter()
+        .any(|(k, _, _, v)| {
         k.key().name() == wireframe::metrics::FRAMES_PROCESSED
             && k.key().labels().any(|l| l.key() == "direction" && l.value() == "inbound")
             && matches!(v, DebugValue::Counter(c) if *c > 0)
-    });
+        });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[test]
fn inbound_frame_metric_increments() {
let (snapshotter, recorder) = snapshotter();
metrics::with_local_recorder(&recorder, || {
wireframe::metrics::inc_frames(wireframe::metrics::Direction::Inbound);
});
let metrics = snapshotter.snapshot().into_vec();
let found = metrics.iter().any(|(k, _, _, v)| {
k.key().name() == wireframe::metrics::FRAMES_PROCESSED
&& k.key().labels().any(|l| l.key() == "direction" && l.value() == "inbound")
&& matches!(v, DebugValue::Counter(c) if *c > 0)
});
assert!(found, "inbound frames metric not recorded");
}
let metrics = snapshotter.snapshot().into_vec();
let found = metrics
.iter()
.any(|(k, _, _, v)| {
k.key().name() == wireframe::metrics::FRAMES_PROCESSED
&& k.key().labels().any(|l| l.key() == "direction" && l.value() == "inbound")
&& matches!(v, DebugValue::Counter(c) if *c > 0)
});
assert!(found, "inbound frames metric not recorded");
🧰 Tools
🪛 GitHub Check: build-test

[warning] 30-30:
Diff in /home/runner/work/wireframe/wireframe/tests/metrics.rs

🪛 GitHub Actions: CI

[warning] 30-30: cargo fmt formatting check failed. Diff detected in code formatting at line 30.

🤖 Prompt for AI Agents
In tests/metrics.rs around lines 23 to 37, the test function
inbound_frame_metric_increments has a formatting issue. Fix the formatting by
ensuring consistent indentation and spacing according to Rust style guidelines,
such as proper alignment of code blocks, consistent use of blank lines, and
correct placement of braces to improve readability and maintainability.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd5becd and 18189be.

📒 Files selected for processing (1)
  • tests/metrics.rs (1 hunks)
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • tests/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • tests/metrics.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • tests/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • tests/metrics.rs
⏰ Context from checks skipped due to timeout of 240000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-test
🔇 Additional comments (2)
tests/metrics.rs (2)

1-4: Module documentation follows guidelines correctly.

The module-level doc comment properly explains the module's purpose and testing approach using the required //! format.


27-43: Well-implemented comprehensive test.

The test correctly validates metric name, direction label, and counter value. The formatting issues from previous reviews appear to have been resolved.

Comment thread tests/metrics.rs Outdated
Comment thread tests/metrics.rs
Comment thread tests/metrics.rs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0dc759 and aeb4205.

📒 Files selected for processing (1)
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (1 hunks)
📓 Path-based instructions (2)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
🧰 Additional context used
📓 Path-based instructions (2)
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aeb4205 and 24dab39.

📒 Files selected for processing (5)
  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (1 hunks)
  • examples/metadata_routing.rs (1 hunks)
  • rust-toolchain.toml (1 hunks)
  • src/server.rs (1 hunks)
  • tests/metrics.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.rs: Comment why, not what. Explain assumptions, edge cases, trade-offs, or complexity. Don't echo the obvious.
Comments must use en-GB-oxendict spelling and grammar.
Function documentation must include clear examples.
Name things precisely. Use clear, descriptive variable and function names. For booleans, prefer names with is, has, or should.
Each file should encapsulate a coherent module. Group related code (e.g., models + utilities + fixtures) close together.
Group by feature, not layer. Colocate views, logic, fixtures, and helpers related to a domain concept rather than splitting by type.
Every module must begin with a module level (//! ) comment explaining the module's purpose and utility.
Document public APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.
Do not use return in single-line functions.
Prefer immutable data and avoid unnecessary mut bindings.
Handle errors with the Result type instead of panicking where feasible.
Avoid unsafe code unless absolutely necessary and document any usage clearly.
Clippy warnings MUST be disallowed.
Lints must not be silenced except as a last resort.
Lint rule suppressions must be tightly scoped and include a clear reason.
Prefer expect over allow.
Fix any warnings emitted during tests in the code itself rather than silencing them.
Write unit and behavioural tests for new functionality. Run both before and after making any change.
Prefer .expect() over .unwrap().
Use predicate functions for conditional criteria with more than two branches.
Where a function is too long, extract meaningfully named helper functions adhering to separation of concerns and CQRS.
Where a function has too many parameters, group related parameters in meaningfully named structs.
Where a function is returning a large error consider using Arc to reduce the amount of data returned.

Files:

  • src/server.rs
  • examples/metadata_routing.rs
  • tests/metrics.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/server.rs
  • examples/metadata_routing.rs
  • tests/metrics.rs
docs/**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

docs/**/*.md: Reference: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Update: When new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve, proactively update the relevant file(s) in the docs/ directory to reflect the latest state. Ensure the documentation remains accurate and current.
Documentation must use en-GB-oxendict spelling and grammar (with the exception of 'license' which is to be left unchanged for community consistency).

Conventions for writing project documentation should be followed as described in the documentation style guide.

docs/**/*.md: Use British English based on the Oxford English Dictionary (en-oxendict) for documentation.
The word "outwith" is acceptable in documentation.
Keep US spelling when used in an API, for example color.
Use the Oxford comma in documentation lists and sentences.
Company names are treated as collective nouns (e.g., "Lille Industries are expanding").
Write headings in sentence case.
Use Markdown headings (#, ##, ###, etc.) in order without skipping levels.
Follow markdownlint recommendations.
Provide code blocks and lists using standard Markdown syntax.
Always provide a language identifier for fenced code blocks; use plaintext for non-code text.
Use - as the first level bullet and renumber lists when items change.
Prefer inline links using [text](url) or angle brackets around the URL.
Ensure blank lines before and after bulleted lists and fenced blocks.
Ensure tables have a delimiter line below the header row.
Expand any uncommon acronym on first use, for example, Continuous Integration (CI).
Wrap paragraphs at 80 columns.
Wrap code at 120 columns.
Do not wrap tables.
Use footnotes referenced with [^label].
Include Mermaid diagrams where they add clarity in documentation.
When embedding figures, use ![alt text](path/to/image) an...

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
**/*.md

📄 CodeRabbit Inference Engine (AGENTS.md)

**/*.md: Validate Markdown files using make markdownlint.
Run make fmt after any documentation changes to format all Markdown files and fix table markup.
Validate Mermaid diagrams in Markdown files by running make nixie.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks must be wrapped at 120 columns.
Tables and headings must not be wrapped.
Use dashes (-) for list bullets.
Use GitHub-flavoured Markdown footnotes ([^1]) for references.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md
🪛 LanguageTool
docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md

[style] ~288-~288: Would you like to use the Oxford spelling “summarizes”? The spelling ‘summarises’ is also correct.
Context: ...e following entity–relationship diagram summarises how the core metrics relate. ```mermai...

(OXFORD_SPELLING_Z_NOT_S)

🔇 Additional comments (3)
rust-toolchain.toml (1)

2-2: Synchronise CI with the new nightly version

Update all CI workflows, Dockerfiles, and dev-container configs to pull nightly-2025-07-22 or rely solely on rust-toolchain.toml; mismatched toolchains will break the build cache and gate the pipeline.

docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md (1)

288-312: LGTM! Excellent metrics documentation with clear visual representation.

The entity-relationship diagram effectively illustrates the core metrics relationships, and the explanatory text clearly communicates the optional nature of the metrics feature. The documentation follows the British English requirements correctly (ignore the static analysis hint suggesting "summarizes" - "summarises" is the correct British spelling per the coding guidelines).

tests/metrics.rs (1)

1-63: LGTM! Comprehensive metrics testing with excellent validation.

The test suite provides thorough coverage of the metrics functionality with proper isolation using metrics::with_local_recorder. Each test validates not only metric existence but also correct labelling and counter increments. The helper function is well-named and documented, and the tests cover the core metrics: outbound/inbound frames and error counting.

Comment thread examples/metadata_routing.rs Outdated
Comment thread src/server.rs Outdated
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 24, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 24, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 840bdaa and b607d09.

📒 Files selected for processing (2)
  • examples/metadata_routing.rs (1 hunks)
  • src/server.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • examples/metadata_routing.rs
  • src/server.rs
🔇 Additional comments (1)
examples/metadata_routing.rs (1)

63-64: Keep the #[expect] attribute as-is – change fully aligns with guidelines

The #[expect(dead_code, reason = "used only in documentation example")] attribute replaces the forbidden #[allow], supplies a clear justification, and is narrowly scoped to the Pong struct. No further action required.

Comment thread src/server.rs
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 24, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 24, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos leynos merged commit e6e14d4 into main Jul 24, 2025
5 checks passed
@leynos leynos deleted the codex/implement-metrics-and-observability-feature branch July 24, 2025 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant