Merge branch 'feature/ImproveLog#4' into develop

pull/11/head
Geoffrey Merck 4 years ago
commit cf9bddc312

@ -36,6 +36,8 @@
#include "RepeaterProtocolHandlerFactory.h"
#include "XLXHostsFileDownloader.h"
#include "Log.h"
#include "LogFileTarget.h"
#include "LogConsoleTarget.h"
int main(int argc, char *argv[])
{
@ -84,6 +86,7 @@ void CDStarGatewayApp::run()
m_thread->Run();
m_thread->Wait();
CLog::logInfo("exiting\n");
CLog::finalise();
}
bool CDStarGatewayApp::createThread()
@ -98,9 +101,12 @@ bool CDStarGatewayApp::createThread()
return false;
}
// Setup Log
TLog log;
config.getLog(log);
CLog::initialize(log.logDir + "dstargateway.log", LS_INFO, true);
CLog::finalise();
if(log.m_displayLevel != LOG_NONE) CLog::addTarget(new CLogConsoleTarget(log.m_displayLevel));
if(log.m_fileLevel != LOG_NONE) CLog::addTarget(new CLogFileTarget(log.m_fileLevel, log.logDir, log.m_fileRotate));
Tpaths paths;
config.getPaths(paths);

@ -126,13 +126,38 @@ bool CDStarGatewayConfig::loadAPRS(const CConfig & cfg)
bool CDStarGatewayConfig::loadLog(const CConfig & cfg)
{
bool ret =cfg.getValue("log", "path", m_log.logDir, 0, 2048, "/var/log/dstargateway/");
bool ret = cfg.getValue("log", "path", m_log.logDir, 0, 2048, "/var/log/dstargateway/");
if(ret && m_log.logDir[m_log.logDir.length() - 1] != '/') {
m_log.logDir.push_back('/');
}
//TODO 20211226 check if directory are accessible
ret = cfg.getValue("log", "fileRoot", m_log.m_fileRoot, 0, 64, "dstargateway") && ret;
ret = cfg.getValue("log", "fileRotate", m_log.m_fileRotate, true) && ret;
std::string levelStr;
ret = cfg.getValue("log", "fileLevel", levelStr, "info", {"trace", "debug", "info", "warning", "error", "fatal", "none"}) && ret;
if(ret) {
if(levelStr == "trace") m_log.m_fileLevel = LOG_TRACE;
else if(levelStr == "debug") m_log.m_fileLevel = LOG_DEBUG;
else if(levelStr == "info") m_log.m_fileLevel = LOG_INFO;
else if(levelStr == "warning") m_log.m_fileLevel = LOG_WARNING;
else if(levelStr == "error") m_log.m_fileLevel = LOG_ERROR;
else if(levelStr == "fatal") m_log.m_fileLevel = LOG_FATAL;
else if(levelStr == "none") m_log.m_fileLevel = LOG_NONE;
}
ret = cfg.getValue("log", "displayLevel", levelStr, "info", {"trace", "debug", "info", "warning", "error", "fatal", "none"}) && ret;
if(ret) {
if(levelStr == "trace") m_log.m_displayLevel = LOG_TRACE;
else if(levelStr == "debug") m_log.m_displayLevel = LOG_DEBUG;
else if(levelStr == "info") m_log.m_displayLevel = LOG_INFO;
else if(levelStr == "warning") m_log.m_displayLevel = LOG_WARNING;
else if(levelStr == "error") m_log.m_displayLevel = LOG_ERROR;
else if(levelStr == "fatal") m_log.m_displayLevel = LOG_FATAL;
else if(levelStr == "none") m_log.m_displayLevel = LOG_NONE;
}
//TODO 20211226 check if directories are accessible
return ret;
}

@ -23,6 +23,7 @@
#include "Defs.h"
#include "Config.h"
#include "LogSeverity.h"
typedef struct {
GATEWAY_TYPE type;
@ -79,6 +80,10 @@ typedef struct {
typedef struct {
std::string logDir;
LOG_SEVERITY m_displayLevel;
LOG_SEVERITY m_fileLevel;
std::string m_fileRoot;
bool m_fileRotate;
} TLog;
typedef struct {

@ -745,7 +745,7 @@ void CDStarGatewayThread::processIrcDDB()
break;
if (!address.empty()) {
CLog::logInfo("USER: %s %s %s %s", user.c_str(), repeater.c_str(), gateway.c_str(), address.c_str());
CLog::logDebug("USER: %s %s %s %s", user.c_str(), repeater.c_str(), gateway.c_str(), address.c_str());
m_cache.updateUser(user, repeater, gateway, address, timestamp, DP_DEXTRA, false, false);
#if defined(ENABLE_NAT_TRAVERSAL)
m_natTraversal->traverseNatG2(address);
@ -764,7 +764,7 @@ void CDStarGatewayThread::processIrcDDB()
CRepeaterHandler::resolveRepeater(repeater, gateway, address, DP_DEXTRA);
if (!address.empty()) {
CLog::logInfo("REPEATER: %s %s %s", repeater.c_str(), gateway.c_str(), address.c_str());
CLog::logDebug("REPEATER: %s %s %s", repeater.c_str(), gateway.c_str(), address.c_str());
m_cache.updateRepeater(repeater, gateway, address, DP_DEXTRA, false, false);
#if defined(ENABLE_NAT_TRAVERSAL)
m_natTraversal->traverseNatG2(address);
@ -784,7 +784,7 @@ void CDStarGatewayThread::processIrcDDB()
CDExtraHandler::gatewayUpdate(gateway, address);
CDPlusHandler::gatewayUpdate(gateway, address);
if (!address.empty()) {
CLog::logInfo("GATEWAY: %s %s", gateway.c_str(), address.c_str());
CLog::logDebug("GATEWAY: %s %s", gateway.c_str(), address.c_str());
m_cache.updateGateway(gateway, address, DP_DEXTRA, false, false);
#if defined(ENABLE_NAT_TRAVERSAL)
m_natTraversal->traverseNatG2(address);

@ -255,7 +255,7 @@ IRCDDB_RESPONSE_TYPE IRCDDBApp::getReplyMessageType()
if (0 == msgType.compare("IDRT_GATEWAY"))
return IDRT_GATEWAY;
CLog::logInfo("IRCDDBApp::getMessageType: unknown msg type: %s\n", msgType.c_str());
CLog::logWarning("IRCDDBApp::getMessageType: unknown msg type: %s\n", msgType.c_str());
return IDRT_NONE;
}

@ -88,27 +88,27 @@ bool CIRCDDBClient::sendHeard( const std::string& myCall, const std::string& myC
const std::string& rpt2, unsigned char flag1, unsigned char flag2, unsigned char flag3 )
{
if (myCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeard:myCall='%s' len != 8\n", myCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeard:myCall='%s' len != 8\n", myCall.c_str());
return false;
}
if (myCallExt.size() != 4) {
CLog::logInfo("CIRCDDBClient::sendHeard:myCallExt='%s' len != 4\n", myCallExt.c_str());
CLog::logDebug("CIRCDDBClient::sendHeard:myCallExt='%s' len != 4\n", myCallExt.c_str());
return false;
}
if (yourCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeard:yourCall='%s' len != 8\n", yourCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeard:yourCall='%s' len != 8\n", yourCall.c_str());
return false;
}
if (rpt1.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeard:rpt1='%s' len != 8\n", rpt1.c_str());
CLog::logDebug("CIRCDDBClient::sendHeard:rpt1='%s' len != 8\n", rpt1.c_str());
return false;
}
if (rpt2.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeard:rpt2='%s' len != 8\n", rpt2.c_str());
CLog::logDebug("CIRCDDBClient::sendHeard:rpt2='%s' len != 8\n", rpt2.c_str());
return false;
}
@ -117,7 +117,7 @@ bool CIRCDDBClient::sendHeard( const std::string& myCall, const std::string& myC
void CIRCDDBClient::sendDStarGatewayInfo(const std::string subcommand, const std::vector<std::string> parms)
{
CLog::logInfo("CIRCDDBClient::sendDStarGatewayInfo subcommand %s parms", subcommand.c_str());
CLog::logDebug("CIRCDDBClient::sendDStarGatewayInfo subcommand %s parms", subcommand.c_str());
for(unsigned int i=0; i < parms.size();i++)
CLog::logInfo(" %s", parms[i].c_str());
CLog::logInfo("\n");
@ -132,27 +132,27 @@ bool CIRCDDBClient::sendHeardWithTXMsg(const std::string& myCall, const std::str
const std::string& rpt2, unsigned char flag1, unsigned char flag2, unsigned char flag3, const std::string& network_destination, const std::string& tx_message)
{
if (myCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:myCall='%s' len != 8\n", myCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:myCall='%s' len != 8\n", myCall.c_str());
return false;
}
if (myCallExt.size() != 4) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:myCallExt='%s' len != 4\n", myCallExt.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:myCallExt='%s' len != 4\n", myCallExt.c_str());
return false;
}
if (yourCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:yourCall='%s' len != 8\n", yourCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:yourCall='%s' len != 8\n", yourCall.c_str());
return false;
}
if (rpt1.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:rpt1='%s' len != 8\n", rpt1.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:rpt1='%s' len != 8\n", rpt1.c_str());
return false;
}
if (rpt2.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:rpt2='%s' len != 8\n", rpt2.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:rpt2='%s' len != 8\n", rpt2.c_str());
return false;
}
@ -161,7 +161,7 @@ bool CIRCDDBClient::sendHeardWithTXMsg(const std::string& myCall, const std::str
dest = std::string(" ");
if (8 != dest.size()) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXMsg:network_destination='%s' len != 8\n", dest.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXMsg:network_destination='%s' len != 8\n", dest.c_str());
return false;
}
@ -184,42 +184,42 @@ bool CIRCDDBClient::sendHeardWithTXStats( const std::string& myCall, const std::
const std::string& rpt2, unsigned char flag1, unsigned char flag2, unsigned char flag3, int num_dv_frames, int num_dv_silent_frames, int num_bit_errors)
{
if ((num_dv_frames <= 0) || (num_dv_frames > 65535)) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:num_dv_frames=%d not in range 1-65535\n", num_dv_frames);
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:num_dv_frames=%d not in range 1-65535\n", num_dv_frames);
return false;
}
if (num_dv_silent_frames > num_dv_frames) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:num_dv_silent_frames=%d > num_dv_frames=%d\n", num_dv_silent_frames, num_dv_frames);
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:num_dv_silent_frames=%d > num_dv_frames=%d\n", num_dv_silent_frames, num_dv_frames);
return false;
}
if (num_bit_errors > (4*num_dv_frames)) { // max 4 bit errors per frame
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:num_bit_errors > (4*num_dv_frames), %d > 4*%d\n", num_bit_errors, num_dv_frames);
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:num_bit_errors > (4*num_dv_frames), %d > 4*%d\n", num_bit_errors, num_dv_frames);
return false;
}
if (myCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:myCall='%s' len != 8\n", myCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:myCall='%s' len != 8\n", myCall.c_str());
return false;
}
if (myCallExt.size() != 4) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:myCallExt='%s' len != 4\n", myCallExt.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:myCallExt='%s' len != 4\n", myCallExt.c_str());
return false;
}
if (yourCall.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:yourCall='%s' len != 8\n", yourCall.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:yourCall='%s' len != 8\n", yourCall.c_str());
return false;
}
if (rpt1.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:rpt1='%s' len != 8\n", rpt1.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:rpt1='%s' len != 8\n", rpt1.c_str());
return false;
}
if (rpt2.size() != 8) {
CLog::logInfo("CIRCDDBClient::sendHeardWithTXStats:rpt2='%s' len != 8\n", rpt2.c_str());
CLog::logDebug("CIRCDDBClient::sendHeardWithTXStats:rpt2='%s' len != 8\n", rpt2.c_str());
return false;
}
@ -245,7 +245,7 @@ bool CIRCDDBClient::sendHeardWithTXStats( const std::string& myCall, const std::
bool CIRCDDBClient::findGateway(const std::string& gatewayCallsign)
{
if (8 != gatewayCallsign.size()) {
CLog::logInfo("CIRCDDBClient::findGateway:gatewayCallsign='%s' len != 8\n", gatewayCallsign.c_str());
CLog::logDebug("CIRCDDBClient::findGateway:gatewayCallsign='%s' len != 8\n", gatewayCallsign.c_str());
return false;
}
std::string gw(gatewayCallsign);
@ -257,7 +257,7 @@ bool CIRCDDBClient::findGateway(const std::string& gatewayCallsign)
bool CIRCDDBClient::findRepeater(const std::string& repeaterCallsign)
{
if (8 != repeaterCallsign.size()) {
CLog::logInfo("CIRCDDBClient::findRepeater:repeaterCallsign='%s' len != 8\n", repeaterCallsign.c_str());
CLog::logDebug("CIRCDDBClient::findRepeater:repeaterCallsign='%s' len != 8\n", repeaterCallsign.c_str());
return false;
}
std::string rptr(repeaterCallsign);
@ -269,7 +269,7 @@ bool CIRCDDBClient::findRepeater(const std::string& repeaterCallsign)
bool CIRCDDBClient::findUser(const std::string& userCallsign)
{
if (8 != userCallsign.size()) {
CLog::logInfo("CIRCDDBClient::findUser:userCall='%s' len != 8\n", userCallsign.c_str());
CLog::logDebug("CIRCDDBClient::findUser:userCall='%s' len != 8\n", userCallsign.c_str());
return false;
}
std::string usr(userCallsign);
@ -292,24 +292,24 @@ bool CIRCDDBClient::receiveRepeater(std::string& repeaterCallsign, std::string&
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
if (rt != IDRT_REPEATER) {
CLog::logInfo("CIRCDDBClient::receiveRepeater: unexpected response type=%d\n", rt);
CLog::logDebug("CIRCDDBClient::receiveRepeater: unexpected response type=%d\n", rt);
return false;
}
IRCMessage *m = d->app->getReplyMessage();
if (m == NULL) {
CLog::logInfo("CIRCDDBClient::receiveRepeater: no message\n");
CLog::logDebug("CIRCDDBClient::receiveRepeater: no message\n");
return false;
}
if (m->getCommand().compare("IDRT_REPEATER")) {
CLog::logInfo("CIRCDDBClient::receiveRepeater: wrong message type, expected 'IDRT_REPEATER, got '%s'\n", m->getCommand().c_str());
CLog::logDebug("CIRCDDBClient::receiveRepeater: wrong message type, expected 'IDRT_REPEATER, got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
if (3 != m->getParamCount()) {
CLog::logInfo("CIRCDDBClient::receiveRepeater: unexpected number of message parameters, expected 3, got %d\n", m->getParamCount());
CLog::logDebug("CIRCDDBClient::receiveRepeater: unexpected number of message parameters, expected 3, got %d\n", m->getParamCount());
delete m;
return false;
}
@ -328,25 +328,25 @@ bool CIRCDDBClient::receiveGateway(std::string& gatewayCallsign, std::string& ad
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
if (rt != IDRT_GATEWAY) {
CLog::logInfo("CIRCDDBClient::receiveGateway: unexpected response type=%d\n", rt);
CLog::logDebug("CIRCDDBClient::receiveGateway: unexpected response type=%d\n", rt);
return false;
}
IRCMessage *m = d->app->getReplyMessage();
if (m == NULL) {
CLog::logInfo("CIRCDDBClient::receiveGateway: no message\n");
CLog::logDebug("CIRCDDBClient::receiveGateway: no message\n");
return false;
}
if (m->getCommand().compare("IDRT_GATEWAY")) {
CLog::logInfo("CIRCDDBClient::receiveGateway: wrong message type, expected 'IDRT_GATEWAY' got '%s'\n", m->getCommand().c_str());
CLog::logDebug("CIRCDDBClient::receiveGateway: wrong message type, expected 'IDRT_GATEWAY' got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
if (2 != m->getParamCount()) {
CLog::logInfo("CIRCDDBClient::receiveGateway: unexpected number of message parameters, expected 2, got %d\n", m->getParamCount());
CLog::logDebug("CIRCDDBClient::receiveGateway: unexpected number of message parameters, expected 2, got %d\n", m->getParamCount());
delete m;
return false;
}
@ -370,25 +370,25 @@ bool CIRCDDBClient::receiveUser(std::string& userCallsign, std::string& repeater
IRCDDB_RESPONSE_TYPE rt = d->app->getReplyMessageType();
if (rt != IDRT_USER) {
CLog::logInfo("CIRCDDBClient::receiveUser: unexpected response type=%d\n", rt);
CLog::logDebug("CIRCDDBClient::receiveUser: unexpected response type=%d\n", rt);
return false;
}
IRCMessage * m = d->app->getReplyMessage();
if (m == NULL) {
CLog::logInfo("CIRCDDBClient::receiveUser: no message\n");
CLog::logDebug("CIRCDDBClient::receiveUser: no message\n");
return false;
}
if (m->getCommand().compare("IDRT_USER")) {
CLog::logInfo("CIRCDDBClient::receiveUser: wrong message type, expected 'IDRT_USER', got '%s'\n", m->getCommand().c_str());
CLog::logDebug("CIRCDDBClient::receiveUser: wrong message type, expected 'IDRT_USER', got '%s'\n", m->getCommand().c_str());
delete m;
return false;
}
if (5 != m->getParamCount()) {
CLog::logInfo("CIRCDDBClient::receiveUser: unexpected number of message parameters, expected 5, got %d\n", m->getParamCount());
CLog::logDebug("CIRCDDBClient::receiveUser: unexpected number of message parameters, expected 5, got %d\n", m->getParamCount());
delete m;
return false;
}

@ -18,18 +18,39 @@
*/
#include <ctime>
#include <sstream>
#include <cassert>
#include "Log.h"
#include "LogConsoleTarget.h"
LOG_SEVERITY CLog::m_level = LS_INFO;
std::string CLog::m_file = "";
bool CLog::m_logToConsole = true;
bool CLog::m_addedTargets(false);
std::recursive_mutex CLog::m_targetsMutex;
std::vector<CLogTarget *> CLog::m_targets = { new CLogConsoleTarget(LOG_DEBUG) };
void CLog::initialize(const std::string& logfile, LOG_SEVERITY logLevel, bool logToConsole)
void CLog::addTarget(CLogTarget* target)
{
m_file = logfile;
m_level = logLevel;
m_logToConsole = logToConsole;
assert(target != nullptr);
std::lock_guard lockTargets(m_targetsMutex);
if(!m_addedTargets) {
// It is the first time we add an external target, clear the default one(s)
m_addedTargets = true;
finalise();
}
m_targets.push_back(target);
}
void CLog::finalise()
{
std::lock_guard lockTargets(m_targetsMutex);
for(auto target : m_targets) {
delete target;
}
m_targets.clear();
}
void CLog::getTimeStamp(std::string & s)
@ -39,4 +60,4 @@ void CLog::getTimeStamp(std::string & s)
char buf[64];
std::strftime(buf, 42, "%Y-%m-%d %T", now_tm);
s = std::string(buf);
}
}

125
Log.h

@ -20,104 +20,105 @@
#pragma once
#include <string>
#include <iostream>
#include <fstream>
#include <chrono>
#include <sstream>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <mutex>
#include <sstream>
#include <cassert>
#include "StringUtils.h"
enum LOG_SEVERITY {
LS_TRACE = 1,
LS_DEBUG,
LS_INFO,
LS_WARNING,
LS_ERROR,
LS_FATAL
};
#include "LogTarget.h"
class CLog
{
private:
static LOG_SEVERITY m_level;
static std::string m_file;
static bool m_logToConsole;
static std::vector<CLogTarget *> m_targets;
static bool m_addedTargets;
static std::recursive_mutex m_targetsMutex;
static void getTimeStamp(std::string & s);
template<typename... Args> static void formatLogMessage(std::string& output, LOG_SEVERITY severity, const std::string & f, Args... args)
{
assert(severity != LOG_NONE);
std::string severityStr;
switch (severity)
{
case LOG_DEBUG:
severityStr = "DEBUG ";
break;
case LOG_ERROR:
severityStr = "ERROR ";
break;
case LOG_FATAL:
severityStr = "FATAL ";
break;
case LOG_INFO :
severityStr = "INFO ";
break;
case LOG_WARNING:
severityStr = "WARNING";
break;
case LOG_TRACE:
severityStr = "TRACE ";
break;
default:
break;
}
std::string message = CStringUtils::string_format(f, args...);
boost::trim(message);
std::string timeUtc;
getTimeStamp(timeUtc);
std::stringstream s;
s << "[" << timeUtc << "] [" << severityStr << "] " << message << std::endl;
output = s.str();
}
public:
static void initialize(const std::string& logfile, LOG_SEVERITY logLevel, bool logToConsole);
static void addTarget(CLogTarget * target);
static void finalise();
template<typename... Args> static void logDebug(const std::string & f, Args... args)
{
log(LS_DEBUG, f, args...);
log(LOG_DEBUG, f, args...);
}
template<typename... Args> static void logInfo(const std::string & f, Args... args)
{
log(LS_INFO, f, args...);
log(LOG_INFO, f, args...);
}
template<typename... Args> static void logWarning(const std::string & f, Args... args)
{
log(LS_WARNING, f, args...);
log(LOG_WARNING, f, args...);
}
template<typename... Args> static void logError(const std::string & f, Args... args)
{
log(LS_ERROR, f, args...);
log(LOG_ERROR, f, args...);
}
template<typename... Args> static void logFatal(const std::string & f, Args... args)
{
log(LS_FATAL, f, args...);
log(LOG_FATAL, f, args...);
}
template<typename... Args> static void log(LOG_SEVERITY severity, const std::string & f, Args... args)
{
if(severity >= CLog::m_level || CLog::m_file.empty()) {
std::string severityStr;
switch (severity)
{
case LS_DEBUG:
severityStr = "DEBUG ";
break;
case LS_ERROR:
severityStr = "ERROR ";
break;
case LS_FATAL:
severityStr = "FATAL ";
break;
case LS_INFO :
severityStr = "INFO ";
break;
case LS_WARNING:
severityStr = "WARNING";
break;
case LS_TRACE:
severityStr = "TRACE ";
break;
default:
break;
}
std::lock_guard lockTarget(m_targetsMutex);
std::string msg;
for(auto target : m_targets) {
if(severity >= target->getLevel()) {
if(msg.empty())
formatLogMessage(msg, severity, f, args...);
std::string message = CStringUtils::string_format(f, args...);
boost::trim(message);
std::string timeUtc;
getTimeStamp(timeUtc);
std::stringstream s;
s << "[" << timeUtc << "] [" << severityStr << "] " << message << std::endl;
if(CLog::m_logToConsole || CLog::m_file.empty())
std::cout << s.str();
std::ofstream file;
file.open(CLog::m_file, std::ios::app);
if(file.is_open()) {
file << s.str();
file.close();
target->printLog(msg);
}
}
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include "LogConsoleTarget.h"
CLogConsoleTarget::CLogConsoleTarget(LOG_SEVERITY logLevel) :
CLogTarget(logLevel)
{
}
void CLogConsoleTarget::printLogInt(const std::string& msg)
{
std::cout << msg;
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#pragma once
#include "LogTarget.h"
class CLogConsoleTarget : public CLogTarget
{
public:
CLogConsoleTarget(LOG_SEVERITY logLevel);
protected:
virtual void printLogInt(const std::string& msg);
};

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <iostream>
#include <fstream>
#include <chrono>
#include <ctime>
#include "LogFileTarget.h"
CLogFileTarget::CLogFileTarget(LOG_SEVERITY logLevel, const std::string & dir, bool rotate) :
CLogTarget(logLevel),
m_dir(dir),
m_rotate(rotate)
{
}
void CLogFileTarget::printLogInt(const std::string& msg)
{
// construct filename
std::string fileName(m_dir);
if(fileName[fileName.length() - 1U] != '/') fileName.push_back('/');
fileName.append("dstargateway");
if(m_rotate) {
std::time_t now = std::time(0);
std::tm* now_tm = std::gmtime(&now);
char buf[64];
std::strftime(buf, 42, "-%Y-%m-%d", now_tm);
fileName.append(std::string(buf));
}
fileName.append(".log");
std::ofstream file;
file.open(fileName, std::ios::app);
if(file.is_open()) {
file << msg;
file.close();
}
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#pragma once
#include <string>
#include "LogTarget.h"
class CLogFileTarget : public CLogTarget
{
public:
CLogFileTarget(LOG_SEVERITY logLevel, const std::string& directory, bool rotate);
protected:
virtual void printLogInt(const std::string& msg);
private:
std::string m_dir;
bool m_rotate;
};

@ -0,0 +1,29 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#pragma once
enum LOG_SEVERITY : unsigned int {
LOG_TRACE = 1,
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR,
LOG_FATAL,
LOG_NONE = 0xFFFFFFFF
};

@ -0,0 +1,35 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "LogTarget.h"
CLogTarget::CLogTarget(LOG_SEVERITY logLevel) :
m_logLevel(logLevel)
{
}
CLogTarget::~CLogTarget()
{
}
void CLogTarget::printLog(const std::string& msg)
{
printLogInt(msg);
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021-2022 by Geoffrey Merck F4FXL / KC3FRA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#pragma once
#include <string>
#include "LogSeverity.h"
class CLogTarget
{
public:
CLogTarget(LOG_SEVERITY logLevel);
virtual ~CLogTarget();
void printLog(const std::string& msg);
LOG_SEVERITY getLevel() { return m_logLevel; }
protected:
virtual void printLogInt(const std::string& msg) = 0;
private:
LOG_SEVERITY m_logLevel;
};

@ -4,17 +4,20 @@
- [2.2. Code Credit](#22-code-credit)
- [2.3. Features](#23-features)
- [3. Building and installing](#3-building-and-installing)
- [3.1. Get latest stable version](#31-get-latest-stable-version)
- [3.2. Prerequisites and dependencies](#32-prerequisites-and-dependencies)
- [3.3. Building](#33-building)
- [3.4. Installing](#34-installing)
- [3.5. Configuring](#35-configuring)
- [3.1. Initial setup](#31-initial-setup)
- [3.2. Get latest stable version](#32-get-latest-stable-version)
- [3.3. Get latest development version version](#33-get-latest-development-version-version)
- [3.4. Prerequisites and dependencies](#34-prerequisites-and-dependencies)
- [3.5. Building](#35-building)
- [3.6. Installing](#36-installing)
- [3.7. Configuring](#37-configuring)
- [4. Contributing](#4-contributing)
- [4.1. Work Flow](#41-work-flow)
- [5. Version History](#5-version-history)
- [5.1. Version 0.3](#51-version-03)
- [5.2. Version 0.2](#52-version-02)
- [5.3. Version 0.1](#53-version-01)
- [5.1. Version 0.4](#51-version-04)
- [5.2. Version 0.3](#52-version-03)
- [5.3. Version 0.2](#53-version-02)
- [5.4. Version 0.1](#54-version-01)
# 1. Introduction
@ -42,12 +45,13 @@ Features that where left out :
- Mobile APRS: Code has been ported, yet I am targeting repeaters so low priority.
# 3. Building and installing
## 3.1. Get latest stable version
## 3.1. Initial setup
Clone the repository (only required initally)
```
git clone https://github.com/F4FXL/DStarGateway.git
cd DStarGateway
```
## 3.2. Get latest stable version
From inside the cloned repository run following commands to get the latest stable version
```
git pull -p
@ -55,22 +59,26 @@ git fetch --tags
latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
git checkout $latestTag
```
## 3.3. Get latest development version version
```
git checkout develop
```
## 3.2. Prerequisites and dependencies
## 3.4. Prerequisites and dependencies
Before first time building you need to install dependencies and prerequisites
```
apt install build-essential libconfig++-dev libcurl4-openssl-dev libboost-dev
```
## 3.3. Building
## 3.5. Building
```
make
```
## 3.4. Installing
## 3.6. Installing
The program is meant to run as a systemd service. All bits an pieces are provided.
```
sudo make install
```
## 3.5. Configuring
## 3.7. Configuring
After installing you have to edit the configuration file. If you went with default paths, the config file is located in `/usr/local/etc/dstargateway.cfg`
The configuration format is quite straight forward. It is organised in sections and key/value pairs.
@ -88,10 +96,12 @@ sudo systemctl stop dstargateway.service
I Use [Git flow](https://danielkummer.github.io/git-flow-cheatsheet/) as my workflow. PR are welcome and shall be done against the develop branch and follow the Git Flow branch naming rules.
# 5. Version History
## 5.1. Version 0.3
## 5.1. Version 0.4
- [improvement] Log enhancements ([#4])(https://github.com/F4FXL/DStarGateway/issues/4)
## 5.2. Version 0.3
- [Improvement] Get ride of libcongif++ dependency. When upgrading from earlier version you need to manualy delete the config file before reinstalling.
## 5.2. Version 0.2
## 5.3. Version 0.2
- [bugfix] ircDDBFreeze when repeater not found ([#1](https://github.com/F4FXL/DStarGateway/issues/1))
- Code sanitization
## 5.3. Version 0.1
## 5.4. Version 0.1
First working version

@ -23,4 +23,4 @@
#include <string>
const std::string VENDOR_NAME("Geoffrey Merck F4FXL / KC3FRA");
const std::string VERSION("0.3");
const std::string VERSION("0.4");

@ -142,6 +142,10 @@ password=12345
[Log]
path=/var/log/dstargateway/
fileRoot= # defaults to dstarGateway
fileRotate= # rotate log files daily, defaults to true
fileLevel= # defaults to info, valid values are trace, debug, info, warning, error, fatal, none
displayLevel= # defaults to info, valid values are trace, debug, info, warning, error, fatal, none
[Paths]
data=/usr/local/share/dstargateway.d/ #Path where the data (hostfiles, audio files etc) can be found

Loading…
Cancel
Save

Powered by TurnKey Linux.