Skip to content

Add metrics for config-load failures and startup latency (#303) - #379

Merged
leynos merged 35 commits into
mainfrom
issue-303-config-load-metrics
Aug 21, 2026
Merged

Add metrics for config-load failures and startup latency (#303)#379
leynos merged 35 commits into
mainfrom
issue-303-config-load-metrics

Conversation

@leynos

@leynos leynos commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #303

Adds the metrics instrumentation requested as a follow-up to PR #297: a config-load failure counter and a startup-latency histogram, plus developer documentation.

Changes

  • Cargo.toml: add the metrics façade (runtime) and metrics-util (dev, debugging feature).
  • src/main.rs: introduce resolve_configuration (spans cli::resolve_merged_diag_json through cli::merge_with_config) and record_config_load_metrics, emitting:
    • netsuke_config_load_total — counter labelled outcome (success/failure);
    • netsuke_config_load_duration_seconds — duration histogram.
      The merge error path is extracted into handle_config_load_error. Because metrics is a façade, the instruments are no-ops until an operator installs a recorder; Netsuke bundles none.
  • docs/developers-guide.md: new Configuration-load observability subsection documenting counter names, label conventions, and suggested histogram buckets.

Testing

  • Unit tests use metrics_util::debugging::DebuggingRecorder + metrics::with_local_recorder to assert the counter carries outcome=failure/outcome=success and that the histogram records exactly one sample.

Structured log fields (operation, error_category) and per-phase counter labels are the scope of the follow-up #304.

Validation

  • make check-fmt / make markdownlint / make lint / make test — pass (37 suites)

🤖 Generated with Claude Code

Summary by Sourcery

Instrument startup configuration loading with bounded outcome and latency metrics while preserving cached discovery, deterministic testing, and parseable diagnostics.

New Features:

  • Add operator-facing startup configuration-load metrics for success or failure outcomes and total startup latency.
  • Add a cached configuration-load benchmark and a Makefile target for measuring large nested configuration merges.

Bug Fixes:

  • Preserve discovered configuration layers for merging without rediscovering or copying complete layer values.
  • Keep configuration diagnostics deferred until the startup output mode is established, preserving valid JSON error output.

Enhancements:

  • Inject configuration environment and monotonic clock dependencies through startup orchestration for deterministic behavior and testing.
  • Restrict the application-owned metrics recorder to bounded phase-level and startup-level configuration series.
  • Expose bounded structured operation and error-category fields for human-readable configuration-load failures.

Documentation:

  • Document startup and phase-level configuration observability, metric contracts, label restrictions, recorder behavior, and verbose snapshots.
  • Add ADR-013 describing application-owned configuration observability and update design, user, and migration documentation.

Tests:

  • Add unit, property-based, integration, logging, documentation, and public-API coverage for configuration metrics, diagnostics, cached discovery, and verbose output.

Chores:

  • Reorganize configuration-load orchestration into a dedicated module and remove the previous configuration-resolution module.

References

@coderabbitai

coderabbitai Bot commented Jun 13, 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

Summary

  • Add netsuke_config_load_total and netsuke_config_load_duration_seconds metrics.
  • Instrument configuration resolution, merging, and startup failures with bounded labels and deterministic timing.
  • Refactor configuration loading to support injected environment providers, cached discovery outcomes, and ownership-preserving layer merging.
  • Add behavioural and property-based tests for successful loads, JSON-resolution failures, and merge failures.
  • Add the bench-config-load benchmark and Makefile target.
  • Document the observability design in ADR-013 and update the developer, user, design, and migration guides.
  • Add compile-time and end-to-end coverage for cached discovery, environment injection, diagnostics, metrics, and configuration precedence.

Walkthrough

Configuration loading now uses cached discovery outcomes, injected environment and clock providers, centralised startup orchestration, bounded diagnostics, and phase plus startup metrics. Tests, benchmarks, and documentation cover the new flow.

Changes

Configuration loading

Layer / File(s) Summary
Cached discovery and deferred diagnostics
src/cli/diag.rs, src/cli/discovery.rs, src/cli/test_support.rs, src/config_load_context_env_tests.rs, tests/ui/*, tests/config_discovery_e2e_tests.rs
Discovery retains cached layers and deferred diagnostics. Startup tests verify injected environment values and cached-layer reuse.
Startup configuration-load orchestration
src/config_load.rs, src/main.rs, src/main_tests.rs
ConfigurationLoadContext resolves, merges, times, records, and reports configuration-load results.
Metric contract and validation
src/config_load_metrics_tests.rs, tests/logging_stderr/*, tests/advanced_usage/*, tests/advanced_usage_tests.rs, tests/features/*
Tests validate bounded labels, counters, duration histograms, diagnostic output, precedence, and verbose snapshots.
Observability documentation and benchmark contracts
docs/*, benches/config_load_cached_merge.rs, Makefile, tests/makefile_test_target/rustflags.rs, tests/documentation_examples_tests.rs
Documentation records the observability design and cached merge API. The new benchmark and Makefile contract test cover cached configuration loading.

Sequence Diagram(s)

sequenceDiagram
  participant Application
  participant ConfigurationLoadContext
  participant DiscoveryOutcome
  participant ConfigurationMerge
  participant MetricsRecorder
  Application->>ConfigurationLoadContext: load configuration with injected environment and clock
  ConfigurationLoadContext->>DiscoveryOutcome: resolve JSON mode and retain layers
  ConfigurationLoadContext->>ConfigurationMerge: merge cached layers with CLI values
  ConfigurationLoadContext->>MetricsRecorder: record phase and startup results
  ConfigurationLoadContext-->>Application: return merged CLI or exit code
Loading

Possibly related PRs

  • leynos/netsuke#547: Shares configuration observability and cached discovery orchestration.
  • leynos/netsuke#548: Provides the cached configuration discovery reused by this startup flow.
  • leynos/netsuke#330: Introduces the injected configuration environment used by startup loading.

Suggested labels: Issue

Suggested reviewers: codescene-delta-analysis

Poem

Cached layers flow through the night,
Clocks mark each loading phase right.
Bounded fields keep secrets away,
Metrics record the startup day.
Discovery waits, then speaks its part.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors, 1 warning, 4 inconclusive)

Check name Status Explanation Resolution
Module-Level Documentation ❌ Error Require fuller module docs: the new helper modules at tests/advanced_usage/config_precedence.rs:1 and tests/logging_stderr/config_tracing_metrics.rs:1 only state a topic. Add //! documentation describing each module's purpose, utility, functions, and relationship to its parent test module.
Unit Architecture ❌ Error The changed resolve_merged_json_with_env now calls outcome.emit_diagnostics() before returning, so the public resolve_* query emits tracing side-effects. Remove emission from the resolver. Return deferred diagnostics for the caller, or add a clearly command-named wrapper that emits them and test the resolver for no events.
Observability ⚠️ Warning The new netsuke_config_load_* metrics are no-ops in production: ConfigMetricsRecorder admits only config_load_* names, while main installs that recorder before startup. Update ConfigMetricsRecorder to admit the startup metric names and exact bounded label sets, then assert both series in a process-recorder snapshot test.
Testing (Unit And Behavioural) ❓ Inconclusive Investigation continues; no verdict yet. Inspect the full PR test boundary and its end-to-end coverage before deciding.
Testing (Compile-Time / Ui) ❓ Inconclusive Investigation in progress; no verdict yet. Inspect the changed compile-time and UI test harnesses before deciding.
Security And Privacy ❓ Inconclusive Investigation is still in progress; no verdict submitted yet. Inspect the full PR diff and configuration diagnostics, metrics, environment handling, and path redaction before deciding.
Performance And Resource Use ❓ Inconclusive Investigation started; no final assessment yet. Inspect the pull-request diff and configuration-load ownership and I/O paths before deciding.
✅ Passed checks (13 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement issue #303 by adding outcome counters, startup-latency histograms, documentation, and deterministic validation.
Out of Scope Changes check ✅ Passed The additional refactoring, diagnostics, cached-layer handling, benchmarks, and tests support configuration-load observability and its stated implementation requirements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Testing (Overall) ✅ Passed Accept the testing coverage: run_with_args tests all three startup outcomes with exact labels and deterministic durations; integration tests verify snapshots, precedence, injected environment use,...
User-Facing Documentation ✅ Passed Pass this check: docs/users-guide.md documents cached configuration APIs, injected environments, diagnostics, metrics, verbosity, and JSON behaviour; the migration guide signposts the additions.
Developer Documentation ✅ Passed Keep the change: the developer's guide documents the new APIs, startup boundary, metrics, clock seam, benchmark, and environment injection; ADR-013 and the design document record the architecture.
Testing (Property / Proof) ✅ Passed Accept this check: the PR adds a substantive proptest over 0–1,000 ms and exercises all three startup outcomes through run_with_args, checking counters, labels, and histograms.
Domain Architecture ✅ Passed Keep this change: the new orchestration is a binary composition-root module, injects environment and clock ports, and leaves domain modules free of new adapter dependencies.
Concurrency And State ✅ Passed Mark PASS: the diff adds synchronous, per-invocation ownership; existing global metrics state remains Once/OnceLock guarded, with local-recorder isolation and concurrent-increment tests.
Architectural Complexity And Maintainability ✅ Passed Keep the change: the private context and injected clock/environment seams support required startup tests; ADR-013 documents the two metric layers, explicit ownership, and no new dependency or cycle...
Rust Compiler Lint Integrity ✅ Passed Placeholder
Title check ✅ Passed The title accurately summarises the metrics added for configuration-load failures and startup latency and references issue #303.
Description check ✅ Passed The description clearly explains the metrics, refactoring, documentation, testing, and related observability changes.
✨ 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-303-config-load-metrics

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

@sourcery-ai

sourcery-ai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds config-load observability by instrumenting startup configuration resolution with metrics, refactoring error handling, and documenting the new metrics, along with tests using a debugging recorder.

Sequence diagram for configuration-load metrics and error handling

sequenceDiagram
    participant main
    participant resolve_configuration
    participant cli as cli_merge
    participant metrics_facade
    participant handle_config_load_error

    main->>resolve_configuration: resolve_configuration(parsed_cli, matches)
    resolve_configuration->>cli: cli::resolve_merged_diag_json(parsed_cli, matches)
    resolve_configuration-->>resolve_configuration: DiagMode::from_json_enabled(...)
    resolve_configuration->>cli: cli::merge_with_config(parsed_cli, matches)
    resolve_configuration-->>metrics_facade: record_config_load_metrics(elapsed, merged.is_ok())
    metrics_facade-->>metrics_facade: metrics::histogram!(CONFIG_LOAD_DURATION_SECONDS)
    metrics_facade-->>metrics_facade: metrics::counter!(CONFIG_LOAD_TOTAL)
    resolve_configuration-->>main: (mode, merged)

    alt [merge succeeded]
        main-->>main: merged.with_default_command()
        main-->>main: configure_runtime(...)
    else [merge failed]
        main->>handle_config_load_error: handle_config_load_error(err, mode)
        handle_config_load_error-->>main: ExitCode::FAILURE
    end
Loading

File-Level Changes

Change Details Files
Instrument configuration-load phase with metrics and refactor startup configuration resolution and error handling.
  • Introduce resolve_configuration to compute diagnostic mode, perform config merge, and time the combined config-load phase.
  • Add CONFIG_LOAD_TOTAL counter and CONFIG_LOAD_DURATION_SECONDS histogram, and implement record_config_load_metrics to emit them via the metrics facade.
  • Extract handle_config_load_error to centralize config-load failure rendering and exit-code mapping, reusing prior JSON vs human-path behavior.
  • Update run_with_args to use resolve_configuration and handle_config_load_error, calling with_default_command only on successful merges.
  • Add unit tests validating counter labeling for success/failure and that exactly one histogram sample is recorded per invocation.
src/main.rs
Document configuration-load observability and metric conventions for operators and developers.
  • Add a Configuration-load observability subsection describing where instrumentation lives and how it behaves with the metrics facade.
  • Document the two emitted instruments, their semantics, and suggested histogram bucket boundaries.
  • Clarify metric naming and label cardinality conventions to guide future metrics additions.
docs/developers-guide.md
Wire in metrics dependencies for runtime use and test-time debugging.
  • Add the metrics crate as a runtime dependency for metrics facade macros.
  • Add metrics-util with debugging feature as a dev-dependency to support DebuggingRecorder-based tests.
  • Update Cargo.lock to capture the new dependency graph.
Cargo.toml
Cargo.lock

Assessment against linked issues

Issue Objective Addressed Explanation
#303 Instrument the config-load error handling paths (including handle_config_load_error / resolve_diag_mode_or_exit / merge_cli_or_exit equivalents) with a counter labelled by outcome (success/failure) to track configuration-load failure rates.
#303 Wrap the startup configuration-resolution phase, from cli::resolve_merged_diag_json through cli::merge_with_config, in a duration histogram to record startup latency.
#303 Add developer documentation to docs/developers-guide.md describing the configuration observability instrumentation, including counter names, label conventions, and histogram buckets.

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.

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

@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

@coderabbitai coderabbitai Bot added the Issue label Aug 9, 2026
chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

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

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 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.

coderabbitai[bot]

This comment was marked as resolved.

@leynos

leynos commented Aug 12, 2026

Copy link
Copy Markdown
Owner Author

Heads-up: issue #303 has been closed as subsumed by #304, which is now the single tracking issue for config-load observability. #547 is designated the vehicle since it adds src/observability.rs; the counter/histogram work here should be rebased onto that structure once #547 merges, to avoid the src/main.rs collision.

codescene-access[bot]

This comment was marked as outdated.

@leynos
leynos force-pushed the issue-303-config-load-metrics branch from 0f68423 to 20b8841 Compare August 14, 2026 00:47
@leynos
leynos changed the base branch from main to issue-304-improve-observability-of-config-load-error-paths-structured-log-fields-metrics-by-phase August 14, 2026 00:47
codescene-access[bot]

This comment was marked as outdated.

leynos and others added 18 commits August 21, 2026 18:55
Include diagnostic resolution in its phase duration while retaining cached
diagnostics for both success and failure. Keep configuration orchestration in
its focused module and require non-empty histogram samples in verbose tests.
Document the bounded tracing fields and make clear that configuration
file names and full paths are never exposed.
Reduce string-heavy helper arguments while preserving the configuration
metrics, precedence cases, and child-process behaviour under test.
Encapsulate captured diagnostics, failure fields, and metrics records in
test-domain types. Separate metrics snapshot assertions from tracing
scenarios so both test modules remain below the enforced size limit.
Keep JSON discovery side-effect free and carry deferred diagnostics to the
startup composition boundary. Reuse the first discovery pass for JSON
preference and merging without cloning complete file layers.

Inject configuration environment access, add cache and tracing proofs, and
benchmark the large cached path.
Align ADR-011 and the users guide with the current cached-layer resolution flow, and shorten the ADR-011 index label for readability.
Document the tuple returned by both resolver APIs and the diagnostic and layer extraction steps required before cached merging.
Restore the startup and diagnostic test bindings lost during the
conflict replay, and keep configuration discovery on its shared cached
layer helper. Remove superseded direct metric coverage and replay-only
documentation whitespace so the rebased branch builds and validates.
Remove the public resolve_json_and_layers_with_env alias, a pure
delegation to resolve_json_and_layers_outcome_with_env with an
identical (OrthoResult<bool>, DiscoveryOutcome) signature, and
standardize every caller, unit test, compile-pass fixture, benchmark,
and documentation reference on the outcome variant. The alias had no
production caller; keeping one resolver API removes a duplicate
interface without distinct behaviour.

Fix the review's documentation findings: shorten the ADR-013 index
label, correct the OrthoConfig 0.9.0 reference, join the split
users-guide sentence, and document the full metric contract (internal
phase-level config_load_* series plus operator-facing
netsuke_config_load_* startup-attempt series) in the migration guide.

Co-Authored-By: Claude <noreply@anthropic.com>
Update the configuration-loading documentation to describe the cached
discovery boundary, and keep integration-test fixture paths UTF-8 and
capability-oriented until the existing process helpers need OS paths.
Defer discovery diagnostics from JSON-resolution queries and retain the
bounded startup metrics in the process recorder. Expand the focused test
module documentation and cover the accepted startup metric series.
Keep the recorder scenario readable while preserving its exact retained
series and rejected-registration checks.
Move the mixed metric registration into a focused test helper while
retaining each series and snapshot assertion unchanged.
@leynos
leynos force-pushed the issue-303-config-load-metrics branch from 68c09b2 to 4da4363 Compare August 21, 2026 17:02
codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Aug 21, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

docs/users-guide.md (1)

845-853: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Correct the cached-resolution return contract.
State that resolve_json_and_layers_with_env returns a DiscoveryOutcome, not

DiscoveredLayers. Require callers to call outcome.into_layers() before they

pass the cached layers to merge_with_cached_file_layers.
Do not describe resolve_json_and_layers_outcome_with_env as a different

return shape. Both supplied functions return DiscoveryOutcome.

Proposed fix
- `netsuke::cli::resolve_json_and_layers_with_env` function returns the resolved
- JSON boolean together with `DiscoveredLayers`; pass those layers to
- `netsuke::cli::merge_with_cached_file_layers` for the full merge.
+ `netsuke::cli::resolve_json_and_layers_with_env` function returns the resolved
+ JSON boolean together with a `DiscoveryOutcome`. Call `into_layers()` on that
+ outcome, then pass the result to `netsuke::cli::merge_with_cached_file_layers`
+ for the full merge.
🤖 Detailed instructions

Use a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results.

In @docs/users-guide.md around lines 845 - 853, Update the cached-resolution
documentation to state that both resolve_json_and_layers_with_env and
resolve_json_and_layers_outcome_with_env return a DiscoveryOutcome. In caller
examples, consume the outcome with into_layers() before passing the resulting
layers to merge_with_cached_file_layers, while preserving the option to emit
diagnostics from the same outcome.

tests/advanced_usage_tests.rs (1)

403-463: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Reduce this integration-test crate to the 400-line limit.
Extract the configuration-precedence fixtures and metric assertions into a

focused sibling module. tests/advanced_usage_tests.rs reaches at least Line

  1. Create a focused follow-up issue if this split is outside this PR.
    Based on learnings, enforce the 400-line limit for crate-root integration test

files and record a focused follow-up when an unrelated split is out of scope.

As per coding guidelines, “Keep each Rust source file at 400 lines or fewer.”

As per path instructions, “Files must not exceed 400 lines in length.”

🤖 Detailed instructions

Use a wyvern agent team to verify each finding against the current code and only fix it if needed. Fix any documentation issues using a scribe agent team. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. Use a scrutineer agent for execution of tests and summarizing the results.

In @tests/advanced_usage_tests.rs around lines 403 - 463, Split the
configuration-precedence fixtures and metric assertions used by
ConfigPrecedenceCase and verbose_config_precedence into a focused sibling
integration-test module, leaving advanced_usage_tests.rs at 400 lines or fewer.
Preserve the existing test cases and assertions, and add a focused follow-up
issue only if completing the split is outside this change’s scope.

Sources: Coding guidelines, Path instructions, Learnings

@coderabbitai

coderabbitai Bot commented Aug 21, 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' '--- PR metadata and check runs ---'
gh pr view 379 --repo leynos/netsuke \
  --json number,state,headRefOid,updatedAt,baseRefName,url
sha="$(gh pr view 379 --repo leynos/netsuke --json headRefOid --jq .headRefOid)"
gh api "repos/leynos/netsuke/commits/${sha}/check-runs?per_page=100" --paginate \
  --jq '.check_runs[] | [.name, .status, (.conclusion // "null"), .details_url] | `@tsv`' || true

printf '%s\n' '--- Relevant files ---'
fd -a -t f -E target \
  'diag.rs|config_load.rs|merge.rs|discovery.*\.rs|config_load.*tests\.rs|config_load_cached_merge\.rs' \
  src tests benches 2>/dev/null | sort

printf '%s\n' '--- Symbol outlines ---'
for file in src/cli/diag.rs src/config_load.rs src/cli/merge.rs src/cli/discovery.rs; do
  if [ -f "$file" ]; then
    printf '\n### %s\n' "$file"
    ast-grep outline "$file" --items all || true
  fi
done

printf '%s\n' '--- Resolver, diagnostic, environment, ownership, cache, and benchmark evidence ---'
rg -n -C 6 -P \
  '\b(resolve_json_and_layers_with_env|resolve_json_and_layers_outcome_with_env|resolve_merged_json_with_env|emit_diagnostics|ConfigurationLoadContext|ConfigEnvProvider|ConfigStdEnvProvider|json_from_layers|into_value\(\)|clone\(\)\.into_value\(|merge_with_cached_file_layers|remove_file|cached.*layer|cache.*merge|bench-config-load)\b' \
  src tests benches Makefile docs Cargo.toml || true

printf '%s\n' '--- Focused implementations ---'
for file in src/cli/diag.rs src/config_load.rs src/cli/merge.rs src/cli/discovery.rs; do
  if [ -f "$file" ]; then
    printf '\n### %s\n' "$file"
    sed -n '1,340p' "$file"
  fi
done

printf '%s\n' '--- Current PR changes in relevant paths ---'
git diff --no-ext-diff origin/main...HEAD -- \
  src/cli/diag.rs src/config_load.rs src/cli/merge.rs src/cli/discovery.rs \
  src/config_load_context_env_tests.rs src/config_load_metrics_tests.rs \
  benches/config_load_cached_merge.rs Makefile \
  tests/ui/config_cached_discovery_embedder_pass.rs || true

Length of output: 157216


@leynos

Mark all three checks as resolved at current PR head 4da4363fa90e7dd45b6017f592df7e11ab82999c.

Check Status Evidence
Testing (Overall) Resolved src/cli/diag.rs::cached_layers_survive_selected_file_removal discovers a selected file with jobs = 7, removes that file, then merges outcome.into_layers() and asserts merged.jobs == Some(7). tests/cli_tests/merge_diag.rs also replaces the file after discovery and proves the original cached value remains effective. A merge-time rediscovery would fail these tests.
Unit Architecture Resolved src/cli/diag.rs::resolve_json_and_layers_outcome_with_env returns (OrthoResult<bool>, DiscoveryOutcome) without emitting diagnostics. src/cli/diag.rs::resolve_json_and_layers_defers_load_diagnostics proves the query emits no events and DiscoveryOutcome::emit_diagnostics() replays the deferred event only at the caller boundary. src/config_load.rs::ConfigurationLoadContext<'a, E> now carries config_env: &'a E into both early resolution and cached merge. src/config_load_context_env_tests.rs::configuration_context_uses_its_injected_environment_for_both_phases verifies both uses.
Performance And Resource Use Resolved src/cli/discovery_layers.rs::retain_layers_and_resolve_json derives the JSON preference while it owns each MergeLayer value, then rebuilds the retained file layer. src/cli/diag.rs::json_from_layers now reads the stored preference. The cached path does not use clone().into_value(). benches/config_load_cached_merge.rs exercises a large nested configuration through JSON resolution and cached merge. Run make bench-config-load to execute it.

No further work is required for these checks. Do not create a follow-up issue.

The current head also has successful build-test, kani-smoke, CodeScene Code Health Review (main), and CodeScene Code Coverage (main) checks.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 21, 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' '--- PR metadata and check runs ---'
gh pr view 379 --repo leynos/netsuke --json number,state,headRefOid,updatedAt,url
head_sha="$(gh pr view 379 --repo leynos/netsuke --json headRefOid --jq .headRefOid)"
gh api "repos/leynos/netsuke/commits/${head_sha}/check-runs?per_page=100" --paginate \
  --jq '.check_runs[] | [.name, .status, .conclusion, .details_url] | `@tsv`' || true

printf '%s\n' '--- Module documentation headers ---'
sed -n '1,110p' tests/advanced_usage/config_precedence.rs
sed -n '1,130p' tests/logging_stderr/config_tracing_metrics.rs

printf '%s\n' '--- Resolver API, diagnostics, and call sites ---'
ast-grep outline src/cli/diag.rs --items all || true
rg -n -C 6 -P \
  '\b(resolve_merged_json_with_env|resolve_json_and_layers_outcome_with_env|emit_diagnostics|defers_load_diagnostics)\b' \
  src/cli/diag.rs src/cli/mod.rs src tests benches || true
sed -n '1,260p' src/cli/diag.rs

printf '%s\n' '--- Recorder admission, production installation, and recorder tests ---'
ast-grep outline src/observability_recorder.rs --items all || true
ast-grep outline src/observability_recorder_tests.rs --items all || true
rg -n -C 8 -P \
  '\b(ConfigMetricsRecorder|accepts_registration|STARTUP_CONFIG_LOAD|CONFIG_LOAD_(COUNTER|DURATION)|netsuke_config_load|with_local_recorder|install)\b' \
  src/observability_recorder.rs src/observability_recorder_tests.rs src/observability.rs src/main.rs src/config_load.rs || true
sed -n '1,260p' src/observability_recorder.rs
sed -n '1,260p' src/observability_recorder_tests.rs

Length of output: 82106


@leynos All three checks are resolved at current PR head 4da4363fa90e7dd45b6017f592df7e11ab82999c.

Check Status Evidence
Module-Level Documentation Resolved tests/advanced_usage/config_precedence.rs documents its precedence and metrics-snapshot coverage, its helper role, and its relationship to advanced_usage_tests. tests/logging_stderr/config_tracing_metrics.rs documents its record expectations, assertion utilities, and relationship to config_tracing.
Unit Architecture Resolved src/cli/diag.rs::resolve_merged_json_with_env calls resolve_json_and_layers_outcome_with_env and returns the result without calling DiscoveryOutcome::emit_diagnostics(). resolve_json_and_layers_defers_load_diagnostics verifies that the query emits no events. The test then verifies that explicit replay emits the deferred diagnostic. src/config_load.rs emits diagnostics only after it sets the tracing filter.
Observability Resolved src/observability_recorder.rs::ConfigMetricsRecorder::accepts_registration admits netsuke_config_load_total only with `outcome=success

The current check runs also show success for build-test, CodeScene Code Health Review (main), and CodeScene Code Coverage (main).

Do not create a follow-up issue. No remaining work is required for these three findings.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 21, 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' '--- PR head ---'
gh pr view 379 --repo leynos/netsuke --json headRefOid,updatedAt,state,url

printf '%s\n' '--- Resolver API definitions and re-exports ---'
ast-grep outline src/cli/diag.rs --items all || true
sed -n '1,180p' src/cli/diag.rs
sed -n '1,120p' src/cli/mod.rs
rg -n -C 3 -P '\bresolve_json_and_layers(?:_outcome)?_with_env\b|\bDiscoveryOutcome\b|\binto_layers\s*\(' \
  src tests benches docs || true

printf '%s\n' '--- User-guide cached-resolution section ---'
nl -ba docs/users-guide.md | sed -n '825,875p'
rg -n -C 6 -P \
  '\bresolve_json_and_layers(?:_outcome)?_with_env\b|\bDiscoveryOutcome\b|\bDiscoveredLayers\b|\binto_layers\s*\(|\bmerge_with_cached_file_layers\b' \
  docs/users-guide.md || true

printf '%s\n' '--- Advanced-usage test module layout and line counts ---'
wc -l tests/advanced_usage_tests.rs
fd -a -t f . tests/advanced_usage | sort | xargs -r -n1 sh -c 'printf "%5s %s\n" "$(wc -l < "$0")" "$0"'
ast-grep outline tests/advanced_usage_tests.rs --items all || true
sed -n '1,80p' tests/advanced_usage_tests.rs
sed -n '360,490p' tests/advanced_usage_tests.rs

printf '%s\n' '--- References to configuration precedence helpers ---'
rg -n -C 4 -P \
  '\b(ConfigPrecedenceCase|verbose_config_precedence|assert_config_metrics_snapshot|contains_metric_record|contains_non_empty_histogram_record)\b' \
  tests/advanced_usage_tests.rs tests/advanced_usage 2>/dev/null || true

Length of output: 38118


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Current user-guide cached-resolution section ---'
awk 'NR >= 975 && NR <= 1020 { printf "%5d  %s\n", NR, $0 }' docs/users-guide.md
printf '%s\n' '--- Current user-guide resolver references ---'
rg -n -C 5 -P \
  '\bresolve_json_and_layers(?:_outcome)?_with_env\b|\bDiscoveryOutcome\b|\bDiscoveredLayers\b|\binto_layers\s*\(|\bmerge_with_cached_file_layers\b' \
  docs/users-guide.md || true

printf '%s\n' '--- Advanced-usage test file size ---'
awk 'END { printf "tests/advanced_usage_tests.rs: %d lines\n", NR }' tests/advanced_usage_tests.rs
printf '%s\n' '--- Advanced-usage sibling modules and sizes ---'
fd -a -t f . tests/advanced_usage -x sh -c \
  'awk -v file="$1" "END { printf \"%5d  %s\\n\", NR, file }" "$1"' sh {} | sort -k2

printf '%s\n' '--- Advanced-usage crate module declarations ---'
sed -n '1,100p' tests/advanced_usage_tests.rs
printf '%s\n' '--- Former configuration-precedence region ---'
sed -n '350,490p' tests/advanced_usage_tests.rs

printf '%s\n' '--- Configuration-precedence ownership ---'
rg -n -C 4 -P \
  '\b(ConfigPrecedenceCase|verbose_config_precedence|assert_config_metrics_snapshot|contains_metric_record|contains_non_empty_histogram_record)\b' \
  tests/advanced_usage_tests.rs tests/advanced_usage 2>/dev/null || true

printf '%s\n' '--- Current relevant checks ---'
sha="$(gh pr view 379 --repo leynos/netsuke --json headRefOid --jq .headRefOid)"
gh api "repos/leynos/netsuke/commits/${sha}/check-runs?per_page=100" --paginate \
  --jq '.check_runs[] | select(.name | test("build-test|CodeScene Code Health"; "i")) | [.name, .status, (.conclusion // "null")] | `@tsv`' || true

Length of output: 17448


@leynos Mark both findings resolved at current head 4da4363fa90e7dd45b6017f592df7e11ab82999c.

Finding Status Evidence
docs/users-guide.md cached-resolution contract Resolved Lines 996-1001 document resolve_json_and_layers_outcome_with_env returning (OrthoResult<bool>, DiscoveryOutcome). The text requires callers to call emit_diagnostics() when needed, then into_layers(), before calling merge_with_cached_file_layers.
tests/advanced_usage_tests.rs 400-line limit Resolved tests/advanced_usage_tests.rs is now 378 lines. tests/advanced_usage/config_precedence.rs contains the extracted ConfigPrecedenceCase, verbose_config_precedence, and metrics assertion helpers.

Do not update docs/users-guide.md to describe resolve_json_and_layers_with_env. The public alias no longer exists. src/cli/mod.rs exports only resolve_json_and_layers_outcome_with_env.

build-test and CodeScene Code Health Review (main) both pass for this head.

You are interacting with an AI system.

codescene-access[bot]

This comment was marked as outdated.

@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 e19c490 into main Aug 21, 2026
17 checks passed
@leynos
leynos deleted the issue-303-config-load-metrics branch August 21, 2026 19:08
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.

Add metrics instrumentation for config-load failure rates and startup latency

4 participants