aboutsummaryrefslogtreecommitdiff
path: root/pw_log
diff options
context:
space:
mode:
authorArmando Montanez <amontanez@google.com>2021-11-17 17:27:41 -0800
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-11-18 03:49:46 +0000
commite221d8462fa3aa51558dfb7ae8f469b8ac6581a0 (patch)
tree6adf5ac6b14fb78c4543e825b566b177744be247 /pw_log
parent31c4105238961dc193bc3dbe56c64e8aa71a8879 (diff)
downloadpigweed-e221d8462fa3aa51558dfb7ae8f469b8ac6581a0.tar.gz
pw_log: Add global config options
Extends pw_log to have configurable global defaults for the per-module options to allow projects to reconfigure defaults to their needs. Change-Id: I0a3ef3cf793cd8513e073d0b652d93be2a234024 Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/69762 Pigweed-Auto-Submit: Armando Montanez <amontanez@google.com> Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com> Reviewed-by: Wyatt Hepler <hepler@google.com>
Diffstat (limited to 'pw_log')
-rw-r--r--pw_log/BUILD.bazel1
-rw-r--r--pw_log/BUILD.gn22
-rw-r--r--pw_log/basic_log_test_plain_c.c10
-rw-r--r--pw_log/docs.rst73
-rw-r--r--pw_log/public/pw_log/config.h41
-rw-r--r--pw_log/public/pw_log/log.h10
-rw-r--r--pw_log/public/pw_log/options.h33
7 files changed, 146 insertions, 44 deletions
diff --git a/pw_log/BUILD.bazel b/pw_log/BUILD.bazel
index 334bc41ef..6bb0a87e5 100644
--- a/pw_log/BUILD.bazel
+++ b/pw_log/BUILD.bazel
@@ -27,6 +27,7 @@ licenses(["notice"])
pw_cc_facade(
name = "facade",
hdrs = [
+ "public/pw_log/config.h",
"public/pw_log/levels.h",
"public/pw_log/log.h",
"public/pw_log/options.h",
diff --git a/pw_log/BUILD.gn b/pw_log/BUILD.gn
index 89b68b994..9b6428459 100644
--- a/pw_log/BUILD.gn
+++ b/pw_log/BUILD.gn
@@ -15,19 +15,34 @@
import("//build_overrides/pigweed.gni")
import("$dir_pw_build/facade.gni")
+import("$dir_pw_build/module_config.gni")
import("$dir_pw_chrono/backend.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_log/backend.gni")
import("$dir_pw_protobuf_compiler/proto.gni")
import("$dir_pw_unit_test/test.gni")
-config("default_config") {
+declare_args() {
+ # The build target that overrides the default configuration options for this
+ # module. This should point to a source set that provides defines through a
+ # public config (which may -include a file or add defines directly).
+ pw_log_CONFIG = pw_build_DEFAULT_MODULE_CONFIG
+}
+
+config("public_include_path") {
include_dirs = [ "public" ]
+ visibility = [ ":*" ]
+}
+
+pw_source_set("config") {
+ public = [ "public/pw_log/config.h" ]
+ public_configs = [ ":public_include_path" ]
+ public_deps = [ pw_log_CONFIG ]
}
pw_facade("pw_log") {
backend = pw_log_BACKEND
- public_configs = [ ":default_config" ]
+ public_configs = [ ":public_include_path" ]
public = [
"public/pw_log/levels.h",
"public/pw_log/log.h",
@@ -35,12 +50,13 @@ pw_facade("pw_log") {
"public/pw_log/short.h",
"public/pw_log/shorter.h",
]
+ public_deps = [ ":config" ]
require_link_deps = [ ":impl" ]
}
pw_source_set("proto_utils") {
- public_configs = [ ":default_config" ]
+ public_configs = [ ":public_include_path" ]
public = [ "public/pw_log/proto_utils.h" ]
public_deps = [
":pw_log.facade",
diff --git a/pw_log/basic_log_test_plain_c.c b/pw_log/basic_log_test_plain_c.c
index ee82374f2..1b7a41d11 100644
--- a/pw_log/basic_log_test_plain_c.c
+++ b/pw_log/basic_log_test_plain_c.c
@@ -85,11 +85,11 @@ void BasicLogTestPlainC(void) {
// Log levels other than the standard ones work; what each backend does is
// implementation defined.
- 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");
+ PW_LOG(0, PW_LOG_FLAGS, "Custom log level: 0");
+ PW_LOG(1, PW_LOG_FLAGS, "Custom log level: 1");
+ PW_LOG(2, PW_LOG_FLAGS, "Custom log level: 2");
+ PW_LOG(3, PW_LOG_FLAGS, "Custom log level: 3");
+ PW_LOG(100, PW_LOG_FLAGS, "Custom log level: 100");
// Logging from a function.
LoggingFromFunctionPlainC();
diff --git a/pw_log/docs.rst b/pw_log/docs.rst
index d66b4357c..406c08e0f 100644
--- a/pw_log/docs.rst
+++ b/pw_log/docs.rst
@@ -1,8 +1,8 @@
.. _module-pw_log:
-------
+======
pw_log
-------
+======
Pigweed's logging module provides facilities for applications to log
information about the execution of their application. The module is split into
two components:
@@ -19,6 +19,7 @@ service for efficiently storing and transmitting log messages. See
protobuf
+--------------
Usage examples
--------------
Here is a typical usage example, showing setting the module name, and using the
@@ -61,7 +62,7 @@ names and go for shorter log macros. Include ``pw_log/short.h`` or
}
Layer diagram example: ``stm32f429i-disc1``
--------------------------------------------
+===========================================
Below is an example diagram showing how the modules connect together for the
``stm32f429i-disc1`` target, where the ``pw_log`` backend is ``pw_log_basic``.
``pw_log_basic`` uses the ``pw_sys_io`` module to log in plaintext, which in
@@ -71,8 +72,7 @@ turn outputs to the STM32F429 bare metal backend for ``pw_sys_io``, which is
.. image:: example_layer_diagram.svg
Logging macros
---------------
-
+==============
These are the primary macros for logging information about the functioning of a
system, intended to be used directly.
@@ -104,7 +104,7 @@ system, intended to be used directly.
.. code-block:: cpp
- PW_LOG(PW_LOG_DEFAULT_FLAGS, PW_LOG_LEVEL_INFO, "Temp is %d degrees", temp);
+ PW_LOG(PW_LOG_FLAGS, PW_LOG_LEVEL_INFO, "Temp is %d degrees", temp);
PW_LOG(UNRELIABLE_DELIVERY, PW_LOG_LEVEL_ERROR, "It didn't work!");
.. note::
@@ -122,13 +122,41 @@ system, intended to be used directly.
.. cpp:function:: PW_LOG_ERROR(fmt, ...)
.. cpp:function:: PW_LOG_CRITICAL(fmt, ...)
- Shorthand for `PW_LOG(PW_LOG_DEFAULT_FLAGS, <level>, fmt, ...)`.
+ Shorthand for `PW_LOG(PW_LOG_FLAGS, <level>, fmt, ...)`.
+
+--------------------
+Module configuration
+--------------------
+This module has configuration options that globally affect the behavior of
+pw_log via compile-time configuration of this module, see the
+:ref:`module documentation <module-structure-compile-time-configuration>` for
+more details.
+
+.. c:macro:: PW_LOG_LEVEL_DEFAULT
+
+ Controls the default value of ``PW_LOG_LEVEL``. Setting
+ ``PW_LOG_LEVEL_DEFAULT`` will change the behavior of all source files that
+ have not explicitly set ``PW_LOG_LEVEL``. Defaults to ``PW_LOG_LEVEL_DEBUG``.
+
+.. c:macro:: PW_LOG_FLAGS_DEFAULT
-Option macros
--------------
-This module defines macros that can be overridden to control the behavior of
-``pw_log`` statements. To override these macros, add ``#define`` statements
-for them before including headers.
+ Controls the default value of ``PW_LOG_FLAGS``. Setting
+ ``PW_LOG_FLAGS_DEFAULT`` will change the behavior of all source files that
+ have not explicitly set ``PW_LOG_FLAGS``. Defaults to ``0``.
+
+.. c:macro:: PW_LOG_ENABLE_IF_DEFAULT
+
+ Controls the default value of ``PW_LOG_ENABLE_IF``. Setting
+ ``PW_LOG_ENABLE_IF_DEFAULT`` will change the behavior of all source files that
+ have not explicitly set ``PW_LOG_ENABLE_IF``. Defaults to
+ ``((level) >= PW_LOG_LEVEL)``.
+
+
+Per-source file configuration
+=============================
+This module defines macros that can be overridden to independently control the
+behavior of ``pw_log`` statements for each C or C++ source file. To override
+these macros, add ``#define`` statements for them before including headers.
The option macro definitions must be visibile to ``pw_log/log.h`` the first time
it is included. To handle potential transitive includes, place these
@@ -159,20 +187,20 @@ source files, not headers. For example:
``PW_LOG_MODULE_NAME_DEFINED`` macro is set to ``1`` or ``0`` to indicate
whether ``PW_LOG_MODULE_NAME`` was overridden.
-.. c:macro:: PW_LOG_DEFAULT_FLAGS
+.. c:macro:: PW_LOG_FLAGS
Log flags to use for the ``PW_LOG_<level>`` macros. Different flags may be
applied when using the ``PW_LOG`` macro directly.
Log backends use flags to change how they handle individual log messages.
Potential uses include assigning logs priority or marking them as containing
- personal information. Defaults to ``0``.
+ personal information. Defaults to ``PW_LOG_FLAGS_DEFAULT``.
.. c:macro:: PW_LOG_LEVEL
Filters logs by level. Source files that define ``PW_LOG_LEVEL`` will display
only logs at or above the chosen level. Log statements below this level will
- be compiled out of optimized builds. Defaults to ``PW_LOG_LEVEL_DEBUG``.
+ be compiled out of optimized builds. Defaults to ``PW_LOG_LEVEL_DEFAULT``.
Example:
@@ -192,7 +220,8 @@ source files, not headers. For example:
Filters logs by an arbitrary expression based on ``level`` and ``flags``.
Source files that define ``PW_LOG_ENABLE_IF(level, flags)`` will display if
- the given expression evaluates true.
+ the given expression evaluates true. Defaults to
+ ``PW_LOG_ENABLE_IF_DEFAULT``.
Example:
@@ -230,9 +259,9 @@ source files, not headers. For example:
At this time, only compile time filtering is supported. In the future, we
plan to add support for runtime filtering.
+------------------
Logging attributes
------------------
-
The logging facade in Pigweed is designed to facilitate the capture of at least
the following attributes:
@@ -257,8 +286,9 @@ complexity, and more.
.. _module-pw_log-circular-deps:
+----------------------------------------------
Avoiding circular dependencies with ``PW_LOG``
--------------------------------------------------
+----------------------------------------------
Because logs are so widely used, including in low-level libraries, it is
common for the ``pw_log`` backend to cause circular dependencies. Because of
this, log backends may avoid declaring explicit dependencies, instead relying
@@ -280,11 +310,12 @@ to directly provide dependencies through include paths only, rather than GN
``public_deps``. In this case, GN header checking can be disabled with
``check_includes = false``.
+-----------------
Design discussion
-----------------
Why not use C++ style stream logging operators like Google Log?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+===============================================================
There are multiple reasons to avoid the C++ stream logging style in embedded,
but the biggest reason is that C++ stream logging defeats log tokenization. By
having the string literals broken up between ``<<`` operators, tokenization
@@ -341,7 +372,7 @@ projects use that approach unless absolutely necessary.
which is useful for more than just logging.
Why does the facade use header redirection instead of C functions?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+==================================================================
Without header redirection, it is not possible to do sophisticated macro
transforms in the backend. For example, to apply tokenization to log strings,
the backend must define the handling macros. Additionally, compile-time
@@ -351,7 +382,7 @@ having the same filtering implementation for all log handling, which is a
restriction we want to avoid.
Why is the module name done as a preprocessor define rather than an argument?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+=============================================================================
APIs are a balance between power and ease of use. In the practical cases we
have seen over the years, most translation units only need to log to one
module, like ``"BLE"``, ``"PWR"``, ``"BAT"`` and so on. Thus, adding the
diff --git a/pw_log/public/pw_log/config.h b/pw_log/public/pw_log/config.h
new file mode 100644
index 000000000..340fbe4cb
--- /dev/null
+++ b/pw_log/public/pw_log/config.h
@@ -0,0 +1,41 @@
+// Copyright 2021 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+// These configuration options differ from the options in pw_log/options.h in
+// that these should be set at a global level in the build system rather than
+// at a module or compile unit level.
+
+// PW_LOG_LEVEL_DEFAULT controls the default value of PW_LOG_LEVEL.
+//
+// Defaults to PW_LOG_LEVEL_DEBUG.
+#ifndef PW_LOG_LEVEL_DEFAULT
+#define PW_LOG_LEVEL_DEFAULT PW_LOG_LEVEL_DEBUG
+#endif // PW_LOG_LEVEL_DEFAULT
+
+// PW_LOG_FLAGS_DEFAULT controls the default value of PW_LOG_FLAGS.
+//
+// For log statements like LOG_INFO that don't have an explicit argument, this
+// is used for the flags value.
+#ifndef PW_LOG_FLAGS_DEFAULT
+#define PW_LOG_FLAGS_DEFAULT 0
+#endif // PW_LOG_FLAGS_DEFAULT
+
+// PW_LOG_ENABLE_IF_DEFAULT controls the default value of PW_LOG_ENABLE_IF.
+//
+// This expression determines whether or not the statement is enabled and
+// should be passed to the backend.
+#ifndef PW_LOG_ENABLE_IF_DEFAULT
+#define PW_LOG_ENABLE_IF_DEFAULT(level, flags) ((level) >= PW_LOG_LEVEL)
+#endif // PW_LOG_ENABLE_IF_DEFAULT
diff --git a/pw_log/public/pw_log/log.h b/pw_log/public/pw_log/log.h
index d3a4b1df3..83342dc71 100644
--- a/pw_log/public/pw_log/log.h
+++ b/pw_log/public/pw_log/log.h
@@ -82,27 +82,27 @@
// of the general PW_LOG().
#ifndef PW_LOG_DEBUG
#define PW_LOG_DEBUG(message, ...) \
- PW_LOG(PW_LOG_LEVEL_DEBUG, PW_LOG_DEFAULT_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_DEBUG, PW_LOG_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_DEFAULT_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_INFO, PW_LOG_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_DEFAULT_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_WARN, PW_LOG_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_DEFAULT_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_ERROR, PW_LOG_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_DEFAULT_FLAGS, message, __VA_ARGS__)
+ PW_LOG(PW_LOG_LEVEL_CRITICAL, PW_LOG_FLAGS, message, __VA_ARGS__)
#endif // PW_LOG_CRITICAL
// Default: Number of bits available for the log flags
diff --git a/pw_log/public/pw_log/options.h b/pw_log/public/pw_log/options.h
index 3bd9c856a..2d20bd6d6 100644
--- a/pw_log/public/pw_log/options.h
+++ b/pw_log/public/pw_log/options.h
@@ -30,6 +30,12 @@
// circular dependencies when implementing the pw_log facade.
#pragma once
+#include "pw_log/config.h"
+
+// These configuration options differ from the options in pw_log/config.h in
+// that these should be set at a module/compile unit level rather than a global
+// level level.
+
// Default: Module name
//
// An empty string is used for the module name if it is not set. The
@@ -44,26 +50,33 @@
#define PW_LOG_MODULE_NAME_DEFINED 0
#endif // PW_LOG_MODULE_NAME
+// Default: Log level filtering
+//
+// All log statements have a level, and this define sets the log level to the
+// globally set default if PW_LOG_LEVEL was not already set by the module.
+// This is compile-time filtering if the level is a constant.
+#ifndef PW_LOG_LEVEL
+#define PW_LOG_LEVEL PW_LOG_LEVEL_DEFAULT
+#endif // PW_LOG_LEVEL
+
// Default: Flags
//
// For log statements like LOG_INFO that don't have an explicit argument, this
// is used for the flags value.
+#ifndef PW_LOG_FLAGS
+#define PW_LOG_FLAGS PW_LOG_FLAGS_DEFAULT
+#endif // PW_LOG_FLAGS
+
+// DEPRECATED: Use PW_LOG_FLAGS.
+// TODO(pwbug/561): Remove this macro after migration.
#ifndef PW_LOG_DEFAULT_FLAGS
-#define PW_LOG_DEFAULT_FLAGS 0
+#define PW_LOG_DEFAULT_FLAGS PW_LOG_FLAGS
#endif // PW_LOG_DEFAULT_FLAGS
-// 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.
-#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)
+#define PW_LOG_ENABLE_IF(level, flags) PW_LOG_ENABLE_IF_DEFAULT(level, flags)
#endif // PW_LOG_ENABLE_IF