11#ifndef logger_logManager_hpp
12#define logger_logManager_hpp
22#include <mx/app/appConfigurator.hpp>
28#include "../common/defaults.hpp"
30#include "generated/logTypes.hpp"
31#include "generated/logStdFormat.hpp"
72template<
class _parentT,
class _logFileT>
196 template<
typename logT>
198 const typename logT::messageT & msg,
209 template<
typename logT>
212 const typename logT::messageT & msg,
220 template<
typename logT>
221 void log(
const typename logT::messageT & msg,
229 template<
typename logT>
231 const typename logT::messageT & msg,
239 template<
typename logT>
246 template<
typename logT>
253template<
class parentT,
class logFileT>
258template<
class parentT,
class logFileT>
261 m_logShutdown =
true;
263 if(m_logThread.joinable()) m_logThread.join();
266 if( !m_logQueue.empty() ) logThreadExec();
270template<
class parentT,
class logFileT>
276template<
class parentT,
class logFileT>
282template<
class parentT,
class logFileT>
285 if(wp == 0)
return -1;
292template<
class parentT,
class logFileT>
298template<
class parentT,
class logFileT>
308template<
class parentT,
class logFileT>
314template<
class parentT,
class logFileT>
317 if(newPrio > 98)
return -1;
318 if(newPrio < 0) newPrio = 0;
320 m_logThreadPrio = newPrio;
324template<
class parentT,
class logFileT>
327 return m_logThreadPrio;
330template<
class parentT,
class logFileT>
333 return m_logThreadRunning;
336template<
class parentT,
class logFileT>
339 config.add(m_configSection+
".logDir",
"L",
"logDir",mx::app::argType::Required, m_configSection,
"logDir",
false,
"string",
"The directory for log files");
340 config.add(m_configSection+
".logExt",
"",
"logExt",mx::app::argType::Required, m_configSection,
"logExt",
false,
"string",
"The extension for log files");
341 config.add(m_configSection+
".maxLogSize",
"",
"maxLogSize",mx::app::argType::Required, m_configSection,
"maxLogSize",
false,
"string",
"The maximum size of log files");
342 config.add(m_configSection+
".writePause",
"",
"writePause",mx::app::argType::Required, m_configSection,
"writePause",
false,
"unsigned long",
"The log thread pause time in ns");
343 config.add(m_configSection+
".logThreadPrio",
"",
"logThreadPrio", mx::app::argType::Required, m_configSection,
"logThreadPrio",
false,
"int",
"The log thread priority");
344 config.add(m_configSection+
".logLevel",
"l",
"logLevel",mx::app::argType::Required, m_configSection,
"logLevel",
false,
"string",
"The log level");
349template<
class parentT,
class logFileT>
354 config(tmp, m_configSection+
".logDir");
355 if(tmp !=
"") this->logPath(tmp);
359 config(tmp, m_configSection+
".logLevel");
369 std::cerr <<
"Unkown log level specified. Using default (INFO)\n";
377 config(this->m_logExt, m_configSection+
".logExt");
380 config(this->m_maxLogSize, m_configSection+
".maxLogSize");
383 config(m_writePause, m_configSection+
".writePause");
386 config(m_logThreadPrio, m_configSection+
".logThreadPrio");
391template<
class parentT,
class logFileT>
397template<
class parentT,
class logFileT>
402 m_logThread = std::thread( _logThreadStart,
this);
404 catch(
const std::exception & e )
406 log<software_error>({__FILE__,__LINE__, 0, 0, std::string(
"Exception on log thread start: ") + e.what()});
411 log<software_error>({__FILE__,__LINE__, 0, 0,
"Unkown exception on log thread start"});
415 if(!m_logThread.joinable())
417 log<software_error>({__FILE__, __LINE__, 0, 0,
"Log thread did not start"});
423 sp.sched_priority = m_logThreadPrio;
425 int rv = pthread_setschedparam( m_logThread.native_handle(), SCHED_OTHER, &sp);
429 log<software_error>({__FILE__, __LINE__, 0, rv, std::string(
"Error setting thread params: ") + strerror(rv)});
437template<
class parentT,
class logFileT>
441 m_logThreadRunning =
true;
443 std::unique_lock<std::mutex> lock(m_qMutex, std::defer_lock);
445 while(!m_logShutdown || !m_logQueue.empty())
447 std::list<bufferPtrT>::iterator beg, it, er, end;
452 beg = m_logQueue.begin();
453 end = m_logQueue.end();
463 if( this->writeLog( *it ) < 0)
465 m_logThreadRunning =
false;
471 m_parent->logMessage( *it );
475 logStdFormat(std::cerr, *it);
484 m_logQueue.erase(er);
494 if(m_logQueue.empty() && !m_logShutdown) std::this_thread::sleep_for( std::chrono::duration<unsigned long, std::nano>(m_writePause));
497 m_logThreadRunning =
false;
500template<
class parentT,
class logFileT>
501template<
typename logT>
503 const typename logT::messageT & msg,
511 return logHeader::createLog<logT>(logBuffer, ts, msg, level);
514template<
class parentT,
class logFileT>
515template<
typename logT>
518 const typename logT::messageT & msg,
522 return logHeader::createLog<logT>(logBuffer, ts, msg, level);
525template<
class parentT,
class logFileT>
526template<
typename logT>
534 if(level > m_logLevel)
return;
538 createLog<logT>(logBuffer, msg, level);
541 std::lock_guard<std::mutex> guard(m_qMutex);
542 m_logQueue.push_back(logBuffer);
547template<
class parentT,
class logFileT>
548template<
typename logT>
550 const typename logT::messageT & msg,
557 if(level > m_logLevel)
return;
561 createLog<logT>(logBuffer, ts, msg, level);
564 std::lock_guard<std::mutex> guard(m_qMutex);
565 m_logQueue.push_back(logBuffer);
569template<
class parentT,
class logFileT>
570template<
typename logT>
576template<
class parentT,
class logFileT>
577template<
typename logT>
Flatlogs single include file.
#define MAGAOX_default_writePause
The default logger writePause.
int8_t logPrioT
The type of the log priority code.
std::shared_ptr< char > bufferPtrT
The log entry buffer smart pointer.
static int logLevel(bufferPtrT &logBuffer, const logPrioT &lvl)
Set the level of a log entry in a logBuffer header.
Empty type for resolving logs with no message.
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
static constexpr logPrioT LOG_DEFAULT
Used to denote "use the default level for this log type".
static constexpr logPrioT LOG_UNKNOWN
Used to denote an unkown log type for internal error handling.
logPrioT logLevelFromString(const std::string &str)
Get the log priority from a string, which might have the number or the name.
The standard MagAOX log manager, used for both process logs and telemetry streams.
int logThreadStart()
Start the logger thread.
int loadConfig(mx::app::appConfigurator &config)
Load the logger section from an application configurator.
void log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry, including a message.
void log(timespecX &ts, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry with no message.
parentT * parent()
Get the logger parent.
static int createLog(bufferPtrT &logBuffer, const typename logT::messageT &msg, const logPrioT &level)
Create a log formatted log entry, filling in a buffer.
std::string m_configSection
The configuration files section name. Default is logger.
unsigned long writePause()
Get the current value of writePause.
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the logger section.
int logThreadPrio()
Get the current value of logThreadPrio.
bool m_logShutdown
Flag to signal the log thread to shutdown.
unsigned long m_writePause
Time, in nanoseconds, to pause between successive batch writes to the file. Default is 1e9....
std::thread m_logThread
A separate thread for actually writing to the file.
void parent(parentT *p)
Set the logger parent.
std::list< bufferPtrT > m_logQueue
Log entries are stored here, and writen to the file by the log thread.
void log(logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry with no message.
logPrioT logLevel()
Get the current value of logLevel.
logPrioT m_logLevel
The minimum log level to actually record. Logs with level below this are rejected....
void log(timespecX &ts, const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry, including a message.
void logThreadExec()
Execute the logger thread.
int logThreadPrio(int newPrio)
Set a new value of logThreadPrio.
int writePause(const unsigned long &wp)
Set a new value of writePause.
int logLevel(logPrioT newLev)
Set a new value of logLevel.
std::mutex m_qMutex
Mutex for accessing the m_logQueue.
static int createLog(bufferPtrT &logBuffer, const timespecX &ts, const typename logT::messageT &msg, const logPrioT &level)
Create a log formatted log entry, filling in a buffer.
logManager()
Default c'tor.
bool logThreadRunning()
Get status of the log thread running flag.
static void _logThreadStart(logManager *l)
Thread starter, called by logThreadStart on thread construction. Calls logThreadExec.
A fixed-width timespec structure.
void gettime()
Fill the the timespecX with the current time.