pw_log: Add compile-time log filtering
This adds compile-time log filtering to the facade, controlled by
macros. By default there is a simple PW_LOG_LEVEL macro that controls
logs by level; and a more involved PW_LOG_ENABLE_IF(level, flags) macro
that can do more sophisticated logic if needed.
Change-Id: I3613ffe3f7cd34c6da5cc17e592725c251bdd775
diff --git a/pw_log/basic_log_test.cc b/pw_log/basic_log_test.cc
index 0c0a92e..1b640c4 100644
--- a/pw_log/basic_log_test.cc
+++ b/pw_log/basic_log_test.cc
@@ -22,6 +22,7 @@
#define PW_LOG_MODULE_NAME "TST"
#define PW_LOG_USE_SHORT_NAMES 1
#define PW_LOG_USE_ULTRA_SHORT_NAMES 1
+#define PW_LOG_LEVEL PW_LOG_LEVEL_DEBUG
#include "pw_log/log.h"
// clang-format on
diff --git a/pw_log/basic_log_test_plain_c.c b/pw_log/basic_log_test_plain_c.c
index b88d5cd..ead81f3 100644
--- a/pw_log/basic_log_test_plain_c.c
+++ b/pw_log/basic_log_test_plain_c.c
@@ -85,11 +85,11 @@
// Log levels other than the standard ones work; what each backend does is
// implementation defined.
- PW_LOG(0, PW_LOG_NO_FLAGS, "Custom log level: 0");
- PW_LOG(1, PW_LOG_NO_FLAGS, "Custom log level: 1");
- PW_LOG(2, PW_LOG_NO_FLAGS, "Custom log level: 2");
- PW_LOG(3, PW_LOG_NO_FLAGS, "Custom log level: 3");
- PW_LOG(100, PW_LOG_NO_FLAGS, "Custom log level: 100");
+ PW_LOG(0, PW_LOG_DEFAULT_FLAGS, "Custom log level: 0");
+ PW_LOG(1, PW_LOG_DEFAULT_FLAGS, "Custom log level: 1");
+ PW_LOG(2, PW_LOG_DEFAULT_FLAGS, "Custom log level: 2");
+ PW_LOG(3, PW_LOG_DEFAULT_FLAGS, "Custom log level: 3");
+ PW_LOG(100, PW_LOG_DEFAULT_FLAGS, "Custom log level: 100");
// Logging from a function.
LoggingFromFunctionPlainC();
diff --git a/pw_log/docs.rst b/pw_log/docs.rst
index be5d74a..120333d 100644
--- a/pw_log/docs.rst
+++ b/pw_log/docs.rst
@@ -120,7 +120,7 @@
.. code-block:: cpp
- PW_LOG(PW_NO_FLAGS, PW_LOG_LEVEL_INFO, "Temperature is %d degrees", temp);
+ PW_LOG(PW_LOG_DEFAULT_FLAGS, PW_LOG_LEVEL_INFO, "Temp is %d degrees", temp);
PW_LOG(UNRELIABLE_DELIVERY, PW_LOG_LEVEL_ERROR, "It didn't work!");
.. note::
@@ -138,7 +138,69 @@
.. cpp:function:: PW_LOG_ERROR(fmt, ...)
.. cpp:function:: PW_LOG_CRITICAL(fmt, ...)
- Shorthand for `PW_LOG(PW_LOG_NO_FLAGS, <level>, fmt, ...)`.
+ Shorthand for `PW_LOG(PW_LOG_DEFAULT_FLAGS, <level>, fmt, ...)`.
+
+Filtering logs
+--------------
+
+``pw_log`` supports compile time filtering of logs through two mechanisms.
+
+1. Filter by level. Source files that define ``PW_LOG_LEVEL`` will display all
+ logs at or above the chosen level.
+
+ Example:
+
+ .. code-block:: cpp
+
+ #include "pw_log/log.h"
+
+ #define PW_LOG_LEVEL PW_LOG_LEVEL_INFO
+
+ void DoSomething() {
+ PW_LOG_DEBUG("This won't be logged at all");
+ PW_LOG_INFO("This is INFO level, and will display");
+ PW_LOG_WARN("This is above INFO level, and will display");
+ }
+
+2. Filter by arbitrary expression based on ``level`` and ``flags``. Source
+ files that define ``PW_LOG_ENABLE_IF(level, flags)`` will display if the
+ given expression returns true.
+
+ Example:
+
+ .. code-block:: cpp
+
+ #include "pw_log/log.h"
+
+ // This define might be supplied by the build system.
+ #define MY_PRODUCT_LOG_PII_ENABLED false
+
+ // This is the PII mask bit selected by the application.
+ #define MY_PRODUCT_PII_MASK (1 << 5)
+
+ // Pigweed's log facade will call this macro to decide to log or not. In
+ // this case, it will drop logs with the PII flag set if display of PII is
+ // not enabled for the application.
+ #define PW_LOG_ENABLE_IF(level, flags) \
+ (level >= PW_LOG_INFO && \
+ !((flags & MY_PRODUCT_PII_MASK) && MY_PRODUCT_LOG_PII_ENABLED)
+
+ void DoSomethingWithSensitiveInfo() {
+ PW_LOG_DEBUG("This won't be logged at all");
+ PW_LOG_INFO("This is INFO level, and will display");
+
+ // In this example, this will not be logged since logging with PII
+ // is disabled by the above macros.
+ PW_LOG(PW_LOG_LEVEL_INFO,
+ MY_PRODUCT_PII_MASK,
+ "Sensitive: %d",
+ sensitive_info);
+ }
+
+.. attention::
+
+ At this time, only compile time filtering is supported. In the future, we
+ plan to add support for runtime filtering.
Logging attributes
------------------
diff --git a/pw_log/public/pw_log/log.h b/pw_log/public/pw_log/log.h
index 66203a8..1eaab54 100644
--- a/pw_log/public/pw_log/log.h
+++ b/pw_log/public/pw_log/log.h
@@ -64,38 +64,65 @@
#endif // PW_LOG_MODULE_NAME
// Default: Flags
-#ifndef PW_LOG_NO_FLAGS
-#define PW_LOG_NO_FLAGS 0
-#endif // PW_LOG_NO_FLAGS
+// For log statements like LOG_INFO that don't have an explicit argument, this
+// is used for the flags value.
+#ifndef PW_LOG_DEFAULT_FLAGS
+#define PW_LOG_DEFAULT_FLAGS 0
+#endif // PW_LOG_DEFAULT_FLAGS
-// Note: The filtering semantics are likely to change.
+// Default: Log level filtering
+//
+// All log statements have a level, and this define is the default filtering.
+// This is compile-time filtering if the level is a constant.
+//
+// TODO(pwbug/17): Convert this to the config system when available.
+#ifndef PW_LOG_LEVEL
+#define PW_LOG_LEVEL PW_LOG_LEVEL_DEBUG
+#endif // PW_LOG_LEVEL
+
+// Default: Log enabled expression
+//
+// This expression determines whether or not the statement is enabled and
+// should be passed to the backend.
+#ifndef PW_LOG_ENABLE_IF
+#define PW_LOG_ENABLE_IF(level, flags) ((level) >= PW_LOG_LEVEL)
+#endif // PW_LOG_ENABLE_IF
+
+#ifndef PW_LOG
+#define PW_LOG(level, flags, message, ...) \
+ do { \
+ if (PW_LOG_ENABLE_IF(level, flags)) { \
+ PW_HANDLE_LOG(level, flags, message, __VA_ARGS__); \
+ } \
+ } while (0)
+#endif // PW_LOG_DEBUG
// For backends that elect to only provide the general PW_LOG() macro and not
// specialized versions, define the standard PW_LOG_<level>() macros in terms
// of the general PW_LOG().
#ifndef PW_LOG_DEBUG
#define PW_LOG_DEBUG(message, ...) \
- PW_LOG(PW_LOG_LEVEL_DEBUG, PW_LOG_NO_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_DEBUG, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_DEBUG
#ifndef PW_LOG_INFO
#define PW_LOG_INFO(message, ...) \
- PW_LOG(PW_LOG_LEVEL_INFO, PW_LOG_NO_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_INFO, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_INFO
#ifndef PW_LOG_WARN
#define PW_LOG_WARN(message, ...) \
- PW_LOG(PW_LOG_LEVEL_WARN, PW_LOG_NO_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_WARN, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_WARN
#ifndef PW_LOG_ERROR
#define PW_LOG_ERROR(message, ...) \
- PW_LOG(PW_LOG_LEVEL_ERROR, PW_LOG_NO_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_ERROR, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_ERROR
#ifndef PW_LOG_CRITICAL
#define PW_LOG_CRITICAL(message, ...) \
- PW_LOG(PW_LOG_LEVEL_CRITICAL, PW_LOG_NO_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_CRITICAL, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_CRITICAL
// Define short, usable names if requested.
diff --git a/pw_log_basic/public/pw_log_basic/log_basic.h b/pw_log_basic/public/pw_log_basic/log_basic.h
index 305b786..6ebb4e1 100644
--- a/pw_log_basic/public/pw_log_basic/log_basic.h
+++ b/pw_log_basic/public/pw_log_basic/log_basic.h
@@ -39,13 +39,13 @@
// char[] variable inside functions with a log.
//
// TODO(pwbug/87): Reconsider the naming of this module when more is in place.
-#define PW_LOG(level, flags, message, ...) \
- do { \
- pw_Log((level), \
- (flags), \
- PW_LOG_MODULE_NAME, \
- __FILE__, \
- __LINE__, \
- __func__, \
- message PW_COMMA_ARGS(__VA_ARGS__)); \
+#define PW_HANDLE_LOG(level, flags, message, ...) \
+ do { \
+ pw_Log((level), \
+ (flags), \
+ PW_LOG_MODULE_NAME, \
+ __FILE__, \
+ __LINE__, \
+ __func__, \
+ message PW_COMMA_ARGS(__VA_ARGS__)); \
} while (0)
diff --git a/pw_log_tokenized/public_overrides/pw_log_backend/log_backend.h b/pw_log_tokenized/public_overrides/pw_log_backend/log_backend.h
index 86f1c2a..b6035d9 100644
--- a/pw_log_tokenized/public_overrides/pw_log_backend/log_backend.h
+++ b/pw_log_tokenized/public_overrides/pw_log_backend/log_backend.h
@@ -18,4 +18,4 @@
#include "pw_log_tokenized/log_tokenized.h"
-#define PW_LOG PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD
+#define PW_HANDLE_LOG PW_LOG_TOKENIZED_TO_GLOBAL_HANDLER_WITH_PAYLOAD
diff --git a/pw_unit_test/logging_event_handler.cc b/pw_unit_test/logging_event_handler.cc
index bd063a2..e1ad080 100644
--- a/pw_unit_test/logging_event_handler.cc
+++ b/pw_unit_test/logging_event_handler.cc
@@ -64,14 +64,17 @@
const char* result = expectation.success ? "Success" : "Failure";
uint32_t level = expectation.success ? PW_LOG_LEVEL_INFO : PW_LOG_LEVEL_ERROR;
PW_LOG(level,
- PW_LOG_NO_FLAGS,
+ PW_LOG_DEFAULT_FLAGS,
"%s:%d: %s",
test_case.file_name,
expectation.line_number,
result);
- PW_LOG(level, PW_LOG_NO_FLAGS, " Expected: %s", expectation.expression);
PW_LOG(level,
- PW_LOG_NO_FLAGS,
+ PW_LOG_DEFAULT_FLAGS,
+ " Expected: %s",
+ expectation.expression);
+ PW_LOG(level,
+ PW_LOG_DEFAULT_FLAGS,
" Actual: %s",
expectation.evaluated_expression);
}