mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-07-31 13:12:30 -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
|
set (wsjtx_CXXSRCS
|
||||||
|
WSJTXLogging.cpp
|
||||||
logbook/logbook.cpp
|
logbook/logbook.cpp
|
||||||
Network/PSKReporter.cpp
|
Network/PSKReporter.cpp
|
||||||
Modulator/Modulator.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 "qt_helpers.hpp"
|
||||||
#include "L10nLoader.hpp"
|
#include "L10nLoader.hpp"
|
||||||
#include "SettingsGroup.hpp"
|
#include "SettingsGroup.hpp"
|
||||||
#include "TraceFile.hpp"
|
//#include "TraceFile.hpp"
|
||||||
|
#include "WSJTXLogging.hpp"
|
||||||
#include "MultiSettings.hpp"
|
#include "MultiSettings.hpp"
|
||||||
#include "widgets/mainwindow.h"
|
#include "widgets/mainwindow.h"
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
@ -98,9 +99,7 @@ namespace
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// ### Add timestamps to all debug messages
|
::qInstallMessageHandler (&WSJTXLogging::qt_log_handler);
|
||||||
// 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}");
|
|
||||||
|
|
||||||
init_random_seed ();
|
init_random_seed ();
|
||||||
|
|
||||||
// make the Qt type magic happen
|
// make the Qt type magic happen
|
||||||
@ -113,15 +112,15 @@ int main(int argc, char *argv[])
|
|||||||
ExceptionCatchingApplication a(argc, argv);
|
ExceptionCatchingApplication a(argc, argv);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// qDebug () << "+++++++++++++++++++++++++++ Resources ++++++++++++++++++++++++++++";
|
// LOG_INfO ("+++++++++++++++++++++++++++ Resources ++++++++++++++++++++++++++++");
|
||||||
// {
|
// {
|
||||||
// QDirIterator resources_iter {":/", QDirIterator::Subdirectories};
|
// QDirIterator resources_iter {":/", QDirIterator::Subdirectories};
|
||||||
// while (resources_iter.hasNext ())
|
// 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
|
QLocale locale; // get the current system locale
|
||||||
setlocale (LC_NUMERIC, "C"); // ensure number forms are in
|
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));
|
QStandardPaths::setTestModeEnabled (parser.isSet (test_option));
|
||||||
|
|
||||||
// support for multiple instances running from a single installation
|
// 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 ())
|
if (QLockFile::LockFailedError == instance_lock.error ())
|
||||||
{
|
{
|
||||||
auto button = MessageBox::query_message (nullptr
|
auto button = MessageBox::query_message (nullptr
|
||||||
, a.translate ("main", "Another instance may be running")
|
, "Another instance may be running"
|
||||||
, a.translate ("main", "try to remove stale lock file?")
|
, "try to remove stale lock file?"
|
||||||
, QString {}
|
, QString {}
|
||||||
, MessageBox::Yes | MessageBox::Retry | MessageBox::No
|
, MessageBox::Yes | MessageBox::Retry | MessageBox::No
|
||||||
, MessageBox::Yes);
|
, MessageBox::Yes);
|
||||||
@ -244,12 +240,11 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WSJT_QDEBUG_TO_FILE
|
WSJTXLogging lg;
|
||||||
// Open a trace file
|
LOG_INFO (program_title (revision ()) << " - Program startup");
|
||||||
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}");
|
// load UI translations
|
||||||
qDebug () << program_title (revision ()) + " - Program startup";
|
L10nLoader l10n {&a, locale, parser.value (lang_option)};
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create a unique writeable temporary directory in a suitable location
|
// Create a unique writeable temporary directory in a suitable location
|
||||||
bool temp_ok {false};
|
bool temp_ok {false};
|
||||||
@ -382,7 +377,7 @@ int main(int argc, char *argv[])
|
|||||||
a.translate ("main", "Unable to create shared memory segment"));
|
a.translate ("main", "Unable to create shared memory segment"));
|
||||||
throw std::runtime_error {"Shared memory error"};
|
throw std::runtime_error {"Shared memory error"};
|
||||||
}
|
}
|
||||||
qDebug () << "shmem size:" << mem_jt9.size ();
|
LOG_INFO ("shmem size:" << mem_jt9.size ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user