mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-25 05:38:46 -05:00
Boost log set up for WSJT-X
Rotated log files limited to ten saved logs with timestamped and counted file names. Logs written to writeable files directory. Formats and file names hard coded with expression templates fro efficiency, but with the ability to provide a user-defined configuration file that overrides the hard-coded defaults. The configuration file must be in the configuration files directory and named wsjtx_log_config.ini.
This commit is contained in:
parent
98997fb745
commit
3fafbdaaa3
@ -248,7 +248,6 @@ set (wsjt_qt_CXXSRCS
|
|||||||
item_delegates/ForeignKeyDelegate.cpp
|
item_delegates/ForeignKeyDelegate.cpp
|
||||||
validators/LiveFrequencyValidator.cpp
|
validators/LiveFrequencyValidator.cpp
|
||||||
GetUserId.cpp
|
GetUserId.cpp
|
||||||
TraceFile.cpp
|
|
||||||
Audio/AudioDevice.cpp
|
Audio/AudioDevice.cpp
|
||||||
Transceiver/Transceiver.cpp
|
Transceiver/Transceiver.cpp
|
||||||
Transceiver/TransceiverBase.cpp
|
Transceiver/TransceiverBase.cpp
|
||||||
@ -753,7 +752,6 @@ set (all_C_and_CXXSRCS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set (TOP_LEVEL_RESOURCES
|
set (TOP_LEVEL_RESOURCES
|
||||||
wsjtx_log_config.ini
|
|
||||||
icons/Darwin/wsjtx.iconset/icon_128x128.png
|
icons/Darwin/wsjtx.iconset/icon_128x128.png
|
||||||
contrib/gpl-v3-logo.svg
|
contrib/gpl-v3-logo.svg
|
||||||
artwork/splash.png
|
artwork/splash.png
|
||||||
@ -885,7 +883,8 @@ find_program(ETAGS etags)
|
|||||||
# set (BOOST_ROOT ${PROJECT_SOURCE_DIR}/boost)
|
# set (BOOST_ROOT ${PROJECT_SOURCE_DIR}/boost)
|
||||||
# endif ()
|
# endif ()
|
||||||
set (Boost_USE_STATIC_LIBS OFF)
|
set (Boost_USE_STATIC_LIBS OFF)
|
||||||
find_package (Boost 1.63 REQUIRED COMPONENTS log_setup log)
|
find_package (Boost 1.63 REQUIRED COMPONENTS log_setup)
|
||||||
|
add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED)
|
||||||
|
|
||||||
#
|
#
|
||||||
# OpenMP
|
# OpenMP
|
||||||
@ -1432,9 +1431,9 @@ set_target_properties (wsjtx PROPERTIES
|
|||||||
|
|
||||||
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
|
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
|
target_link_libraries (wsjtx wsjt_fort)
|
||||||
else ()
|
else ()
|
||||||
target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
|
target_link_libraries (wsjtx wsjt_fort_omp)
|
||||||
if (OpenMP_C_FLAGS)
|
if (OpenMP_C_FLAGS)
|
||||||
set_target_properties (wsjtx PROPERTIES
|
set_target_properties (wsjtx PROPERTIES
|
||||||
COMPILE_FLAGS "${OpenMP_C_FLAGS}"
|
COMPILE_FLAGS "${OpenMP_C_FLAGS}"
|
||||||
@ -1450,6 +1449,7 @@ else ()
|
|||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
target_link_libraries (wsjtx Qt5::SerialPort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
|
||||||
|
|
||||||
# make a library for WSJT-X UDP servers
|
# make a library for WSJT-X UDP servers
|
||||||
# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
|
# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
|
||||||
|
107
WSJTXLogging.cpp
107
WSJTXLogging.cpp
@ -1,9 +1,21 @@
|
|||||||
#include "WSJTXLogging.hpp"
|
#include "WSJTXLogging.hpp"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <boost/log/core.hpp>
|
||||||
|
#include <boost/log/utility/exception_handler.hpp>
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <boost/log/sinks/text_file_backend.hpp>
|
||||||
|
#include <boost/log/sinks/async_frontend.hpp>
|
||||||
|
#include <boost/log/sinks/debug_output_backend.hpp>
|
||||||
|
#include <boost/log/expressions.hpp>
|
||||||
|
#include <boost/log/expressions/formatters/date_time.hpp>
|
||||||
|
#include <boost/log/support/date_time.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <boost/container/flat_map.hpp>
|
#include <boost/container/flat_map.hpp>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -15,21 +27,48 @@
|
|||||||
#include "qt_helpers.hpp"
|
#include "qt_helpers.hpp"
|
||||||
|
|
||||||
namespace logging = boost::log;
|
namespace logging = boost::log;
|
||||||
|
namespace keywords = logging::keywords;
|
||||||
|
namespace expr = logging::expressions;
|
||||||
|
namespace sinks = logging::sinks;
|
||||||
|
namespace ptime = boost::posix_time;
|
||||||
namespace container = boost::container;
|
namespace container = boost::container;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Top level exception handler that gets exceptions from filters and
|
||||||
|
// formatters.
|
||||||
|
struct exception_handler
|
||||||
|
{
|
||||||
|
typedef void result;
|
||||||
|
|
||||||
|
void operator () (std::runtime_error const& e) const
|
||||||
|
{
|
||||||
|
std::cout << "std::runtime_error: " << e.what () << std::endl;
|
||||||
|
}
|
||||||
|
void operator () (std::logic_error const& e) const
|
||||||
|
{
|
||||||
|
std::cout << "std::logic_error: " << e.what () << std::endl;
|
||||||
|
//throw;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
WSJTXLogging::WSJTXLogging ()
|
WSJTXLogging::WSJTXLogging ()
|
||||||
{
|
{
|
||||||
|
// Catch relevant exceptions from logging.
|
||||||
|
logging::core::get ()->set_exception_handler
|
||||||
|
(
|
||||||
|
logging::make_exception_handler<std::runtime_error, std::logic_error> (exception_handler {})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check for a user-defined logging configuration settings file.
|
||||||
QFile log_config {QStandardPaths::locate (QStandardPaths::ConfigLocation, "wsjtx_log_config.ini")};
|
QFile log_config {QStandardPaths::locate (QStandardPaths::ConfigLocation, "wsjtx_log_config.ini")};
|
||||||
if (!log_config.exists ())
|
if (log_config.exists () && log_config.open (QFile::ReadOnly) && log_config.isReadable ())
|
||||||
{
|
|
||||||
log_config.setFileName (":/wsjtx_log_config.ini");
|
|
||||||
}
|
|
||||||
if (log_config.open (QFile::ReadOnly) && log_config.isReadable ())
|
|
||||||
{
|
{
|
||||||
QTextStream ts {&log_config};
|
QTextStream ts {&log_config};
|
||||||
auto config = ts.readAll ();
|
auto config = ts.readAll ();
|
||||||
|
|
||||||
// substitute variable
|
// Substitution variables.
|
||||||
container::flat_map<QString, QString> replacements =
|
container::flat_map<QString, QString> replacements =
|
||||||
{
|
{
|
||||||
{"DesktopLocation", QStandardPaths::writableLocation (QStandardPaths::DesktopLocation)},
|
{"DesktopLocation", QStandardPaths::writableLocation (QStandardPaths::DesktopLocation)},
|
||||||
@ -42,6 +81,7 @@ WSJTXLogging::WSJTXLogging ()
|
|||||||
{"AppDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppDataLocation)},
|
{"AppDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppDataLocation)},
|
||||||
{"AppLocalDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)},
|
{"AppLocalDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)},
|
||||||
};
|
};
|
||||||
|
// Parse the configration settings substituting the variable if found.
|
||||||
QString new_config;
|
QString new_config;
|
||||||
int pos {0};
|
int pos {0};
|
||||||
QRegularExpression subst_vars {R"(\${([^}]+)})"};
|
QRegularExpression subst_vars {R"(\${([^}]+)})"};
|
||||||
@ -59,11 +99,62 @@ WSJTXLogging::WSJTXLogging ()
|
|||||||
std::stringbuf buffer {new_config.toStdString (), std::ios_base::in};
|
std::stringbuf buffer {new_config.toStdString (), std::ios_base::in};
|
||||||
std::istream stream {&buffer};
|
std::istream stream {&buffer};
|
||||||
Logger::init_from_config (stream);
|
Logger::init_from_config (stream);
|
||||||
|
LOG_INFO ("Unable to read logging configuration file: " << log_config.fileName ());
|
||||||
}
|
}
|
||||||
else
|
else // Default setup
|
||||||
{
|
{
|
||||||
LOG_WARN ("Unable to read logging configuration file: " << log_config.fileName ());
|
//
|
||||||
|
// Define sinks, filters, and formatters using expression
|
||||||
|
// templates for efficiency.
|
||||||
|
//
|
||||||
|
// Default log file location.
|
||||||
|
QDir app_data {QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)};
|
||||||
|
Logger::init (); // Basic setup of attributes
|
||||||
|
auto core = logging::core::get ();
|
||||||
|
//
|
||||||
|
// Sink intended for general use that passes everything above
|
||||||
|
// selected severity levels per channel. Log file is appended
|
||||||
|
// between sessions and rotated to limit storage space usage.
|
||||||
|
//
|
||||||
|
auto sys_sink = boost::make_shared<sinks::asynchronous_sink<sinks::text_file_backend>>
|
||||||
|
(
|
||||||
|
keywords::auto_flush = false
|
||||||
|
, keywords::file_name = app_data.absoluteFilePath ("wsjtx_syslog.log").toStdString ()
|
||||||
|
, keywords::target_file_name = app_data.absoluteFilePath ("old_logs/wsjtx_syslog_%Y-%m-%d_%H-%M-%S.%N.log").toStdString ()
|
||||||
|
, keywords::rotation_size = 5 * 1024 * 1024
|
||||||
|
, keywords::time_based_rotation = sinks::file::rotation_at_time_point (0, 0, 0)
|
||||||
|
, keywords::open_mode = std::ios_base::out | std::ios_base::app
|
||||||
|
, keywords::enable_final_rotation = false
|
||||||
|
);
|
||||||
|
sys_sink->locked_backend ()->set_file_collector
|
||||||
|
(
|
||||||
|
sinks::file::make_collector
|
||||||
|
(
|
||||||
|
keywords::target = app_data.absoluteFilePath ("old_logs").toStdString ()
|
||||||
|
, keywords::max_size = 40 * 1024 * 1024
|
||||||
|
, keywords::min_free_space = 1024 * 1024 * 1024
|
||||||
|
, keywords::max_files = 10
|
||||||
|
)
|
||||||
|
);
|
||||||
|
sys_sink->locked_backend ()->scan_for_files ();
|
||||||
|
sys_sink->set_formatter
|
||||||
|
(
|
||||||
|
expr::stream
|
||||||
|
<< "[" << expr::format_date_time<ptime::ptime> ("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
|
||||||
|
<< "][" << expr::format_date_time<ptime::time_duration> ("Uptime", "%O:%M:%S.%f")
|
||||||
|
<< "][" << logging::trivial::severity
|
||||||
|
<< "] " << expr::message
|
||||||
|
);
|
||||||
|
core->add_sink (sys_sink);
|
||||||
|
|
||||||
|
#if !defined (NDEBUG) && defined (Q_OS_WIN)
|
||||||
|
// auto windbg_sink = boost::make_shared<sinks::synchronous_sink<sinks::debug_output_backend>> ();
|
||||||
|
// windbg_sink->set_filter (logging::trivial::severity >= logging::trivial::trace && expr::is_debugger_present ());
|
||||||
|
// logging::core::get ()->add_sink (windbg_sink);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
// Indicate start of logging
|
||||||
|
LOG_INFO ("Log Start");
|
||||||
}
|
}
|
||||||
|
|
||||||
WSJTXLogging::~WSJTXLogging ()
|
WSJTXLogging::~WSJTXLogging ()
|
||||||
|
@ -17,12 +17,10 @@ Destination="TextFile"
|
|||||||
Asynchronous="true"
|
Asynchronous="true"
|
||||||
# If AutoFlush is true then non-buffered output
|
# If AutoFlush is true then non-buffered output
|
||||||
AutoFlush="true"
|
AutoFlush="true"
|
||||||
Append="true"
|
|
||||||
# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID, Line, File, Function
|
# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID, Line, File, Function
|
||||||
# TimeStamp and Uptime support boost date time format:
|
# TimeStamp and Uptime support boost date time format:
|
||||||
# http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
# http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
||||||
#Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %File%(%Line%) %Function%: %Message%"
|
Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %File%(%Line%) %Function%: %Message%"
|
||||||
Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Severity%\t] %Message%"
|
|
||||||
# Target directory in which rotated files will be stored.
|
# Target directory in which rotated files will be stored.
|
||||||
Target="${AppLocalDataLocation}/old_logs"
|
Target="${AppLocalDataLocation}/old_logs"
|
||||||
# FileName pattern to use. %N is a counter for files.
|
# FileName pattern to use. %N is a counter for files.
|
||||||
@ -31,14 +29,17 @@ TargetFileName="wsjtx_syslog_%5N.log"
|
|||||||
# RotationSize in bytes, File size, in bytes, upon which file rotation will be performed.
|
# RotationSize in bytes, File size, in bytes, upon which file rotation will be performed.
|
||||||
# Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs.
|
# Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs.
|
||||||
RotationSize="1048576"
|
RotationSize="1048576"
|
||||||
EnableFinalRotation="false"
|
# If Append is true then do not start a new log file for each session
|
||||||
|
Append="false"
|
||||||
|
# EnableFinalRotation will rotate on close, make this false if using Append true
|
||||||
|
EnableFinalRotation="true"
|
||||||
# Matching used so that only files matching FileName pattern are deleted.
|
# Matching used so that only files matching FileName pattern are deleted.
|
||||||
ScanForFiles="Matching"
|
ScanForFiles="Matching"
|
||||||
# MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted.
|
# MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted.
|
||||||
#MaxSize=100485760
|
#MaxSize=100485760
|
||||||
# MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted.
|
# MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted.
|
||||||
#MinFreeSpace=1485760
|
#MinFreeSpace=1485760
|
||||||
MaxFiles="10"
|
#MaxFiles="10"
|
||||||
# Specify level of log, options are: trace, debug, info, warning, error, fatal
|
# Specify level of log, options are: trace, debug, info, warning, error, fatal
|
||||||
# Since Channel not part of filter all log output will be included.
|
# Since Channel not part of filter all log output will be included.
|
||||||
# If only SYSLOG logging desired, change to: Filter="%Severity% >= trace & %Channel% matches \"SYSLOG\""
|
# If only SYSLOG logging desired, change to: Filter="%Severity% >= trace & %Channel% matches \"SYSLOG\""
|
||||||
@ -50,7 +51,7 @@ Destination="TextFile"
|
|||||||
# If Asynchronous true then thread dedicated to writing to log, otherwise blocks main thread to write.
|
# If Asynchronous true then thread dedicated to writing to log, otherwise blocks main thread to write.
|
||||||
Asynchronous="true"
|
Asynchronous="true"
|
||||||
# If AutoFlush is true then non-buffered output
|
# If AutoFlush is true then non-buffered output
|
||||||
AutoFlush="true"
|
AutoFlush="false"
|
||||||
Append="true"
|
Append="true"
|
||||||
# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID
|
# Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID
|
||||||
# TimeStamp and Uptime support boost date time format:
|
# TimeStamp and Uptime support boost date time format:
|
||||||
|
Loading…
Reference in New Issue
Block a user