diff --git a/src/Logging.cpp b/src/Logging.cpp
index 9ae94f08..cd72e395 100644
--- a/src/Logging.cpp
+++ b/src/Logging.cpp
@@ -6,8 +6,10 @@
#include "Logging.h"
#include "config/nheko.h"
+#include "spdlog/cfg/helpers.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
+#include "spdlog/spdlog.h"
#include <iostream>
#include <QString>
@@ -61,19 +63,20 @@ qmlMessageHandler(QtMsgType type, const QMessageLogContext &context, const QStri
}
namespace nhlog {
-bool enable_debug_log_from_commandline = false;
void
-init(const std::string &file_path)
+init(const QString &level, const QString &path, bool to_stderr)
{
- auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
- file_path, MAX_FILE_SIZE, MAX_LOG_FILES);
-
- auto console_sink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
-
std::vector<spdlog::sink_ptr> sinks;
- sinks.push_back(file_sink);
- sinks.push_back(console_sink);
+ if (!path.isEmpty()) {
+ auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
+ path.toStdString(), MAX_FILE_SIZE, MAX_LOG_FILES);
+ sinks.push_back(file_sink);
+ }
+ if (to_stderr) {
+ auto console_sink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
+ sinks.push_back(console_sink);
+ }
mtx::utils::log::log()->sinks() = sinks;
net_logger = std::make_shared<spdlog::logger>("net", std::begin(sinks), std::end(sinks));
@@ -82,7 +85,7 @@ init(const std::string &file_path)
crypto_logger = std::make_shared<spdlog::logger>("crypto", std::begin(sinks), std::end(sinks));
qml_logger = std::make_shared<spdlog::logger>("qml", std::begin(sinks), std::end(sinks));
- if (nheko::enable_debug_log || enable_debug_log_from_commandline) {
+ if (nheko::enable_debug_log) {
db_logger->set_level(spdlog::level::trace);
ui_logger->set_level(spdlog::level::trace);
crypto_logger->set_level(spdlog::level::trace);
@@ -91,6 +94,17 @@ init(const std::string &file_path)
mtx::utils::log::log()->set_level(spdlog::level::trace);
}
+ spdlog::register_logger(net_logger);
+ spdlog::register_logger(ui_logger);
+ spdlog::register_logger(db_logger);
+ spdlog::register_logger(crypto_logger);
+ spdlog::register_logger(qml_logger);
+ // We assume the mtxclient library will register its own logger.
+
+ if (!level.isEmpty()) {
+ spdlog::cfg::helpers::load_levels(level.toStdString());
+ }
+
qInstallMessageHandler(qmlMessageHandler);
}
diff --git a/src/Logging.h b/src/Logging.h
index 4a5109a6..23ff8236 100644
--- a/src/Logging.h
+++ b/src/Logging.h
@@ -6,11 +6,15 @@
#pragma once
#include <memory>
-#include <spdlog/logger.h>
+#include <string>
+
+#include <QString>
+
+#include "spdlog/logger.h"
namespace nhlog {
void
-init(const std::string &file);
+init(const QString &level, const QString &path, bool to_stderr);
std::shared_ptr<spdlog::logger>
ui();
@@ -27,5 +31,4 @@ crypto();
std::shared_ptr<spdlog::logger>
qml();
-extern bool enable_debug_log_from_commandline;
}
diff --git a/src/main.cpp b/src/main.cpp
index 47ebba27..f76d8ca6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -202,8 +202,24 @@ main(int argc, char *argv[])
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption debugOption(QStringLiteral("debug"), QStringLiteral("Enable debug output"));
+ QCommandLineOption debugOption(QStringLiteral("debug"),
+ QObject::tr("Alias for '--log-level trace'."));
parser.addOption(debugOption);
+ QCommandLineOption logLevel(
+ QStringList() << QStringLiteral("l") << QStringLiteral("log-level"),
+ QObject::tr("Set the global log level, or a comma-separated list of <component>=<level> "
+ "pairs, or both. For example, to set the default log level to 'warn' but "
+ "disable logging for the 'ui' component, pass 'warn,ui=off'. "
+ "levels:{trace,debug,info,warning,error,critical,off} "
+ "components:{crypto,db,mtx,net,qml,ui}"),
+ QObject::tr("level"));
+ parser.addOption(logLevel);
+ QCommandLineOption logType(
+ QStringList() << QStringLiteral("L") << QStringLiteral("log-type"),
+ QObject::tr("Set the log output type. A comma-separated list is allowed. "
+ "The default is 'file,stderr'. types:{file,stderr,none}"),
+ QObject::tr("type"));
+ parser.addOption(logType);
// This option is not actually parsed via Qt due to the need to parse it before the app
// name is set. It only exists to keep Qt from complaining about the --profile/-p
@@ -254,15 +270,36 @@ main(int argc, char *argv[])
}
#endif
- if (parser.isSet(debugOption))
- nhlog::enable_debug_log_from_commandline = true;
-
try {
- nhlog::init(QStringLiteral("%1/nheko.log")
- .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
- .toStdString());
+ QString level;
+ if (parser.isSet(logLevel)) {
+ level = parser.value(logLevel);
+ } else if (parser.isSet(debugOption)) {
+ level = "trace";
+ } else {
+ level = qEnvironmentVariable("NHEKO_LOG_LEVEL");
+ }
+
+ QStringList targets =
+ (parser.isSet(logType) ? parser.value(logType)
+ : qEnvironmentVariable("NHEKO_LOG_TYPE", "file,stderr"))
+ .split(',', Qt::SkipEmptyParts);
+ targets.removeAll("none");
+ bool to_stderr = bool(targets.removeAll("stderr"));
+ QString path = targets.removeAll("file")
+ ? QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+ .filePath("nheko.log")
+ : QLatin1String("");
+ if (!targets.isEmpty()) {
+ std::cerr << "Invalid log type '" << targets.first().toStdString().c_str() << "'"
+ << std::endl;
+ std::exit(1);
+ }
+
+ nhlog::init(level, path, to_stderr);
+
} catch (const spdlog::spdlog_ex &ex) {
- std::cout << "Log initialization failed: " << ex.what() << std::endl;
+ std::cerr << "Log initialization failed: " << ex.what() << std::endl;
std::exit(1);
}
|