From 39622251a17efd5d940fba5f35dea6fb6f8b2c06 Mon Sep 17 00:00:00 2001 From: Wiebe Cazemier Date: Sun, 17 Mar 2024 17:01:51 +0100 Subject: [PATCH] Add new setting 'log_level' --- FlashMQTests/tst_maintests.cpp | 4 +-- configfileparser.cpp | 28 ++++++++++++++++++ flashmq_plugin.h | 1 + logger.cpp | 53 ++++++++++++++++++++++++++++------ logger.h | 14 ++++++++- mainapp.cpp | 3 +- man/flashmq.conf.5 | 13 ++++++++- man/flashmq.conf.5.dbk5 | 20 +++++++++++++ man/flashmq.conf.5.html | 20 +++++++++++++ settings.h | 11 ++++--- 10 files changed, 149 insertions(+), 18 deletions(-) diff --git a/FlashMQTests/tst_maintests.cpp b/FlashMQTests/tst_maintests.cpp index a71f2dd9..6261c159 100644 --- a/FlashMQTests/tst_maintests.cpp +++ b/FlashMQTests/tst_maintests.cpp @@ -1060,10 +1060,10 @@ void MainTests::testSavingSessions() void MainTests::testParsePacketHelper(const std::string &topic, uint8_t from_qos, bool retain) { - Logger::getInstance()->setFlags(false, false, true); + Logger::getInstance()->setFlags(LogLevel::None, false); Settings settings; - settings.logDebug = false; + settings.logLevel = LogLevel::Info; std::shared_ptr store(new SubscriptionStore()); PluginLoader pluginLoader; std::shared_ptr t(new ThreadData(0, settings, pluginLoader)); diff --git a/configfileparser.cpp b/configfileparser.cpp index ee3eff2e..68e812cf 100644 --- a/configfileparser.cpp +++ b/configfileparser.cpp @@ -182,6 +182,7 @@ ConfigFileParser::ConfigFileParser(const std::string &path) : validKeys.insert("max_packet_size"); validKeys.insert("log_debug"); validKeys.insert("log_subscriptions"); + validKeys.insert("log_level"); validKeys.insert("mosquitto_password_file"); validKeys.insert("mosquitto_acl_file"); validKeys.insert("allow_anonymous"); @@ -724,6 +725,8 @@ void ConfigFileParser::loadFile(bool test) if (testKeyValidity(key, "quiet", validKeys)) { + Logger::getInstance()->log(LOG_WARNING) << "The config option '" << key << "' is deprecated. Use log_level instead."; + bool tmp = stringTruthiness(value); tmpSettings.quiet = tmp; } @@ -774,10 +777,35 @@ void ConfigFileParser::loadFile(bool test) if (testKeyValidity(key, "log_debug", validKeys)) { + Logger::getInstance()->log(LOG_WARNING) << "The config option '" << key << "' is deprecated. Use log_level instead."; + bool tmp = stringTruthiness(value); tmpSettings.logDebug = tmp; } + if (testKeyValidity(key, "log_level", validKeys)) + { + const std::string v = str_tolower(value); + LogLevel level = LogLevel::None; + + if (v == "debug") + level = LogLevel::Debug; + else if (v == "info") + level = LogLevel::Info; + else if (v == "notice") + level = LogLevel::Notice; + else if (v == "warning") + level = LogLevel::Warning; + else if (v == "error") + level = LogLevel::Warning; + else if (v == "none") + level = LogLevel::None; + else + throw ConfigFileException("Invalid log level: " + value); + + tmpSettings.logLevel = level; + } + if (testKeyValidity(key, "log_subscriptions", validKeys)) { bool tmp = stringTruthiness(value); diff --git a/flashmq_plugin.h b/flashmq_plugin.h index 794ed3c1..a8bd7b3d 100644 --- a/flashmq_plugin.h +++ b/flashmq_plugin.h @@ -38,6 +38,7 @@ #define LOG_NOTICE 0x02 #define LOG_WARNING 0x04 #define LOG_ERR 0x08 +#define LOG_ERROR 0x08 #define LOG_DEBUG 0x10 #define LOG_SUBSCRIBE 0x20 #define LOG_UNSUBSCRIBE 0x40 diff --git a/logger.cpp b/logger.cpp index 5bc1b96f..29a973b7 100644 --- a/logger.cpp +++ b/logger.cpp @@ -172,24 +172,59 @@ void Logger::setLogPath(const std::string &path) this->logPath = path; } -void Logger::setFlags(bool logDebug, bool logSubscriptions, bool quiet) +/** + * @brief Logger::setFlags sets the log level based on a maximum desired level. + * @param level Level based on the defines LOG_*. + * @param logSubscriptions + * @param quiet + * + * The log levels are mosquitto-compatible, and while the terminology is similar to the syslog standard, they are unfortunately + * not in order of verbosity/priority. So, we use our own enum for the config setting, so that DEBUG is indeed more verbose than INFO. + * + * The subscriptions flag is still set explicitly, because you may want that irrespective of the log level. + */ +void Logger::setFlags(LogLevel level, bool logSubscriptions) { - curLogLevel = LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_SUBSCRIBE | LOG_UNSUBSCRIBE ; + curLogLevel = 0; - if (logDebug) + if (level <= LogLevel::Debug) curLogLevel |= LOG_DEBUG; - else - curLogLevel &= ~LOG_DEBUG; + if (level <= LogLevel::Info) + curLogLevel |= LOG_INFO; + if (level <= LogLevel::Notice) + curLogLevel |= LOG_NOTICE; + if (level <= LogLevel::Warning) + curLogLevel |= LOG_WARNING; + if (level <= LogLevel::Error) + curLogLevel |= LOG_ERR; if (logSubscriptions) curLogLevel |= (LOG_UNSUBSCRIBE | LOG_SUBSCRIBE); else curLogLevel &= ~(LOG_UNSUBSCRIBE | LOG_SUBSCRIBE); +} - if (!quiet) - curLogLevel |= (LOG_NOTICE | LOG_INFO); - else - curLogLevel &= ~(LOG_NOTICE | LOG_INFO); +/** + * @brief Logger::setFlags is provided for backwards compatability + * @param logDebug + * @param quiet + */ +void Logger::setFlags(std::optional logDebug, std::optional quiet) +{ + if (logDebug) + { + if (logDebug.value()) + curLogLevel |= LOG_DEBUG; + else + curLogLevel &= ~LOG_DEBUG; + } + + // It only makes sense to allow quiet to mute things in backward compatability mode, not enable LOG_NOTICE and LOG_INFO again. + if (quiet) + { + if (quiet.value()) + curLogLevel &= ~(LOG_NOTICE | LOG_INFO); + } } void Logger::quit() diff --git a/logger.h b/logger.h index c5afb3a3..97e522e7 100644 --- a/logger.h +++ b/logger.h @@ -17,10 +17,21 @@ See LICENSE for license details. #include #include #include +#include #include "semaphore.h" #include "flashmq_plugin.h" +enum class LogLevel +{ + Debug, + Info, + Notice, + Warning, + Error, + None +}; + int logSslError(const char *str, size_t len, void *u); /** @@ -82,7 +93,8 @@ class Logger void noLongerLogToStd(); void setLogPath(const std::string &path); - void setFlags(bool logDebug, bool logSubscriptions, bool quiet); + void setFlags(LogLevel level, bool logSubscriptions); + void setFlags(std::optional logDebug, std::optional quiet); void quit(); diff --git a/mainapp.cpp b/mainapp.cpp index 9c0f3579..f2cae8a4 100644 --- a/mainapp.cpp +++ b/mainapp.cpp @@ -973,7 +973,8 @@ void MainApp::loadConfig(bool reload) logger->setLogPath(settings.logPath); logger->queueReOpen(); - logger->setFlags(settings.logDebug, settings.logSubscriptions, settings.quiet); + logger->setFlags(settings.logLevel, settings.logSubscriptions); + logger->setFlags(settings.logDebug, settings.quiet); setlimits(); diff --git a/man/flashmq.conf.5 b/man/flashmq.conf.5 index 974a0e3d..d90b9554 100644 --- a/man/flashmq.conf.5 +++ b/man/flashmq.conf.5 @@ -5,7 +5,7 @@ \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac -.TH flashmq.conf 5 "16 March 2024" "" "" +.TH flashmq.conf 5 "17 March 2024" "" "" .SH NAME flashmq.conf \- FlashMQ configuration file format .SH SYNOPSIS @@ -63,9 +63,18 @@ This configuration parameter sets the path to FlashMQ's log file. If you omit th Default value: \*(T<\fI/var/log/flashmq/flashmq.log\fR\*(T> .TP +\*(T<\fBlog_level\fR\*(T> \fIinfo/notice/warning/error/none\fR +Set the log level to specified level and above. That means \fInotice\fR will log \fInotice\fR, \fIwarning\fR and \fIerror\fR. + +Use this setting over the deprecated \*(T<\fBlog_debug\fR\*(T> and \*(T<\fBquiet\fR\*(T>. If you do have those directives, they override the \*(T<\fBlog_level\fR\*(T>, for backwards compatability reasons. + +Default value: \*(T. +.TP \*(T<\fBlog_debug\fR\*(T> \fItrue/false\fR Debug logging obviously creates a lot of log noise, so should only be done to diagnose problems. +Deprecated. Use \*(T<\fBlog_level\fR\*(T> instead. + Default value: \*(T .TP \*(T<\fBlog_subscriptions\fR\*(T> \fItrue/false\fR @@ -145,6 +154,8 @@ Default value: \*(T<1209600\*(T> \*(T<\fBquiet\fR\*(T> \fItrue/false\fR Don't log LOG_INFO and LOG_NOTICE. This is useful when you have a lot of foot traffic, because otherwise the log gets filled with connect/disconnect notices. +Deprecated. Use \*(T<\fBlog_level\fR\*(T> instead. + Default value: \*(T .TP \*(T<\fBstorage_dir\fR\*(T> \fI/path/to/dir\fR diff --git a/man/flashmq.conf.5.dbk5 b/man/flashmq.conf.5.dbk5 index 41698553..aed8f08c 100644 --- a/man/flashmq.conf.5.dbk5 +++ b/man/flashmq.conf.5.dbk5 @@ -121,12 +121,29 @@ + + info/notice/warning/error/none + + + Set the log level to specified level and above. That means notice will log notice, warning and error. + + + Use this setting over the deprecated and . If you do have those directives, they override the , for backwards compatability reasons. + + + Default value: info. + + + true/false Debug logging obviously creates a lot of log noise, so should only be done to diagnose problems. + + Deprecated. Use instead. + Default value: false @@ -291,6 +308,9 @@ Don't log LOG_INFO and LOG_NOTICE. This is useful when you have a lot of foot traffic, because otherwise the log gets filled with connect/disconnect notices. + + Deprecated. Use instead. + Default value: false diff --git a/man/flashmq.conf.5.html b/man/flashmq.conf.5.html index 81cb5797..9373b192 100644 --- a/man/flashmq.conf.5.html +++ b/man/flashmq.conf.5.html @@ -177,11 +177,28 @@ +
log_level info/notice/warning/error/none#
+
+

+ Set the log level to specified level and above. That means notice will log notice, warning and error. +

+

+ Use this setting over the deprecated log_debug and quiet. If you do have those directives, they override the log_level, for backwards compatability reasons. +

+

+ Default value: info. +

+
+ +
log_debug true/false#

Debug logging obviously creates a lot of log noise, so should only be done to diagnose problems.

+

+ Deprecated. Use log_level instead. +

Default value: false

@@ -346,6 +363,9 @@

Don't log LOG_INFO and LOG_NOTICE. This is useful when you have a lot of foot traffic, because otherwise the log gets filled with connect/disconnect notices.

+

+ Deprecated. Use log_level instead. +

Default value: false

diff --git a/settings.h b/settings.h index 20713d03..94b500e4 100644 --- a/settings.h +++ b/settings.h @@ -14,6 +14,7 @@ See LICENSE for license details. #include #include #include +#include #include "mosquittoauthoptcompatwrap.h" #include "listener.h" @@ -57,22 +58,24 @@ class Settings // Actual config options with their defaults. std::string pluginPath; std::string logPath; - bool quiet = false; + std::optional quiet; bool allowUnsafeClientidChars = false; bool allowUnsafeUsernameChars = false; bool pluginSerializeInit = false; bool pluginSerializeAuthChecks = false; + bool logSubscriptions = false; int clientInitialBufferSize = 1024; // Must be power of 2 uint32_t maxPacketSize = ABSOLUTE_MAX_PACKET_SIZE; uint32_t clientMaxWriteBufferSize = 1048576; uint16_t maxIncomingTopicAliasValue = 65535; uint16_t maxOutgoingTopicAliasValue = 65535; #ifdef TESTING - bool logDebug = true; + std::optional logDebug; + LogLevel logLevel = LogLevel::Debug; #else - bool logDebug = false; + std::optional logDebug; + LogLevel logLevel = LogLevel::Info; #endif - bool logSubscriptions = false; std::string mosquittoPasswordFile; std::string mosquittoAclFile; bool allowAnonymous = false;