feat(logging): add configurable operational logging#413
Conversation
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
…ent-relay-logging Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
WalkthroughAdds configurable operational logging with human and JSONL output, asynchronous file sinks, runtime lifecycle management, CLI and TOML/environment configuration, validation tests, and refreshed Rust dependency attribution records. ChangesOperational logging
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant LoggingArgs
participant LoggingRuntime
participant build_logger
participant AsyncFileSink
CLI->>LoggingArgs: resolve CLI, environment, or TOML settings
LoggingArgs->>LoggingRuntime: configure LoggingConfig
LoggingRuntime->>build_logger: build logger and sinks
build_logger->>AsyncFileSink: create bounded asynchronous file sink
LoggingRuntime-->>CLI: retain LoggingRuntime during dispatch
CLI->>LoggingRuntime: drop or shutdown
LoggingRuntime->>AsyncFileSink: flush queued records
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
License DiffCompared against Lockfile license changesLockfile License ChangesRustAdded
Removed
Updated/Changed
NodeAdded
Removed
Updated/Changed
PythonAdded
Removed
Updated/Changed
Status output |
24e823d to
7b0bc50
Compare
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
7b0bc50 to
71cd417
Compare
…ay-logging Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
…ay-logging Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
willkill07
left a comment
There was a problem hiding this comment.
Logging should be part of core, not just the CLI.
I also don't understand why/how nemo_relay.h has been changed.
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
|
I addressed the open configuration and initialization items from the latest review:
Logging remains under |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/cli/src/commands/mod.rs`:
- Around line 59-65: Update the initialize_logging decision in the CLI command
dispatch to disable logging for every dry-run mode, including run, install, and
uninstall, rather than relying only on Command::skips_logging. Ensure these
commands bypass logging setup even with an invalid logging configuration, and
add a CLI test covering that behavior.
In `@crates/cli/src/commands/root.rs`:
- Around line 128-134: The dry-run run command must bypass logging
initialization, and its assertion must be tested through CLI dispatch. Update
Command::skips_logging() to match RunCommand only when dry-run is enabled; in
crates/cli/tests/coverage/agents/launcher_tests.rs:1594-1600, move the assertion
to a CLI dispatch test because the launcher path bypasses this logging gate.
In `@crates/cli/tests/coverage/shared/config_tests.rs`:
- Around line 2919-2928: Extend the test around resolved.logging.sinks and its
LogSinkConfig::File entry to exercise the configured sink through the runtime,
not just parsed values. Initialize the logger using the resolved configuration,
emit a trace record, then read the configured log_a file and assert the trace
record is present, ensuring sink-level Trace overrides the global Debug filter.
In `@crates/core/src/logging/config.rs`:
- Around line 240-247: Make both RawLoggingConfig and RawFileLogSinkConfig
reject unknown fields by applying serde’s deny-unknown-fields behavior to each
struct. Add tests covering misspelled or unsupported fields such as
queue_capcity and sink, asserting deserialization fails instead of silently
using defaults or omitting sinks.
In `@crates/core/src/logging/mod.rs`:
- Around line 110-117: Serialize logger installation and removal across teardown
and configure flows so swap_logger(None) cannot overwrite a newer logger
installed concurrently. Update the relevant teardown logic around swap_logger
and the configure path to use a process-wide synchronization mechanism or
generation validation, preserving the newest installation. Add a concurrent
regression test covering reconfiguration racing with teardown.
- Around line 56-60: Update the initialization flow around
spdlog::init_log_crate_proxy and set_logger so an initialization failure is
propagated when the process has a foreign global logger, rather than silently
ignored. Treat SetLoggerError as benign only for genuine re-entry where the
Relay proxy is already installed, and preserve receiver/filter setup for
successful initialization.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 7ead193d-202f-42f5-ba42-73727a0736fb
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (19)
ATTRIBUTIONS-Rust.mdcrates/cli/src/commands/logging.rscrates/cli/src/commands/mod.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/root.rscrates/cli/src/configuration/logging.rscrates/cli/src/configuration/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/Cargo.tomlcrates/core/src/lib.rscrates/core/src/logging/config.rscrates/core/src/logging/format.rscrates/core/src/logging/mod.rscrates/core/src/logging/sink.rscrates/core/tests/coverage/logging_sink_tests.rscrates/core/tests/coverage/logging_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (22)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.rs: If any Rust code changed, always runjust test-rust.
If any Rust code changed, also runcargo fmt --all.
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/src/lib.rscrates/core/Cargo.tomlcrates/core/tests/coverage/logging_sink_tests.rscrates/core/src/logging/sink.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/core/tests/coverage/logging_tests.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/core/src/logging/sink.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/core/src/lib.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/cli/src/configuration/mod.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/core/src/lib.rscrates/core/Cargo.tomlcrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rsATTRIBUTIONS-Rust.mdcrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/src/lib.rscrates/core/Cargo.tomlcrates/core/tests/coverage/logging_sink_tests.rscrates/core/src/logging/sink.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/cli/src/commands/plugins/subcommands.rscrates/cli/src/commands/mod.rscrates/cli/src/configuration/types.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/src/commands/logging.rscrates/cli/src/commands/root.rscrates/core/src/logging/sink.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/cli/src/configuration/logging.rscrates/core/tests/coverage/logging_tests.rscrates/cli/src/configuration/mod.rs
crates/{core,adaptive}/**/*.rs
⚙️ CodeRabbit configuration file
crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.
Files:
crates/core/src/lib.rscrates/core/tests/coverage/logging_sink_tests.rscrates/core/src/logging/sink.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/src/logging/format.rscrates/core/tests/coverage/logging_tests.rs
**/Cargo.toml
📄 CodeRabbit inference engine (.agents/skills/prepare-code-freeze/SKILL.md)
Confirm or infer the target release version from
upstream/main:Cargo.toml. Derive the release branch asrelease/<major>.<minor>.Keep Rust package names and workspace metadata in
Cargo.tomlinternally consistent across the project.
Files:
crates/core/Cargo.toml
**/*.toml
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all TOML files using the
#comment form.
Files:
crates/core/Cargo.toml
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/core/tests/coverage/logging_sink_tests.rscrates/cli/tests/coverage/agents/launcher_tests.rscrates/cli/tests/coverage/commands/main_tests.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/tests/coverage/logging_tests.rs
**/*.{md,rst,html,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
**/*.{md,rst,html,txt}: Always spellNVIDIAin all caps. Do not useNvidia,nvidia,nVidia,nVIDIA, orNV.
Usean NVIDIAbefore a noun because the name starts with an 'en' sound.
Do not add a registered trademark symbol afterNVIDIAwhen referring to the company.
Use trademark symbols with product names only when the document type or legal guidance requires them.
Verify official capitalization, spacing, and hyphenation for product names.
Precede NVIDIA product names withNVIDIAon first mention when it is natural and accurate.
Do not rewrite product names for grammar or title-case rules.
Preserve third-party product names according to the owner's spelling.
Include the company name and full model qualifier on first use when it helps identify the model.
Preserve the official capitalization and punctuation of model names.
Use shorter family names only after the full name is established.
Spell out a term on first use and put the acronym in parentheses unless the acronym is widely understood by the intended audience.
Use the acronym on later mentions after it has been defined.
For long documents, reintroduce the full term if readers might lose context.
Form plurals of acronyms withs, not an apostrophe, such asGPUs.
In headings, common acronyms can remain abbreviated. Spell out the term in the first or second sentence of the body.
Common terms such asCPU,GPU,PC,API, andUIusually do not need to be spelled out for developer audiences.
Files:
ATTRIBUTIONS-Rust.md
**/*.{md,rst,html}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-brand-terminology.md)
Link the first mention of a product name when the destination helps the reader.
Files:
ATTRIBUTIONS-Rust.md
**/*.{md,rst,txt}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
Spell
NVIDIAin all caps. Do not useNvidia,nvidia, orNV.
Files:
ATTRIBUTIONS-Rust.md
**/*.{md,rst}
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-guide.md)
**/*.{md,rst}: Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text. Avoid raw URLs and weak anchors such as "here" or "read more."
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative steps. Keep steps parallel and split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English.
Usecanfor possibility and reservemayfor permission.
Useafterfor temporal relationships instead ofonce.
Preferrefer tooverseewhen the wording points readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical docs.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values.
Use numerals for 10 or greater and include commas in thousands.
Do not add trademark symbols to learning-oriented docs unless the source, platform, or legal guidance explicitly requires them.
Files:
ATTRIBUTIONS-Rust.md
**/*.md
📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-technical-docs.md)
**/*.md: Use title case consistently in technical documentation headings
Avoid quotation marks, ampersands, and exclamation marks in headings
Keep product, event, research, and whitepaper names in their official title case
Use title case for table headers
Do not force social-media sentence case into technical docs
Format code elements, commands, parameters, package names, and expressions in monospace
Format directories, file names, and paths in monospace using backticks
Use angle brackets inside monospace for variables inside paths, such as/home/<username>/.login
Format error messages and strings in quotation marks, keeping literal code strings in code formatting when clearer
Format UI buttons, menus, fields, and labels in bold
Use angle brackets between UI labels for menu paths, such as File > Save As
Use italics for new terms on first use, sparingly and only when introducing the term
Use italics for publication titles
Format keyboard shortcuts in plain text, such as Press Ctrl+Alt+Delete
Use owner/repo link text for GitHub repositories, preferring[NVIDIA/NeMo](link)over prose references like 'the GitHub repo'
Introduce every code block with a complete sentence
Do not make a code block complete the grammar of the previous sentence
Do not continue a sentence after a code block
Use syntax highlighting when the format supports it for code blocks
Avoid the word 'snippet' unless the surrounding docs already use it as a term of art
Keep inline method, function, and class references consistent with nearby docs, omitting empty parentheses for prose readability when no call is shown
Use descriptive anchor text that matches the destination title when possible for links
Avoid raw URLs in running text
Avoid generic anchor text such as 'here,' 'this page,' and 'read more'
Include acronyms in link text when a linked term includes an acronym
Do not link long sentences or multiple sentences
Avoid links that pull readers away from a procedure unless the link is a p...
Files:
ATTRIBUTIONS-Rust.md
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Update
README.md,fern/, package READMEs, and binding-support notes when public behavior, package names, examples, or supported bindings change.
**/*.{md,mdx}: Prefer the documented public API, not internal shortcuts
Keep package names, repo references, and build commands current
Keep release-process and release-notes guidance in repo-maintainer docs such asRELEASING.md, not as user-facing docs pages orCHANGELOG.md
Keep stable user-facing wrappers atscripts/root in docs and examples; only point at namespaced helper paths when documenting internal maintenance work
When detailed dynamic plugin guides exist, keep Rust native plugin examples, Python worker plugin examples, andgrpc-v1protocol details on separate pagesIf links in documentation change, run
just docs-linkcheck.
Files:
ATTRIBUTIONS-Rust.md
**/*.{md,markdown,mdx}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Markdown/MDX documentation files using the HTML comment block form.
Files:
ATTRIBUTIONS-Rust.md
🪛 markdownlint-cli2 (0.23.0)
ATTRIBUTIONS-Rust.md
[warning] 2303-2303: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 2306-2306: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 2306-2306: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 2307-2307: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 2307-2307: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 4902-4902: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 4905-4905: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 4905-4905: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 4906-4906: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 4906-4906: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 4971-4971: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 4974-4974: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 4974-4974: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 4975-4975: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 4975-4975: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 8979-8979: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 8982-8982: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 8982-8982: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 8983-8983: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 8983-8983: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 9188-9188: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9191-9191: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 9191-9191: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9192-9192: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 9192-9192: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 9397-9397: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9400-9400: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 9400-9400: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9401-9401: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 9401-9401: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 9606-9606: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9609-9609: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 9609-9609: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9610-9610: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 9610-9610: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 9815-9815: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9818-9818: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 9818-9818: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 9819-9819: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 9819-9819: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 12530-12530: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 12533-12533: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 12533-12533: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 12534-12534: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 12534-12534: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 12949-12949: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 12952-12952: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 12952-12952: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 12953-12953: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 12953-12953: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 12954-12954: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 12954-12954: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 13133-13133: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 13134-13134: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 13134-13134: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 25583-25583: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 25586-25586: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 25586-25586: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 25587-25587: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 25587-25587: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 35780-35780: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 35783-35783: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 35783-35783: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 35784-35784: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 35784-35784: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 37957-37957: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 37960-37960: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 37960-37960: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 37961-37961: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 37961-37961: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 37962-37962: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 37962-37962: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 38166-38166: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 38167-38167: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 38167-38167: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 38434-38434: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 38437-38437: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 38437-38437: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 38438-38438: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 38438-38438: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 38439-38439: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 38439-38439: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 38643-38643: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 38644-38644: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 38644-38644: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 40618-40618: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40621-40621: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 40621-40621: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40622-40622: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 40622-40622: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 40699-40699: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40702-40702: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 40702-40702: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40703-40703: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 40703-40703: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 40780-40780: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40783-40783: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 40783-40783: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 40784-40784: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 40784-40784: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 41324-41324: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41327-41327: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41327-41327: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41328-41328: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41328-41328: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41329-41329: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 41329-41329: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 41533-41533: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41534-41534: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 41534-41534: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 41558-41558: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41561-41561: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41561-41561: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41562-41562: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41562-41562: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41563-41563: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 41563-41563: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 41767-41767: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41768-41768: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 41768-41768: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 41792-41792: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41795-41795: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41795-41795: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41796-41796: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 41796-41796: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 41797-41797: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 41797-41797: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42001-42001: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42002-42002: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42002-42002: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42026-42026: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42029-42029: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42029-42029: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42030-42030: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42030-42030: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42031-42031: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42031-42031: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42235-42235: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42236-42236: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42236-42236: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42260-42260: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42263-42263: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42263-42263: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42264-42264: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42264-42264: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42265-42265: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42265-42265: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42469-42469: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42470-42470: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42470-42470: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42494-42494: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42497-42497: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42497-42497: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42498-42498: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42498-42498: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42499-42499: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42499-42499: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42503-42503: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42504-42504: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42504-42504: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42508-42508: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42511-42511: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42511-42511: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42512-42512: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42512-42512: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42513-42513: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42513-42513: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42717-42717: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42718-42718: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42718-42718: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42742-42742: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42745-42745: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42745-42745: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42746-42746: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 42746-42746: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42747-42747: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42747-42747: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 42951-42951: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 42952-42952: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 42952-42952: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 47525-47525: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 47528-47528: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 47528-47528: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 47529-47529: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 47529-47529: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 47530-47530: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 47530-47530: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 47709-47709: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 47710-47710: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 47710-47710: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 50014-50014: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50017-50017: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 50017-50017: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50018-50018: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 50018-50018: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 50223-50223: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50226-50226: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 50226-50226: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50227-50227: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 50227-50227: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50228-50228: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 50228-50228: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 50432-50432: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50433-50433: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 50433-50433: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 50457-50457: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50460-50460: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 50460-50460: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50461-50461: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Above
(MD022, blanks-around-headings)
[warning] 50461-50461: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50462-50462: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 50462-50462: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 50666-50666: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 50667-50667: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
[warning] 50667-50667: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (22)
ATTRIBUTIONS-Rust.md (1)
2303-2511: 📐 Maintainability & Code Quality
ATTRIBUTIONS-Rust.mdis already excluded from markdownlint. The repo’s pre-commit config exemptsATTRIBUTIONS-*.md, and the Rust attribution hook only regenerates the file fromCargo.lock; the MD022/MD031/MD040 note is not actionable.> Likely an incorrect or invalid review comment.crates/core/Cargo.toml (1)
103-104: LGTM!crates/cli/src/configuration/logging.rs (2)
70-76: 🗄️ Data Integrity & IntegrationPreserve normalized duplicate-path validation on this adapter path.
This code only rejects an empty path and stores the
PathBufunchanged. Confirm that everyLogSinkConfig::Filecreated here passes through the core validator before use; otherwise equivalent paths such aslogs/app.jsonlandlogs/../logs/app.jsonlcan bypass the promised duplicate-path rejection.Also applies to: 101-106
1-64: LGTM!Also applies to: 66-69, 78-100, 107-114
crates/cli/src/configuration/mod.rs (1)
4-4: LGTM!Also applies to: 18-18, 56-56, 98-132, 1160-1160
crates/cli/src/configuration/types.rs (1)
10-10: LGTM!Also applies to: 61-61
crates/cli/tests/coverage/commands/main_tests.rs (1)
115-140: LGTM!Also applies to: 142-176, 178-193, 195-208
crates/core/tests/coverage/logging_sink_tests.rs (1)
1-15: LGTM!crates/core/src/lib.rs (2)
37-37: LGTM!
63-63: 📐 Maintainability & Code QualityRun the required core-runtime validation before handoff.
Run
cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings,just test-rust,cargo deny check,validate-change, the full Rust/Python/Go/Node.js matrix, anduv run pre-commit run --all-files.As per coding guidelines, core runtime and public Rust API changes require these validation passes.
Source: Coding guidelines
crates/core/src/logging/mod.rs (2)
1-55: LGTM!Also applies to: 62-109, 118-134
61-61: 🎯 Functional CorrectnessPer-sink levels are intentionally constrained by the process maximum.
LoggingConfig::levelsets the global minimum for both thelogfacade and thespdlog::Logger; file sinks only apply an additional, stricter filter, so aTracesink underDebugis not a supported case.> Likely an incorrect or invalid review comment.crates/core/src/logging/format.rs (1)
1-180: LGTM!crates/core/src/logging/sink.rs (1)
1-118: LGTM!Also applies to: 123-306
crates/cli/src/commands/mod.rs (1)
11-11: LGTM!Also applies to: 66-83
crates/cli/tests/coverage/shared/config_tests.rs (1)
12-15: LGTM!Also applies to: 174-178, 2864-2918, 2929-3133
crates/core/src/logging/config.rs (2)
31-45: 📐 Maintainability & Code QualityConfirm the required core-runtime validation completed.
Verify formatting, strict Clippy, Rust tests,
cargo deny check,validate-change, the full language matrix, and the final pre-commit pass.As per coding guidelines, changes to
crates/coremust run the full language matrix andvalidate-change, while Rust-facing API changes must pass formatting, Clippy, tests, andcargo deny check.Source: Coding guidelines
1-30: LGTM!Also applies to: 46-239, 249-270, 280-339
crates/cli/src/commands/logging.rs (1)
1-75: LGTM!crates/cli/src/commands/plugins/subcommands.rs (1)
14-18: LGTM!crates/cli/src/commands/root.rs (1)
11-11: LGTM!Also applies to: 44-45
crates/core/tests/coverage/logging_tests.rs (1)
1-891: LGTM!
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/cli/tests/coverage/shared/config_tests.rs`:
- Around line 719-750: Update logging_resolution_respects_environment_user_scope
to isolate inherited NEMO_RELAY_LOG* environment variables: capture every
matching variable, clear them before entering PluginConfigDiscoveryScope, and
restore their original values when the test guard is dropped. Keep the
fixture-based logging resolution assertions focused on config files and add
coverage for the changed scope-guard behavior if required by the API contract.
- Around line 760-762: Strengthen the test after enable_user_scope and
resolve_logging_config by asserting that user_only contains the configured user
logging level, not just the absence of a project sink. Use the existing expected
user-level value or configuration symbol so the test verifies user-scope
selection rather than a default or empty result.
In `@crates/core/tests/coverage/logging_tests.rs`:
- Around line 934-972: Update concurrent_stale_teardown_preserves_newest_logger
so stale teardown cannot proceed until the configure thread has installed the
newer runtime. Add synchronization or an existing lifecycle test hook around
init_logging, and assert the installation event before allowing drop(stale);
retain the final logger identity assertion to verify the newest logger remains
installed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 55f809fa-e72e-4633-b8ef-0ea9a576b1a4
📒 Files selected for processing (6)
crates/cli/src/configuration/logging.rscrates/cli/src/configuration/mod.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/config.rscrates/core/src/logging/mod.rscrates/core/tests/coverage/logging_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (13)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.rs: If any Rust code changed, always runjust test-rust.
If any Rust code changed, also runcargo fmt --all.
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
Files:
crates/cli/src/configuration/mod.rscrates/cli/src/configuration/logging.rscrates/cli/tests/coverage/shared/config_tests.rscrates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/cli/tests/coverage/shared/config_tests.rscrates/core/tests/coverage/logging_tests.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
Files:
crates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
crates/{core,adaptive}/**/*.rs
⚙️ CodeRabbit configuration file
crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.
Files:
crates/core/src/logging/mod.rscrates/core/src/logging/config.rscrates/core/tests/coverage/logging_tests.rs
🔇 Additional comments (4)
crates/core/src/logging/mod.rs (1)
33-54: 📐 Maintainability & Code QualityProvide the required validation results before handoff.
crates/core/src/logging/mod.rs#L33-L54: runcargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings,just test-rust,cargo deny check,validate-change, and the required full language matrix.crates/core/src/logging/config.rs#L241-L241: include this core logging change in the same validation run.crates/core/src/logging/config.rs#L274-L274: include this core logging change in the same validation run.crates/cli/src/configuration/logging.rs#L18-L18: run the required Rust formatter, clippy, and test target.crates/cli/src/configuration/logging.rs#L30-L30: run the required Rust formatter, clippy, and test target.crates/cli/src/configuration/mod.rs#L107-L107: run the required Rust formatter, clippy, and test target.As per coding guidelines, “Any Rust change must run
just test-rust,”cargo fmt --all, andcargo clippy --workspace --all-targets -- -D warnings; core changes also require broader validation.Source: Coding guidelines
crates/core/tests/coverage/logging_tests.rs (2)
12-29: 📐 Maintainability & Code QualityConfirm the required Rust validation matrix completed.
Please verify
cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings,just test-rust,validate-change, the full Rust/Python/Go/Node matrix, anduv run pre-commit run --all-files.As per coding guidelines, “Any Rust change must run
just test-rust,” “also runcargo fmt --all,” and “also runcargo clippy --workspace --all-targets -- -D warnings.”Source: Coding guidelines
808-832: LGTM!Also applies to: 974-1004
crates/cli/tests/coverage/shared/config_tests.rs (1)
3123-3161: LGTM!
|
/ok to test 697a2cb |
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
|
/ok to test 6c5e76c |
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
|
/ok to test 7b1a0cc |
Salonijain27
left a comment
There was a problem hiding this comment.
Approved from a dependency point of view
|
/ok to test a443ada |
|
/merge |
#### Overview Documents the operational logging configuration and source-selection behavior introduced by #413. This docs-only PR should merge after or with #413 so the documented options match released CLI and library behavior. - [x] I confirm this contribution is my own work, or I have the right to submit it under this project's license. - [x] I searched existing issues and open pull requests, and this does not duplicate existing work. #### Details - Document always-on stderr logging, built-in defaults, and the configuration-editing commands that intentionally skip logging initialization. - Explain the single-source precedence across CLI options, environment variables, discovered `config.toml`, and defaults. - Document direct CLI and environment settings, absolute TOML configuration paths, and the shared Rust `LoggingRuntime` entry points. - Update the `[logging]` and `[[logging.sinks]]` example for asynchronous file delivery and the fixed 8,192-entry queue safety limit. #### Where should the reviewer start? - `docs/nemo-relay-cli/basic-usage.mdx` #### Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to) - Relates to #413 - Relates to RELAY-451 ## Summary by CodeRabbit * **Documentation** * Added an “Operational Logging” page and expanded Basic Usage to explain when operational logging is initialized and how to configure it. * Clarified that runtime logging setup is handled during operational command execution, while configuration-related commands avoid logging initialization to prevent blocking repairs. * Documented the precedence order for logging settings (CLI `--log-*` / `--log-config-path`, then `NEMO_RELAY_LOG*` env vars, then `[logging]` in resolved `config.toml`, then defaults). * Added guidance on normal runtime environment variables (including when `OTEL_*` applies) and detailed logging schema/sink options. Authors: - Eric Evans II (https://github.com/ericevans-nv) Approvers: - Will Killian (https://github.com/willkill07) - Maryam Najafian (https://github.com/mnajafian-nv) - https://github.com/lvojtku URL: #419
Overview
Add configurable, process-wide operational logging backed by the
logfacade andspdlog-rs. Operational commands initialize logging during top-level dispatch, before command execution.nemo-relay configandnemo-relay plugins editintentionally skip initialization so invalid logging configuration cannot prevent users from repairing it.This PR establishes the logging configuration and runtime. Broader production operational event call sites will be added separately.
Details
LoggingConfigandLoggingRuntimeAPIs shared by CLI and library integrations.config.tomldiscovery, environment configuration, explicit absolute TOML paths, and direct CLI settings. CLI sources take precedence over environment configuration, which takes precedence over discovered file configuration and defaults.[logging]inconfig.toml. A separate interactive logging editor is outside this PR.ATTRIBUTIONS-Rust.mdfor the new Rust dependencies.Where should the reviewer start?
crates/core/src/logging/for configuration types, runtime ownership, formatting, sinks, and shutdown behaviorcrates/cli/src/commands/logging.rsandcrates/cli/src/commands/mod.rsfor configuration-source selection and early command initializationcrates/cli/src/configuration/logging.rsfor normal Relay TOML integrationcrates/core/tests/coverage/logging_tests.rsandcrates/cli/tests/coverage/shared/config_tests.rsfor runtime and configuration guaranteescrates/cli/tests/coverage/commands/main_tests.rsfor CLI precedence and command policyRelated Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit