Skip to content

Feature/add logger #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

Feature/add logger #40

wants to merge 9 commits into from

Conversation

kimkulling
Copy link
Owner

@kimkulling kimkulling commented Jul 21, 2025

Summary by CodeRabbit

  • New Features

    • Added a flexible logging system with multiple verbosity levels, domain-tagged messages, optional timestamps, and support for multiple output streams.
    • Added convenient helpers and macros for automatic file/line logging.
    • Build now integrates the new logging component.
  • Improvements

    • Enhanced string handling with append operators and element access.
    • Increased default string buffer capacity and clarified copy/buffer logic.

Copy link
Contributor

coderabbitai bot commented Jul 21, 2025

Walkthrough

Adds a new Logger subsystem (header + implementation) integrated into the build and extends TStringBase with new append/index operators and a larger initial buffer; includes helper logging macros, multi-stream support, and minor copyFrom refactor.

Changes

Cohort / File(s) Change Summary
Build integration
CMakeLists.txt
Added include/cppcore/Common/Logger.h and code/Common/Logger.cpp to the cppcore_common_src source group.
Logging subsystem
include/cppcore/Common/Logger.h, code/Common/Logger.cpp
New Logger singleton, AbstractLogStream interface, StdLogStream, verbosity and print modes, stream registration/unregistration, message formatting with optional trace/timestamps, helper free functions and convenience macros.
String core updates
include/cppcore/Common/TStringBase.h
Added operator+= (append string), operator+=(char), operator[] const; increased InitSize from 256 to 512; mCapacity adjusted; copyFrom refactored to use early returns and minor signature whitespace fix.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller
    participant Macros as Logging Macro (file/line)
    participant Logger as Logger (singleton)
    participant Streams as LogStream(s)

    Caller->>Macros: log_xxx(domain, "msg")
    Macros->>Logger: log(level, domain, msg, file, line)
    alt Logger verbosity allows
        Logger->>Logger: format(level, domain, msg, optional trace, datetime?)
        loop for each active stream
            Logger->>Streams: write(formattedMessage)
        end
        Streams-->>Caller: (side-effect: output)
    else suppressed
        Logger-->>Caller: no-op
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I’m a rabbit with a tiny pen,
I added logs and hopped again.
Streams lined up, tags held tight,
Strings grew wider overnight.
Hop—trace, warn, and debug delight! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/add_logger

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
🪧 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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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: 10

🧹 Nitpick comments (3)
code/Common/Logger.cpp (2)

256-270: Implement getDateTime functionality

The getDateTime method is stubbed out and always returns "none", making the timestamp feature non-functional.

Would you like me to implement a proper datetime formatting function using standard C++ chrono library? This would provide actual timestamps for log messages when PrintMode::WithDateTime is used.


48-55: Optimize stripFilename for cross-platform compatibility

The current implementation only handles forward slashes and could be more efficient.

Consider using std::filesystem for better cross-platform support:

-static ::std::string stripFilename(const ::std::string &filename) {
-    if (filename.empty()) {
-        return filename;
-    }
-
-    ::std::string::size_type pos = filename.find_last_of("/");
-    if (pos == ::std::string::npos) {
-        return filename;
-    }
-    const ::std::string strippedName = filename.substr(pos + 1, filename.size() - pos - 1);
-
-    return strippedName;
-}
+static ::std::string stripFilename(const ::std::string &filename) {
+    if (filename.empty()) {
+        return filename;
+    }
+    // Handle both forward and backward slashes
+    ::std::string::size_type pos = filename.find_last_of("/\\");
+    if (pos == ::std::string::npos) {
+        return filename;
+    }
+    return filename.substr(pos + 1);
+}
include/cppcore/Common/Logger.h (1)

207-252: Fix documentation inconsistencies

The documentation for the logging macros references osre_trace, osre_debug, etc., but the actual macro names are log_trace, log_debug, etc.

Update the documentation to match the actual macro names:

-///	@fn		osre_trace
+///	@fn		log_trace

And fix the typo "writhe" → "write" in lines 234, 242, and 250.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4d2c0c and 0b0c425.

📒 Files selected for processing (4)
  • CMakeLists.txt (1 hunks)
  • code/Common/Logger.cpp (1 hunks)
  • include/cppcore/Common/Logger.h (1 hunks)
  • include/cppcore/Common/TStringBase.h (3 hunks)
🔇 Additional comments (2)
CMakeLists.txt (1)

78-79: Build configuration looks good!

The Logger header and source files are correctly added to the cppcore_common_src group, maintaining consistency with the project structure.

include/cppcore/Common/Logger.h (1)

143-143: Update default parameter after fixing enum typo

After fixing the WhithoutDateTime typo, update this line as well.

Comment on lines 162 to 182
inline void TStringBase<T>::copyFrom(TStringBase<T> &base, const T *ptr, size_t size) {
if (ptr != nullptr) {
T *targetPtr = base.mBuffer;
if (size > 0) {
if (size > base.mCapacity) {
if (base.mStringBuffer != nullptr) {
delete [] base.mStringBuffer;
}
base.mStringBuffer = new T[size];
base.mCapacity = size;
targetPtr = base.mStringBuffer;
}
memcpy(targetPtr, ptr, size * sizeof(T));
base.mSize = size;
if (ptr == nullptr) {
return;
}

T *targetPtr = base.mBuffer;
if (size == 0) {
return;
}

if (size > base.mCapacity) {
if (base.mStringBuffer != nullptr) {
delete [] base.mStringBuffer;
}
base.mStringBuffer = new T[size];
base.mCapacity = size;
targetPtr = base.mStringBuffer;
}
memcpy(targetPtr, ptr, size * sizeof(T));
base.mSize = size;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

copyFrom doesn't ensure null termination

The copyFrom method uses memcpy but doesn't ensure null termination for C-style strings, which could lead to issues when using c_str().

Add null termination after copying:

     memcpy(targetPtr, ptr, size * sizeof(T));
     base.mSize = size;
+    // Ensure null termination
+    if (base.mStringBuffer != nullptr) {
+        base.mStringBuffer[size] = '\0';
+    } else if (size < InitSize) {
+        base.mBuffer[size] = '\0';
+    }

Also, when allocating mStringBuffer, allocate size + 1 to accommodate the null terminator:

-        base.mStringBuffer = new T[size];
+        base.mStringBuffer = new T[size + 1];
-        base.mCapacity = size;
+        base.mCapacity = size + 1;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
inline void TStringBase<T>::copyFrom(TStringBase<T> &base, const T *ptr, size_t size) {
if (ptr != nullptr) {
T *targetPtr = base.mBuffer;
if (size > 0) {
if (size > base.mCapacity) {
if (base.mStringBuffer != nullptr) {
delete [] base.mStringBuffer;
}
base.mStringBuffer = new T[size];
base.mCapacity = size;
targetPtr = base.mStringBuffer;
}
memcpy(targetPtr, ptr, size * sizeof(T));
base.mSize = size;
if (ptr == nullptr) {
return;
}
T *targetPtr = base.mBuffer;
if (size == 0) {
return;
}
if (size > base.mCapacity) {
if (base.mStringBuffer != nullptr) {
delete [] base.mStringBuffer;
}
base.mStringBuffer = new T[size];
base.mCapacity = size;
targetPtr = base.mStringBuffer;
}
memcpy(targetPtr, ptr, size * sizeof(T));
base.mSize = size;
}
inline void TStringBase<T>::copyFrom(TStringBase<T> &base, const T *ptr, size_t size) {
if (ptr == nullptr) {
return;
}
T *targetPtr = base.mBuffer;
if (size == 0) {
return;
}
if (size > base.mCapacity) {
if (base.mStringBuffer != nullptr) {
delete [] base.mStringBuffer;
}
// Allocate an extra slot for the null terminator
base.mStringBuffer = new T[size + 1];
base.mCapacity = size + 1;
targetPtr = base.mStringBuffer;
}
memcpy(targetPtr, ptr, size * sizeof(T));
base.mSize = size;
// Ensure null termination
if (base.mStringBuffer != nullptr) {
base.mStringBuffer[size] = '\0';
} else if (size < InitSize) {
base.mBuffer[size] = '\0';
}
}
🤖 Prompt for AI Agents
In include/cppcore/Common/TStringBase.h lines 162 to 182, the copyFrom method
copies data using memcpy but does not ensure null termination for C-style
strings, which can cause issues with c_str(). Fix this by allocating
mStringBuffer with size + 1 when resizing, and after copying, explicitly set the
character at index size to the null terminator to guarantee proper string
termination.

Comment on lines +203 to +212
template <class T>
inline TStringBase<T> &TStringBase<T>::operator += (const TStringBase<T> &rhs) {
if (rhs.isEmpty()) {
return *this;
}

copyFrom(*this, rhs.c_str(), rhs.size());

return *this;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

operator+= replaces content instead of appending

The operator+= implementation uses copyFrom which replaces the entire string content rather than appending to it. This is incorrect behavior for a concatenation operator.

The operator should append the content, not replace it. Consider implementing proper string concatenation logic that:

  1. Calculates the new total size
  2. Reallocates if necessary
  3. Copies the existing content and appends the new content
  4. Updates the size accordingly
🤖 Prompt for AI Agents
In include/cppcore/Common/TStringBase.h around lines 203 to 212, the operator+=
incorrectly replaces the string content instead of appending. To fix this,
modify the operator to calculate the new total size by adding the current size
and rhs size, reallocate the internal buffer if needed to accommodate the new
size, copy the existing content followed by the rhs content into the buffer, and
update the size member to reflect the concatenated string length before
returning *this.

Comment on lines +220 to +223
template <class T>
inline T TStringBase<T>::operator[](size_t index) const {
return mBuffer[index];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add bounds checking to operator[]

The index operator doesn't validate the index against the string size, which could lead to out-of-bounds access.

Add bounds checking:

 template <class T>
 inline T TStringBase<T>::operator[](size_t index) const {
+    if (index >= mSize) {
+        // Handle error - throw exception or return default value
+        throw std::out_of_range("Index out of bounds");
+    }
-    return mBuffer[index];
+    return c_str()[index];
}

Also note that the current implementation always returns from mBuffer, but it should use c_str() to handle cases where mStringBuffer is in use.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
template <class T>
inline T TStringBase<T>::operator[](size_t index) const {
return mBuffer[index];
}
template <class T>
inline T TStringBase<T>::operator[](size_t index) const {
if (index >= mSize) {
// Handle error - throw exception or return default value
throw std::out_of_range("Index out of bounds");
}
return c_str()[index];
}
🤖 Prompt for AI Agents
In include/cppcore/Common/TStringBase.h around lines 220 to 223, the operator[]
lacks bounds checking and always accesses mBuffer directly, which risks
out-of-bounds errors and ignores cases where mStringBuffer is used. Modify
operator[] to first check if the index is within the valid range of the string
size, throwing an exception or handling the error if not. Then, access the
character via c_str() instead of mBuffer to correctly handle both buffer storage
scenarios.

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: 1

♻️ Duplicate comments (2)
code/Common/Logger.cpp (2)

156-160: Refactor fragile indentation logic.

The hardcoded character positions (6, 7) for detecting indentation markers remain fragile and should be refactored as previously suggested.


184-188: Refactor fragile indentation logic.

The hardcoded character positions (6, 7) for detecting indentation markers remain fragile and should be refactored as previously suggested.

🧹 Nitpick comments (4)
code/Common/Logger.cpp (4)

83-106: Consider thread safety for the singleton pattern.

The singleton implementation is correct for single-threaded use. For multi-threaded environments, consider using std::once_flag or similar mechanisms to ensure thread-safe initialization.


138-148: Simplify the verbosity condition.

The condition for info() can be simplified since it covers most verbosity modes except potentially a hypothetical "Silent" mode.

Consider simplifying to:

-if (getVerboseMode() == VerboseMode::Normal || getVerboseMode() == VerboseMode::Verbose || getVerboseMode() == VerboseMode::Debug || getVerboseMode() == VerboseMode::Trace) {
+if (getVerboseMode() != VerboseMode::Silent) { // assuming Silent mode exists

Or use a numeric comparison if verbosity levels are ordered.


231-236: Consider ownership semantics for log streams.

The unregisterLogStream method deletes the stream, which assumes the Logger owns all registered streams. This could cause issues if streams are shared or managed externally. Consider documenting this ownership model or providing separate methods for owned vs. unowned streams.


272-312: Consider refactoring to reduce code duplication.

All helper print functions follow the same pattern. Consider extracting the common logic into a template or helper function to reduce duplication.

Example approach:

template<typename LogMethod>
void printHelper(LogMethod method, const String &domain, const String &file, int line, const String &msg) {
    String message = msg;
    addTraceInfo(file, line, message);
    (Logger::getInstance()->*method)(domain, message);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b0c425 and 123a525.

📒 Files selected for processing (3)
  • code/Common/Logger.cpp (1 hunks)
  • include/cppcore/Common/Logger.h (1 hunks)
  • include/cppcore/Common/TStringBase.h (3 hunks)
🪛 GitHub Actions: CMake
code/Common/Logger.cpp

[warning] 253-253: Compiler warning: unused variable ‘Space’ [-Wunused-variable]

🚧 Files skipped from review as they are similar to previous changes (2)
  • include/cppcore/Common/TStringBase.h
  • include/cppcore/Common/Logger.h
🧰 Additional context used
🪛 GitHub Actions: CMake
code/Common/Logger.cpp

[warning] 253-253: Compiler warning: unused variable ‘Space’ [-Wunused-variable]

🔇 Additional comments (7)
code/Common/Logger.cpp (7)

1-30: LGTM!

The license header and includes are properly structured and appropriate for the logger implementation.


32-69: Well-implemented helper functions.

The static helper functions are correctly implemented with proper error handling:

  • appendDomain safely handles empty domains
  • stripFilename properly handles edge cases
  • addTraceInfo conditionally adds trace information based on verbosity mode

71-82: LGTM!

The AbstractLogStream methods are correctly implemented for managing stream activation state.


108-114: LGTM!

Simple and correct getter/setter implementation for verbosity mode.


239-250: LGTM!

Constructor and destructor are properly implemented, with consistent ownership semantics for managing log streams.


268-270: LGTM!

Simple and correct implementation of standard output stream.


314-315: LGTM!

Proper namespace closing.

Copy link

sonarqubecloud bot commented Aug 22, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
E Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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: 1

♻️ Duplicate comments (1)
code/Common/Logger.cpp (1)

180-184: Refactor fragile marker detection; also fix off-by-one

Hardcoded indices (6,7) assume all prefixes are exactly six characters and break easily if formats change. Prior feedback already flagged this. Please centralize the prefix length and compare substrings.

-    if (msg.size() > 8) {
-        if (msg[6] == '=' && msg[7] == '>') {
-            mIntention += 2;
-        }
-    }
+    // Example: make detection resilient
+    static constexpr size_t kSeverityPrefixLen = 6;
+    if (msg.size() >= kSeverityPrefixLen + 2) {
+        const char* s = msg.c_str() + kSeverityPrefixLen;
+        if (s[0] == '=' && s[1] == '>') {
+            mIntention += 2;
+        }
+    }

Optionally, consider detecting markers at the start of the message portion via a small helper that doesn’t rely on magic numbers. This would also let you freely normalize prefixes (e.g., include a space after “Fatal:”/“Trace:”).

🧹 Nitpick comments (7)
code/Common/Logger.cpp (7)

41-53: Handle Windows paths in stripFilename (support both '/' and '')

Current implementation only looks for '/', so Windows-style paths won't be stripped. Also, the final substr can be simplified.

- static ::std::string stripFilename(const ::std::string &filename) {
+ static ::std::string stripFilename(const ::std::string &filename) {
     if (filename.empty()) {
         return filename;
     }
 
-    ::std::string::size_type pos = filename.find_last_of("/");
+    ::std::string::size_type pos = filename.find_last_of("/\\");
     if (pos == ::std::string::npos) {
         return filename;
     }
-    const ::std::string strippedName = filename.substr(pos + 1, filename.size() - pos - 1);
-
-    return strippedName;
+    return filename.substr(pos + 1);
 }

172-178: Respect stream activation and remove trailing space before newline

  • Only write to active streams.
  • " \n" appends a trailing blank before newline; it’s unnecessary.
-    logMsg += String(" \n", 2);
+    logMsg += String("\n", 1);
     for (size_t i = 0; i < mLogStreams.size(); ++i) {
         AbstractLogStream *stream = mLogStreams[i];
-        if (stream != nullptr) {
+        if (stream != nullptr && stream->isActive()) {
             stream->write(logMsg);
         }
     }

222-233: Avoid iterator invalidation/logic pitfalls in unregister; clarify ownership

  • After remove(i) the array shrinks; continuing the loop is unnecessary and error-prone if duplicates aren’t expected.
  • API appears to transfer ownership to Logger (it deletes streams on unregister and in destructor). Please document this in the header to prevent double-deletes by callers.
     for (size_t i = 0; i < mLogStreams.size(); ++i) {
         if (mLogStreams[i] == logStream) {
             delete mLogStreams[i];
             mLogStreams.remove(i);
+            break;
         }
     }

Would you confirm that ownership is intended to be transferred to Logger on register? If not, we should remove the delete here and only remove the pointer.


245-259: Implement getDateTime using std::chrono instead of returning "none"

Returning a placeholder breaks the WithDateTime mode. A small, portable implementation avoids the commented custom DateTime dependency.

 String Logger::getDateTime() {
-    //static const uint32_t Space = 2;
-    /* DateTime currentDateTime = DateTime::getCurrentUTCTime();
-    std::stringstream stream;
-    stream.fill('0');
-    stream << std::setw(Space) << currentDateTime.getCurrentDay() << "."
-           << std::setw(Space) << currentDateTime.getCurrentMonth() << "."
-           << std::setw(Space * 2) << currentDateTime.getCurrentYear() << " "
-           << std::setw(Space) << currentDateTime.getCurrentHour() << ":"
-           << std::setw(Space) << currentDateTime.getCurrentMinute() << ":"
-           << std::setw(Space) << currentDateTime.getCurrentSeconds();
-           */
-    String todo("none", 4);
-    return todo;
+    using clock = std::chrono::system_clock;
+    std::time_t t = clock::to_time_t(clock::now());
+    std::tm tm{};
+#if defined(_WIN32)
+    gmtime_s(&tm, &t);
+#else
+    gmtime_r(&t, &tm);
+#endif
+    std::ostringstream stream;
+    stream.fill('0');
+    stream << std::setw(2) << tm.tm_mday << "."
+           << std::setw(2) << (tm.tm_mon + 1) << "."
+           << std::setw(4) << (tm.tm_year + 1900) << " "
+           << std::setw(2) << tm.tm_hour << ":"
+           << std::setw(2) << tm.tm_min << ":"
+           << std::setw(2) << tm.tm_sec;
+    const std::string s = stream.str();
+    return String(s.c_str(), s.size());
 }

Additional includes required at top of file:

#include <chrono>
#include <ctime>

114-123: Reduce duplication in severity handlers (trace/debug/info) and normalize prefixes

The three methods share the same pattern. Consider extracting a small helper that builds the “prefix + message + domain” and calls print(), which will also make it easier to standardize spacing after the colon across all severities.

Example idea:

  • String makeLog(const char* prefix, const String& msg, const String& domain);
  • Then trace/debug/info call that helper with "Trace:", "Dbg: ", "Info: " etc.

This will also simplify future changes to the indentation marker detection.

Also applies to: 125-134, 136-147


149-171: Consider thread-safety for multi-threaded logging

print() reads/writes shared state (mIntention, mLogStreams). If Logger is used from multiple threads, races are possible. A single mutex protecting indentation updates and stream iteration would be sufficient.

If thread-safety is a requirement, I can propose a minimal locking strategy (lock in print/register/unregister) that does not leak into the public API.


91-98: Minor: avoid unnecessary static_cast in getInstance()

create()’s return value can simply be ignored; the cast adds noise.

-    if (nullptr == sLogger) {
-        static_cast<void>(create());
-    }
+    if (nullptr == sLogger) {
+        create();
+    }
📜 Review details

Configuration used: CodeRabbit UI

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 5e6c1d8 and 85a8c28.

📒 Files selected for processing (2)
  • code/Common/Logger.cpp (1 hunks)
  • include/cppcore/Common/Logger.h (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • include/cppcore/Common/Logger.h
🧰 Additional context used
🧬 Code graph analysis (1)
code/Common/Logger.cpp (1)
include/cppcore/Common/Logger.h (3)
  • mVerboseMode (192-194)
  • getVerboseMode (123-186)
  • mIntention (193-193)
🔇 Additional comments (1)
code/Common/Logger.cpp (1)

69-79: LGTM on stream activation methods

activate/deactivate/isActive are straightforward and correct.

Comment on lines +154 to +156
if (msg.size() > 8 && msg[6] == '<' && msg[7] == '=') {
mIntention -= 2;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix underflow and boundary bugs in indentation handling

  • mIntention is uint32_t and can underflow on “<=” messages, leading to massive indentation and potential performance issues.
  • Condition should be size >= 8 to safely access [6] and [7]; size > 8 misses minimal markers like exactly "=>"/"<=".
-    if (msg.size() > 8 && msg[6] == '<' && msg[7] == '=') {
-        mIntention -= 2;
-    }
+    if (msg.size() >= 8 && msg[6] == '<' && msg[7] == '=') {
+        if (mIntention >= 2) {
+            mIntention -= 2;
+        } else {
+            mIntention = 0;
+        }
+    }
 
     String logMsg;
     if (0 != mIntention) {
         for (uint32_t i = 0; i < mIntention; i++) {
             logMsg += ' ';
         }
     }

Also applies to: 160-163

🤖 Prompt for AI Agents
In code/Common/Logger.cpp around lines 154-156 (and similarly 160-163), the
indentation adjustment reads characters at indices 6 and 7 but uses msg.size() >
8 which incorrectly excludes messages of length 8 and risks out-of-bounds
access; also mIntention is uint32_t and decrementing by 2 can underflow. Change
the size check to msg.size() >= 8 to ensure indices 6 and 7 exist, and guard the
decrement by testing that mIntention >= 2 (or use saturated subtraction) before
subtracting 2 to prevent underflow; apply the same fixes to the other block at
160-163.

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.

2 participants