Skip to content

Improve config-load observability (#304) - #547

Merged
leynos merged 31 commits into
mainfrom
issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase
Aug 19, 2026
Merged

Improve config-load observability (#304)#547
leynos merged 31 commits into
mainfrom
issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase

Conversation

@lodyai

@lodyai lodyai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

This branch instruments the two configuration-loading phases so operators can
identify failures, compare outcomes, and inspect startup latency without
unbounded telemetry labels.

Closes #304.

Review walkthrough

  • Start with src/observability.rs for the bounded metric vocabulary, error categorization, process recorder, and isolated recorder-backed tests.
  • Review src/main.rs for the configuration phase timing, outcome recording, and contextual error events at the CLI composition root.
  • Check src/main_tests.rs for the structured log-field contract, then docs/developers-guide.md for its maintenance contract.

Validation

  • make check-fmt: passed
  • make typecheck: passed
  • make lint: passed
  • make test: passed (1,913 nextest tests and doctests)
  • make markdownlint: passed
  • make nixie: passed
  • coderabbit review --agent: passed with zero findings after each milestone

References

Summary by Sourcery

Instrument configuration loading with bounded observability and reuse cached discovery results across startup resolution and final merging.

New Features:

  • Add bounded configuration-load metrics for diagnostic-mode resolution and full configuration merging.
  • Add structured configuration failure context with operation and low-cardinality error category fields.
  • Expose cached configuration-discovery APIs so early JSON resolution and final merging reuse one discovery pass.

Bug Fixes:

  • Prevent repeated configuration discovery and diagnostic replay from re-reading the environment or filesystem.
  • Prevent configuration telemetry and diagnostics from exposing raw paths, file names, formatted errors, or unbounded labels.

Enhancements:

  • Refactor configuration discovery to retain layers, errors, and replayable bounded diagnostics in a discovery outcome.
  • Emit drained configuration metrics snapshots for verbose human-mode command completion while keeping JSON output clean.

Documentation:

  • Document cached discovery APIs, bounded observability contracts, and updated configuration diagnostics behavior.

Tests:

  • Add unit, property, integration, and binary-level coverage for discovery replay, layer precedence, telemetry filtering, timing, and structured failure output.

Chores:

  • Centralize shared integration-test fixtures and metric snapshot assertions.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fd99db5a-5230-4e90-9504-9f66576b5f11

📥 Commits

Reviewing files that changed from the base of the PR and between c5ba939 and e7e4fc7.

📒 Files selected for processing (3)
  • src/observability.rs
  • src/observability_recorder.rs
  • src/observability_tests.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/monotony (auto-detected)
  • leynos/rstest-bdd (auto-detected)
  • leynos/ortho-config (auto-detected)
  • leynos/whitaker (auto-detected)
  • leynos/shared-actions (auto-detected)

Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.


Summary

  • Add bounded metrics for configuration-load phases, outcomes, and durations.
  • Add structured error fields for operation and coarse error category.
  • Cache discovered configuration layers to avoid repeated discovery and preserve deferred diagnostics.
  • Prevent raw configuration paths and filenames from appearing in discovery traces.
  • Install a process-wide metrics recorder and emit snapshots during verbose shutdown paths.
  • Add binary-level and unit tests for failure paths, metric labels, snapshots, error classification, and structured logging.
  • Document the observability contract and cached discovery behaviour in the user, developer, and design guides.
  • Move metrics-util to regular dependencies.

Validation

  • Pass formatting, type checking, linting, tests, Markdown linting, Nixie, and CodeRabbit validation.

Walkthrough

Configuration loading now performs one discovery pass, reuses cached layers, defers bounded diagnostics, and records phase metrics. Human-readable failures include structured fields. Verbose runs emit metric snapshots. JSON diagnostics remain machine-readable.

Changes

Configuration observability

Layer / File(s) Summary
Define observability contracts
Cargo.toml, src/observability*.rs, test_support/src/*, typos*.toml
Add bounded configuration metrics, error classification, recorder lifecycle, and metric test helpers.
Cache discovery and defer diagnostics
src/cli/discovery*.rs
Retain discovered layers and bounded diagnostic metadata. Replay diagnostics without repeated environment or filesystem access.
Reuse layers during resolution and merging
src/cli/diag.rs, src/cli/merge.rs, src/cli/mod.rs, src/main.rs
Resolve JSON mode from cached layers, merge supplied layers, record configuration phases, emit structured failure fields, and produce verbose snapshots.
Validate and document observable behaviour
src/main_tests.rs, src/main_config_tests.rs, tests/*, docs/*
Validate privacy, metrics, precedence, replay, cached merging, and the updated discovery and observability contracts.

Sequence Diagram(s)

sequenceDiagram
  participant main
  participant discovery
  participant merge
  participant observability
  main->>observability: init_metrics()
  main->>discovery: resolve_json_and_layers_outcome_with_env()
  discovery-->>main: DiscoveryOutcome and DiscoveredLayers
  main->>merge: merge_with_cached_file_layers()
  merge-->>main: merged configuration or error
  main->>observability: emit_metrics_snapshot() when verbose
Loading

Possibly related PRs

Suggested labels: Issue

Poem

Metrics start at launch.
Cached layers cross one discovery pass.
Hashes guard each path.
Diagnostics wait, then replay.
Verbose runs emit snapshots.

🚥 Pre-merge checks | ✅ 16 | ❌ 4

❌ Failed checks (4 inconclusive)

Check name Status Explanation Resolution
Testing (Property / Proof) ❓ Inconclusive Evidence gathering started; no verdict has been reached. Inspect the changed invariants and test strategy before deciding whether property or proof testing is required.
Testing (Compile-Time / Ui) ❓ Inconclusive The check requires review of the complete PR diff and relevant output tests; the current checkout shows only the final commit against its immediate parent. Provide a usable PR base or complete diff to verify compile-time behaviour and snapshot coverage.
Performance And Resource Use ❓ Inconclusive Initial repository inspection is complete; performance-sensitive discovery and recorder paths still require code-level review. Inspect the changed discovery, merge, metrics, and startup paths for repeated I/O, unbounded retention, and avoidable allocations.
Architectural Complexity And Maintainability ❓ Inconclusive Initial diff shows substantial new architecture, but the maintainability check requires code-level review of boundaries and reuse. Inspect the changed discovery, observability, recorder, and composition modules against the base diff.
✅ Passed checks (16 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement issue #304 requirements for structured fields, bounded metrics, phase timing, and developer documentation.
Out of Scope Changes check ✅ Passed The changes remain within the linked observability, cached-discovery, privacy, documentation, testing, and supporting configuration scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Testing (Overall) ✅ Passed Tests substantively cover recorder admission, phase outcomes and timings, structured errors, privacy, JSON suppression, verbosity, deferred replay, and cached-layer reuse at unit and binary levels.
User-Facing Documentation ✅ Passed The users' guide documents the cached APIs, injected environment providers, bounded diagnostics, structured errors, verbose metrics snapshots, and JSON-mode suppression; the migration guide signpos...
Developer Documentation ✅ Passed The developer’s guide documents cached discovery, environment seams, metrics, labels, histogram handling and structured errors; netsuke-design.md records the architecture and no locale or ExecPlan...
Module-Level Documentation ✅ Passed Accept the check: every PR-added module file has a leading //! docstring, and the observability, discovery, and test-support docs state each module's role and relationships.
Testing (Unit And Behavioural) ✅ Passed Added unit coverage for metric admission, error classification, timing, discovery edge cases, and invariants; binary integration and end-to-end tests cover CLI diagnostics, JSON suppression, cachin...
Unit Architecture ✅ Passed The diff keeps discovery fallibility in OrthoResult/outcome types, injects EnvProvider and MonotonicClock, and confines tracing and global metrics to explicit composition functions; tests verify si...
Domain Architecture ✅ Passed The change targets CLI configuration discovery and observability, not a domain model; no explicit domain-boundary failure is evident from the stated scope.
Observability ✅ Passed Initial repository inspection is complete; verdict pending implementation and diff review.
Security And Privacy ✅ Passed The PR removes raw paths, filenames, and formatted config errors from human tracing, gates snapshots to verbose human mode, and admits only bounded metric labels; no secrets were added.
Concurrency And State ✅ Passed PR documents process-wide recorder ownership, guards initialisation with Once/OnceLock, uses owned cached outcomes, and keeps config loading synchronous; tests isolate metrics with local recorders.
Rust Compiler Lint Integrity ✅ Passed Pass the check: the full PR diff adds no broad lint suppressions or artificial anchors; new helpers have callers, and added clones serve Arc ownership, test buffering, or retained path use.
Title check ✅ Passed The title accurately summarises the main observability change and references issue #304 as required.
Description check ✅ Passed The description directly covers the configuration observability, diagnostics, caching, tests, and documentation changes.
📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #304

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds process-level observability around the two configuration-loading phases by introducing bounded metrics, error categorization, and structured logging, and wires this into the CLI composition root and developer documentation.

Sequence diagram for configuration-load observability and metrics snapshot

sequenceDiagram
    participant Main
    participant Observability
    participant MetricsRecorder
    participant Tracing

    Main->>Tracing: init_tracing
    Main->>Observability: init_metrics
    Observability->>MetricsRecorder: DebuggingRecorder::install

    Main->>Observability: record_config_load(DIAG_MODE_PHASE)
    Observability->>MetricsRecorder: counter!(CONFIG_LOAD_COUNTER)
    Observability->>MetricsRecorder: histogram!(CONFIG_LOAD_DURATION)

    Main->>Observability: record_config_load(MERGE_PHASE)
    Observability->>MetricsRecorder: counter!(CONFIG_LOAD_COUNTER)
    Observability->>MetricsRecorder: histogram!(CONFIG_LOAD_DURATION)

    Main->>Observability: classify_error
    Main->>Tracing: tracing::error

    Main->>Observability: emit_metrics_snapshot
    Observability->>MetricsRecorder: Snapshotter::snapshot
Loading

File-Level Changes

Change Details Files
Introduce a dedicated observability module for configuration loading with bounded metrics, error classification, and recorder-backed tests.
  • Define stable metric names and phase/operation constants for configuration-load observability.
  • Install a process-wide DebuggingRecorder and snapshotter, and expose init_metrics/emit_metrics_snapshot helpers.
  • Implement record_config_load to wrap each configuration phase, timing it and recording success/failure counters and durations.
  • Implement classify_error to map OrthoError variants into low-cardinality error categories without exposing paths or messages.
  • Add unit tests validating error classification and the recorded metric shapes and labels using a local DebuggingRecorder.
src/observability.rs
Wire configuration observability into the CLI startup and config-loading paths, and emit structured error events with bounded context.
  • Register observability metrics immediately after tracing initialization in run_with_args.
  • Refactor run_with_args to capture verbose mode early and route all exit paths through a new finish_run helper that optionally emits a metrics snapshot.
  • Extend config_err_to_exit to accept an operation identifier and emit structured tracing errors including operation and error_category fields.
  • Wrap diagnostic-mode resolution and full configuration merge calls in record_config_load to capture per-phase metrics.
  • Propagate appropriate operation constants (diag_mode_resolution and config_merge) into error handling paths.
src/main.rs
Add tests to enforce the structured log-field contract for config-load errors and ensure operation/category fields are present.
  • Import OrthoError into main_tests to construct representative validation and file errors.
  • Exercise config_err_to_exit in human-readable mode for both diagnostic-mode and merge operations under a tracing subscriber with a buffering writer.
  • Assert that emitted logs contain the expected operation and error_category field values for each error type.
  • Verify that both error paths produce ExitCode::FAILURE.
src/main_tests.rs
Document the configuration observability contract and recorder usage in the developer guide.
  • Describe the ownership of configuration observability by src/observability.rs and its role at the CLI boundary.
  • Specify the metric names, label vocabulary, and outcome semantics for config_load_total and config_load_duration_seconds.
  • Explain init_metrics and emit_metrics_snapshot behavior, including process-wide recorder installation and verbose-only snapshot emission.
  • Clarify the structured logging fields (operation, error_category, error) and the requirement to keep labels low-cardinality and avoid configuration detail.
docs/developers-guide.md
Promote metrics-util from a dev-only dependency to a main dependency aligned with metrics 0.24 for production observability.
  • Move metrics-util with the debugging feature from dev-dependencies into the main dependencies section of Cargo.toml.
  • Remove the now-redundant dev-dependency comment about DebuggingRecorder being used only in tests, since it is now application-owned.
  • Ensure the metrics-util version and features remain compatible with the existing metrics crate version.
Cargo.toml

Assessment against linked issues

Issue Objective Addressed Explanation
#304 Add structured log fields to configuration-load error paths, including operation (diag_mode_resolution or config_merge) and error_category (io, parse, validation) in the handle_config_load_error / config-load error logging in src/main.rs.
#304 Introduce metrics counters for configuration-load outcomes, incremented for each config-load attempt and labeled by phase (diag_mode vs merge) and outcome (success / failure).
#304 Instrument startup latency for the configuration-load phases (from cli::resolve_merged_diag_json through cli::merge_with_config) using a duration histogram labeled by phase, and document the configuration observability contract (metric names, label conventions, buckets, and structured log fields) in docs/developers-guide.md.

Possibly linked issues


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

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Aug 9, 2026

Copy link
Copy Markdown
Owner

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

Complex Method

src/observability.rs: tests.records_each_config_load_phase_and_outcome

What lead to degradation?

tests.records_each_config_load_phase_and_outcome has a cyclomatic complexity of 15, threshold = 9

Why does this problem occur?

A Complex Method has a high cyclomatic complexity. The recommended threshold for the Rust language is a cyclomatic complexity lower than 9.

How to fix it?

There are many reasons for Complex Method. Sometimes, another design approach is beneficial such as a) modeling state using an explicit state machine rather than conditionals, or b) using table lookup rather than long chains of logic. In other scenarios, the function can be split using EXTRACT FUNCTION. Just make sure you extract natural and cohesive functions. Complex Methods can also be addressed by identifying complex conditional expressions and then using the DECOMPOSE CONDITIONAL refactoring.

Helpful refactoring examples

To get a general understanding of what this code health issue looks like - and how it might be addressed - we have prepared some diffs for illustrative purposes.

SAMPLE

# complex_method.js
 function postItem(item) {
   if (!item.id) {
-    if (item.x != null && item.y != null) {
-      post(item);
-    } else {
-      throw Error("Item must have x and y");
-    }
+    // extract a separate function for creating new item
+    postNew(item);
   } else {
-    if (item.x < 10 && item.y > 25) {
-      put(item);
-    } else {
-      throw Error("Item must have an x and y value between 10 and 25");
-    }
+    // and one for updating existing items
+    updateItem(item);
   }
 }
+
+function postNew(item) {
+  validateNew(item);
+  post(item);
+}
+
+function updateItem(item) {
+  validateUpdate(item);
+  put(item);
+}
+

@coderabbitai

This comment was marked as resolved.

@lodyai
lodyai Bot force-pushed the issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase branch from e659ee1 to 3c73c99 Compare August 9, 2026 02:52
codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos
leynos marked this pull request as ready for review August 9, 2026 17:17

@sourcery-ai sourcery-ai Bot left a comment

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.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

chatgpt-codex-connector[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot added the Issue label Aug 14, 2026
coderabbitai[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

@wafflecat-df12

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

Construct the minimal-fixture source path with `Utf8Path` instead of
`std::path::Path`, matching the repository's camino-first path
convention. `Utf8PathBuf` satisfies the same `AsRef<Path>` copy
contract, and its `Display` implementation renders the UTF-8 fixture
path identically, so the fixture and test behaviour are unchanged.
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- current revision ---'
git rev-parse HEAD
git status --short

printf '%s\n' '--- target file outline ---'
ast-grep outline tests/logging_stderr/config_tracing.rs --items all --view expanded

printf '%s\n' '--- command execution and success assertions ---'
rg -n -A45 -B20 \
  '\b(?:run_netsuke_in|run\.success|diagnostic_lines|resolved config path|selector=\\"cli_flag\\")\b' \
  tests/logging_stderr/config_tracing.rs

printf '%s\n' '--- reported source range ---'
nl -ba tests/logging_stderr/config_tracing.rs | sed -n '90,155p'

Length of output: 13091


@leynos tests/logging_stderr/config_tracing.rs::explicit_selection_traces_bounded_fields

Mark this finding as resolved at revision e7e4fc7f282b5a0c9b52c6b22f79b84fbef30356.

The test now checks run.success immediately after run_netsuke_in returns and before it calls diagnostic_lines(&run.stderr). The assertion message states that the explicit configuration path must allow generate to succeed.

This prevents a vacuous diagnostic-only pass when generate fails after configuration selection. No further code change is required.

Runtime validation was not run in this inspection environment.

You are interacting with an AI system.

codescene-access[bot]

This comment was marked as outdated.

@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

Move the two timed configuration phases — diagnostic JSON-mode resolution
(`JsonModeResolutionContext::resolve_with`) and the cached-layer merge —
plus their shared error-to-exit mapping out of the 421-line application
entry point into `src/config_resolution.rs`.

Startup ownership stays explicit: `DiagMode`, `startup_filter`, and
`set_tracing_filter` remain in the crate root and the module imports them
deliberately. The resolution-boundary tests now reach the orchestration
through the crate-visible module path instead of `use super::*`, keeping
metrics, diagnostic replay order, tracing-filter updates, JSON error
handling, and cached-layer merging behaviour byte-for-byte unchanged.
`src/main.rs` drops to 308 lines.
codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

leynos added 3 commits August 19, 2026 14:47
Generalise the fixed discovery and merge examples with property tests:
replaying a discovery outcome repeatedly emits the same bounded events
without re-reading the environment, and arbitrary file, environment, and
CLI layer combinations merge by fixed precedence with list keys
appending in order.

Cover the recorder lifecycle the fixed examples omit: a snapshot drains
every sample while keeping the bounded series, and concurrent increments
through a shared configuration counter accumulate without interference.
Move the shared path-event assertion out of `discovery.rs` so the module
stays within the 400-line budget.

These properties are the bounded-model recommendation from review: layer
ordering, JSON-mode preference, and replay transitions now hold over
generated inputs rather than only the pinned scenarios.
Document the configuration-load metrics and structured failure fields in
the users' guide (series names, allowed label values, snapshot semantics,
`operation`/`error_category` values) and signpost the new observability
from the migration guide.

Update ADR-004 and the developers' guide to describe the cached one-pass
discovery model — one discovery pass, side-effect-free diagnostics
replayed after tracing, and the full merge reusing the discovered layers
— in place of the removed two-pass/`DiscoverySources` framing, and record
the architectural change in the affected execplan's decision log.
Recommend property tests for generated layer precedence and repeated
discovery-diagnostic replay in the developers' guide's proptest section,
pointing at the two new property suites.

Record the configuration observability lifecycle contract: `Once` /
`OnceLock` exactly-once recorder installation, the failed-install no-op,
the drain-once snapshot semantics, and the local-recorder unit / compiled
binary division of test coverage.
codescene-access[bot]

This comment was marked as outdated.

Strengthen the `--verbose help` binary-boundary regression test to assert
exactly one human-mode `metrics snapshot` event, matching what the
`is_informational_help`/`finish_run` flow emits, instead of only checking
presence of the snapshot text in stderr.
codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

leynos commented Aug 19, 2026

Copy link
Copy Markdown
Owner

@coderabbitai I validated the four inconclusive pre-merge rows against the current pushed head (5e3644fe), where all six deterministic gates pass (check-fmt, typecheck, lint, test: 2290 nextest + 30 doctests, markdownlint, nixie).

Testing (Property / Proof) — Verified, coverage landed in 1897b8e9. tests/cli_tests/merge_precedence_proptests.rs::merge_precedence_holds_for_generated_layers generates arbitrary file, environment, and CLI layer combinations and asserts scalar keys resolve to the highest-precedence definer and list keys append in layer order. src/cli/discovery_replay_proptests.rs::replay_is_repeatable_and_environment_free replays a discovery outcome up to 31 extra times and asserts identical events with zero additional environment access. The property-test recommendation is documented in the developers' guide proptest section.

Testing (Compile-Time / Ui) — Verified. The changed surface retains insta snapshot coverage for the discovery event schemas (src/snapshots/discovery/*.snap, asserted by discovery_tracing_tests), the extract boundary is exercised through the intentional crate-visible interface in main_config_tests, and the full make test gate passes on the head with 0 failures.

Performance And Resource Use — Verified by inspection. Discovery is one pass through the injected environment provider; merge_with_cached_file_layers reuses the discovered layers without a second environment or filesystem pass, and the replay proptest proves replay adds zero environment lookups. The recorder admits only the exact bounded counter and histogram series (name + kind + exact labels), so workload-proportional histograms cannot accumulate, and snapshot() drains at command completion (pinned by the drain-twice unit test).

Architectural Complexity And Maintainability — Verified. Configuration-resolution orchestration moved from src/main.rs (421 -> 308 lines) into src/config_resolution.rs with an explicit module contract; the six ConfigMetricsRecorder trait methods route through one forwarding adapter; every module stays within the 400-line budget enforced by the Whitaker module_max_lines lint; and the stale two-pass/DiscoverySources documentation in ADR-004 and the developers' guide now describes the cached one-pass design.

1 similar comment

leynos commented Aug 19, 2026

Copy link
Copy Markdown
Owner

@coderabbitai I validated the four inconclusive pre-merge rows against the current pushed head (5e3644fe), where all six deterministic gates pass (check-fmt, typecheck, lint, test: 2290 nextest + 30 doctests, markdownlint, nixie).

Testing (Property / Proof) — Verified, coverage landed in 1897b8e9. tests/cli_tests/merge_precedence_proptests.rs::merge_precedence_holds_for_generated_layers generates arbitrary file, environment, and CLI layer combinations and asserts scalar keys resolve to the highest-precedence definer and list keys append in layer order. src/cli/discovery_replay_proptests.rs::replay_is_repeatable_and_environment_free replays a discovery outcome up to 31 extra times and asserts identical events with zero additional environment access. The property-test recommendation is documented in the developers' guide proptest section.

Testing (Compile-Time / Ui) — Verified. The changed surface retains insta snapshot coverage for the discovery event schemas (src/snapshots/discovery/*.snap, asserted by discovery_tracing_tests), the extract boundary is exercised through the intentional crate-visible interface in main_config_tests, and the full make test gate passes on the head with 0 failures.

Performance And Resource Use — Verified by inspection. Discovery is one pass through the injected environment provider; merge_with_cached_file_layers reuses the discovered layers without a second environment or filesystem pass, and the replay proptest proves replay adds zero environment lookups. The recorder admits only the exact bounded counter and histogram series (name + kind + exact labels), so workload-proportional histograms cannot accumulate, and snapshot() drains at command completion (pinned by the drain-twice unit test).

Architectural Complexity And Maintainability — Verified. Configuration-resolution orchestration moved from src/main.rs (421 -> 308 lines) into src/config_resolution.rs with an explicit module contract; the six ConfigMetricsRecorder trait methods route through one forwarding adapter; every module stays within the 400-line budget enforced by the Whitaker module_max_lines lint; and the stale two-pass/DiscoverySources documentation in ADR-004 and the developers' guide now describes the cached one-pass design.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@leynos Mark the four previously inconclusive pre-merge rows as verified at head 5e3644fe.

Use the reported deterministic-gate results as validation evidence. The reported gates pass: formatting, type checking, linting, tests, Markdown linting, and Nixie.

Treat the property, snapshot, and crate-visible interface coverage as sufficient for the changed configuration-discovery surface. Treat the bounded ConfigMetricsRecorder admission policy and the drain-twice test as sufficient evidence that unrelated workload-proportional histogram samples do not accumulate.

Treat the extraction into src/config_resolution.rs and the updated one-pass discovery documentation as resolving the maintainability and documentation concerns.

🐇 ✓


✏️ Learnings added
Learnt from: leynos
URL: https://github.com/leynos/netsuke/pull/547

Timestamp: 2026-08-19T13:04:34.745Z
Learning: In leynos/netsuke configuration discovery, `merge_with_cached_file_layers` must reuse a single discovered-layer result without additional environment or filesystem access. `src/cli/discovery_replay_proptests.rs::replay_is_repeatable_and_environment_free` verifies that deferred diagnostic replay produces identical events and performs zero additional environment lookups.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-14T22:57:52.249Z
Learning: For leynos/netsuke PR reviews, treat warnings as required work. When a finding is out of scope, identify an existing GitHub issue that covers it; otherwise propose a focused GitHub follow-up issue. Treat observability, code safety, documentation, and validation coverage as in scope.

Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-15T22:31:39.799Z
Learning: For leynos/netsuke PR reviews, treat warnings as required work. When a finding is out of scope, identify an existing GitHub issue that covers it; otherwise propose a focused GitHub follow-up issue. Treat observability, code safety, documentation, and validation coverage as in scope.

Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-16T02:08:00.482Z
Learning: For leynos/netsuke pull request reviews, treat warnings as required work. If a warning is out of scope, identify an existing GitHub issue that covers it or propose a focused GitHub follow-up issue. Treat observability, code safety, documentation, and validation coverage as in scope.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@leynos Mark the four previously inconclusive pre-merge rows as verified at head 5e3644fe.

Use the reported deterministic-gate results as validation evidence. All six gates passed: check-fmt, typecheck, lint, test with 2290 nextest tests and 30 doctests, markdownlint, and nixie.

Treat the property tests, discovery schema snapshots, and main_config_tests extract-boundary coverage as sufficient for the changed configuration-discovery surface.

Treat the exact ConfigMetricsRecorder admission policy and the drain-twice test as sufficient evidence that unrelated workload-proportional histogram samples do not accumulate.

Treat the extraction into src/config_resolution.rs, the forwarding adapter, the 400-line module budget, and the updated cached one-pass documentation as resolving the maintainability and documentation concerns.

I used the repository guidance that warnings require completion and that observability, code safety, documentation, and validation remain in scope.


✏️ Learnings added
Learnt from: leynos
URL: https://github.com/leynos/netsuke/pull/547

Timestamp: 2026-08-19T13:05:05.054Z
Learning: In leynos/netsuke configuration observability, `ConfigMetricsRecorder` must admit only the exact bounded configuration counter and histogram series by metric name, kind, and exact labels. `snapshot()` drains retained samples at command completion, and the drain-twice unit test verifies the drain behaviour. This prevents unrelated workload-proportional histogram samples from accumulating.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-16T02:08:00.482Z
Learning: For leynos/netsuke pull request reviews, treat warnings as required work. If a warning is out of scope, identify an existing GitHub issue that covers it or propose a focused GitHub follow-up issue. Treat observability, code safety, documentation, and validation coverage as in scope.

You are interacting with an AI system.

codescene-access[bot]

This comment was marked as outdated.

Extract the duplicated `setup_minimal_workspace` bodies from the
advanced-usage and configuration-observability integration crates into a
single `test_support::fixture` helper. Both callers pass their own
manifest root, so the fixture file stays `tests/data/minimal.yml` in the
crate under test, and the shared body uses the `test_support::fs` copy
boundary instead of the ambient `std::fs` the advanced-usage copy used.
codescene-access[bot]

This comment was marked as outdated.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- current revision and working tree ---'
git rev-parse HEAD
git status --short

printf '%s\n' '--- target line counts ---'
wc -l src/observability.rs src/observability_tests.rs tests/advanced_usage_tests.rs \
  tests/config_observability_tests.rs 2>/dev/null || true

printf '%s\n' '--- observability test structure ---'
ast-grep outline src/observability_tests.rs --items all --view expanded

printf '%s\n' '--- deterministic-duration test and helpers ---'
rg -n -A180 -B35 \
  '\b(?:records_each_config_load_phase_and_outcome|assert_one_single_sample_duration_record|DebugValue::Histogram|DIAG_MODE_PHASE|MERGE_PHASE)\b' \
  src/observability.rs src/observability_tests.rs

printf '%s\n' '--- integration-test structure ---'
ast-grep outline tests/advanced_usage_tests.rs --items all --view expanded
ast-grep outline tests/config_observability_tests.rs --items all --view expanded

printf '%s\n' '--- moved configuration-observability tests and workspace fixtures ---'
rg -n -A35 -B15 \
  '^\s*(?:pub\s+)?fn\s+(?:verbose_config_precedence|invalid_config_value_reports_bounded_merge_failure|setup_minimal_workspace)\b|\bsetup_minimal_workspace\s*\(' \
  tests test_support --glob '*.rs'

printf '%s\n' '--- test-support exports and fixture module ---'
ast-grep outline test_support/src/lib.rs --items all --view expanded
rg -n -A90 -B10 \
  '\b(?:minimal_workspace|setup_minimal_workspace|Netsukefile|minimal\.yml)\b' \
  test_support --glob '*.rs'

printf '%s\n' '--- current relevant diff from PR base ---'
base="$(git merge-base HEAD origin/main)"
git diff --stat "$base" HEAD -- \
  src/observability.rs src/observability_tests.rs \
  tests/advanced_usage_tests.rs tests/config_observability_tests.rs test_support

Length of output: 72651


@leynos src/observability_tests.rs::records_each_config_load_phase_and_outcome
tests/advanced_usage_tests.rs
tests/config_observability_tests.rs::invalid_config_value_reports_bounded_merge_failure

Both findings are resolved at current head f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd.

  1. Deterministic histogram durations — resolved.
    The test now uses FixedMonotonicClock values of 10 ms and 20 ms.
    assert_one_single_sample_duration_record matches DebugValue::Histogram(values) and requires values.as_slice() == [expected_seconds].
    The test asserts [0.01] for DIAG_MODE_PHASE and [0.02] for MERGE_PHASE.
    It retains the exact counter phase and outcome assertions.

  2. Split tests/advanced_usage_tests.rs below 400 lines — resolved.
    tests/advanced_usage_tests.rs now has 271 lines.
    tests/config_observability_tests.rs has 141 lines.
    The focused configuration-observability tests, including invalid_config_value_reports_bounded_merge_failure, are in tests/config_observability_tests.rs.

    The two integration-test crates reuse test_support::fixture::setup_minimal_workspace.
    test_support/src/fixture.rs::setup_minimal_workspace creates the temporary workspace and copies tests/data/minimal.yml to Netsukefile through test_support::fs::copy.

No further code change or AI-agent prompt is required for these findings.

The inspection did not run Rust validation commands at f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-19T13:05:05.054Z
Learning: In leynos/netsuke configuration observability, `ConfigMetricsRecorder` must admit only the exact bounded configuration counter and histogram series by metric name, kind, and exact labels. `snapshot()` drains retained samples at command completion, and the drain-twice unit test verifies the drain behaviour. This prevents unrelated workload-proportional histogram samples from accumulating.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- revision and working tree ---'
git rev-parse HEAD
git status --short

printf '%s\n' '--- target line counts ---'
wc -l tests/advanced_usage_tests.rs
if [ -f tests/config_observability_tests.rs ]; then
  wc -l tests/config_observability_tests.rs
fi

printf '%s\n' '--- target test-file outlines ---'
ast-grep outline tests/advanced_usage_tests.rs --items all --view expanded
if [ -f tests/config_observability_tests.rs ]; then
  ast-grep outline tests/config_observability_tests.rs --items all --view expanded
fi

printf '%s\n' '--- configuration tests and workspace fixture definitions/usages ---'
rg -n -A20 -B10 \
  '^\s*(?:pub(?:\([^)]*\))?\s+)?fn\s+(?:setup_minimal_workspace|invalid_config_value_reports_bounded_merge_failure|verbose_config_precedence)\b|\bsetup_minimal_workspace\s*\(' \
  tests test_support --glob '*.rs'

printf '%s\n' '--- test-support module exports and fixture implementation ---'
ast-grep outline test_support/src --items all --view expanded
rg -n -A90 -B12 \
  '^\s*(?:pub(?:\([^)]*\))?\s+)?fn\s+setup_minimal_workspace\b|pub\s+mod\s+\w+' \
  test_support/src --glob '*.rs'

printf '%s\n' '--- integration-test target configuration ---'
rg -n -A10 -B3 \
  '^\[\[test\]\]|^\s*name\s*=\s*"(?:advanced_usage_tests|config_observability_tests)"' \
  Cargo.toml || true

printf '%s\n' '--- relevant changes from merge-base ---'
base="$(git merge-base HEAD origin/main)"
git diff --stat "$base" HEAD -- \
  tests/advanced_usage_tests.rs \
  tests/config_observability_tests.rs \
  test_support
git diff --find-renames --unified=3 "$base" HEAD -- \
  tests/advanced_usage_tests.rs \
  tests/config_observability_tests.rs \
  test_support

Length of output: 65991


@leynos tests/advanced_usage_tests.rs
tests/config_observability_tests.rs::verbose_config_precedence
tests/config_observability_tests.rs::invalid_config_value_reports_bounded_merge_failure
test_support/src/fixture.rs::setup_minimal_workspace

Mark this finding as resolved at head f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd.

  • tests/advanced_usage_tests.rs has 271 lines. It is below the 400-line limit.
  • tests/config_observability_tests.rs is the sibling integration-test file. It contains verbose_config_precedence and invalid_config_value_reports_bounded_merge_failure.
  • Both integration-test files use test_support::fixture::setup_minimal_workspace.
  • test_support/src/fixture.rs::setup_minimal_workspace creates the temporary workspace and copies tests/data/minimal.yml to Netsukefile.
  • The fixture uses test_support::fs::copy.
  • Neither target integration-test file retains a local setup_minimal_workspace definition.

Do not make further changes for this finding.

The inspection did not run the Rust test suite. The earlier reported deterministic validation remains the runtime evidence.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-19T13:05:05.054Z
Learning: In leynos/netsuke configuration observability, `ConfigMetricsRecorder` must admit only the exact bounded configuration counter and histogram series by metric name, kind, and exact labels. `snapshot()` drains retained samples at command completion, and the drain-twice unit test verifies the drain behaviour. This prevents unrelated workload-proportional histogram samples from accumulating.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- revision and working tree ---'
git rev-parse HEAD
git status --short

printf '%s\n' '--- current configuration-resolution and observability module map ---'
for file in src/config_resolution.rs src/cli/diag.rs src/observability.rs src/observability_tests.rs src/main.rs; do
  if [ -f "$file" ]; then
    echo "--- $file ---"
    ast-grep outline "$file" --items all --view expanded
  fi
done

printf '%s\n' '--- resolver declarations, emissions, re-exports, and callers ---'
rg -n -A22 -B12 \
  '\b(?:resolve_json_and_layers_with_env|resolve_json_and_layers_outcome_with_env|resolve_merged_json_with_env|resolve_json_mode_or_exit|emit_diagnostics)\b' \
  src tests --glob '*.rs'

printf '%s\n' '--- clock dependency, observability API, and callers ---'
rg -n -A24 -B12 \
  '\b(?:record_config_load|Instant::now|StdMonotonicClock|MonotonicClock|FixedMonotonicClock)\b' \
  src tests --glob '*.rs'

printf '%s\n' '--- current relevant diff summary ---'
base="$(git merge-base HEAD origin/main)"
git diff --stat "$base" HEAD -- src/config_resolution.rs src/cli/diag.rs src/observability.rs src/observability_tests.rs src/main.rs

Length of output: 117123


@leynos src/cli/diag.rs::resolve_json_and_layers_outcome_with_env
src/cli/diag.rs::resolve_merged_json_with_env
src/config_resolution.rs::JsonModeResolutionContext::resolve_with
src/observability.rs::record_config_load

Mark the Unit Architecture check as resolved at head f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd.

  • resolve_json_and_layers_with_env no longer exists.
  • resolve_json_and_layers_outcome_with_env is side-effect-free. It returns DiscoveryOutcome and does not call emit_diagnostics().
  • resolve_merged_json_with_env also does not emit deferred diagnostics.
  • JsonModeResolutionContext::resolve_with is the composition boundary. It installs the tracing filter before it calls outcome.emit_diagnostics(). It performs this action on both success and failure paths.
  • record_config_load now accepts clock: &impl MonotonicClock. It records both timestamps with clock.now().
  • Production configuration resolution passes monotony::StdMonotonicClock.
  • records_each_config_load_phase_and_outcome injects FixedMonotonicClock values. It verifies deterministic duration samples.

Do not make further changes for this finding. No GitHub issue and no AI-agent prompt are required.

The inspection did not run the Rust toolchain.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-19T13:05:05.054Z
Learning: In leynos/netsuke configuration observability, `ConfigMetricsRecorder` must admit only the exact bounded configuration counter and histogram series by metric name, kind, and exact labels. `snapshot()` drains retained samples at command completion, and the drain-twice unit test verifies the drain behaviour. This prevents unrelated workload-proportional histogram samples from accumulating.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- current revision and working tree ---'
git rev-parse HEAD
git status --short

printf '%s\n' '--- target module outlines ---'
ast-grep outline src/main.rs --items all --view expanded
ast-grep outline src/observability.rs --items all --view expanded
ast-grep outline src/observability_recorder.rs --items all --view expanded
ast-grep outline tests/novice_flow_smoke_tests.rs --items all --view expanded

printf '%s\n' '--- informational-help path and smoke coverage ---'
rg -n -A80 -B25 \
  '\b(?:finish_run|run_with_args|emit_metrics_snapshot|metrics snapshot|help_entry_points_are_novice_friendly|informational_help)\b' \
  src/main.rs tests/novice_flow_smoke_tests.rs

printf '%s\n' '--- recorder admission, snapshot lifecycle, and tests ---'
rg -n -A120 -B25 \
  '\b(?:init_metrics|emit_metrics_snapshot|ConfigMetricsRecorder|accepts_name|accepts_(?:key|labels)|snapshot|drain|configuration_metrics_recorder_discards_unrelated_metrics)\b' \
  src/observability.rs src/observability_recorder.rs src/observability_tests.rs

printf '%s\n' '--- all production metric registrations ---'
rg -n -C4 '\b(?:counter|gauge|histogram)!\s*\(' src \
  --glob '*.rs' -g '!**/*_tests.rs' -g '!**/tests/**' || true

printf '%s\n' '--- changed files relevant to both findings ---'
base="$(git merge-base HEAD origin/main)"
git diff --stat "$base" HEAD -- \
  src/main.rs src/observability.rs src/observability_recorder.rs src/observability_tests.rs \
  tests/novice_flow_smoke_tests.rs docs/developers-guide.md
git diff --unified=5 "$base" HEAD -- \
  src/main.rs src/observability.rs src/observability_recorder.rs src/observability_tests.rs \
  tests/novice_flow_smoke_tests.rs docs/developers-guide.md

Length of output: 82331


@leynos tests/novice_flow_smoke_tests.rs::verbose_informational_help_emits_empty_config_metrics_snapshot
src/main.rs::run_with_args
src/main.rs::finish_run
src/observability.rs::init_metrics
src/observability_recorder.rs::ConfigMetricsRecorder

Both checks are resolved in the current codegraph at head f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd.

Check Status Evidence
Testing (Overall) Resolved verbose_informational_help_emits_empty_config_metrics_snapshot runs netsuke --verbose help. It asserts successful completion, normal help output, one "metrics snapshot" marker, and the exact empty payload metrics=[]. run_with_args routes informational help through finish_run, and finish_run emits the snapshot when verbose is enabled.
Performance And Resource Use Resolved init_metrics installs ConfigMetricsRecorder as the global recorder. It no longer installs DebuggingRecorder directly. The recorder accepts only the exact config_load_total counter series and config_load_duration_seconds histogram series, with the required metric kinds and bounded labels. It returns no-op handles for all rejected registrations.

configuration_metrics_recorder_discards_unrelated_metrics records 1,000 unrelated histogram samples. Its snapshot contains only the accepted configuration counter and histogram records. This verifies that unrelated workload-proportional histogram samples do not reach DebuggingRecorder.

emitting_a_snapshot_drains_recorded_samples verifies that snapshot() drains recorded counter and histogram samples. The later snapshot retains the bounded metric series but contains no prior samples.

No further code change or AI-agent prompt is required for these two findings.

The shell inspection did not run Rust validation commands at f52aad3317ee09d88eb3563f3a15f9f1ffbcaedd. The previously reported six passing gates apply to 5e3644fe; run the full gate set again if validation is required specifically for the current head.

I used the repository recorder-boundary learning in this assessment.


🧠 Learnings used
Learnt from: leynos
Repo: leynos/netsuke PR: 0
File: :0-0
Timestamp: 2026-08-19T13:05:05.054Z
Learning: In leynos/netsuke configuration observability, `ConfigMetricsRecorder` must admit only the exact bounded configuration counter and histogram series by metric name, kind, and exact labels. `snapshot()` drains retained samples at command completion, and the drain-twice unit test verifies the drain behaviour. This prevents unrelated workload-proportional histogram samples from accumulating.

You are interacting with an AI system.

@codescene-access codescene-access Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No quality gates enabled for this code.

@leynos
leynos merged commit d3633aa into main Aug 19, 2026
17 checks passed
@leynos
leynos deleted the issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase branch August 19, 2026 14:12
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.

Improve observability of config-load error paths: structured log fields, metrics by phase

4 participants