Skip to content
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

[GAIAPLAT-869] Is-log-level-enabled API #757

Merged
merged 3 commits into from
Jun 30, 2021
Merged

Conversation

phillipov
Copy link
Contributor

@phillipov phillipov commented Jun 23, 2021

This PR addresses GAIAPLAT-869 which provides functions to the logging API to check whether a certain log level is enabled.

This can prevent expensive calculations that are only used for logging purposes (if that log level is not used):

if (gaia_log::app().is_debug_enabled())
{
    int num = very_slow_function();
    gaia_log::app().debug("value: {}", num);
}

@phillipov phillipov requested review from daxhaw and simone-gaia June 23, 2021 23:02
@@ -0,0 +1,92 @@
global_pattern = "[%Y-%m-%dT%T.%e] [%l] [%P %t] <%n>: %v"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I made all these log_<level>.conf files to set the system to every log level for testing. I copied them from the original gaia_log.conf. If there is a better way to initialize the system at a specific log level, let me know.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, can you add this comment in the Cmake file above?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, a better way is to use variable substitution. See https://cmake.org/cmake/help/latest/command/configure_file.html

Copy link
Contributor

@daxhaw daxhaw Jun 23, 2021

Choose a reason for hiding this comment

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

You have a couple options that I think are preferable to creating a .conf file per log level:

  1. There are six log levels. Coincidentally, we specify six loggers. I think it would be sufficient to have a single additional .conf file that sets each logger at a different log level. Then you could do your check that each logger had a particular log level. You'd still need another .conf file to test off.
  2. Check out debug_logger.hpp. This is a logger specifically exposed for testing. This gives you access to the underlying spdlogger shared pointer. So, you could create a debug log, then set the level you want to check at runtime and then do your checking. No extra .conf files required.

I prefer option 2. You can look at test_rule_stats.cpp to show the use of the debug logger.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah right, the debug_logger is quite useful here, I'd go with that too.

/**
* Returns true if the log level is "trace".
*/
bool trace()
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer the suggestion @simone-gaia had in GAIAPLAT-869. Namely these methods should follow the pattern of: is_<level>_enabled()? I.e. is_trace_enabled().

@@ -83,6 +99,14 @@ class logger_t
m_spdlogger->debug(format, args...);
}

/**
* Returns true if the log level is at or above "debug".
Copy link
Contributor

@daxhaw daxhaw Jun 23, 2021

Choose a reason for hiding this comment

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

consider: `Returns true if the log level is at "debug" or higher.

Copy link
Contributor

@daxhaw daxhaw left a comment

Choose a reason for hiding this comment

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

See comments for details: please rename the methods for checking whether the log level is enabled. I also suggested an alternative to creating a .conf file per log level.

Copy link
Contributor

@simone-gaia simone-gaia left a comment

Choose a reason for hiding this comment

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

Generally looks good, I would change the method names and use variable substitution for the config files.

Also, if you can do a quick search of .trace( and .debug( in the production/ folder, and wrap the calls that seem expensive with is_<level>_enabled(). I did a quick search myself and I did't see anything, maybe you can find something.

@@ -41,6 +41,19 @@ set_target_properties(gaia_common PROPERTIES LINK_FLAGS "${GAIA_LINK_FLAGS}")
# The logging unit test needs a logger configuration file.
configure_file("${GAIA_LOG_CONFIG}" "${PROJECT_BINARY_DIR}/gaia_log.conf")

set(LOG_LEVEL_CONFIGS_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/tests/logging_configs")
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't quite get why we need one file per log level. What you usually have is a different file for each stage of the development process (eg. dev, beta, gamma, prod). The log level is tuned based on the requirement of each stage. Usually dev is the more verbose and prod is the least verbose. In Gaia's case, I don't think we need more than dev and prod.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am gonna defer wrapping expensive log calls in production to a future JIRA ticket. That future PR will have a much larger blast radius, especially if speeding up non-logging code is going to expose race conditions (or something).

@@ -0,0 +1,92 @@
global_pattern = "[%Y-%m-%dT%T.%e] [%l] [%P %t] <%n>: %v"
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, can you add this comment in the Cmake file above?

@@ -0,0 +1,92 @@
global_pattern = "[%Y-%m-%dT%T.%e] [%l] [%P %t] <%n>: %v"
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, a better way is to use variable substitution. See https://cmake.org/cmake/help/latest/command/configure_file.html

gaia_log::shutdown();
}

TEST(logger_test, is_log_level_enabled)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I see the point of all the files above. Good job!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Those files have been removed as part of the refactoring for debug_logger_t.


TEST(logger_test, is_log_level_enabled)
{
// Trace is the deepest log level, so every log level must be active.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: maybe "deepest" to "most verbose"?

return debug_logger_ptr;
}

void verify_log_levels(gaia_spdlog::level::level_enum log_level, bool trace_status, bool debug_status, bool info_status, bool warn_status, bool error_status, bool critical_status)
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of passing all these flags, which makes (IMO) the calling test code less comprehensible, consider omitting all the bool flags and instead moving that logic into this helper function. I.e.:

// pseudo code only, but note deliberate fallthrough.
ftrace=fdebug=finfo=fwarn=ferror=fcritical=false;
switch (log_level)
case trace:
    ftrace = true;
case debug:
    fdebug=true;
case info:
    finfo=true;
case warn:
    fwarn=true;
case error:
    finfo=true;
case critical:
    fcritical=true;
   break;

Then your EXPECT_EQ as follows.

Copy link
Contributor

@simone-gaia simone-gaia left a comment

Choose a reason for hiding this comment

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

LGTM


verify_log_levels(gaia_spdlog::level::err, false, false, false, false, true, true);

// Critical is the shallowest log level, so all other log levels must be inactive.
Copy link
Contributor

Choose a reason for hiding this comment

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

Along the lines of Dax's comment, "shallowest" to "least verbose"

*/
bool is_trace_enabled()
{
return m_spdlogger->level() == gaia_spdlog::level::level_enum::trace;
Copy link
Contributor

Choose a reason for hiding this comment

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

Spdlog has a should_log API, consider using it (unless it isn't convenient for some reason).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It works perfectly, thank you for the suggestion!

Copy link
Contributor

@simone-gaia simone-gaia left a comment

Choose a reason for hiding this comment

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

Still LGMT.

Copy link
Contributor

@daxhaw daxhaw left a comment

Choose a reason for hiding this comment

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

Looks good!

@phillipov phillipov merged commit c246b54 into master Jun 30, 2021
@LaurentiuCristofor LaurentiuCristofor deleted the phillip/is_log_level branch October 15, 2021 20:13
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.

3 participants