Skip to content

[Comgr] Create a Global Logger Class for Comgr#3116

Open
theSK2005 wants to merge 13 commits into
amd-stagingfrom
skushwah/comgr-logger
Open

[Comgr] Create a Global Logger Class for Comgr#3116
theSK2005 wants to merge 13 commits into
amd-stagingfrom
skushwah/comgr-logger

Conversation

@theSK2005

@theSK2005 theSK2005 commented Jun 29, 2026

Copy link
Copy Markdown

Addresses this Jira Issue https://amd-hub.atlassian.net/browse/LCOMPILER-1886

  • Creates a COMGR::Logger class with a global instance to allow all Comgr APIs to access the same set of logging utilities
  • Creates separate log streams and APIs and allows logging granularity to be toggleable
  • Replaces logging in comgr.cpp with new logging scheme
  • Allows thread-safe access to log streams with mutexes/locks

@lamb-j lamb-j requested a review from MixedMatched June 29, 2026 18:22

@MixedMatched MixedMatched left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just a few things. Overall great work!

Comment thread amd/comgr/src/comgr-logger.cpp Outdated
Comment thread amd/comgr/src/comgr-logger.cpp Outdated
Comment thread amd/comgr/src/comgr.cpp
Comment thread amd/comgr/src/comgr.cpp Outdated
Comment thread amd/comgr/src/comgr-logger.h Outdated
Comment thread amd/comgr/src/comgr.cpp Outdated
Comment thread amd/comgr/README.md Outdated
@theSK2005 theSK2005 marked this pull request as ready for review June 29, 2026 22:39
@chinmaydd

Copy link
Copy Markdown

Nit: Title should be updated with prefix [Comgr]

@theSK2005 theSK2005 changed the title Create a Global Logger Class for Comgr [Comgr] Create a Global Logger Class for Comgr Jun 29, 2026
Comment on lines +88 to +89
static const char *LogLevel = getenv("AMD_COMGR_LOG_LEVEL");
return LogLevel ? StringRef(LogLevel) : StringRef();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We probably want to be case-insensitive here ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Also, whats the rationale behind using strings over numbers to denote severity ?

I would lean more to using numbers since thats what we currently do in runtime.

Its also easier to think about IMO

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Internally Comgr can map an integer to a severity level. But externally I think we should just expose them as numbers

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

the case insensitivity is handled in comgr-logger.cpp, are you saying to move that the case lower to here?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I suppose the sensitivity discussion is irrelevant if we're exposing numbers instead

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Oh sorry, when I posted that comment, I didn't see the more recent ones. Personally, I think that these labels make it more clear for both assigning LogLevels to a particular output and for toggling the threshold for what logs a user would like to see.

@chinmaydd chinmaydd Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I disagree. There's a few reasons:

  • The precedent has already been set by various other projects in the ROCm / HIP ecosystem. See 1, 2, 3 etc. Since Comgr is a member of the ROCm ecosystem we want to play along.

  • Its intuitive to think about "big number = more logging". This way you dont have to worry about the exact number assigned to the level of logging. You can just say COMGR_LOG_LEVEL = 100 and the user gets what they want. Very likely, they are not going to be choosing between these levels. They'd want the maximum possible logging when debugging an error. In fact, I have been using AMD_LOG_LEVEL=7 for runtime and I have no clue what the individual numbers map to.

  • Tangential to point 2, you cant really establish an intuitive relationship between the various levels. How are "info" and "warning" related ? Does "error" give me more or less logging than "debug" ? Its confusing.

@theSK2005 theSK2005 Jun 30, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

That makes sense, thanks for the clarification. I'll do a 0-20 level logging and let the users have autonomy.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We dont want to do 0-100 exactly. We still want to do 0-4 or 0-5 (depending on the available levels).

However, we do want to perform numeric comparison rather than equality when checking against the parsed value.


// The capture stream is per-thread so that a captured Action on one thread does
// not collect log output emitted by an unrelated API on another thread.
thread_local raw_ostream *ThreadCaptureStream = nullptr;

@chinmaydd chinmaydd Jun 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comgr doesnt support multithreaded execution yet. Do we need thread_local ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comgr can be run in multiple threads and is thread safe, via a mutex around LLVM calls that cause issues

Comment thread amd/comgr/src/comgr-logger.cpp Outdated
Comment on lines +78 to +87
return LogLevel::None;
if (Requested.equals_insensitive("error"))
return LogLevel::Error;
if (Requested.equals_insensitive("warning"))
return LogLevel::Warning;
if (Requested.equals_insensitive("info"))
return LogLevel::Info;
if (Requested.equals_insensitive("debug"))
return LogLevel::Debug;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Commented out code should be removed

@chinmaydd chinmaydd added the comgr Related to Code Object Manager label Jun 29, 2026
@chinmaydd

chinmaydd commented Jun 30, 2026

Copy link
Copy Markdown

Nice, we are starting to get there!

Whats the reasoning behind the 0-20? We should just advertise the 4 levels (1-4) and leave everything else to numeric comparison. I'm counting the 0 here as equivalent to LOG_LEVEL_NONE. Named enums work great in this case.

We should take inspiration from other projects in the ecosystem that I've linked.

I'm not a fan of the verbose comment strategy that LLMs have. We should keep them to a minimum unless absolutely necessary.


Some other review points (LLM generated, but I think they make sense):

  • Fix the AMD_COMGR_LOG_LEVEL docs/API mismatch: README.md and amd_comgr.h.in document symbolic values, but parseLogLevel only accepts numeric 0-20 values.
  • Report redirect-open failures independently of Logger::emit(5, ...), since low or zero log levels can now suppress a diagnostic that used to reach comgr.log.
  • Add an integration test through amd_comgr_do_action for AMD_COMGR_REDIRECT_LOGS plus AMD_COMGR_LOG_LEVEL; the new tests only cover Logger in isolation.
  • Add coverage that AMD_COMGR_LOG_LEVEL takes precedence over AMD_COMGR_EMIT_VERBOSE_LOGS, especially for level 0 and invalid values.
  • Replace raw severity literals like 5 and 20 with named constants so call sites communicate intent.
  • Use unsigned or uint32_t for LogLevel instead of uint8_t to avoid char-like behavior and unnecessary narrowing.
  • Bind Logger &Log = getLogger(); once in amd_comgr_do_action instead of repeating getLogger() throughout the block.
  • Make TeeStream take a Logger & explicitly instead of reaching back to the global logger inside write_impl.
  • Avoid exposing both getSink() and writeToSink() if direct sink writes are unsafe; prefer one higher-level logging/tee API.
  • Trim the large explanatory comments in comgr-logger.h, comgr.cpp, and test-unit/CMakeLists.txt; several restate the implementation rather than clarifying it.
  • Keep the public docs and source comments aligned with the final numeric AMD_COMGR_LOG_LEVEL design, not the old symbolic severity names.
  • Consider using named test constants for common levels and severities in LoggerTest.cpp instead of repeating magic numbers.

Comment thread amd/comgr/src/comgr-logger.cpp
Comment on lines +71 to +74
// Record the failure rather than writing it to stderr here. The Logger is
// constructed before any action's log buffer exists; the action layer
// surfaces this message into the returned comgr.log via getSinkError(),
// restoring the pre-Logger behavior of reporting it to the caller.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

shorten?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

+1 need to shorten more

Comment thread amd/comgr/src/comgr-logger.cpp
Comment thread amd/comgr/src/comgr-logger.h Outdated
Comment on lines +42 to +47
/// Severity of a log message, and the logger's configured threshold, expressed
/// on a 0-to-4 scale where 0 silences logging and higher values are more
/// verbose. A message is emitted only when its severity is non-zero and does
/// not exceed the configured level (see Logger::isEnabled). Callers choose the
/// numeric severity passed to Logger::emit; larger numbers are reserved for
/// more detailed diagnostics.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

shorten?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same for the other function definitions in this file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

+1 need to shorten more. I think this is mostly okay, but could use some concise language

Comment thread amd/comgr/src/comgr.cpp Outdated
Comment thread amd/comgr/src/comgr.cpp Outdated
Comment thread amd/comgr/src/comgr.cpp Outdated
@lamb-j

lamb-j commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Can we use a named enum (None=0, Error=1, Warning=2, Info=3, Debug=4) with the Severity <= Level checks?

@lamb-j

lamb-j commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Some LLM comments:

  1. Test coverage gaps:
    - Precedence: no test that an explicit AMD_COMGR_LOG_LEVEL beats verbose — e.g. parseLogLevel("0", true) == 0, parseLogLevel("2", true) == 2.
    - No integration test driving AMD_COMGR_REDIRECT_LOGS + AMD_COMGR_LOG_LEVEL through amd_comgr_do_action; current tests exercise Logger in
    isolation only.
  2. TeeStream should take a Logger & instead of reaching back to getLogger() inside write_impl.
  3. Reconsider exposing both getSink() and writeToSink(). Raw sink access is what enabled the unsynchronized flush at :1445; a single tee/flush
    API that owns the lock removes that footgun.
  4. Bind Logger &Log = getLogger() once in amd_comgr_do_action rather than ~6 repeat calls.

@theSK2005 theSK2005 requested a review from lamb-j July 1, 2026 20:22
@theSK2005

Copy link
Copy Markdown
Author

@lamb-j @chinmaydd my last commits just addressed all of your recent comments, please check when you're able to

Comment thread amd/comgr/README.md
returned to the caller as normal. If this is set to "stdout"/"-" or "stderr",
logs are instead redirected to the standard output or error stream,
logs are additionally copied to the standard output or error stream,
respectively. If this is set to any other value, it is interpreted as a

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Should explain what the log levels denote


StringRef getLogLevel() {
static const char *LogLevel = getenv("AMD_COMGR_LOG_LEVEL");
return LogLevel ? StringRef(LogLevel) : StringRef();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LogLevel should be an enum as @lamb-j mentioned. This function should return that enum

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Check how Sam is trying to do something similar at #2478

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

just to confirm, this means to revert LogLevel away from using numbers (suggested here #3116 (comment)) and back to using the original None, Error, Warning, Debug, Info enum, correct?

Comment thread amd/comgr/src/comgr-logger.h Outdated
/// not exceed the configured level (see Logger::isEnabled). Callers choose the
/// numeric severity passed to Logger::emit; larger numbers are reserved for
/// more detailed diagnostics.
using LogLevel = uint32_t;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

enum

Comment thread amd/comgr/src/comgr.cpp
Comment on lines +1338 to +1341
// Tee Logger output emitted during this action into the in-memory buffer
// backing the AMD_COMGR_DATA_KIND_LOG data object, so emit() calls (here and
// in any Logger-aware API reached from this action) are collected for the
// caller alongside the global redirect sink.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

comments too verbose in this file. please fix

Comment thread amd/comgr/src/comgr.cpp Outdated
<< " Comgr Branch-Commit: " << xstringify(AMD_COMGR_GIT_BRANCH)
<< '-' << xstringify(AMD_COMGR_GIT_COMMIT) << '\n'
<< "\t LLVM Commit: " << clang::getLLVMRevision();
Log.emit(/*Severity=*/4, HeaderStr);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

no hardcoded numbers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comgr Related to Code Object Manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants