Skip to content

Add the logging system#36

Merged
JoltedJon merged 1 commit into
Redot-Engine:masterfrom
Shakai-Dev:logging-pr
Jul 6, 2026
Merged

Add the logging system#36
JoltedJon merged 1 commit into
Redot-Engine:masterfrom
Shakai-Dev:logging-pr

Conversation

@Shakai-Dev

@Shakai-Dev Shakai-Dev commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added an asynchronous logging system with configurable verbosity, sink management, and runtime metrics.
    • Introduced built-in output options for console, file, and rolling file logs.
    • Exposed logging through the main core module for easier access.
  • Documentation

    • Added guidance for using the logging sinks and rolling file naming behavior.
  • Build/Integration

    • Updated project wiring to include the new logging component and corrected third-party path casing in submodule references.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a new core.logging C++20 module providing asynchronous, lock-free ring-buffer logging with ConsoleSink, FileSink, and RollingFileSink, lifecycle/control APIs, templated log/fatal entry points, CMake wiring, a doctest suite, sink documentation, plus an unrelated submodule path casing fix and a comment tweak.

Changes

core.logging Runtime Logging Feature

Layer / File(s) Summary
Module interface, build wiring, and re-export
Engine/cpp/Runtime/Core/Logging/Logging.cppm, Engine/cpp/Runtime/Core/CMakeLists.txt, Engine/cpp/Runtime/CMakeLists.txt, Engine/cpp/Runtime/Core/Core.cppm
Declares core.logging module types (LogVerbosity, LogCategory, LogMessage, ILogSink and concrete sinks, LoggerMetrics), lifecycle/control functions, and templated log/fatal; registers the Logging target, links it into Core, and re-exports it via core.cppm.
Ring-buffer state and enqueue/dequeue
Engine/cpp/Runtime/Core/Logging/Logging.cpp
Defines module-level ring buffer state, sink-list holder, thread/uptime helpers, and implements sequence-numbered enqueue/dequeue plus the worker dispatch loop.
Lifecycle, control APIs, and fatal path
Engine/cpp/Runtime/Core/Logging/Logging.cpp
Implements init/shutdown, flush(timeout), verbosity/sink management, enqueue_log gating, and execute_fatal with bounded sink flush plus abort.
Console, file, and rolling sinks
Engine/cpp/Runtime/Core/Logging/Logging.cpp
Implements ConsoleSink, FileSink (append-mode, directory creation), and RollingFileSink (size-triggered rolling with timestamp+sequence filenames).
Behavioral tests and sink documentation
Engine/cpp/Runtime/Core/Logging/Logging.test.cpp, Docs/LoggingSinks.md
Adds doctest coverage for lifecycle, async dispatch, flush, sequencing, verbosity filtering, multi-sink handling, overflow, fatal path, file output, formatting, category overrides, and metrics; documents sink architecture.

Estimated code review effort: 4 (Complex) | ~60 minutes

Unrelated Cleanup

Layer / File(s) Summary
Submodule path casing and comment fix
.gitmodules, Engine/cpp/Runtime/Core/IO/ImageLoader.cpp
Updates bx/bimg/bgfx submodule paths to Engine/cpp/ThirdParty/... casing and rewords a TODO comment with no logic changes.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant LogAPI as log()/fatal()
  participant Internal as internal::enqueue_log/execute_fatal
  participant Queue as ring buffer + worker
  participant Sink as ILogSink (Console/File/Rolling)

  Caller->>LogAPI: log(verbosity, category, fmt, args...)
  LogAPI->>Internal: format text, call enqueue_log
  Internal->>Queue: publish LogMessage or drop on overflow
  Queue->>Sink: worker dequeues and writes message
  Caller->>LogAPI: fatal(category, fmt, args...)
  LogAPI->>Internal: execute_fatal(category, text)
  Internal->>Sink: write + flush within deadline
  Internal->>Internal: invoke fatal_hook and abort
Loading

Suggested reviewers: OldDev78, mcdubhghlas

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing the new logging subsystem.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
Engine/cpp/runtime/core/logging/logging.test.cpp (1)

247-265: ⚡ Quick win

Make fatal_hook restoration exception-safe.

This test mutates global process state and restores it manually; if control exits unexpectedly before Line 264, later tests inherit the wrong hook.

Suggested fix
-    draco::core::logging::internal::fatal_hook = [] { throw FatalTestException{}; };
+    auto previous_fatal_hook = draco::core::logging::internal::fatal_hook;
+    struct FatalHookRestore final
+    {
+        void (**slot)();
+        void (*old_value)();
+        ~FatalHookRestore() { *slot = old_value; }
+    } fatal_hook_restore{&draco::core::logging::internal::fatal_hook, previous_fatal_hook};
+
+    draco::core::logging::internal::fatal_hook = [] { throw FatalTestException{}; };
@@
-    draco::core::logging::internal::fatal_hook = [] { std::abort(); };
     shutdown();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Engine/cpp/runtime/core/logging/logging.test.cpp` around lines 247 - 265, The
fatal_hook is manually restored after the test logic, but if an exception is
thrown before reaching the restoration line at the end, the global state remains
corrupted for subsequent tests. Wrap the fatal_hook assignment at the beginning
of the test in a RAII pattern or scope guard that guarantees the hook is
restored to its original state (std::abort) even if exceptions occur during the
LOG_FATAL call or any other operation within the test scope. Ensure the
restoration happens automatically when exiting the test scope, rather than
relying on manual restoration at a specific line.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Engine/cpp/runtime/core/logging/logging.cpp`:
- Around line 444-451: The timestamp format at line 444 uses second-level
precision which causes filename collisions when multiple log rolls occur within
the same second, causing the std::ios::trunc flag at line 451 to overwrite
previously rotated logs. Add higher precision to the timestamp (such as
milliseconds or microseconds) or implement a counter-based collision avoidance
mechanism in the new_path construction at line 450 to ensure each rolled log
file gets a unique filename even when rolls happen within the same second.
- Around line 195-219: The init() function creates a new worker thread and
assigns it to g_worker_thread without checking if a thread is already running.
To prevent std::terminate errors from repeated init() calls, add a guard before
the thread creation line that checks if g_worker_thread is joinable; if it is,
return early from the init() function to prevent reassigning an active thread.
The check should happen before g_worker_thread is assigned the new
std::thread(worker_loop).
- Around line 162-169: The worker thread loop (where sink->write(msg) is called
around line 166-169), the flush() function (lines 258-260), and the fatal()
function (lines 368-369) all invoke sink I/O operations without synchronization,
creating a data race when using std::ofstream-backed sinks. Add a new mutex
(separate from the existing g_sink_update_mutex which only protects sink list
modifications) to serialize all sink I/O operations. Lock this mutex around the
sink->write() call in the worker thread dequeue loop, around the flush
operations in the flush() function, and around the sink operations in the
fatal() function to ensure thread-safe access to the sink objects across all
three call sites.

In `@Engine/cpp/runtime/core/logging/logging.test.cpp`:
- Around line 288-306: The test has two issues: the ifstream object infile
opened at the file validation section is never closed before attempting to
remove the file at the end of the test, which causes cross-platform failures on
Windows where open files cannot be deleted; additionally, the hardcoded
test_output.log path can cause collisions when tests run in parallel. Fix this
by ensuring the infile stream is closed before file removal (either by wrapping
the file reading operations in a separate scope or explicitly calling
infile.close()) and by replacing the hardcoded test_path string with a unique
temporary file path using std::filesystem mechanisms to generate a unique name
per test run.

In `@Engine/cpp/runtime/core/logging/macros.h`:
- Around line 3-12: The SET_CATEGORY_VERBOSITY macro uses
std::memory_order_relaxed which is declared in the <atomic> header, but the
header file does not include it. Add `#include` <atomic> at the top of the file
near the existing `#include` <format> to ensure the header is self-sufficient and
all dependencies are properly declared, preventing potential compilation issues
for callers that may not have included <atomic> before using these macros.

---

Nitpick comments:
In `@Engine/cpp/runtime/core/logging/logging.test.cpp`:
- Around line 247-265: The fatal_hook is manually restored after the test logic,
but if an exception is thrown before reaching the restoration line at the end,
the global state remains corrupted for subsequent tests. Wrap the fatal_hook
assignment at the beginning of the test in a RAII pattern or scope guard that
guarantees the hook is restored to its original state (std::abort) even if
exceptions occur during the LOG_FATAL call or any other operation within the
test scope. Ensure the restoration happens automatically when exiting the test
scope, rather than relying on manual restoration at a specific line.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2530ce9c-7b86-4ae8-8d00-4f2021e58a00

📥 Commits

Reviewing files that changed from the base of the PR and between 4b1ebc5 and 7f2885b.

📒 Files selected for processing (8)
  • Engine/cpp/runtime/CMakeLists.txt
  • Engine/cpp/runtime/core/CMakeLists.txt
  • Engine/cpp/runtime/core/core.cppm
  • Engine/cpp/runtime/core/io/image_loader.cpp
  • Engine/cpp/runtime/core/logging/logging.cpp
  • Engine/cpp/runtime/core/logging/logging.cppm
  • Engine/cpp/runtime/core/logging/logging.test.cpp
  • Engine/cpp/runtime/core/logging/macros.h

Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp
Comment thread Engine/cpp/runtime/core/logging/logging.cpp Outdated
Comment thread Engine/cpp/runtime/core/logging/logging.test.cpp
Comment thread Engine/cpp/runtime/core/logging/macros.h Outdated

@JoltedJon JoltedJon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@OldDev78 Please check out my comments on my review

Comment thread Engine/cpp/runtime/core/logging/macros.h Outdated
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/runtime/core/logging/logging.cppm Outdated
Comment thread Engine/cpp/runtime/core/logging/logging.cppm Outdated
Comment thread Engine/cpp/Runtime/Core/IO/ImageLoader.cpp
Comment thread Engine/cpp/runtime/core/logging/logging.test.cpp Outdated

@OldDev78 OldDev78 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Too much dependencies on headers and macros leaked through the .cppm. Most headers are for sure moveable to the .cpp, as is more of the implementation. Use pimpl if needed for hiding STL dependencies.
Use variadic templates instead of macros.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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)
Engine/cpp/runtime/core/logging/logging.cpp (1)

198-226: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Concurrent init() calls can trigger std::terminate.

The joinable() guard at line 200 is not thread-safe. If two threads call init() simultaneously, both may pass the guard before either assigns to g_worker_thread. When the second thread assigns a new std::thread to g_worker_thread, the destructor of the first thread (which is joinable) is invoked, causing std::terminate.

If concurrent init() is not a supported usage pattern, document this clearly. Otherwise, protect with a mutex or use std::call_once.

🛡️ Suggested fix using std::call_once
+static std::once_flag g_init_flag;
+
+static void init_impl()
+{
+    g_start_time = std::chrono::steady_clock::now();
+    // ... rest of initialization
+    g_worker_thread = std::thread(worker_loop);
+}
+
 void init()
 {
-    if (g_worker_thread.joinable()) { 
-        return; 
-    }
-    // ... initialization code ...
-    g_worker_thread = std::thread(worker_loop);
+    std::call_once(g_init_flag, init_impl);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Engine/cpp/runtime/core/logging/logging.cpp` around lines 198 - 226, The
joinable() check in the init() function is not thread-safe and can result in
multiple threads passing the guard and attempting to initialize g_worker_thread
simultaneously, causing std::terminate when the second thread's assignment
destroys the first thread object. Replace the joinable() guard with a static
std::once_flag and wrap the entire initialization logic (from g_start_time
assignment through g_worker_thread assignment) inside a std::call_once block to
ensure thread-safe one-time initialization of the logging system regardless of
concurrent init() calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Engine/cpp/runtime/core/logging/logging.cpp`:
- Around line 362-363: In the execute_fatal function where strncpy is called to
copy text into msg.text, the length parameter should be limited to not exceed
the actual size of the source string. Replace the strncpy call to use
std::min(text.size(), MaxLogMessageLength - 1) as the length parameter instead
of just MaxLogMessageLength - 1. This ensures we never attempt to read past the
bounds of the text string, matching the fix applied to enqueue_log.
- Around line 344-345: The std::strncpy call in the logging message construction
reads from text.data() which is a std::string_view and is not guaranteed to be
null-terminated, risking out-of-bounds reads past the view's actual size.
Replace the strncpy call with memcpy, passing the explicit size from text.size()
and calculating the length to copy as the minimum of text.size() and
(MaxLogMessageLength - 1) to ensure you only copy the actual contents of the
string_view without reading past its boundaries, then explicitly set the null
terminator at the end as currently done.

In `@Engine/cpp/runtime/core/logging/logging.cppm`:
- Around line 98-103: The fatal hook declarations fatal_hook and execute_fatal
are currently exported as part of the public module API within the export
namespace, which unintentionally exposes them for runtime override and weakens
fail-fast guarantees. Move the internal namespace block containing fatal_hook
and execute_fatal declarations out of the export namespace section so they are
no longer part of the exported module surface, or alternatively gate these
declarations behind a test-only API macro to restrict their visibility to
testing code only.
- Around line 4-7: Add explicit includes for symbols that are directly used in
the logging module interface but currently missing from the header section.
Include the `<concepts>` header to support the use of `std::constructible_from`
and include the `<utility>` header to support the use of `std::forward`
throughout the module. These symbols are used in the interface definitions but
relying on transitive includes from other headers like `<format>` is
non-portable and can cause compilation failures across different toolchain
combinations.

---

Outside diff comments:
In `@Engine/cpp/runtime/core/logging/logging.cpp`:
- Around line 198-226: The joinable() check in the init() function is not
thread-safe and can result in multiple threads passing the guard and attempting
to initialize g_worker_thread simultaneously, causing std::terminate when the
second thread's assignment destroys the first thread object. Replace the
joinable() guard with a static std::once_flag and wrap the entire initialization
logic (from g_start_time assignment through g_worker_thread assignment) inside a
std::call_once block to ensure thread-safe one-time initialization of the
logging system regardless of concurrent init() calls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b101be71-74b6-41d5-9c3b-54ff8a905856

📥 Commits

Reviewing files that changed from the base of the PR and between f8bc400 and 860e2ad.

📒 Files selected for processing (4)
  • Docs/LoggingSinks.md
  • Engine/cpp/runtime/core/logging/logging.cpp
  • Engine/cpp/runtime/core/logging/logging.cppm
  • Engine/cpp/runtime/core/logging/logging.test.cpp
✅ Files skipped from review due to trivial changes (1)
  • Docs/LoggingSinks.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • Engine/cpp/runtime/core/logging/logging.test.cpp

Comment thread Engine/cpp/runtime/core/logging/logging.cpp Outdated
Comment thread Engine/cpp/runtime/core/logging/logging.cpp Outdated
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
@Shakai-Dev
Shakai-Dev force-pushed the logging-pr branch 3 times, most recently from a0c7815 to 4c6f4e1 Compare June 22, 2026 14:27
@Shakai-Dev
Shakai-Dev requested review from JoltedJon and OldDev78 June 22, 2026 14:30
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cppm
Comment thread Engine/cpp/runtime/core/logging/logging.cpp Outdated
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp
Comment thread Engine/cpp/runtime/core/logging/logging.cpp Outdated
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp
Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp

@OldDev78 OldDev78 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just address @mcdubhghlas comments, and it can be merged.
Optionally, consider adding constexpr flags exports here or in platform to allow ruling out portions of code in the implementation. We actually could use those in more places too.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Engine/cpp/runtime/core/logging/logging.cpp`:
- Around line 19-20: The logging timestamp formatting code is missing the
required standard header for time types and formatting. Update the include list
in logging.cpp so the section that uses std::tm, localtime_s/localtime_r, and
std::put_time also includes <ctime>, alongside the existing source_location and
system_error headers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7acfb87f-6aa4-4faa-a268-288e7c1b0a7c

📥 Commits

Reviewing files that changed from the base of the PR and between 860e2ad and e5bb604.

📒 Files selected for processing (4)
  • Docs/LoggingSinks.md
  • Engine/cpp/runtime/core/logging/logging.cpp
  • Engine/cpp/runtime/core/logging/logging.cppm
  • Engine/cpp/runtime/core/logging/logging.test.cpp
✅ Files skipped from review due to trivial changes (1)
  • Docs/LoggingSinks.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • Engine/cpp/runtime/core/logging/logging.cppm
  • Engine/cpp/runtime/core/logging/logging.test.cpp

Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp
JoltedJon
JoltedJon previously approved these changes Jun 30, 2026

@JoltedJon JoltedJon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Changes look good to me

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Engine/cpp/Runtime/Core/Logging/Logging.cpp`:
- Around line 568-570: The RollingFileSink destructor is defined twice, causing
a redefinition error; remove the duplicate out-of-line definition so only one
RollingFileSink::~RollingFileSink() = default; remains in Logging.cpp. Use the
RollingFileSink special member definition as the unique location to verify there
is a single destructor implementation and no other repeated defaulted definition
for the same class.

In `@Engine/cpp/Runtime/Core/Logging/Logging.test.cpp`:
- Around line 65-90: Wrap the logger lifecycle in RAII inside the logging tests
so `init()` and `shutdown()` always pair even if a `REQUIRE` aborts early;
update the affected `TEST_CASE`s in `Logging.test.cpp` to use a guard/scoped
helper around `draco::core::logging::init()` and `shutdown()` instead of
trailing calls. Also fix `Category Overrides Validation` to save and restore the
`LogRendering` and `LogPhysics` override values after the test, so later tests
do not inherit mutated state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdd9c48c-7760-4260-814c-446e7a8d1508

📥 Commits

Reviewing files that changed from the base of the PR and between e5bb604 and 2fa1443.

📒 Files selected for processing (9)
  • .gitmodules
  • Docs/LoggingSinks.md
  • Engine/cpp/Runtime/CMakeLists.txt
  • Engine/cpp/Runtime/Core/CMakeLists.txt
  • Engine/cpp/Runtime/Core/Core.cppm
  • Engine/cpp/Runtime/Core/IO/ImageLoader.cpp
  • Engine/cpp/Runtime/Core/Logging/Logging.cpp
  • Engine/cpp/Runtime/Core/Logging/Logging.cppm
  • Engine/cpp/Runtime/Core/Logging/Logging.test.cpp
✅ Files skipped from review due to trivial changes (3)
  • Engine/cpp/Runtime/Core/IO/ImageLoader.cpp
  • .gitmodules
  • Docs/LoggingSinks.md

Comment thread Engine/cpp/Runtime/Core/Logging/Logging.cpp Outdated
Comment on lines +65 to +90
TEST_CASE("Logger init and shutdown do not crash")
{
using namespace draco::core::logging;
init();
shutdown();
}

TEST_CASE("Logger dispatches messages to sinks (async)")
{
using namespace draco::core::logging;
init();

auto sink = std::make_shared<TestSink>();
add_sink(sink);

log(LogVerbosity::Info, LogTest, "Hello Logging");

wait_for_condition([&] { return sink->write_count.load() >= 1; });

REQUIRE(sink->write_count.load() == 1);
REQUIRE(sink->last.category == &LogTest);
REQUIRE(sink->last.verbosity == LogVerbosity::Info);
REQUIRE(std::string_view(sink->last.text) == "Hello Logging");

shutdown();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the test file structure first
ast-grep outline Engine/cpp/Runtime/Core/Logging/Logging.test.cpp --view expanded

# Locate init/shutdown definitions and category override usage
rg -n "void init\\(|void shutdown\\(|override_verbosity|add_sink\\(|wait_for_condition|REQUIRE\\(" Engine/cpp/Runtime/Core/Logging -S

# Show the test file with line numbers
sed -n '1,430p' Engine/cpp/Runtime/Core/Logging/Logging.test.cpp

Repository: Redot-Engine/DraconicEngine

Length of output: 15025


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect logging runtime definitions relevant to teardown and worker-thread lifecycle
rg -n "joinable\\(|shutdown\\(|init\\(|g_worker_thread|g_sinks|g_queue|override_verbosity" Engine/cpp/Runtime/Core/Logging -S

Repository: Redot-Engine/DraconicEngine

Length of output: 3902


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the logging runtime implementation around init/shutdown and category handling
sed -n '200,280p' Engine/cpp/Runtime/Core/Logging/Logging.cpp
sed -n '330,370p' Engine/cpp/Runtime/Core/Logging/Logging.cpp

# Inspect the test file includes for the missing mutex header concern
sed -n '1,30p' Engine/cpp/Runtime/Core/Logging/Logging.test.cpp

# Inspect exported module headers for any mutex declaration transitively provided
sed -n '1,160p' Engine/cpp/Runtime/Core/Logging/Logging.cppm
sed -n '1,160p' Engine/cpp/Runtime/Core/Std/StdTypes.cppm

Repository: Redot-Engine/DraconicEngine

Length of output: 9550


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the module that may provide std::mutex transitively
fd -a "StdTypes.cppm|StdTypes.*|stdtypes.*|Std.*cppm" Engine/cpp/Runtime/Core

# Search for mutex/lock_guard declarations across core runtime module interfaces
rg -n "std::mutex|lock_guard|`#include` <mutex>|import <mutex>" Engine/cpp/Runtime/Core -S

Repository: Redot-Engine/DraconicEngine

Length of output: 2025


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the StdTypes module interface and the top of the logging test for transitive includes
sed -n '1,220p' Engine/cpp/Runtime/Core/Definitions/StdTypes.cppm
sed -n '1,80p' Engine/cpp/Runtime/Core/Logging/Logging.test.cpp

Repository: Redot-Engine/DraconicEngine

Length of output: 2805


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba Engine/cpp/Runtime/Core/Definitions/StdTypes.cppm | sed -n '1,220p'

Repository: Redot-Engine/DraconicEngine

Length of output: 205


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba Engine/cpp/Runtime/Core/Logging/Logging.test.cpp | sed -n '1,90p'

Repository: Redot-Engine/DraconicEngine

Length of output: 205


Wrap logger init/shutdown in RAII for these tests.

Most TEST_CASEs call init() and shutdown() as plain trailing statements. Any REQUIRE before the final call skips teardown, leaving the worker thread and registered sinks alive; the next test’s init() then no-ops because the thread is still joinable, so one failure can cascade through the rest of the suite.

Also restore the LogRendering and LogPhysics override values in Category Overrides Validation; they stay mutated for later tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Engine/cpp/Runtime/Core/Logging/Logging.test.cpp` around lines 65 - 90, Wrap
the logger lifecycle in RAII inside the logging tests so `init()` and
`shutdown()` always pair even if a `REQUIRE` aborts early; update the affected
`TEST_CASE`s in `Logging.test.cpp` to use a guard/scoped helper around
`draco::core::logging::init()` and `shutdown()` instead of trailing calls. Also
fix `Category Overrides Validation` to save and restore the `LogRendering` and
`LogPhysics` override values after the test, so later tests do not inherit
mutated state.

@OldDev78 OldDev78 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good now.

@JoltedJon
JoltedJon merged commit b642f33 into Redot-Engine:master Jul 6, 2026
2 checks passed
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.

4 participants