diff --git a/bazel/BUILD b/bazel/BUILD index eccf2bb26a2eb..4e5b79f5e73cd 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -323,6 +323,11 @@ config_setting( values = {"define": "manual_stamp=manual_stamp"}, ) +config_setting( + name = "android_logger", + values = {"define": "logger=android"}, +) + alias( name = "apple", actual = select( diff --git a/bazel/README.md b/bazel/README.md index 14ffa1c463a0b..3bdd2fee08cd4 100644 --- a/bazel/README.md +++ b/bazel/README.md @@ -448,6 +448,7 @@ The following optional features can be enabled on the Bazel build command-line: This is needed if the `version_info_lib` is compiled via a non-binary bazel rules, e.g `envoy_cc_library`. Otherwise, the linker will fail to resolve symbols that are included via the `linktamp` rule, which is only available to binary targets. This is being tracked as a feature in: https://github.com/envoyproxy/envoy/issues/6859. +* Process logging for Android applications can be enabled with `--define logger=android`. ## Disabling extensions diff --git a/source/common/common/BUILD b/source/common/common/BUILD index ec8330f0c744c..feb5f85c467f1 100644 --- a/source/common/common/BUILD +++ b/source/common/common/BUILD @@ -133,10 +133,41 @@ envoy_cc_library( hdrs = ["logger.h"], external_deps = ["abseil_synchronization"], deps = [ + ":base_logger_lib", ":lock_guard_lib", ":macros", ":non_copyable", - ], + ] + select({ + "//bazel:android_logger": ["logger_impl_lib_android"], + "//conditions:default": ["logger_impl_lib_standard"], + }), +) + +envoy_cc_library( + name = "base_logger_lib", + srcs = ["base_logger.cc"], + hdrs = ["base_logger.h"], +) + +envoy_cc_library( + name = "logger_impl_lib_standard", + hdrs = ["standard/logger_impl.h"], + strip_include_prefix = "standard", + deps = [":base_logger_lib"], +) + +envoy_cc_library( + name = "logger_impl_lib_android", + srcs = select({ + "//bazel:android_logger": ["android/logger_impl.cc"], + "//conditions:default": [], + }), + hdrs = select({ + "//bazel:android_logger": ["android/logger_impl.h"], + "//conditions:default": [], + }), + strip_include_prefix = "android", + deps = [":base_logger_lib"], ) envoy_cc_library( diff --git a/source/common/common/android/logger_impl.cc b/source/common/common/android/logger_impl.cc new file mode 100644 index 0000000000000..90af89767d041 --- /dev/null +++ b/source/common/common/android/logger_impl.cc @@ -0,0 +1,13 @@ +#include "common/common/logger_impl.h" + +#include "spdlog/sinks/android_sink.h" + +namespace Envoy { +namespace Logger { + +AndroidLogger::AndroidLogger(const std::string& name) + : Logger(std::make_shared( + name, std::make_shared>())) {} + +} // namespace Logger +} // namespace Envoy diff --git a/source/common/common/android/logger_impl.h b/source/common/common/android/logger_impl.h new file mode 100644 index 0000000000000..11bb1a7a48383 --- /dev/null +++ b/source/common/common/android/logger_impl.h @@ -0,0 +1,21 @@ +#pragma once + +#include "common/common/base_logger.h" + +namespace Envoy { +namespace Logger { + +#define GENERATE_LOGGER(X) AndroidLogger(#X), + +/** + * Logger that uses spdlog::sinks::android_sink. + */ +class AndroidLogger : public Logger { +private: + AndroidLogger(const std::string& name); + + friend class Registry; +}; + +} // namespace Logger +} // namespace Envoy diff --git a/source/common/common/base_logger.cc b/source/common/common/base_logger.cc new file mode 100644 index 0000000000000..912c649337d65 --- /dev/null +++ b/source/common/common/base_logger.cc @@ -0,0 +1,17 @@ +#include "common/common/base_logger.h" + +namespace Envoy { +namespace Logger { + +const char* Logger::DEFAULT_LOG_FORMAT = "[%Y-%m-%d %T.%e][%t][%l][%n] %v"; + +Logger::Logger(std::shared_ptr logger) : logger_(logger) { + logger_->set_pattern(DEFAULT_LOG_FORMAT); + logger_->set_level(spdlog::level::trace); + + // Ensure that critical errors, especially ASSERT/PANIC, get flushed + logger_->flush_on(spdlog::level::critical); +} + +} // namespace Logger +} // namespace Envoy diff --git a/source/common/common/base_logger.h b/source/common/common/base_logger.h new file mode 100644 index 0000000000000..4404c62d9ac07 --- /dev/null +++ b/source/common/common/base_logger.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include "spdlog/spdlog.h" + +namespace Envoy { +namespace Logger { + +/** + * Logger wrapper for a spdlog logger. + */ +class Logger { +public: + /* This is simple mapping between Logger severity levels and spdlog severity levels. + * The only reason for this mapping is to go around the fact that spdlog defines level as err + * but the method to log at err level is called LOGGER.error not LOGGER.err. All other level are + * fine spdlog::info corresponds to LOGGER.info method. + */ + using Levels = enum { + trace = spdlog::level::trace, // NOLINT(readability-identifier-naming) + debug = spdlog::level::debug, // NOLINT(readability-identifier-naming) + info = spdlog::level::info, // NOLINT(readability-identifier-naming) + warn = spdlog::level::warn, // NOLINT(readability-identifier-naming) + error = spdlog::level::err, // NOLINT(readability-identifier-naming) + critical = spdlog::level::critical, // NOLINT(readability-identifier-naming) + off = spdlog::level::off // NOLINT(readability-identifier-naming) + }; + + spdlog::string_view_t levelString() const { + return spdlog::level::level_string_views[logger_->level()]; + } + std::string name() const { return logger_->name(); } + void setLevel(spdlog::level::level_enum level) { logger_->set_level(level); } + spdlog::level::level_enum level() const { return logger_->level(); } + + static const char* DEFAULT_LOG_FORMAT; + +protected: + Logger(std::shared_ptr logger); + +private: + std::shared_ptr logger_; // Use shared_ptr here to allow static construction + // of vector in Registry::allLoggers(). + // TODO(junr03): expand Logger's public API to delete this friendship. + friend class Registry; +}; + +} // namespace Logger +} // namespace Envoy diff --git a/source/common/common/logger.cc b/source/common/common/logger.cc index a168b259d1225..3fe1fd0209745 100644 --- a/source/common/common/logger.cc +++ b/source/common/common/logger.cc @@ -16,18 +16,8 @@ namespace Envoy { namespace Logger { -#define GENERATE_LOGGER(X) Logger(#X), - -const char* Logger::DEFAULT_LOG_FORMAT = "[%Y-%m-%d %T.%e][%t][%l][%n] %v"; - -Logger::Logger(const std::string& name) { - logger_ = std::make_shared(name, Registry::getSink()); - logger_->set_pattern(DEFAULT_LOG_FORMAT); - logger_->set_level(spdlog::level::trace); - - // Ensure that critical errors, especially ASSERT/PANIC, get flushed - logger_->flush_on(spdlog::level::critical); -} +StandardLogger::StandardLogger(const std::string& name) + : Logger(std::make_shared(name, Registry::getSink())) {} SinkDelegate::SinkDelegate(DelegatingLogSinkSharedPtr log_sink) : previous_delegate_(log_sink->delegate()), log_sink_(log_sink) { diff --git a/source/common/common/logger.h b/source/common/common/logger.h index f3faa690b9394..cc4352ea02133 100644 --- a/source/common/common/logger.h +++ b/source/common/common/logger.h @@ -7,7 +7,9 @@ #include "envoy/thread/thread.h" +#include "common/common/base_logger.h" #include "common/common/fmt.h" +#include "common/common/logger_impl.h" #include "common/common/macros.h" #include "common/common/non_copyable.h" @@ -72,39 +74,12 @@ enum class Id { // clang-format on /** - * Logger wrapper for a spdlog logger. + * Logger that uses the DelegatingLogSink. */ -class Logger { -public: - /* This is simple mapping between Logger severity levels and spdlog severity levels. - * The only reason for this mapping is to go around the fact that spdlog defines level as err - * but the method to log at err level is called LOGGER.error not LOGGER.err. All other level are - * fine spdlog::info corresponds to LOGGER.info method. - */ - using Levels = enum { - trace = spdlog::level::trace, // NOLINT(readability-identifier-naming) - debug = spdlog::level::debug, // NOLINT(readability-identifier-naming) - info = spdlog::level::info, // NOLINT(readability-identifier-naming) - warn = spdlog::level::warn, // NOLINT(readability-identifier-naming) - error = spdlog::level::err, // NOLINT(readability-identifier-naming) - critical = spdlog::level::critical, // NOLINT(readability-identifier-naming) - off = spdlog::level::off // NOLINT(readability-identifier-naming) - }; - - spdlog::string_view_t levelString() const { - return spdlog::level::level_string_views[logger_->level()]; - } - std::string name() const { return logger_->name(); } - void setLevel(spdlog::level::level_enum level) { logger_->set_level(level); } - spdlog::level::level_enum level() const { return logger_->level(); } - - static const char* DEFAULT_LOG_FORMAT; - +class StandardLogger : public Logger { private: - Logger(const std::string& name); + StandardLogger(const std::string& name); - std::shared_ptr logger_; // Use shared_ptr here to allow static construction - // of constant vector below. friend class Registry; }; diff --git a/source/common/common/standard/logger_impl.h b/source/common/common/standard/logger_impl.h new file mode 100644 index 0000000000000..a07664151c654 --- /dev/null +++ b/source/common/common/standard/logger_impl.h @@ -0,0 +1,11 @@ +#pragma once + +#include "common/common/base_logger.h" + +namespace Envoy { +namespace Logger { + +#define GENERATE_LOGGER(X) StandardLogger(#X), + +} // namespace Logger +} // namespace Envoy