mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-03-22 12:08:43 -04:00
Set up for Boost logging in WSJT-X
uses a settings file to define log sink back-ends, by default uses :/wsjtx_log_config.ini from the resources file-system. Users may override by placing their own wsjtx_log_config.ini into the WSJT-X config location. The settings file format is as described in the Boost log documentation (https://www.boost.org/doc/libs/1_74_0/libs/log/doc/html/log/detailed/utilities.html#log.detailed.utilities.setup.settings_file) with the additional feature that allows some pre-defined variables to be expanded. The predefined variables refer to standard locations in the file-system, and allow log files and rotation target directory paths to be specified. The pre-defined variables are: DesktopLocation DocumentsLocation TempLocation HomeLocation CacheLocation GenericCacheLocation GenericDataLocation AppDataLocation and must be used enclosed on braces and preceded by a '$' character. E.g. to define the pattern for a sink's log file: FileName="${AppLocalDataLocation}/wsjtx_syslog.log" this would place the log file wsjtx_syslog.log in the WSJT-X log files directory, on all platforms.
This commit is contained in:
parent
b420c9f6d3
commit
f66788691d
@ -305,6 +305,7 @@ set (jt9_FSRCS
|
||||
)
|
||||
|
||||
set (wsjtx_CXXSRCS
|
||||
WSJTXLogging.cpp
|
||||
logbook/logbook.cpp
|
||||
Network/PSKReporter.cpp
|
||||
Modulator/Modulator.cpp
|
||||
|
114
WSJTXLogging.cpp
Normal file
114
WSJTXLogging.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "WSJTXLogging.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/container/flat_map.hpp>
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QString>
|
||||
#include <QStandardPaths>
|
||||
#include <QRegularExpression>
|
||||
#include <QMessageLogContext>
|
||||
|
||||
#include "Logger.hpp"
|
||||
#include "qt_helpers.hpp"
|
||||
|
||||
namespace logging = boost::log;
|
||||
namespace container = boost::container;
|
||||
|
||||
WSJTXLogging::WSJTXLogging ()
|
||||
{
|
||||
QFile log_config {QStandardPaths::locate (QStandardPaths::ConfigLocation, "wsjtx_log_config.ini")};
|
||||
if (!log_config.exists ())
|
||||
{
|
||||
log_config.setFileName (":/wsjtx_log_config.ini");
|
||||
}
|
||||
if (log_config.open (QFile::ReadOnly) && log_config.isReadable ())
|
||||
{
|
||||
QTextStream ts {&log_config};
|
||||
auto config = ts.readAll ();
|
||||
|
||||
// substitute variable
|
||||
container::flat_map<QString, QString> replacements =
|
||||
{
|
||||
{"DesktopLocation", QStandardPaths::writableLocation (QStandardPaths::DesktopLocation)},
|
||||
{"DocumentsLocation", QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation)},
|
||||
{"TempLocation", QStandardPaths::writableLocation (QStandardPaths::TempLocation)},
|
||||
{"HomeLocation", QStandardPaths::writableLocation (QStandardPaths::HomeLocation)},
|
||||
{"CacheLocation", QStandardPaths::writableLocation (QStandardPaths::CacheLocation)},
|
||||
{"GenericCacheLocation", QStandardPaths::writableLocation (QStandardPaths::GenericCacheLocation)},
|
||||
{"GenericDataLocation", QStandardPaths::writableLocation (QStandardPaths::GenericDataLocation)},
|
||||
{"AppDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppDataLocation)},
|
||||
{"AppLocalDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)},
|
||||
};
|
||||
QString new_config;
|
||||
int pos {0};
|
||||
QRegularExpression subst_vars {R"(\${([^}]+)})"};
|
||||
auto iter = subst_vars.globalMatch (config);
|
||||
while (iter.hasNext ())
|
||||
{
|
||||
auto match = iter.next ();
|
||||
auto const& name = match.captured (1);
|
||||
auto repl_iter = replacements.find (name);
|
||||
auto repl = repl_iter != replacements.end () ? repl_iter->second : "${" + name + "}";
|
||||
new_config += config.mid (pos, match.capturedStart (1) - 2 - pos) + repl;
|
||||
pos = match.capturedEnd (0);
|
||||
}
|
||||
new_config += config.mid (pos);
|
||||
std::stringbuf buffer {new_config.toStdString (), std::ios_base::in};
|
||||
std::istream stream {&buffer};
|
||||
Logger::init_from_config (stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARN ("Unable to read logging configuration file: " << log_config.fileName ());
|
||||
}
|
||||
}
|
||||
|
||||
WSJTXLogging::~WSJTXLogging ()
|
||||
{
|
||||
LOG_INFO ("Log Finish");
|
||||
auto lg = logging::core::get ();
|
||||
lg->flush ();
|
||||
lg->remove_all_sinks ();
|
||||
}
|
||||
|
||||
// Reroute Qt messages to the system logger
|
||||
void WSJTXLogging::qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg)
|
||||
{
|
||||
// Convert Qt message types to logger severities
|
||||
auto severity = boost::log::trivial::trace;
|
||||
switch (type)
|
||||
{
|
||||
case QtDebugMsg: severity = boost::log::trivial::debug; break;
|
||||
case QtInfoMsg: severity = boost::log::trivial::info; break;
|
||||
case QtWarningMsg: severity = boost::log::trivial::warning; break;
|
||||
case QtCriticalMsg: severity = boost::log::trivial::error; break;
|
||||
case QtFatalMsg: severity = boost::log::trivial::fatal; break;
|
||||
}
|
||||
// Map non-default Qt categories to logger channels, Qt logger
|
||||
// context is mapped to the appropriate logger attributes.
|
||||
auto log = Logger::sys::get ();
|
||||
if (!qstrcmp (context.category, "default"))
|
||||
{
|
||||
BOOST_LOG_SEV (log, severity)
|
||||
<< boost::log::add_value ("Line", context.line)
|
||||
<< boost::log::add_value ("File", context.file)
|
||||
<< boost::log::add_value ("Function", context.function)
|
||||
<< msg.toStdString ();
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_LOG_CHANNEL_SEV (log, context.category, severity)
|
||||
<< boost::log::add_value ("Line", context.line)
|
||||
<< boost::log::add_value ("File", context.file)
|
||||
<< boost::log::add_value ("Function", context.function)
|
||||
<< msg.toStdString ();
|
||||
}
|
||||
if (QtFatalMsg == type)
|
||||
{
|
||||
// bail out
|
||||
throw std::runtime_error {"Fatal Qt Error"};
|
||||
}
|
||||
}
|
23
WSJTXLogging.hpp
Normal file
23
WSJTXLogging.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef WSJTX_LOGGING_HPP__
|
||||
#define WSJTX_LOGGING_HPP__
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class QString;
|
||||
|
||||
//
|
||||
// Class WSJTXLogging - wraps application specific logging
|
||||
//
|
||||
class WSJTXLogging final
|
||||
{
|
||||
public:
|
||||
explicit WSJTXLogging ();
|
||||
~WSJTXLogging ();
|
||||
|
||||
//
|
||||
// Install this as the Qt message handler (qInstallMessageHandler)
|
||||
// to integrate Qt messages.
|
||||
static void qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const&);
|
||||
};
|
||||
|
||||
#endif
|
33
main.cpp
33
main.cpp
@ -34,7 +34,8 @@
|
||||
#include "qt_helpers.hpp"
|
||||
#include "L10nLoader.hpp"
|
||||
#include "SettingsGroup.hpp"
|
||||
#include "TraceFile.hpp"
|
||||
//#include "TraceFile.hpp"
|
||||
#include "WSJTXLogging.hpp"
|
||||
#include "MultiSettings.hpp"
|
||||
#include "widgets/mainwindow.h"
|
||||
#include "commons.h"
|
||||
@ -98,9 +99,7 @@ namespace
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ### Add timestamps to all debug messages
|
||||
// qSetMessagePattern ("[%{time yyyyMMdd HH:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{message}");
|
||||
|
||||
::qInstallMessageHandler (&WSJTXLogging::qt_log_handler);
|
||||
init_random_seed ();
|
||||
|
||||
// make the Qt type magic happen
|
||||
@ -113,15 +112,15 @@ int main(int argc, char *argv[])
|
||||
ExceptionCatchingApplication a(argc, argv);
|
||||
try
|
||||
{
|
||||
// qDebug () << "+++++++++++++++++++++++++++ Resources ++++++++++++++++++++++++++++";
|
||||
// LOG_INfO ("+++++++++++++++++++++++++++ Resources ++++++++++++++++++++++++++++");
|
||||
// {
|
||||
// QDirIterator resources_iter {":/", QDirIterator::Subdirectories};
|
||||
// while (resources_iter.hasNext ())
|
||||
// {
|
||||
// qDebug () << resources_iter.next ();
|
||||
// LOG_INFO (resources_iter.next ());
|
||||
// }
|
||||
// }
|
||||
// qDebug () << "--------------------------- Resources ----------------------------";
|
||||
// LOG_INFO ("--------------------------- Resources ----------------------------");
|
||||
|
||||
QLocale locale; // get the current system locale
|
||||
setlocale (LC_NUMERIC, "C"); // ensure number forms are in
|
||||
@ -179,9 +178,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// load UI translations
|
||||
L10nLoader l10n {&a, locale, parser.value (lang_option)};
|
||||
|
||||
QStandardPaths::setTestModeEnabled (parser.isSet (test_option));
|
||||
|
||||
// support for multiple instances running from a single installation
|
||||
@ -224,8 +220,8 @@ int main(int argc, char *argv[])
|
||||
if (QLockFile::LockFailedError == instance_lock.error ())
|
||||
{
|
||||
auto button = MessageBox::query_message (nullptr
|
||||
, a.translate ("main", "Another instance may be running")
|
||||
, a.translate ("main", "try to remove stale lock file?")
|
||||
, "Another instance may be running"
|
||||
, "try to remove stale lock file?"
|
||||
, QString {}
|
||||
, MessageBox::Yes | MessageBox::Retry | MessageBox::No
|
||||
, MessageBox::Yes);
|
||||
@ -244,12 +240,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
#if WSJT_QDEBUG_TO_FILE
|
||||
// Open a trace file
|
||||
TraceFile trace_file {temp_dir.absoluteFilePath (a.applicationName () + "_trace.log")};
|
||||
qSetMessagePattern ("[%{time yyyyMMdd HH:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}");
|
||||
qDebug () << program_title (revision ()) + " - Program startup";
|
||||
#endif
|
||||
WSJTXLogging lg;
|
||||
LOG_INFO (program_title (revision ()) << " - Program startup");
|
||||
|
||||
// load UI translations
|
||||
L10nLoader l10n {&a, locale, parser.value (lang_option)};
|
||||
|
||||
// Create a unique writeable temporary directory in a suitable location
|
||||
bool temp_ok {false};
|
||||
@ -382,7 +377,7 @@ int main(int argc, char *argv[])
|
||||
a.translate ("main", "Unable to create shared memory segment"));
|
||||
throw std::runtime_error {"Shared memory error"};
|
||||
}
|
||||
qDebug () << "shmem size:" << mem_jt9.size ();
|
||||
LOG_INFO ("shmem size:" << mem_jt9.size ());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user