Skip to content

OTEL logs#21356

Merged
vkalintiris merged 74 commits intomasterfrom
sjr
Jan 14, 2026
Merged

OTEL logs#21356
vkalintiris merged 74 commits intomasterfrom
sjr

Conversation

@vkalintiris
Copy link
Contributor

@vkalintiris vkalintiris commented Nov 26, 2025

  • Adds journal-viewer plugin replacing the existing systemd-journal plugin.
  • Improves the existing otel plugin to ingest Otel logs in a systemd-compatible way.

@github-actions github-actions bot added area/docs area/collectors Everything related to data collection area/build Build system (autotools and cmake). collectors/systemd-journal area/plugins.d labels Nov 26, 2025
@vkalintiris
Copy link
Contributor Author

@cubic-dev-ai review this PR

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented Nov 27, 2025

@cubic-dev-ai review this PR

@vkalintiris I've started the AI code review. It'll take a few minutes to complete.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

40 issues found across 203 files

Note: This PR contains a large number of files. cubic only reviews up to 150 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all 40 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs:83">
Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/src/lib.rs:185">
`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</violation>
</file>

<file name="src/crates/journal-core/src/file/offset_array.rs">

<violation number="1" location="src/crates/journal-core/src/file/offset_array.rs:312">
When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</violation>
</file>

<file name="src/crates/journal-core/src/file/index_filter.rs">

<violation number="1" location="src/crates/journal-core/src/file/index_filter.rs:53">
`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</violation>

<violation number="2" location="src/crates/journal-core/src/file/index_filter.rs:65">
`end + 1` overflows when `end == u32::MAX`, so filtering the final bucket panics.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/query.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/query.rs:202">
`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</violation>
</file>

<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:234">
Backward pagination subtracts 1 from a `u64` anchor without checking for zero, causing underflow when the anchor is at the beginning of the log.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:520">
Log entries are fetched without applying the user’s selection filter, so the returned table ignores the requested filters.</violation>
</file>

<file name="src/crates/journal-core/src/file/guarded_cell.rs">

<violation number="1" location="src/crates/journal-core/src/file/guarded_cell.rs:225">
`with_guarded` keeps the guard mutably borrowed while invoking the user closure, so any re-entrant guard check panics via `RefCell` instead of returning `ValueGuardInUse`. Release the borrow before calling `f` and reacquire it only to mark the guard as held after `f` succeeds.</violation>
</file>

<file name="src/crates/journal-core/src/file/file.rs">

<violation number="1" location="src/crates/journal-core/src/file/file.rs:670">
`JournalFile::sync()` flushes only the header map and window manager but ignores the writable data/field hash table mmaps, so hash table updates are not persisted despite calling `sync()`.</violation>

<violation number="2" location="src/crates/journal-core/src/file/file.rs:839">
`object_header_mut` also skips locking the GuardedCell guard, allowing concurrent remapping while a mutable header reference is live and causing UB.</violation>
</file>

<file name="src/crates/journal-engine/src/histogram.rs">

<violation number="1" location="src/crates/journal-engine/src/histogram.rs:694">
Existing partial bucket responses are never resumed because an empty file list is returned when no new buckets are created, so histograms can get stuck partially indexed after any interrupted indexing run.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/mod.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/mod.rs:184">
Starting the watcher after scanning the directory introduces a race window where files created between those two operations are permanently missed; initialize the watcher before (or re-scan after) the directory walk to avoid dropping journal files.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/lib.rs:334">
The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</violation>

<violation number="2" location="src/crates/netdata-plugin/rt/src/lib.rs:866">
When a function name is not registered the runtime just logs an error and returns, leaving the transaction without any `FunctionResult` so Netdata never receives completion and the request hangs. Send an explicit error result (e.g., 404) before returning.</violation>
</file>

<file name="src/crates/netdata-plugin/protocol/src/tokio_codec.rs">

<violation number="1" location="src/crates/netdata-plugin/protocol/src/tokio_codec.rs:203">
Encoding `Message::FunctionProgress` panics because the encoder uses `unimplemented!()`, so sending a progress update will crash the codec instead of emitting a protocol frame.</violation>
</file>

<file name="src/crates/journal-common/src/time.rs">

<violation number="1" location="src/crates/journal-common/src/time.rs:162">
Unchecked Seconds subtraction wraps instead of panicking on underflow, contradicting the API/tests and producing bogus timestamps in release builds.</violation>

<violation number="2" location="src/crates/journal-common/src/time.rs:187">
Unchecked Microseconds subtraction wraps on underflow in release builds, so the operator violates its own panic contract and can emit wildly incorrect timestamps.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/table.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/table.rs:144">
Truncating cell text with `&amp;display[..*width]` can cut through a UTF-8 code point, panicking whenever a non-ASCII value needs truncation. Ensure truncation only happens on valid character boundaries.</violation>
</file>

<file name="src/crates/netdata-plugin/types/src/http_access.rs">

<violation number="1" location="src/crates/netdata-plugin/types/src/http_access.rs:47">
`from_hex` only recognizes a lowercase `0x` prefix, so uppercase hex values (`0X…`) that were valid before now parse as zero permissions.</violation>
</file>

<file name="src/crates/journal-engine/src/indexing.rs">

<violation number="1" location="src/crates/journal-engine/src/indexing.rs:512">
Propagate iterator errors from `collect_indexes` instead of logging and returning `Ok`, otherwise callers are told indexing succeeded even when it aborted early.</violation>
</file>

<file name="src/crates/journal-core/src/file/reader.rs">

<violation number="1" location="src/crates/journal-core/src/file/reader.rs:71">
`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</violation>

<violation number="2" location="src/crates/journal-core/src/file/reader.rs:332">
`load_remappings` ignores all errors from `field_data_objects`, so real I/O or corruption failures while loading remapping data are silently turned into success and remappings never load.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/charts/writer.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/charts/writer.rs:35">
Escape apostrophes (and other special characters) before wrapping chart and dimension metadata in single quotes so user-provided titles/names cannot break the generated Netdata commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:335">
Hex `_CAP_EFFECTIVE` values without a `0x` prefix are parsed as decimal, so no capability names are ever shown.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:580">
`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/README.md">

<violation number="1" location="src/crates/netdata-plugin/docs/README.md:494">
The example for payload handling ends with `FUNCTION PAYLOAD END`, but the Netdata protocol actually sends `FUNCTION_PAYLOAD_END`; using the wrong command name will prevent plugins from detecting the end of payload data.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md">

<violation number="1" location="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md:371">
Sample log explorer row inserts `rowOptions` in column index 1, which misaligns the `priority` column and contradicts the documented data layout. Move `rowOptions` to the end of the row.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/DYNCFG.md">

<violation number="1" location="src/crates/netdata-plugin/docs/DYNCFG.md:53">
DynCfg documentation should state that the `cmds` field must be space-separated (and examples should use spaces), because the parser ignores `|` characters and otherwise registers zero supported commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs:13">
`info` defaults to `true` in `JournalRequest::default()`, but serde deserialization uses `false` because `#[serde(default)]` falls back to `bool::default()`. Requests that omit this flag will incorrectly suppress metadata. Provide an explicit serde default that returns `true`.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/examples/simple_usage.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:14">
The Server Settings tab lists a `workers` field, but `WebServerConfig` only defines `host` and `port`, so the generated schema advertises a nonexistent control. Add the missing field or update the metadata to match the struct.</violation>

<violation number="2" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:18">
The Security tab lists fields (`enable_tls`, `tls_cert_path`, `api_key`) that are not defined on `WebServerConfig`, so the schema describes controls that do not exist. Define these fields or remove them from the metadata.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/monitor.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/monitor.rs:21">
The notify watcher callback drops `Err` results silently, so filesystem monitoring failures are never reported; log or propagate the error instead of ignoring it.</violation>
</file>

<file name="src/crates/journal-registry/README.md">

<violation number="1" location="src/crates/journal-registry/README.md:29">
`main` returns immediately after spawning the background event processor, so the Tokio runtime shuts down and cancels the loop before it can handle any events. Keep the runtime alive (e.g., await the join handle or block on a signal) instead of returning immediately.</violation>
</file>

<file name="src/crates/journal-common/src/compat.rs">

<violation number="1" location="src/crates/journal-common/src/compat.rs:38">
The compatibility helper panics on a zero divisor because it performs `value % divisor` without guarding against zero, unlike the standard `is_multiple_of` which returns `false` when the divisor is zero. Add a zero check before performing the modulo to preserve compatibility.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/transformations.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/transformations.rs:395">
Negative realtime timestamps are split incorrectly because `/` and `%` yield mismatched seconds and a negative remainder, producing invalid nanoseconds for chrono. Use `div_euclid` and `rem_euclid` so seconds and sub-second parts stay consistent even when the timestamp is before the Unix epoch.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/Cargo.toml">

<violation number="1" location="src/crates/netdata-plugin/rt/Cargo.toml:2">
Crate name `rt` does not match the workspace dependency alias `netdata-plugin-rt`, so any dependency on `netdata-plugin-rt` will fail to resolve.</violation>
</file>

<file name="src/crates/rdp/src/main.rs">

<violation number="1" location="src/crates/rdp/src/main.rs:307">
Unchecked exponentiation of the test count overflows for fuzz lengths ≥11, causing the CLI to panic or wrap before fuzzing. Guard the input or use checked/saturating arithmetic when summing `total_tests`.</violation>
</file>

<file name="src/crates/netdata-otel/otel-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-otel/otel-plugin/src/lib.rs:79">
`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</violation>
</file>

<file name="src/crates/netdata-log-viewer/README.md">

<violation number="1" location="src/crates/netdata-log-viewer/README.md:242">
The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

40 issues found across 203 files

Note: This PR contains a large number of files. cubic only reviews up to 150 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all 40 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs:83">
Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/src/lib.rs:185">
`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</violation>
</file>

<file name="src/crates/journal-core/src/file/offset_array.rs">

<violation number="1" location="src/crates/journal-core/src/file/offset_array.rs:312">
When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</violation>
</file>

<file name="src/crates/journal-core/src/file/index_filter.rs">

<violation number="1" location="src/crates/journal-core/src/file/index_filter.rs:53">
`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</violation>

<violation number="2" location="src/crates/journal-core/src/file/index_filter.rs:65">
`end + 1` overflows when `end == u32::MAX`, so filtering the final bucket panics.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/query.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/query.rs:202">
`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</violation>
</file>

<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:234">
Backward pagination subtracts 1 from a `u64` anchor without checking for zero, causing underflow when the anchor is at the beginning of the log.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:520">
Log entries are fetched without applying the user’s selection filter, so the returned table ignores the requested filters.</violation>
</file>

<file name="src/crates/journal-core/src/file/guarded_cell.rs">

<violation number="1" location="src/crates/journal-core/src/file/guarded_cell.rs:225">
`with_guarded` keeps the guard mutably borrowed while invoking the user closure, so any re-entrant guard check panics via `RefCell` instead of returning `ValueGuardInUse`. Release the borrow before calling `f` and reacquire it only to mark the guard as held after `f` succeeds.</violation>
</file>

<file name="src/crates/journal-core/src/file/file.rs">

<violation number="1" location="src/crates/journal-core/src/file/file.rs:670">
`JournalFile::sync()` flushes only the header map and window manager but ignores the writable data/field hash table mmaps, so hash table updates are not persisted despite calling `sync()`.</violation>

<violation number="2" location="src/crates/journal-core/src/file/file.rs:839">
`object_header_mut` also skips locking the GuardedCell guard, allowing concurrent remapping while a mutable header reference is live and causing UB.</violation>
</file>

<file name="src/crates/journal-engine/src/histogram.rs">

<violation number="1" location="src/crates/journal-engine/src/histogram.rs:694">
Existing partial bucket responses are never resumed because an empty file list is returned when no new buckets are created, so histograms can get stuck partially indexed after any interrupted indexing run.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/mod.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/mod.rs:184">
Starting the watcher after scanning the directory introduces a race window where files created between those two operations are permanently missed; initialize the watcher before (or re-scan after) the directory walk to avoid dropping journal files.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/lib.rs:334">
The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</violation>

<violation number="2" location="src/crates/netdata-plugin/rt/src/lib.rs:866">
When a function name is not registered the runtime just logs an error and returns, leaving the transaction without any `FunctionResult` so Netdata never receives completion and the request hangs. Send an explicit error result (e.g., 404) before returning.</violation>
</file>

<file name="src/crates/netdata-plugin/protocol/src/tokio_codec.rs">

<violation number="1" location="src/crates/netdata-plugin/protocol/src/tokio_codec.rs:203">
Encoding `Message::FunctionProgress` panics because the encoder uses `unimplemented!()`, so sending a progress update will crash the codec instead of emitting a protocol frame.</violation>
</file>

<file name="src/crates/journal-common/src/time.rs">

<violation number="1" location="src/crates/journal-common/src/time.rs:162">
Unchecked Seconds subtraction wraps instead of panicking on underflow, contradicting the API/tests and producing bogus timestamps in release builds.</violation>

<violation number="2" location="src/crates/journal-common/src/time.rs:187">
Unchecked Microseconds subtraction wraps on underflow in release builds, so the operator violates its own panic contract and can emit wildly incorrect timestamps.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/table.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/table.rs:144">
Truncating cell text with `&amp;display[..*width]` can cut through a UTF-8 code point, panicking whenever a non-ASCII value needs truncation. Ensure truncation only happens on valid character boundaries.</violation>
</file>

<file name="src/crates/netdata-plugin/types/src/http_access.rs">

<violation number="1" location="src/crates/netdata-plugin/types/src/http_access.rs:47">
`from_hex` only recognizes a lowercase `0x` prefix, so uppercase hex values (`0X…`) that were valid before now parse as zero permissions.</violation>
</file>

<file name="src/crates/journal-engine/src/indexing.rs">

<violation number="1" location="src/crates/journal-engine/src/indexing.rs:512">
Propagate iterator errors from `collect_indexes` instead of logging and returning `Ok`, otherwise callers are told indexing succeeded even when it aborted early.</violation>
</file>

<file name="src/crates/journal-core/src/file/reader.rs">

<violation number="1" location="src/crates/journal-core/src/file/reader.rs:71">
`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</violation>

<violation number="2" location="src/crates/journal-core/src/file/reader.rs:332">
`load_remappings` ignores all errors from `field_data_objects`, so real I/O or corruption failures while loading remapping data are silently turned into success and remappings never load.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/charts/writer.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/charts/writer.rs:35">
Escape apostrophes (and other special characters) before wrapping chart and dimension metadata in single quotes so user-provided titles/names cannot break the generated Netdata commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:335">
Hex `_CAP_EFFECTIVE` values without a `0x` prefix are parsed as decimal, so no capability names are ever shown.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:580">
`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/README.md">

<violation number="1" location="src/crates/netdata-plugin/docs/README.md:494">
The example for payload handling ends with `FUNCTION PAYLOAD END`, but the Netdata protocol actually sends `FUNCTION_PAYLOAD_END`; using the wrong command name will prevent plugins from detecting the end of payload data.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md">

<violation number="1" location="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md:371">
Sample log explorer row inserts `rowOptions` in column index 1, which misaligns the `priority` column and contradicts the documented data layout. Move `rowOptions` to the end of the row.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/DYNCFG.md">

<violation number="1" location="src/crates/netdata-plugin/docs/DYNCFG.md:53">
DynCfg documentation should state that the `cmds` field must be space-separated (and examples should use spaces), because the parser ignores `|` characters and otherwise registers zero supported commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs:13">
`info` defaults to `true` in `JournalRequest::default()`, but serde deserialization uses `false` because `#[serde(default)]` falls back to `bool::default()`. Requests that omit this flag will incorrectly suppress metadata. Provide an explicit serde default that returns `true`.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/examples/simple_usage.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:14">
The Server Settings tab lists a `workers` field, but `WebServerConfig` only defines `host` and `port`, so the generated schema advertises a nonexistent control. Add the missing field or update the metadata to match the struct.</violation>

<violation number="2" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:18">
The Security tab lists fields (`enable_tls`, `tls_cert_path`, `api_key`) that are not defined on `WebServerConfig`, so the schema describes controls that do not exist. Define these fields or remove them from the metadata.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/monitor.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/monitor.rs:21">
The notify watcher callback drops `Err` results silently, so filesystem monitoring failures are never reported; log or propagate the error instead of ignoring it.</violation>
</file>

<file name="src/crates/journal-registry/README.md">

<violation number="1" location="src/crates/journal-registry/README.md:29">
`main` returns immediately after spawning the background event processor, so the Tokio runtime shuts down and cancels the loop before it can handle any events. Keep the runtime alive (e.g., await the join handle or block on a signal) instead of returning immediately.</violation>
</file>

<file name="src/crates/journal-common/src/compat.rs">

<violation number="1" location="src/crates/journal-common/src/compat.rs:38">
The compatibility helper panics on a zero divisor because it performs `value % divisor` without guarding against zero, unlike the standard `is_multiple_of` which returns `false` when the divisor is zero. Add a zero check before performing the modulo to preserve compatibility.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/transformations.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/transformations.rs:395">
Negative realtime timestamps are split incorrectly because `/` and `%` yield mismatched seconds and a negative remainder, producing invalid nanoseconds for chrono. Use `div_euclid` and `rem_euclid` so seconds and sub-second parts stay consistent even when the timestamp is before the Unix epoch.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/Cargo.toml">

<violation number="1" location="src/crates/netdata-plugin/rt/Cargo.toml:2">
Crate name `rt` does not match the workspace dependency alias `netdata-plugin-rt`, so any dependency on `netdata-plugin-rt` will fail to resolve.</violation>
</file>

<file name="src/crates/rdp/src/main.rs">

<violation number="1" location="src/crates/rdp/src/main.rs:307">
Unchecked exponentiation of the test count overflows for fuzz lengths ≥11, causing the CLI to panic or wrap before fuzzing. Guard the input or use checked/saturating arithmetic when summing `total_tests`.</violation>
</file>

<file name="src/crates/netdata-otel/otel-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-otel/otel-plugin/src/lib.rs:79">
`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</violation>
</file>

<file name="src/crates/netdata-log-viewer/README.md">

<violation number="1" location="src/crates/netdata-log-viewer/README.md:242">
The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

}

// Initialize result vector with capacity for efficiency
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
Copy link
Contributor

Choose a reason for hiding this comment

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

Vec::with_capacity(limit) tries to reserve usize::MAX elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating usize::MAX.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/src/logs/query.rs, line 202:

<comment>`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</comment>

<file context>
@@ -0,0 +1,414 @@
+    }
+
+    // Initialize result vector with capacity for efficiency
+    let mut collected_entries: Vec&lt;LogEntryId&gt; = Vec::with_capacity(limit);
+
+    for file_index in relevant_indexes {
</file context>
Suggested change
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
let mut collected_entries: Vec<LogEntryId> = Vec::new();

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

40 issues found across 203 files

Note: This PR contains a large number of files. cubic only reviews up to 150 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all 40 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs:83">
Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/src/lib.rs:185">
`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</violation>
</file>

<file name="src/crates/journal-core/src/file/offset_array.rs">

<violation number="1" location="src/crates/journal-core/src/file/offset_array.rs:312">
When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</violation>
</file>

<file name="src/crates/journal-core/src/file/index_filter.rs">

<violation number="1" location="src/crates/journal-core/src/file/index_filter.rs:53">
`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</violation>

<violation number="2" location="src/crates/journal-core/src/file/index_filter.rs:65">
`end + 1` overflows when `end == u32::MAX`, so filtering the final bucket panics.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/query.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/query.rs:202">
`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</violation>
</file>

<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:234">
Backward pagination subtracts 1 from a `u64` anchor without checking for zero, causing underflow when the anchor is at the beginning of the log.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:520">
Log entries are fetched without applying the user’s selection filter, so the returned table ignores the requested filters.</violation>
</file>

<file name="src/crates/journal-core/src/file/guarded_cell.rs">

<violation number="1" location="src/crates/journal-core/src/file/guarded_cell.rs:225">
`with_guarded` keeps the guard mutably borrowed while invoking the user closure, so any re-entrant guard check panics via `RefCell` instead of returning `ValueGuardInUse`. Release the borrow before calling `f` and reacquire it only to mark the guard as held after `f` succeeds.</violation>
</file>

<file name="src/crates/journal-core/src/file/file.rs">

<violation number="1" location="src/crates/journal-core/src/file/file.rs:670">
`JournalFile::sync()` flushes only the header map and window manager but ignores the writable data/field hash table mmaps, so hash table updates are not persisted despite calling `sync()`.</violation>

<violation number="2" location="src/crates/journal-core/src/file/file.rs:839">
`object_header_mut` also skips locking the GuardedCell guard, allowing concurrent remapping while a mutable header reference is live and causing UB.</violation>
</file>

<file name="src/crates/journal-engine/src/histogram.rs">

<violation number="1" location="src/crates/journal-engine/src/histogram.rs:694">
Existing partial bucket responses are never resumed because an empty file list is returned when no new buckets are created, so histograms can get stuck partially indexed after any interrupted indexing run.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/mod.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/mod.rs:184">
Starting the watcher after scanning the directory introduces a race window where files created between those two operations are permanently missed; initialize the watcher before (or re-scan after) the directory walk to avoid dropping journal files.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/lib.rs:334">
The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</violation>

<violation number="2" location="src/crates/netdata-plugin/rt/src/lib.rs:866">
When a function name is not registered the runtime just logs an error and returns, leaving the transaction without any `FunctionResult` so Netdata never receives completion and the request hangs. Send an explicit error result (e.g., 404) before returning.</violation>
</file>

<file name="src/crates/netdata-plugin/protocol/src/tokio_codec.rs">

<violation number="1" location="src/crates/netdata-plugin/protocol/src/tokio_codec.rs:203">
Encoding `Message::FunctionProgress` panics because the encoder uses `unimplemented!()`, so sending a progress update will crash the codec instead of emitting a protocol frame.</violation>
</file>

<file name="src/crates/journal-common/src/time.rs">

<violation number="1" location="src/crates/journal-common/src/time.rs:162">
Unchecked Seconds subtraction wraps instead of panicking on underflow, contradicting the API/tests and producing bogus timestamps in release builds.</violation>

<violation number="2" location="src/crates/journal-common/src/time.rs:187">
Unchecked Microseconds subtraction wraps on underflow in release builds, so the operator violates its own panic contract and can emit wildly incorrect timestamps.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/table.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/table.rs:144">
Truncating cell text with `&amp;display[..*width]` can cut through a UTF-8 code point, panicking whenever a non-ASCII value needs truncation. Ensure truncation only happens on valid character boundaries.</violation>
</file>

<file name="src/crates/netdata-plugin/types/src/http_access.rs">

<violation number="1" location="src/crates/netdata-plugin/types/src/http_access.rs:47">
`from_hex` only recognizes a lowercase `0x` prefix, so uppercase hex values (`0X…`) that were valid before now parse as zero permissions.</violation>
</file>

<file name="src/crates/journal-engine/src/indexing.rs">

<violation number="1" location="src/crates/journal-engine/src/indexing.rs:512">
Propagate iterator errors from `collect_indexes` instead of logging and returning `Ok`, otherwise callers are told indexing succeeded even when it aborted early.</violation>
</file>

<file name="src/crates/journal-core/src/file/reader.rs">

<violation number="1" location="src/crates/journal-core/src/file/reader.rs:71">
`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</violation>

<violation number="2" location="src/crates/journal-core/src/file/reader.rs:332">
`load_remappings` ignores all errors from `field_data_objects`, so real I/O or corruption failures while loading remapping data are silently turned into success and remappings never load.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/charts/writer.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/charts/writer.rs:35">
Escape apostrophes (and other special characters) before wrapping chart and dimension metadata in single quotes so user-provided titles/names cannot break the generated Netdata commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:335">
Hex `_CAP_EFFECTIVE` values without a `0x` prefix are parsed as decimal, so no capability names are ever shown.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:580">
`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/README.md">

<violation number="1" location="src/crates/netdata-plugin/docs/README.md:494">
The example for payload handling ends with `FUNCTION PAYLOAD END`, but the Netdata protocol actually sends `FUNCTION_PAYLOAD_END`; using the wrong command name will prevent plugins from detecting the end of payload data.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md">

<violation number="1" location="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md:371">
Sample log explorer row inserts `rowOptions` in column index 1, which misaligns the `priority` column and contradicts the documented data layout. Move `rowOptions` to the end of the row.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/DYNCFG.md">

<violation number="1" location="src/crates/netdata-plugin/docs/DYNCFG.md:53">
DynCfg documentation should state that the `cmds` field must be space-separated (and examples should use spaces), because the parser ignores `|` characters and otherwise registers zero supported commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs:13">
`info` defaults to `true` in `JournalRequest::default()`, but serde deserialization uses `false` because `#[serde(default)]` falls back to `bool::default()`. Requests that omit this flag will incorrectly suppress metadata. Provide an explicit serde default that returns `true`.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/examples/simple_usage.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:14">
The Server Settings tab lists a `workers` field, but `WebServerConfig` only defines `host` and `port`, so the generated schema advertises a nonexistent control. Add the missing field or update the metadata to match the struct.</violation>

<violation number="2" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:18">
The Security tab lists fields (`enable_tls`, `tls_cert_path`, `api_key`) that are not defined on `WebServerConfig`, so the schema describes controls that do not exist. Define these fields or remove them from the metadata.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/monitor.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/monitor.rs:21">
The notify watcher callback drops `Err` results silently, so filesystem monitoring failures are never reported; log or propagate the error instead of ignoring it.</violation>
</file>

<file name="src/crates/journal-registry/README.md">

<violation number="1" location="src/crates/journal-registry/README.md:29">
`main` returns immediately after spawning the background event processor, so the Tokio runtime shuts down and cancels the loop before it can handle any events. Keep the runtime alive (e.g., await the join handle or block on a signal) instead of returning immediately.</violation>
</file>

<file name="src/crates/journal-common/src/compat.rs">

<violation number="1" location="src/crates/journal-common/src/compat.rs:38">
The compatibility helper panics on a zero divisor because it performs `value % divisor` without guarding against zero, unlike the standard `is_multiple_of` which returns `false` when the divisor is zero. Add a zero check before performing the modulo to preserve compatibility.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/transformations.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/transformations.rs:395">
Negative realtime timestamps are split incorrectly because `/` and `%` yield mismatched seconds and a negative remainder, producing invalid nanoseconds for chrono. Use `div_euclid` and `rem_euclid` so seconds and sub-second parts stay consistent even when the timestamp is before the Unix epoch.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/Cargo.toml">

<violation number="1" location="src/crates/netdata-plugin/rt/Cargo.toml:2">
Crate name `rt` does not match the workspace dependency alias `netdata-plugin-rt`, so any dependency on `netdata-plugin-rt` will fail to resolve.</violation>
</file>

<file name="src/crates/rdp/src/main.rs">

<violation number="1" location="src/crates/rdp/src/main.rs:307">
Unchecked exponentiation of the test count overflows for fuzz lengths ≥11, causing the CLI to panic or wrap before fuzzing. Guard the input or use checked/saturating arithmetic when summing `total_tests`.</violation>
</file>

<file name="src/crates/netdata-otel/otel-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-otel/otel-plugin/src/lib.rs:79">
`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</violation>
</file>

<file name="src/crates/netdata-log-viewer/README.md">

<violation number="1" location="src/crates/netdata-log-viewer/README.md:242">
The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

info!("Catalog function initialized");

// let path = "/var/log/journal";
let path = "/home/vk/repos/tmp/aws-4320";
Copy link
Contributor

Choose a reason for hiding this comment

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

Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs, line 83:

<comment>Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</comment>

<file context>
@@ -0,0 +1,108 @@
+    info!(&quot;Catalog function initialized&quot;);
+
+    // let path = &quot;/var/log/journal&quot;;
+    let path = &quot;/home/vk/repos/tmp/aws-4320&quot;;
+    match catalog_function.watch_directory(path) {
+        Ok(()) =&gt; {}
</file context>
Suggested change
let path = "/home/vk/repos/tmp/aws-4320";
let path = "/var/log/journal";

}

// Build config declaration
self.config_declaration = Some(config_props.build());
Copy link
Contributor

Choose a reason for hiding this comment

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

netdata_schema() now panics for types without x-config-* metadata because ConfigDeclarationBuilder::build unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving NetdataSchema on ordinary structs doesn’t crash.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-plugin/schema/src/lib.rs, line 185:

<comment>`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</comment>

<file context>
@@ -0,0 +1,300 @@
+        }
+
+        // Build config declaration
+        self.config_declaration = Some(config_props.build());
+    }
+}
</file context>

loop {
{
let array = journal_file.offset_array_ref(node.offset())?;
let remaining_items = node.remaining_items.get();
Copy link
Contributor

Choose a reason for hiding this comment

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

When copying subsequent arrays, use next_node.remaining_items instead of the previous node’s value; otherwise the last array is read past its valid entries.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/offset_array.rs, line 312:

<comment>When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</comment>

<file context>
@@ -294,10 +295,37 @@ impl List {
+        loop {
+            {
+                let array = journal_file.offset_array_ref(node.offset())?;
+                let remaining_items = node.remaining_items.get();
+                array.collect_offsets(0, remaining_items, offsets)?;
+            }
</file context>
Suggested change
let remaining_items = node.remaining_items.get();
let remaining_items = next_node.remaining_items.get();

IndexFilterExpr::None => false,
IndexFilterExpr::Match(bitmap) => !bitmap.is_empty(),
IndexFilterExpr::Conjunction(filter_exprs) => {
filter_exprs.iter().all(|expr| expr.has_matches())
Copy link
Contributor

Choose a reason for hiding this comment

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

has_matches returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/index_filter.rs, line 53:

<comment>`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</comment>

<file context>
@@ -0,0 +1,369 @@
+            IndexFilterExpr::None =&gt; false,
+            IndexFilterExpr::Match(bitmap) =&gt; !bitmap.is_empty(),
+            IndexFilterExpr::Conjunction(filter_exprs) =&gt; {
+                filter_exprs.iter().all(|expr| expr.has_matches())
+            }
+            IndexFilterExpr::Disjunction(filter_exprs) =&gt; {
</file context>

}

// Initialize result vector with capacity for efficiency
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
Copy link
Contributor

Choose a reason for hiding this comment

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

Vec::with_capacity(limit) tries to reserve usize::MAX elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating usize::MAX.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/src/logs/query.rs, line 202:

<comment>`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</comment>

<file context>
@@ -0,0 +1,414 @@
+    }
+
+    // Initialize result vector with capacity for efficiency
+    let mut collected_entries: Vec&lt;LogEntryId&gt; = Vec::with_capacity(limit);
+
+    for file_index in relevant_indexes {
</file context>
Suggested change
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
let mut collected_entries: Vec<LogEntryId> = Vec::new();

runtime.block_on(async_run(args))
}

async fn async_run(_args: Vec<String>) -> i32 {
Copy link
Contributor

Choose a reason for hiding this comment

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

run(args) accepts CLI arguments but async_run ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-otel/otel-plugin/src/lib.rs, line 79:

<comment>`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</comment>

<file context>
@@ -0,0 +1,192 @@
+    runtime.block_on(async_run(args))
+}
+
+async fn async_run(_args: Vec&lt;String&gt;) -&gt; i32 {
+    initialize_tracing();
+
</file context>

}

pub fn step(&mut self, journal_file: &'a JournalFile<M>, direction: Direction) -> Result<bool> {
self.drop_guards();
Copy link
Contributor

Choose a reason for hiding this comment

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

field_data_restart never resets self.field_data_iterator, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/reader.rs, line 71:

<comment>`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</comment>

<file context>
@@ -0,0 +1,466 @@
+    }
+
+    pub fn step(&amp;mut self, journal_file: &amp;&#39;a JournalFile&lt;M&gt;, direction: Direction) -&gt; Result&lt;bool&gt; {
+        self.drop_guards();
+
+        if let Some(filter) = self.filter.as_mut() {
</file context>

docker ps | grep jaeger

# Check connectivity
nc -zv localhost 4317
Copy link
Contributor

Choose a reason for hiding this comment

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

The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/README.md, line 242:

<comment>The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</comment>

<file context>
@@ -0,0 +1,258 @@
+docker ps | grep jaeger
+
+# Check connectivity
+nc -zv localhost 4317
+```
+
</file context>
Suggested change
nc -zv localhost 4317
+nc -zv localhost 4318

transaction,
status: 400,
expires: 0,
format: "text/plain".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

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

The 400 response emitted for an empty payload is JSON but format is set to "text/plain", so the content type is wrong. Use application/json to match the actual payload.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-plugin/rt/src/lib.rs, line 334:

<comment>The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</comment>

<file context>
@@ -0,0 +1,1015 @@
+                        transaction,
+                        status: 400,
+                        expires: 0,
+                        format: &quot;text/plain&quot;.to_string(),
+                        payload: format!(&quot;Invalid request: {}&quot;, e).as_bytes().to_vec(),
+                    };
</file context>
Suggested change
format: "text/plain".to_string(),
format: "application/json".to_string(),

_ => return raw_value.to_string(),
};

description.to_string()
Copy link
Contributor

Choose a reason for hiding this comment

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

MessageIdTransformation drops the actual MESSAGE_ID and returns only the description, contradicting the documented "UUID (description)" output.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs, line 580:

<comment>`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</comment>

<file context>
@@ -0,0 +1,613 @@
+            _ =&gt; return raw_value.to_string(),
+        };
+
+        description.to_string()
+    }
+}
</file context>
Suggested change
description.to_string()
format!("{} ({})", raw_value, description)

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

40 issues found across 203 files

Note: This PR contains a large number of files. cubic only reviews up to 150 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all 40 issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs:83">
Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/src/lib.rs:185">
`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</violation>
</file>

<file name="src/crates/journal-core/src/file/offset_array.rs">

<violation number="1" location="src/crates/journal-core/src/file/offset_array.rs:312">
When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</violation>
</file>

<file name="src/crates/journal-core/src/file/index_filter.rs">

<violation number="1" location="src/crates/journal-core/src/file/index_filter.rs:53">
`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</violation>

<violation number="2" location="src/crates/journal-core/src/file/index_filter.rs:65">
`end + 1` overflows when `end == u32::MAX`, so filtering the final bucket panics.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/query.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/query.rs:202">
`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</violation>
</file>

<file name="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs">

<violation number="1" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:234">
Backward pagination subtracts 1 from a `u64` anchor without checking for zero, causing underflow when the anchor is at the beginning of the log.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/log-viewer-plugin/src/catalog.rs:520">
Log entries are fetched without applying the user’s selection filter, so the returned table ignores the requested filters.</violation>
</file>

<file name="src/crates/journal-core/src/file/guarded_cell.rs">

<violation number="1" location="src/crates/journal-core/src/file/guarded_cell.rs:225">
`with_guarded` keeps the guard mutably borrowed while invoking the user closure, so any re-entrant guard check panics via `RefCell` instead of returning `ValueGuardInUse`. Release the borrow before calling `f` and reacquire it only to mark the guard as held after `f` succeeds.</violation>
</file>

<file name="src/crates/journal-core/src/file/file.rs">

<violation number="1" location="src/crates/journal-core/src/file/file.rs:670">
`JournalFile::sync()` flushes only the header map and window manager but ignores the writable data/field hash table mmaps, so hash table updates are not persisted despite calling `sync()`.</violation>

<violation number="2" location="src/crates/journal-core/src/file/file.rs:839">
`object_header_mut` also skips locking the GuardedCell guard, allowing concurrent remapping while a mutable header reference is live and causing UB.</violation>
</file>

<file name="src/crates/journal-engine/src/histogram.rs">

<violation number="1" location="src/crates/journal-engine/src/histogram.rs:694">
Existing partial bucket responses are never resumed because an empty file list is returned when no new buckets are created, so histograms can get stuck partially indexed after any interrupted indexing run.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/mod.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/mod.rs:184">
Starting the watcher after scanning the directory introduces a race window where files created between those two operations are permanently missed; initialize the watcher before (or re-scan after) the directory walk to avoid dropping journal files.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/lib.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/lib.rs:334">
The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</violation>

<violation number="2" location="src/crates/netdata-plugin/rt/src/lib.rs:866">
When a function name is not registered the runtime just logs an error and returns, leaving the transaction without any `FunctionResult` so Netdata never receives completion and the request hangs. Send an explicit error result (e.g., 404) before returning.</violation>
</file>

<file name="src/crates/netdata-plugin/protocol/src/tokio_codec.rs">

<violation number="1" location="src/crates/netdata-plugin/protocol/src/tokio_codec.rs:203">
Encoding `Message::FunctionProgress` panics because the encoder uses `unimplemented!()`, so sending a progress update will crash the codec instead of emitting a protocol frame.</violation>
</file>

<file name="src/crates/journal-common/src/time.rs">

<violation number="1" location="src/crates/journal-common/src/time.rs:162">
Unchecked Seconds subtraction wraps instead of panicking on underflow, contradicting the API/tests and producing bogus timestamps in release builds.</violation>

<violation number="2" location="src/crates/journal-common/src/time.rs:187">
Unchecked Microseconds subtraction wraps on underflow in release builds, so the operator violates its own panic contract and can emit wildly incorrect timestamps.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/table.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/table.rs:144">
Truncating cell text with `&amp;display[..*width]` can cut through a UTF-8 code point, panicking whenever a non-ASCII value needs truncation. Ensure truncation only happens on valid character boundaries.</violation>
</file>

<file name="src/crates/netdata-plugin/types/src/http_access.rs">

<violation number="1" location="src/crates/netdata-plugin/types/src/http_access.rs:47">
`from_hex` only recognizes a lowercase `0x` prefix, so uppercase hex values (`0X…`) that were valid before now parse as zero permissions.</violation>
</file>

<file name="src/crates/journal-engine/src/indexing.rs">

<violation number="1" location="src/crates/journal-engine/src/indexing.rs:512">
Propagate iterator errors from `collect_indexes` instead of logging and returning `Ok`, otherwise callers are told indexing succeeded even when it aborted early.</violation>
</file>

<file name="src/crates/journal-core/src/file/reader.rs">

<violation number="1" location="src/crates/journal-core/src/file/reader.rs:71">
`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</violation>

<violation number="2" location="src/crates/journal-core/src/file/reader.rs:332">
`load_remappings` ignores all errors from `field_data_objects`, so real I/O or corruption failures while loading remapping data are silently turned into success and remappings never load.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/src/charts/writer.rs">

<violation number="1" location="src/crates/netdata-plugin/rt/src/charts/writer.rs:35">
Escape apostrophes (and other special characters) before wrapping chart and dimension metadata in single quotes so user-provided titles/names cannot break the generated Netdata commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:335">
Hex `_CAP_EFFECTIVE` values without a `0x` prefix are parsed as decimal, so no capability names are ever shown.</violation>

<violation number="2" location="src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs:580">
`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/README.md">

<violation number="1" location="src/crates/netdata-plugin/docs/README.md:494">
The example for payload handling ends with `FUNCTION PAYLOAD END`, but the Netdata protocol actually sends `FUNCTION_PAYLOAD_END`; using the wrong command name will prevent plugins from detecting the end of payload data.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md">

<violation number="1" location="src/crates/netdata-plugin/docs/FUNCTION_UI_DEVELOPER_GUIDE.md:371">
Sample log explorer row inserts `rowOptions` in column index 1, which misaligns the `priority` column and contradicts the documented data layout. Move `rowOptions` to the end of the row.</violation>
</file>

<file name="src/crates/netdata-plugin/docs/DYNCFG.md">

<violation number="1" location="src/crates/netdata-plugin/docs/DYNCFG.md:53">
DynCfg documentation should state that the `cmds` field must be space-separated (and examples should use spaces), because the parser ignores `|` characters and otherwise registers zero supported commands.</violation>
</file>

<file name="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs">

<violation number="1" location="src/crates/netdata-log-viewer/journal-function/src/netdata/types.rs:13">
`info` defaults to `true` in `JournalRequest::default()`, but serde deserialization uses `false` because `#[serde(default)]` falls back to `bool::default()`. Requests that omit this flag will incorrectly suppress metadata. Provide an explicit serde default that returns `true`.</violation>
</file>

<file name="src/crates/netdata-plugin/schema/examples/simple_usage.rs">

<violation number="1" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:14">
The Server Settings tab lists a `workers` field, but `WebServerConfig` only defines `host` and `port`, so the generated schema advertises a nonexistent control. Add the missing field or update the metadata to match the struct.</violation>

<violation number="2" location="src/crates/netdata-plugin/schema/examples/simple_usage.rs:18">
The Security tab lists fields (`enable_tls`, `tls_cert_path`, `api_key`) that are not defined on `WebServerConfig`, so the schema describes controls that do not exist. Define these fields or remove them from the metadata.</violation>
</file>

<file name="src/crates/journal-registry/src/registry/monitor.rs">

<violation number="1" location="src/crates/journal-registry/src/registry/monitor.rs:21">
The notify watcher callback drops `Err` results silently, so filesystem monitoring failures are never reported; log or propagate the error instead of ignoring it.</violation>
</file>

<file name="src/crates/journal-registry/README.md">

<violation number="1" location="src/crates/journal-registry/README.md:29">
`main` returns immediately after spawning the background event processor, so the Tokio runtime shuts down and cancels the loop before it can handle any events. Keep the runtime alive (e.g., await the join handle or block on a signal) instead of returning immediately.</violation>
</file>

<file name="src/crates/journal-common/src/compat.rs">

<violation number="1" location="src/crates/journal-common/src/compat.rs:38">
The compatibility helper panics on a zero divisor because it performs `value % divisor` without guarding against zero, unlike the standard `is_multiple_of` which returns `false` when the divisor is zero. Add a zero check before performing the modulo to preserve compatibility.</violation>
</file>

<file name="src/crates/journal-engine/src/logs/transformations.rs">

<violation number="1" location="src/crates/journal-engine/src/logs/transformations.rs:395">
Negative realtime timestamps are split incorrectly because `/` and `%` yield mismatched seconds and a negative remainder, producing invalid nanoseconds for chrono. Use `div_euclid` and `rem_euclid` so seconds and sub-second parts stay consistent even when the timestamp is before the Unix epoch.</violation>
</file>

<file name="src/crates/netdata-plugin/rt/Cargo.toml">

<violation number="1" location="src/crates/netdata-plugin/rt/Cargo.toml:2">
Crate name `rt` does not match the workspace dependency alias `netdata-plugin-rt`, so any dependency on `netdata-plugin-rt` will fail to resolve.</violation>
</file>

<file name="src/crates/rdp/src/main.rs">

<violation number="1" location="src/crates/rdp/src/main.rs:307">
Unchecked exponentiation of the test count overflows for fuzz lengths ≥11, causing the CLI to panic or wrap before fuzzing. Guard the input or use checked/saturating arithmetic when summing `total_tests`.</violation>
</file>

<file name="src/crates/netdata-otel/otel-plugin/src/lib.rs">

<violation number="1" location="src/crates/netdata-otel/otel-plugin/src/lib.rs:79">
`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</violation>
</file>

<file name="src/crates/netdata-log-viewer/README.md">

<violation number="1" location="src/crates/netdata-log-viewer/README.md:242">
The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

info!("Catalog function initialized");

// let path = "/var/log/journal";
let path = "/home/vk/repos/tmp/aws-4320";
Copy link
Contributor

Choose a reason for hiding this comment

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

Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/log-viewer-plugin/src/lib.rs, line 83:

<comment>Hard-coding a developer-specific path prevents the plugin from watching the system journal. Point it back to the real journald directory (e.g., /var/log/journal) or make it configurable.</comment>

<file context>
@@ -0,0 +1,108 @@
+    info!(&quot;Catalog function initialized&quot;);
+
+    // let path = &quot;/var/log/journal&quot;;
+    let path = &quot;/home/vk/repos/tmp/aws-4320&quot;;
+    match catalog_function.watch_directory(path) {
+        Ok(()) =&gt; {}
</file context>
Suggested change
let path = "/home/vk/repos/tmp/aws-4320";
let path = "/var/log/journal";

}

// Build config declaration
self.config_declaration = Some(config_props.build());
Copy link
Contributor

Choose a reason for hiding this comment

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

netdata_schema() now panics for types without x-config-* metadata because ConfigDeclarationBuilder::build unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving NetdataSchema on ordinary structs doesn’t crash.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-plugin/schema/src/lib.rs, line 185:

<comment>`netdata_schema()` now panics for types without `x-config-*` metadata because `ConfigDeclarationBuilder::build` unwraps every field even when none were provided. Ensure config declarations are only built when all required fields exist (or provide sane defaults) so deriving `NetdataSchema` on ordinary structs doesn’t crash.</comment>

<file context>
@@ -0,0 +1,300 @@
+        }
+
+        // Build config declaration
+        self.config_declaration = Some(config_props.build());
+    }
+}
</file context>

loop {
{
let array = journal_file.offset_array_ref(node.offset())?;
let remaining_items = node.remaining_items.get();
Copy link
Contributor

Choose a reason for hiding this comment

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

When copying subsequent arrays, use next_node.remaining_items instead of the previous node’s value; otherwise the last array is read past its valid entries.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/offset_array.rs, line 312:

<comment>When copying subsequent arrays, use `next_node.remaining_items` instead of the previous node’s value; otherwise the last array is read past its valid entries.</comment>

<file context>
@@ -294,10 +295,37 @@ impl List {
+        loop {
+            {
+                let array = journal_file.offset_array_ref(node.offset())?;
+                let remaining_items = node.remaining_items.get();
+                array.collect_offsets(0, remaining_items, offsets)?;
+            }
</file context>
Suggested change
let remaining_items = node.remaining_items.get();
let remaining_items = next_node.remaining_items.get();

IndexFilterExpr::None => false,
IndexFilterExpr::Match(bitmap) => !bitmap.is_empty(),
IndexFilterExpr::Conjunction(filter_exprs) => {
filter_exprs.iter().all(|expr| expr.has_matches())
Copy link
Contributor

Choose a reason for hiding this comment

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

has_matches returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/index_filter.rs, line 53:

<comment>`has_matches` returns true for conjunctions even when their intersection is empty, so AND filters can yield false positives.</comment>

<file context>
@@ -0,0 +1,369 @@
+            IndexFilterExpr::None =&gt; false,
+            IndexFilterExpr::Match(bitmap) =&gt; !bitmap.is_empty(),
+            IndexFilterExpr::Conjunction(filter_exprs) =&gt; {
+                filter_exprs.iter().all(|expr| expr.has_matches())
+            }
+            IndexFilterExpr::Disjunction(filter_exprs) =&gt; {
</file context>

}

// Initialize result vector with capacity for efficiency
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
Copy link
Contributor

Choose a reason for hiding this comment

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

Vec::with_capacity(limit) tries to reserve usize::MAX elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating usize::MAX.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/src/logs/query.rs, line 202:

<comment>`Vec::with_capacity(limit)` tries to reserve `usize::MAX` elements whenever the caller leaves the limit unset, so the default path panics or OOMs before processing any logs. Use a bounded capacity (or start with an empty Vec) instead of allocating `usize::MAX`.</comment>

<file context>
@@ -0,0 +1,414 @@
+    }
+
+    // Initialize result vector with capacity for efficiency
+    let mut collected_entries: Vec&lt;LogEntryId&gt; = Vec::with_capacity(limit);
+
+    for file_index in relevant_indexes {
</file context>
Suggested change
let mut collected_entries: Vec<LogEntryId> = Vec::with_capacity(limit);
let mut collected_entries: Vec<LogEntryId> = Vec::new();

runtime.block_on(async_run(args))
}

async fn async_run(_args: Vec<String>) -> i32 {
Copy link
Contributor

Choose a reason for hiding this comment

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

run(args) accepts CLI arguments but async_run ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-otel/otel-plugin/src/lib.rs, line 79:

<comment>`run(args)` accepts CLI arguments but `async_run` ignores them, so callers cannot configure the plugin via the provided argument vector despite the documented contract.</comment>

<file context>
@@ -0,0 +1,192 @@
+    runtime.block_on(async_run(args))
+}
+
+async fn async_run(_args: Vec&lt;String&gt;) -&gt; i32 {
+    initialize_tracing();
+
</file context>

}

pub fn step(&mut self, journal_file: &'a JournalFile<M>, direction: Direction) -> Result<bool> {
self.drop_guards();
Copy link
Contributor

Choose a reason for hiding this comment

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

field_data_restart never resets self.field_data_iterator, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-core/src/file/reader.rs, line 71:

<comment>`field_data_restart` never resets `self.field_data_iterator`, so calling it does not actually restart field data enumeration and later calls keep skipping previously returned objects.</comment>

<file context>
@@ -0,0 +1,466 @@
+    }
+
+    pub fn step(&amp;mut self, journal_file: &amp;&#39;a JournalFile&lt;M&gt;, direction: Direction) -&gt; Result&lt;bool&gt; {
+        self.drop_guards();
+
+        if let Some(filter) = self.filter.as_mut() {
</file context>

docker ps | grep jaeger

# Check connectivity
nc -zv localhost 4317
Copy link
Contributor

Choose a reason for hiding this comment

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

The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/README.md, line 242:

<comment>The Jaeger connectivity check probes port 4317 even though the Quick Start container mapping exposes Jaeger on host port 4318, so the documented troubleshooting command will always fail.</comment>

<file context>
@@ -0,0 +1,258 @@
+docker ps | grep jaeger
+
+# Check connectivity
+nc -zv localhost 4317
+```
+
</file context>
Suggested change
nc -zv localhost 4317
+nc -zv localhost 4318

transaction,
status: 400,
expires: 0,
format: "text/plain".to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

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

The 400 response emitted for an empty payload is JSON but format is set to "text/plain", so the content type is wrong. Use application/json to match the actual payload.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-plugin/rt/src/lib.rs, line 334:

<comment>The 400 response emitted for an empty payload is JSON but `format` is set to `&quot;text/plain&quot;`, so the content type is wrong. Use `application/json` to match the actual payload.</comment>

<file context>
@@ -0,0 +1,1015 @@
+                        transaction,
+                        status: 400,
+                        expires: 0,
+                        format: &quot;text/plain&quot;.to_string(),
+                        payload: format!(&quot;Invalid request: {}&quot;, e).as_bytes().to_vec(),
+                    };
</file context>
Suggested change
format: "text/plain".to_string(),
format: "application/json".to_string(),

_ => return raw_value.to_string(),
};

description.to_string()
Copy link
Contributor

Choose a reason for hiding this comment

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

MessageIdTransformation drops the actual MESSAGE_ID and returns only the description, contradicting the documented "UUID (description)" output.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs, line 580:

<comment>`MessageIdTransformation` drops the actual MESSAGE_ID and returns only the description, contradicting the documented `&quot;UUID (description)&quot;` output.</comment>

<file context>
@@ -0,0 +1,613 @@
+            _ =&gt; return raw_value.to_string(),
+        };
+
+        description.to_string()
+    }
+}
</file context>
Suggested change
description.to_string()
format!("{} ({})", raw_value, description)

netdata.spec.in Outdated
%caps(cap_dac_read_search=ep) %attr(0750,root,netdata) %{_libexecdir}/%{name}/plugins.d/systemd-journal.plugin
# CAP_DAC_READ_SEARCH required for reading journal files.
%caps(cap_dac_read_search=ep) %attr(0750,root,netdata) %{_libexecdir}/%{name}/plugins.d/journal-viewer-plugin
%config(noreplace) %{_libdir}/%{name}/conf.d/journal-viewer.yml
Copy link
Member

Choose a reason for hiding this comment

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

This shouldn’t be flagged as a config file, because it’s not exepcted to be edited by the user.

@Ferroin
Copy link
Member

Ferroin commented Dec 5, 2025

Static build failures will need a rebase to include #21401.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

9 issues found across 244 files (changes from recent commits).

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="docs/ai-powered-alert-configuration/ai-powered-alert-configuration.md">

<violation number="1">
P3: Typo: &quot;masterfull&quot; should be &quot;masterful&quot; (single &#39;l&#39;).</violation>
</file>

<file name="src/crates/journal-index/src/file_index.rs">

<violation number="1" location="src/crates/journal-index/src/file_index.rs:97">
P2: Potential integer underflow: if `indexed_at` is in the future relative to `now` (e.g., due to clock skew), the subtraction will panic in debug mode or wrap around in release mode. Consider using `saturating_sub` to handle this edge case gracefully.</violation>
</file>

<file name="packaging/PLATFORM_SUPPORT.md">

<violation number="1">
P2: Incorrect EOL date for Ubuntu 24.10. The EOL date &#39;2024-07-01&#39; predates Ubuntu 24.10&#39;s release (October 2024). Based on Ubuntu&#39;s 9-month non-LTS support cycle, the EOL should be around July 2025.</violation>
</file>

<file name="src/crates/journal-engine/examples/index.rs">

<violation number="1" location="src/crates/journal-engine/examples/index.rs:58">
P2: Hardcoded developer-specific path in example code. Consider using a more generic placeholder path like `PathBuf::from(&quot;./test-data&quot;)` or requiring the command-line argument instead of defaulting to a user-specific path.</violation>
</file>

<file name="src/collectors/windows.plugin/perflib-adcs.c">

<violation number="1">
P1: Data source mismatch: The function fetches `ADCSRetrievalsProcessingTime` via `perflibGetObjectCounter` but this line reads from `ADCSRequestCryptoSigningTime` which is never populated. This will report uninitialized data. The `perflibGetObjectCounter` call should also be changed to `&amp;ac-&gt;ADCSRequestCryptoSigningTime`.</violation>
</file>

<file name="src/collectors/windows.plugin/GetHardwareInfo.c">

<violation number="1">
P2: Incomplete error handling for `ExpandEnvironmentStringsA`. The function returns the required buffer size (&gt; 0) when the buffer is too small, not 0. The current check only catches complete failures, potentially allowing truncated/undefined data when the expanded path exceeds `MAX_PATH`.</violation>
</file>

<file name="src/collectors/windows.plugin/GetSensors.c">

<violation number="1">
P2: Resource leak: `PropVariantClear(&amp;pv)` is not called before returning `NULL` when `wcstombs` fails. The PROPVARIANT contains allocated memory (`VT_LPWSTR`) that will leak.</violation>
</file>

<file name="src/crates/journal-engine/src/indexing.rs">

<violation number="1" location="src/crates/journal-engine/src/indexing.rs:208">
P1: Cache lookup errors silently drop keys from processing. When cache lookup fails, the key should be added to `keys_to_compute` to allow recomputation, otherwise the result set will be incomplete without the caller knowing which keys were lost.</violation>

<violation number="2" location="src/crates/journal-engine/src/indexing.rs:276">
P2: Computation errors are silently dropped in Phase 4. When file indexing fails, there&#39;s no logging and the key is lost from the response. Consider logging the error to aid debugging.</violation>
</file>

Reply to cubic to teach it or ask questions. Tag @cubic-dev-ai to re-run a review.

PathBuf::from(arg)
} else {
// PathBuf::from("/mnt/slow-disk/otel-aws")
PathBuf::from("/home/vk/repos/tmp/otel-aws")
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P2: Hardcoded developer-specific path in example code. Consider using a more generic placeholder path like PathBuf::from("./test-data") or requiring the command-line argument instead of defaulting to a user-specific path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/examples/index.rs, line 58:

<comment>Hardcoded developer-specific path in example code. Consider using a more generic placeholder path like `PathBuf::from(&quot;./test-data&quot;)` or requiring the command-line argument instead of defaulting to a user-specific path.</comment>

<file context>
@@ -0,0 +1,135 @@
+        PathBuf::from(arg)
+    } else {
+        // PathBuf::from(&quot;/mnt/slow-disk/otel-aws&quot;)
+        PathBuf::from(&quot;/home/vk/repos/tmp/otel-aws&quot;)
+    };
+
</file context>

✅ Addressed in 92ad496

// Phase 4: Update registry and cache, then collect responses
for (key, response) in computed_results {
// Update registry and cache on success
if let Ok(index) = response {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P2: Computation errors are silently dropped in Phase 4. When file indexing fails, there's no logging and the key is lost from the response. Consider logging the error to aid debugging.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/src/indexing.rs, line 276:

<comment>Computation errors are silently dropped in Phase 4. When file indexing fails, there&#39;s no logging and the key is lost from the response. Consider logging the error to aid debugging.</comment>

<file context>
@@ -339,187 +109,183 @@ impl IndexingEngineBuilder {
+    // Phase 4: Update registry and cache, then collect responses
+    for (key, response) in computed_results {
+        // Update registry and cache on success
+        if let Ok(index) = response {
+            let _ = registry.update_time_range(
+                &amp;key.file,
</file context>

✅ Addressed in 114529f

Comment on lines +208 to +210
Err(e) => {
error!("cached file index lookup error {}", e);
}
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Dec 30, 2025

Choose a reason for hiding this comment

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

P1: Cache lookup errors silently drop keys from processing. When cache lookup fails, the key should be added to keys_to_compute to allow recomputation, otherwise the result set will be incomplete without the caller knowing which keys were lost.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/crates/journal-engine/src/indexing.rs, line 208:

<comment>Cache lookup errors silently drop keys from processing. When cache lookup fails, the key should be added to `keys_to_compute` to allow recomputation, otherwise the result set will be incomplete without the caller knowing which keys were lost.</comment>

<file context>
@@ -339,187 +109,183 @@ impl IndexingEngineBuilder {
+                cache_misses += 1;
+                keys_to_compute.push(key);
+            }
+            Err(e) =&gt; {
+                error!(&quot;cached file index lookup error {}&quot;, e);
+            }
</file context>
Suggested change
Err(e) => {
error!("cached file index lookup error {}", e);
}
Err(e) => {
// Cache error - need to compute
error!("cached file index lookup error {}", e);
keys_to_compute.push(key);
}
Fix with Cubic

@thiagoftsm thiagoftsm requested a review from Ferroin January 7, 2026 18:41
@thiagoftsm
Copy link
Contributor

I was unable to see any chart data or log entries generated from this PR when running on Slackware and Arch Linux. What I observed on both distributions were empty directories:

[root@archlinux netdata]# ls -lh /var/log/netdata/otel/v1/8553030a4e43481b8a05d5c40840507a/
total 0

In both scenarios, I have logging configured to use files.

I ran these tests because, after reading the original post, I thought this configuration might have been overlooked.

@vkalintiris , is it expected to have no new data written when using log files?

@vkalintiris
Copy link
Contributor Author

What I observed on both distributions were empty directories:

[root@archlinux netdata]# ls -lh /var/log/netdata/otel/v1/8553030a4e43481b8a05d5c40840507a/
total 0

This is expected because journal log files will be created in this directory only when ingesting OpenTelemetry logs.

I was unable to see any chart data or log entries generated from this PR when running on Slackware and Arch Linux.

The PR does not create any new charts. Any log messages created by the journal-viewer plugin should be in the destination of your [logs] configuration of netdata.conf.

In both scenarios, I have logging configured to use files.

I ran these tests because, after reading the original post, I thought this configuration might have been overlooked.

@vkalintiris , is it expected to have no new data written when using log files?

Can you share your [logs] configuration from netdata.conf?

Are you able to see systemd logs from your system on the logs UI tab on the agent's dashboard? That is, logs similar to what you'd see by running journalctl?

@vkalintiris vkalintiris merged commit d0905d9 into master Jan 14, 2026
143 of 148 checks passed
@ilyam8 ilyam8 deleted the sjr branch January 14, 2026 22:04
vkalintiris added a commit to vkalintiris/netdata that referenced this pull request Feb 10, 2026
vkalintiris added a commit to vkalintiris/netdata that referenced this pull request Feb 10, 2026
vkalintiris added a commit that referenced this pull request Feb 11, 2026
* Revert "Refactor function progress: move timeout and progress authority to the plugin runtime and agent (#21723)"

This reverts commit 09cbde1.

* Revert "Improve log message when deferred response is too big. (#21720)"

This reverts commit 453bc9d.

* Revert "Use info-level log for undhandled modification events. (#21719)"

This reverts commit 986a187.

* Revert "Handle fields with high-cardinality and big payloads. (#21716)"

This reverts commit 80a5a9f.

* Revert "Set status flag of active journal file to archived on shutdown. (#21707)"

This reverts commit c2cd26f.

* Revert "Make new journal viewer plugin a mandatory dependency for native packages to ensure clean upgrades. (#21701)"

This reverts commit 3ee561b.

* Revert "Document logs functionality of otel plugin (#21705)"

This reverts commit 83ac4e5.

* Revert "Update README links to correct otel-plugin paths (#21699)"

This reverts commit 088c20a.

* Revert "Add object size and bounds validation when reading journal files. (#21697)"

This reverts commit e482ca8.

* Revert "Handle transient systemd state flag changes. (#21695)"

This reverts commit 5638b80.

* Revert "Keep window manager state consistent on `mmap` failures. (#21693)"

This reverts commit c56d358.

* Revert "Always capture backtrace on panic. (#21681)"

This reverts commit 191de6f.

* Revert "Use debug level for logging of requests. (#21625)"

This reverts commit 2e0dd48.

* Revert "Assortement of journal-viewer plugin fixes. (#21612)"

This reverts commit 8f048c8.

* Revert "Fix 32-bit builds of journal-viewer plugin. (#21580)"

This reverts commit d98adc0.

* Revert "Fix response when no log entries have been found. (#21581)"

This reverts commit d0c06b8.

* Revert "Proper decompression of data object payloads. (#21578)"

This reverts commit 7f4ce41.

* Revert "bring back systemd-journal.plugin setcap (from source install) (#21569)"

This reverts commit ad6ee9c.

* Revert "Use host-prefixed log directories under containers. (#21568)"

This reverts commit 1fac565.

* Revert "Allow systemd-journal plugin if journal-viewer does not exist. (#21561)"

This reverts commit 2b180ba.

* Revert "Add sentry error reporting (#21558)"

This reverts commit ffcec41.

* Revert "OTEL logs (#21356)"

This reverts commit d0905d9.

* Add Rust cargo workspace for journal-viewer and otel plugins alongside systemd-journal.plugin

Copy the Rust crates from origin/master into src/crates/ as an independent
cargo workspace. This brings back the journal-viewer plugin, otel plugin,
and their supporting crates (journal-core, journal-engine, journal-index,
journal-registry, journal-log-writer, netdata-plugin, etc.) without
modifying the existing systemd-journal.plugin or its Rust FFI backend
under src/crates/jf/.

The outer workspace's Cargo.toml excludes the jf/ directory so the two
workspaces remain independent:
- src/crates/jf/: used exclusively by the C-based systemd-journal.plugin
- src/crates/: the new cargo workspace for journal-viewer and otel plugins

* Switch otel-plugin to build from src/crates/ workspace instead of src/crates/jf/

Split the corrosion_import_crate call so that each Rust workspace is
imported independently:
- journal_reader_ffi from src/crates/jf/ (for systemd-journal.plugin)
- otel-plugin from src/crates/ (the main cargo workspace)

Also add the otel-plugin rustflags for tracing_unstable and static builds,
and update config install paths and docs map to point to
src/crates/netdata-otel/otel-plugin/.

* Add full build and packaging support for journal-viewer-plugin

Add ENABLE_PLUGIN_JOURNAL_VIEWER as a new CMake option, independent of
the existing ENABLE_PLUGIN_SYSTEMD_JOURNAL. Both plugins coexist without
conflicts or replacements.

CMake (CMakeLists.txt):
- New ENABLE_PLUGIN_JOURNAL_VIEWER option (default: ON)
- Import journal-viewer-plugin from the main src/crates/ workspace via
  Corrosion, alongside otel-plugin
- Rustflags: --cfg=tracing_unstable, io_uring_skip_arch_check on 32-bit,
  crt-static for static builds
- Install target and config file processing for journal-viewer.yaml

Packaging:
- Debian: new netdata-plugin-journal-viewer package with postinst for
  cap_dac_read_search capability (Packaging.cmake, postinst)
- RPM: new journal-viewer subpackage with caps and file entries
  (netdata.spec.in)

Installer and build entry points:
- netdata-installer.sh: --enable/--disable-plugin-journal-viewer CLI
  flags and setcap/permissions block for the plugin binary
- packaging/installer/functions.sh: PLUGIN_JOURNAL_VIEWER CMake feature
- packaging/docker/Dockerfile: --enable-plugin-journal-viewer in build
- packaging/makeself/jobs/70-netdata-git.install.sh: enable for all
  architectures except armv6l

The plugin defaults to disabled in the installer (like otel) and is
explicitly enabled in Docker and static/makeself builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rename journal-viewer-plugin to otel-signal-viewer-plugin

The journal-viewer name was confusing alongside systemd-journal.plugin
since both implied journal log viewing. Rename to otel-signal-viewer to
reflect the plugin's actual purpose: viewing OTel signals (logs now,
traces in the future).

Renamed across all layers:
- Rust crate: package name, binary name, directory, config file
- CMake: ENABLE_PLUGIN_OTEL_SIGNAL_VIEWER option, Corrosion targets,
  rustflags, install targets, config processing
- RPM: subpackage, file lists, exclusions
- Debian: package definition, postinst directory
- Installer: CLI flags (--enable/--disable-plugin-otel-signal-viewer),
  variable (ENABLE_OTEL_SIGNAL_VIEWER), permissions block
- Docker: installer flag, chmod loop
- Makeself: static build flags
- Rust source: function name, chart contexts, plugin runtime name,
  config filename references
- Documentation: map.yaml label, crate README

* Fix installer flag

* Update docs/.map/map.yaml

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* Remove duplicate source entry

* Guard Recommends tag against old RPM on Amazon Linux 2

* Disable otel-signal-viewer plugin on Windows.

* Bring back function cancellation on timeout and useful diagnostic.

* Reference correct plugin in README.md

* Remove RUSTFLAGS from static builds.

* Update function description.

* Update otel-signal-viewer configuration file.

* Replace runtime relative path resolution with CMake template substitution.

Both the otel and otel-signal-viewer plugins used a resolve_relative_path()
helper to turn relative config paths into absolute ones at runtime, using
Netdata environment variables as the base directory.

The otel-signal-viewer plugin already had a .yaml.in template with CMake
variables for its paths, making its resolve_relative_path() call redundant
(the paths were already absolute after CMake substitution).

Unify both plugins on the CMake approach:

- Convert otel.yaml to otel.yaml.in with @configdir_POST@ and @logdir_POST@
  so paths are absolute at install time.
- Add configure_file() in CMakeLists.txt for the otel plugin config (matching
  the existing pattern used by otel-signal-viewer).
- Remove resolve_relative_path() from both plugins since all stock config
  paths are now absolute after CMake processing.

User-edited configs must use absolute paths going forward, otherwise
relative paths will be resolved relative to the plugin's runtime path.

* Address packaging review comments.

- Restore BUILD_ARCH ARG in Dockerfile for correct arch in cross-build CI.
- Deduplicate NETDATA_CMAKE_OPTIONS in makeself static build script.
- Add Obsoletes for journal-viewer in RPM otel-signal-viewer package.
- Add Replaces/Conflicts for journal-viewer in DEB otel-signal-viewer package.

* Finish restoring BUILD_ARCH for Docker images.

* Fix up dependencies for native packages properly.

In reality we actually need to use a transitional package to migrate
users back to the journal viewer instead of obsoleting the old package.

* Make the signal viewer plugin a mandatory dependency of the OTel plugin.

* Address Cubic review comments.

* Fix DEB package dependencies.

* Update src/collectors/systemd-journal.plugin/passive_journal_centralization_guide_no_encryption.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Revert "Remove RUSTFLAGS from static builds."

This reverts commit 3ff5ae3.

The per-target corrosion_add_target_rustflags() for journal_reader_ffi
does not work for static builds on Alpine/musl because Corrosion
determines native-static-libs during CMake configure time, before
target-specific rustflags are applied. Without crt-static during that
extraction, Rust reports -lgcc_s as a required native library, but
Alpine doesn't ship libgcc_s.a (only libgcc_s.so). The -static linker
flag then fails to find it.

The global RUSTFLAGS export in 70-netdata-git.install.sh is set before
CMake runs, so Corrosion's configure-time execute_process inherits it
from the environment and correctly reports -lgcc_eh (which exists as a
static archive) instead of -lgcc_s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix static build permissions for otel plugins.

The static build post-installer was missing otel-plugin and
otel-signal-viewer-plugin from the ownership/permissions setup,
causing the netdata user to get "Permission denied" when trying
to execute them. The DEB packages handled this correctly via
their postinst scripts, but the static build equivalent in
install-or-update.sh was never updated when these plugins were
added.

* Fix missing chmod 4750 fallback for otel-signal-viewer-plugin when setcap is unavailable.

The else branch (no setcap) was missing the fallback chmod for
otel-signal-viewer-plugin, so it would lack needed privileges on
systems without setcap.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Austin S. Hemmelgarn <austin@netdata.cloud>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Ancairon pushed a commit to Ancairon/netdata that referenced this pull request Feb 12, 2026
* Revert "Refactor function progress: move timeout and progress authority to the plugin runtime and agent (netdata#21723)"

This reverts commit 09cbde1.

* Revert "Improve log message when deferred response is too big. (netdata#21720)"

This reverts commit 453bc9d.

* Revert "Use info-level log for undhandled modification events. (netdata#21719)"

This reverts commit 986a187.

* Revert "Handle fields with high-cardinality and big payloads. (netdata#21716)"

This reverts commit 80a5a9f.

* Revert "Set status flag of active journal file to archived on shutdown. (netdata#21707)"

This reverts commit c2cd26f.

* Revert "Make new journal viewer plugin a mandatory dependency for native packages to ensure clean upgrades. (netdata#21701)"

This reverts commit 3ee561b.

* Revert "Document logs functionality of otel plugin (netdata#21705)"

This reverts commit 83ac4e5.

* Revert "Update README links to correct otel-plugin paths (netdata#21699)"

This reverts commit 088c20a.

* Revert "Add object size and bounds validation when reading journal files. (netdata#21697)"

This reverts commit e482ca8.

* Revert "Handle transient systemd state flag changes. (netdata#21695)"

This reverts commit 5638b80.

* Revert "Keep window manager state consistent on `mmap` failures. (netdata#21693)"

This reverts commit c56d358.

* Revert "Always capture backtrace on panic. (netdata#21681)"

This reverts commit 191de6f.

* Revert "Use debug level for logging of requests. (netdata#21625)"

This reverts commit 2e0dd48.

* Revert "Assortement of journal-viewer plugin fixes. (netdata#21612)"

This reverts commit 8f048c8.

* Revert "Fix 32-bit builds of journal-viewer plugin. (netdata#21580)"

This reverts commit d98adc0.

* Revert "Fix response when no log entries have been found. (netdata#21581)"

This reverts commit d0c06b8.

* Revert "Proper decompression of data object payloads. (netdata#21578)"

This reverts commit 7f4ce41.

* Revert "bring back systemd-journal.plugin setcap (from source install) (netdata#21569)"

This reverts commit ad6ee9c.

* Revert "Use host-prefixed log directories under containers. (netdata#21568)"

This reverts commit 1fac565.

* Revert "Allow systemd-journal plugin if journal-viewer does not exist. (netdata#21561)"

This reverts commit 2b180ba.

* Revert "Add sentry error reporting (netdata#21558)"

This reverts commit ffcec41.

* Revert "OTEL logs (netdata#21356)"

This reverts commit d0905d9.

* Add Rust cargo workspace for journal-viewer and otel plugins alongside systemd-journal.plugin

Copy the Rust crates from origin/master into src/crates/ as an independent
cargo workspace. This brings back the journal-viewer plugin, otel plugin,
and their supporting crates (journal-core, journal-engine, journal-index,
journal-registry, journal-log-writer, netdata-plugin, etc.) without
modifying the existing systemd-journal.plugin or its Rust FFI backend
under src/crates/jf/.

The outer workspace's Cargo.toml excludes the jf/ directory so the two
workspaces remain independent:
- src/crates/jf/: used exclusively by the C-based systemd-journal.plugin
- src/crates/: the new cargo workspace for journal-viewer and otel plugins

* Switch otel-plugin to build from src/crates/ workspace instead of src/crates/jf/

Split the corrosion_import_crate call so that each Rust workspace is
imported independently:
- journal_reader_ffi from src/crates/jf/ (for systemd-journal.plugin)
- otel-plugin from src/crates/ (the main cargo workspace)

Also add the otel-plugin rustflags for tracing_unstable and static builds,
and update config install paths and docs map to point to
src/crates/netdata-otel/otel-plugin/.

* Add full build and packaging support for journal-viewer-plugin

Add ENABLE_PLUGIN_JOURNAL_VIEWER as a new CMake option, independent of
the existing ENABLE_PLUGIN_SYSTEMD_JOURNAL. Both plugins coexist without
conflicts or replacements.

CMake (CMakeLists.txt):
- New ENABLE_PLUGIN_JOURNAL_VIEWER option (default: ON)
- Import journal-viewer-plugin from the main src/crates/ workspace via
  Corrosion, alongside otel-plugin
- Rustflags: --cfg=tracing_unstable, io_uring_skip_arch_check on 32-bit,
  crt-static for static builds
- Install target and config file processing for journal-viewer.yaml

Packaging:
- Debian: new netdata-plugin-journal-viewer package with postinst for
  cap_dac_read_search capability (Packaging.cmake, postinst)
- RPM: new journal-viewer subpackage with caps and file entries
  (netdata.spec.in)

Installer and build entry points:
- netdata-installer.sh: --enable/--disable-plugin-journal-viewer CLI
  flags and setcap/permissions block for the plugin binary
- packaging/installer/functions.sh: PLUGIN_JOURNAL_VIEWER CMake feature
- packaging/docker/Dockerfile: --enable-plugin-journal-viewer in build
- packaging/makeself/jobs/70-netdata-git.install.sh: enable for all
  architectures except armv6l

The plugin defaults to disabled in the installer (like otel) and is
explicitly enabled in Docker and static/makeself builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Rename journal-viewer-plugin to otel-signal-viewer-plugin

The journal-viewer name was confusing alongside systemd-journal.plugin
since both implied journal log viewing. Rename to otel-signal-viewer to
reflect the plugin's actual purpose: viewing OTel signals (logs now,
traces in the future).

Renamed across all layers:
- Rust crate: package name, binary name, directory, config file
- CMake: ENABLE_PLUGIN_OTEL_SIGNAL_VIEWER option, Corrosion targets,
  rustflags, install targets, config processing
- RPM: subpackage, file lists, exclusions
- Debian: package definition, postinst directory
- Installer: CLI flags (--enable/--disable-plugin-otel-signal-viewer),
  variable (ENABLE_OTEL_SIGNAL_VIEWER), permissions block
- Docker: installer flag, chmod loop
- Makeself: static build flags
- Rust source: function name, chart contexts, plugin runtime name,
  config filename references
- Documentation: map.yaml label, crate README

* Fix installer flag

* Update docs/.map/map.yaml

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* Remove duplicate source entry

* Guard Recommends tag against old RPM on Amazon Linux 2

* Disable otel-signal-viewer plugin on Windows.

* Bring back function cancellation on timeout and useful diagnostic.

* Reference correct plugin in README.md

* Remove RUSTFLAGS from static builds.

* Update function description.

* Update otel-signal-viewer configuration file.

* Replace runtime relative path resolution with CMake template substitution.

Both the otel and otel-signal-viewer plugins used a resolve_relative_path()
helper to turn relative config paths into absolute ones at runtime, using
Netdata environment variables as the base directory.

The otel-signal-viewer plugin already had a .yaml.in template with CMake
variables for its paths, making its resolve_relative_path() call redundant
(the paths were already absolute after CMake substitution).

Unify both plugins on the CMake approach:

- Convert otel.yaml to otel.yaml.in with @configdir_POST@ and @logdir_POST@
  so paths are absolute at install time.
- Add configure_file() in CMakeLists.txt for the otel plugin config (matching
  the existing pattern used by otel-signal-viewer).
- Remove resolve_relative_path() from both plugins since all stock config
  paths are now absolute after CMake processing.

User-edited configs must use absolute paths going forward, otherwise
relative paths will be resolved relative to the plugin's runtime path.

* Address packaging review comments.

- Restore BUILD_ARCH ARG in Dockerfile for correct arch in cross-build CI.
- Deduplicate NETDATA_CMAKE_OPTIONS in makeself static build script.
- Add Obsoletes for journal-viewer in RPM otel-signal-viewer package.
- Add Replaces/Conflicts for journal-viewer in DEB otel-signal-viewer package.

* Finish restoring BUILD_ARCH for Docker images.

* Fix up dependencies for native packages properly.

In reality we actually need to use a transitional package to migrate
users back to the journal viewer instead of obsoleting the old package.

* Make the signal viewer plugin a mandatory dependency of the OTel plugin.

* Address Cubic review comments.

* Fix DEB package dependencies.

* Update src/collectors/systemd-journal.plugin/passive_journal_centralization_guide_no_encryption.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Revert "Remove RUSTFLAGS from static builds."

This reverts commit 3ff5ae3.

The per-target corrosion_add_target_rustflags() for journal_reader_ffi
does not work for static builds on Alpine/musl because Corrosion
determines native-static-libs during CMake configure time, before
target-specific rustflags are applied. Without crt-static during that
extraction, Rust reports -lgcc_s as a required native library, but
Alpine doesn't ship libgcc_s.a (only libgcc_s.so). The -static linker
flag then fails to find it.

The global RUSTFLAGS export in 70-netdata-git.install.sh is set before
CMake runs, so Corrosion's configure-time execute_process inherits it
from the environment and correctly reports -lgcc_eh (which exists as a
static archive) instead of -lgcc_s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix static build permissions for otel plugins.

The static build post-installer was missing otel-plugin and
otel-signal-viewer-plugin from the ownership/permissions setup,
causing the netdata user to get "Permission denied" when trying
to execute them. The DEB packages handled this correctly via
their postinst scripts, but the static build equivalent in
install-or-update.sh was never updated when these plugins were
added.

* Fix missing chmod 4750 fallback for otel-signal-viewer-plugin when setcap is unavailable.

The else branch (no setcap) was missing the fallback chmod for
otel-signal-viewer-plugin, so it would lack needed privileges on
systems without setcap.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Austin S. Hemmelgarn <austin@netdata.cloud>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/build Build system (autotools and cmake). area/ci area/collectors Everything related to data collection area/daemon area/docs area/metadata Integrations metadata area/packaging Packaging and operating systems support area/plugins.d collectors/systemd-journal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants