Skip to content

Conversation

@lalinsky
Copy link
Owner

  • Create shared log.zig module with single .nats scope
  • Replace all module-specific scoped loggers with shared logger
  • Update tests to use std.log.default for test-specific logging
  • Remove redundant std.debug.print in jetstream.zig

This allows clients to easily filter or disable all NATS library logs using the single .nats scope while keeping test logs separate.

- Create shared log.zig module with single .nats scope
- Replace all module-specific scoped loggers with shared logger
- Update tests to use std.log.default for test-specific logging
- Remove redundant std.debug.print in jetstream.zig

This allows clients to easily filter or disable all NATS library logs
using the single .nats scope while keeping test logs separate.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 30, 2025

Walkthrough

Centralizes logging by adding src/log.zig and switching many modules and tests to use that logger or the default logger; removes one std.debug.print call in src/jetstream.zig. No public APIs or control flow changes.

Changes

Cohort / File(s) Change Summary
Centralized module logger
src/log.zig
Add pub const log = std.log.scoped(.nats); to expose a reusable logger.
Modules switching to central logger
src/connection.zig, src/dispatcher.zig, src/response_manager.zig, src/socket.zig, src/subscription.zig
Replace per-module std.log.scoped(.…) with const log = @import("log.zig").log;; all existing log.* calls retained.
JetStream logging tweak
src/jetstream.zig
Switch to @import("log.zig").log; remove a std.debug.print of JetStream error details; other logic unchanged.
Parser tests use central logger
src/parser.zig
Import @import("log.zig").log; and replace std.log.info test logs with log.info; parsing logic unchanged.
Tests switching to default logger
tests/... (e.g., tests/core_request_reply_test.zig, tests/headers_test.zig, tests/jetstream_*_test.zig, tests/minimal_test.zig, tests/reconnection_test.zig, tests/subscribe_test.zig, tests/utils.zig)
Replace test-scoped std.log.scoped(.…) with std.log.default; test code and assertions unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch unify-log-scope

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

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

Status, Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/dispatcher.zig (1)

260-271: Guard against ref_count underflow in releaseGlobalPool

global_pool_ref_count is u32. Calling release more times than acquire will underflow (debug builds trap; release builds wrap), leaking the pool and threads.

Apply:

 pub fn releaseGlobalPool() void {
   global_pool_mutex.lock();
   defer global_pool_mutex.unlock();

-  global_pool_ref_count -= 1;
+  if (global_pool_ref_count == 0) {
+    log.err("releaseGlobalPool called with ref_count=0; ignoring", .{});
+    return;
+  }
+  global_pool_ref_count -= 1;

   if (global_pool_ref_count == 0) {
     log.debug("Last reference released, shutting down global dispatcher pool", .{});
     if (global_pool) |pool| {
       pool.deinit();
       global_pool = null;
     }
   } else {
     log.debug("Global dispatcher pool released, ref count: {}", .{global_pool_ref_count});
   }
 }
🧹 Nitpick comments (8)
tests/jetstream_stream_test.zig (1)

6-6: Drop unused logger alias in this test file

log isn’t used here. Remove it to avoid dead code.

-const log = std.log.default;
tests/minimal_test.zig (1)

5-5: Remove unused log alias

This test doesn’t call log.*; drop the alias.

-const log = std.log.default;
src/log.zig (1)

3-3: Optional: add a short doc comment.

A brief note on why .nats exists (consumer filtering) would help future readers.

- pub const log = std.log.scoped(.nats);
+ /// Central logging scope for the NATS library.
+ /// Consumers can filter/disable all library logs via this scope.
+ pub const log = std.log.scoped(.nats);
src/socket.zig (1)

17-17: Drop unused logger import

This file doesn’t log anything. Keeping an unused top-level const is noise and risks future “unused” checks failing.

Apply:

-const log = @import("log.zig").log;
src/dispatcher.zig (2)

216-234: Cap thread pool size from env to avoid accidental fork bombs

A fat-fingered NATS_THREAD_POOL_MAX can spawn hundreds of threads. Soft-cap it and log.

Example:

 fn getThreadPoolSize(allocator: Allocator) usize {
+    const max_threads: usize = 64;
     if (std.process.getEnvVarOwned(allocator, "NATS_THREAD_POOL_MAX")) |env_value| {
       defer allocator.free(env_value);
       if (std.fmt.parseInt(usize, env_value, 10)) |size| {
         if (size > 0) {
-            log.debug("Using NATS_THREAD_POOL_MAX={}", .{size});
-            return size;
+            const capped = if (size > max_threads) blk: {
+                log.warn("NATS_THREAD_POOL_MAX={} exceeds cap {}; using cap", .{ size, max_threads });
+                break :blk max_threads;
+            } else size;
+            log.debug("Using NATS_THREAD_POOL_MAX={}", .{capped});
+            return capped;
         } else {
             log.warn("NATS_THREAD_POOL_MAX must be > 0, using default", .{});
         }
       } else |_| {
         log.warn("Invalid NATS_THREAD_POOL_MAX value '{s}', using default", .{env_value});
       }
     } else |_| {
       // Environment variable not set, use default
     }
     return 1; // Default size
 }

239-247: Consider spawning outside the global lock

Minor: starting threads while holding global_pool_mutex increases contention. You can create and assign under lock, then start outside. If you keep it as-is for simplicity, fine.

If you want to check how often acquire/release are called (to justify the change), we can add temporary counters with logs; say the word and I’ll sketch it.

src/parser.zig (1)

749-749: Downgrade chatty per-iteration logs to debug

These run inside tight loops over chunk sizes and spam CI logs at info level.

Apply:

-        log.info("chunk_size: {}", .{chunk_size});
+        log.debug("chunk_size: {}", .{chunk_size});

Also applies to: 769-769, 793-793, 811-811, 835-835

src/jetstream.zig (1)

751-757: Tone down or enrich the “adding consumer” log

info without context is noisy in apps using this lib. Either make it debug, or include stream/consumer for signal.

Option A (debug):

-        log.info("adding consumer", .{});
+        log.debug("adding consumer", .{});

Option B (keep info, add context):

-        log.info("adding consumer", .{});
+        const cname = if (config.name) |n| n else (config.durable_name orelse "ephemeral");
+        log.info("adding consumer: stream={s}, consumer={s}", .{ stream_name, cname });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8385ca2 and d855d36.

📒 Files selected for processing (20)
  • src/connection.zig (1 hunks)
  • src/dispatcher.zig (1 hunks)
  • src/jetstream.zig (1 hunks)
  • src/log.zig (1 hunks)
  • src/parser.zig (6 hunks)
  • src/response_manager.zig (1 hunks)
  • src/socket.zig (1 hunks)
  • src/subscription.zig (1 hunks)
  • tests/core_request_reply_test.zig (1 hunks)
  • tests/headers_test.zig (1 hunks)
  • tests/jetstream_duplicate_ack_test.zig (1 hunks)
  • tests/jetstream_large_list_test.zig (1 hunks)
  • tests/jetstream_nak_test.zig (1 hunks)
  • tests/jetstream_push_test.zig (1 hunks)
  • tests/jetstream_stream_test.zig (1 hunks)
  • tests/jetstream_sync_test.zig (1 hunks)
  • tests/jetstream_test.zig (1 hunks)
  • tests/minimal_test.zig (1 hunks)
  • tests/reconnection_test.zig (1 hunks)
  • tests/subscribe_test.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

Format code using zig fmt before commit

Files:

  • tests/headers_test.zig
  • tests/jetstream_stream_test.zig
  • tests/jetstream_push_test.zig
  • src/connection.zig
  • src/dispatcher.zig
  • tests/jetstream_large_list_test.zig
  • tests/reconnection_test.zig
  • tests/minimal_test.zig
  • tests/jetstream_test.zig
  • src/socket.zig
  • tests/core_request_reply_test.zig
  • src/response_manager.zig
  • src/parser.zig
  • tests/jetstream_duplicate_ack_test.zig
  • tests/subscribe_test.zig
  • src/subscription.zig
  • src/log.zig
  • tests/jetstream_nak_test.zig
  • src/jetstream.zig
  • tests/jetstream_sync_test.zig
🧠 Learnings (5)
📓 Common learnings
Learnt from: lalinsky
PR: lalinsky/nats.zig#31
File: tests/jetstream_pull_test.zig:21-23
Timestamp: 2025-08-25T14:51:33.570Z
Learning: The nats.zig project uses a "tests:beforeEach" test in tests/all_tests.zig that runs before each test to clean up all JetStream streams and consumers, ensuring test isolation. This eliminates the need for unique test resource names as each test starts with a clean JetStream state.
📚 Learning: 2025-08-29T10:22:22.247Z
Learnt from: CR
PR: lalinsky/nats.zig#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-29T10:22:22.247Z
Learning: Run `zig build test` to confirm your changes are working

Applied to files:

  • tests/headers_test.zig
  • tests/jetstream_test.zig
📚 Learning: 2025-08-25T14:51:33.570Z
Learnt from: lalinsky
PR: lalinsky/nats.zig#31
File: tests/jetstream_pull_test.zig:21-23
Timestamp: 2025-08-25T14:51:33.570Z
Learning: The nats.zig project uses a "tests:beforeEach" test in tests/all_tests.zig that runs before each test to clean up all JetStream streams and consumers, ensuring test isolation. This eliminates the need for unique test resource names as each test starts with a clean JetStream state.

Applied to files:

  • tests/jetstream_stream_test.zig
  • tests/jetstream_push_test.zig
  • tests/jetstream_large_list_test.zig
  • tests/minimal_test.zig
  • tests/jetstream_test.zig
  • tests/jetstream_duplicate_ack_test.zig
  • tests/jetstream_nak_test.zig
  • tests/jetstream_sync_test.zig
📚 Learning: 2025-08-25T02:49:59.119Z
Learnt from: lalinsky
PR: lalinsky/nats.zig#28
File: src/response_manager.zig:89-105
Timestamp: 2025-08-25T02:49:59.119Z
Learning: In this NATS Zig codebase, subscriptions are reference counted, so calling deinit() on a subscription from multiple locations (like both Connection and ResponseManager) is safe and doesn't cause double-free issues.

Applied to files:

  • tests/jetstream_push_test.zig
📚 Learning: 2025-08-30T18:48:28.310Z
Learnt from: lalinsky
PR: lalinsky/nats.zig#66
File: src/connection.zig:317-323
Timestamp: 2025-08-30T18:48:28.310Z
Learning: In src/connection.zig, the establishConnection() call in connectToServer() is during initial connection setup where no race conditions exist - the connection starts disconnected and other threads would see the connecting status and wait appropriately.

Applied to files:

  • src/response_manager.zig
🔇 Additional comments (19)
tests/subscribe_test.zig (1)

6-6: Using std.log.default in tests is the right call.

Keeps test logs separate from the library’s .nats scope as intended. LGTM.

tests/core_request_reply_test.zig (1)

5-5: Tests bound to std.log.default look good.

Aligns with the PR goal of isolating library logs under .nats while letting tests use the default logger.

tests/reconnection_test.zig (1)

5-5: Good switch to std.log.default for test logging.

Matches the unified logging approach.

tests/jetstream_test.zig (1)

6-6: Test logger moved to std.log.default — approved.

Consistent with a single .nats scope for the library.

tests/jetstream_push_test.zig (1)

6-6: Switch to std.log.default is consistent and correct.

Keeps push tests’ output independent from the library scope.

tests/jetstream_large_list_test.zig (1)

6-6: LGTM: switch to std.log.default for tests

Matches the PR goal of isolating test logs from the shared .nats scope. No functional impact.

tests/headers_test.zig (1)

5-5: LGTM: test logging moved to default logger

Keeps test output separate from .nats-scoped library logs. All usages compile against std.log.default.

tests/jetstream_nak_test.zig (1)

6-6: LGTM: use default logger for tests

Consistent with the unified .nats scope for library code and separate test logging.

tests/jetstream_sync_test.zig (1)

6-6: LGTM: tests now use std.log.default.

This cleanly separates test logs from the library’s .nats scope as intended.

src/log.zig (2)

3-3: Single .nats scope looks good.

Central export keeps callsites simple and consistent.


3-3: All log scope and debug-print checks passed: no std.log.scoped calls outside src/log.zig, no std.debug.print in src/, no scoped logs in tests, and all modules import the central logger consistently.

src/response_manager.zig (1)

25-25: LGTM: switched to central .nats logger.

Consistent with the PR goal; usage sites already call log.debug/warn here.

src/connection.zig (1)

39-39: LGTM: centralized logger import.

Matches the new logging approach; no behavior change.

src/dispatcher.zig (2)

20-20: Centralized logger import looks good

Aligned with the single .nats scope goal.


183-197: Stop/start logs are helpful; keep them at info

These are the right granularity for ops.

tests/jetstream_duplicate_ack_test.zig (1)

6-6: Switching tests to std.log.default is the right call

Keeps library logs filterable via .nats while tests remain visible.

src/parser.zig (1)

18-18: Centralized logger import for test logs: OK

No impact on parser logic; just aligns test logging.

src/jetstream.zig (2)

22-22: Adopting the shared .nats logger

Matches the PR’s objective and keeps JetStream logs under a single scope.


564-569: Good: replaced ad-hoc print with scoped logging

Error context is preserved and now filterable.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
tests/utils.zig (1)

4-4: Should this be public?

If other tests import this binding from utils, make it pub; otherwise keeping it private is fine.

-const log = std.log.default;
+pub const log = std.log.default;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d855d36 and d81721c.

📒 Files selected for processing (1)
  • tests/utils.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.zig

📄 CodeRabbit inference engine (CLAUDE.md)

Format code using zig fmt before commit

Files:

  • tests/utils.zig
🧠 Learnings (2)
📓 Common learnings
Learnt from: lalinsky
PR: lalinsky/nats.zig#67
File: src/dispatcher.zig:20-20
Timestamp: 2025-08-30T21:03:43.986Z
Learning: In the nats.zig project, test_runner.zig and files in the examples/ directory are fine to keep their std.debug.print calls - these don't need to be replaced with the centralized logging system.
📚 Learning: 2025-08-30T21:03:43.986Z
Learnt from: lalinsky
PR: lalinsky/nats.zig#67
File: src/dispatcher.zig:20-20
Timestamp: 2025-08-30T21:03:43.986Z
Learning: In the nats.zig project, test_runner.zig and files in the examples/ directory are fine to keep their std.debug.print calls - these don't need to be replaced with the centralized logging system.

Applied to files:

  • tests/utils.zig
🔇 Additional comments (1)
tests/utils.zig (1)

4-4: Tests: switch to std.log.default — good call

This keeps test logs separate from the library’s .nats scope, matching the PR goal.

@lalinsky lalinsky merged commit e814239 into main Aug 30, 2025
6 checks passed
@lalinsky lalinsky deleted the unify-log-scope branch August 30, 2025 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant