11#ifndef logger_logManager_hpp
12#define logger_logManager_hpp
22#include <mx/app/appConfigurator.hpp>
28#include "../common/defaults.hpp"
72template<
class _parentT,
class _logFileT>
209 template<
typename logT>
211 const typename logT::messageT & msg,
222 template<
typename logT>
225 const typename logT::messageT & msg,
233 template<
typename logT>
234 void log(
const typename logT::messageT & msg,
242 template<
typename logT>
244 const typename logT::messageT & msg,
252 template<
typename logT>
259 template<
typename logT>
266template<
class parentT,
class logFileT>
271template<
class parentT,
class logFileT>
274 m_logShutdown =
true;
276 if(m_logThread.joinable()) m_logThread.join();
279 if( !m_logQueue.empty() ) logThreadExec();
283template<
class parentT,
class logFileT>
289template<
class parentT,
class logFileT>
295template<
class parentT,
class logFileT>
302template<
class parentT,
class logFileT>
305 return m_logShutdown;
308template<
class parentT,
class logFileT>
311 if(wp == 0)
return -1;
318template<
class parentT,
class logFileT>
324template<
class parentT,
class logFileT>
334template<
class parentT,
class logFileT>
340template<
class parentT,
class logFileT>
343 if(newPrio > 98)
return -1;
344 if(newPrio < 0) newPrio = 0;
346 m_logThreadPrio = newPrio;
350template<
class parentT,
class logFileT>
353 return m_logThreadPrio;
356template<
class parentT,
class logFileT>
359 return m_logThreadRunning;
362template<
class parentT,
class logFileT>
365 config.add(m_configSection+
".logDir",
"L",
"logDir",mx::app::argType::Required, m_configSection,
"logDir",
false,
"string",
"The directory for log files");
366 config.add(m_configSection+
".logExt",
"",
"logExt",mx::app::argType::Required, m_configSection,
"logExt",
false,
"string",
"The extension for log files");
367 config.add(m_configSection+
".maxLogSize",
"",
"maxLogSize",mx::app::argType::Required, m_configSection,
"maxLogSize",
false,
"string",
"The maximum size of log files");
368 config.add(m_configSection+
".writePause",
"",
"writePause",mx::app::argType::Required, m_configSection,
"writePause",
false,
"unsigned long",
"The log thread pause time in ns");
369 config.add(m_configSection+
".logThreadPrio",
"",
"logThreadPrio", mx::app::argType::Required, m_configSection,
"logThreadPrio",
false,
"int",
"The log thread priority");
370 config.add(m_configSection+
".logLevel",
"l",
"logLevel",mx::app::argType::Required, m_configSection,
"logLevel",
false,
"string",
"The log level");
375template<
class parentT,
class logFileT>
380 config(tmp, m_configSection+
".logDir");
381 if(tmp !=
"") this->logPath(tmp);
385 config(tmp, m_configSection+
".logLevel");
395 std::cerr <<
"Unkown log level specified. Using default (INFO)\n";
403 config(this->m_logExt, m_configSection+
".logExt");
406 config(this->m_maxLogSize, m_configSection+
".maxLogSize");
409 config(m_writePause, m_configSection+
".writePause");
412 config(m_logThreadPrio, m_configSection+
".logThreadPrio");
417template<
class parentT,
class logFileT>
423template<
class parentT,
class logFileT>
428 m_logThread = std::thread( _logThreadStart,
this);
430 catch(
const std::exception & e )
432 log<software_error>({__FILE__,__LINE__, 0, 0, std::string(
"Exception on log thread start: ") + e.what()});
437 log<software_error>({__FILE__,__LINE__, 0, 0,
"Unkown exception on log thread start"});
441 if(!m_logThread.joinable())
443 log<software_error>({__FILE__, __LINE__, 0, 0,
"Log thread did not start"});
449 sp.sched_priority = m_logThreadPrio;
451 int rv = pthread_setschedparam( m_logThread.native_handle(), SCHED_OTHER, &sp);
455 log<software_error>({__FILE__, __LINE__, 0, rv, std::string(
"Error setting thread params: ") + strerror(rv)});
463template<
class parentT,
class logFileT>
467 m_logThreadRunning =
true;
469 std::unique_lock<std::mutex> lock(m_qMutex, std::defer_lock);
472 while(!m_logShutdown || !m_logQueue.empty())
474 std::list<bufferPtrT>::iterator beg, it, er, end;
479 beg = m_logQueue.begin();
480 end = m_logQueue.end();
490 mx::error_t errc = this->writeLog( *it );
491 if( errc != mx::error_t::noerror)
493 m_logThreadRunning =
false;
499 m_parent->logMessage( *it );
512 m_logQueue.erase(er);
522 if(m_logQueue.empty() && !m_logShutdown) std::this_thread::sleep_for( std::chrono::duration<unsigned long, std::nano>(m_writePause));
525 m_logThreadRunning =
false;
528template<
class parentT,
class logFileT>
529template<
typename logT>
531 const typename logT::messageT & msg,
539 return logHeader::createLog<logT>(logBuffer, ts, msg, level);
542template<
class parentT,
class logFileT>
543template<
typename logT>
546 const typename logT::messageT & msg,
550 return logHeader::createLog<logT>(logBuffer, ts, msg, level);
553template<
class parentT,
class logFileT>
554template<
typename logT>
562 if(level > m_logLevel)
return;
566 createLog<logT>(logBuffer, msg, level);
569 std::lock_guard<std::mutex> guard(m_qMutex);
570 m_logQueue.push_back(logBuffer);
575template<
class parentT,
class logFileT>
576template<
typename logT>
578 const typename logT::messageT & msg,
585 if(level > m_logLevel)
return;
589 createLog<logT>(logBuffer, ts, msg, level);
592 std::lock_guard<std::mutex> guard(m_qMutex);
593 m_logQueue.push_back(logBuffer);
597template<
class parentT,
class logFileT>
598template<
typename logT>
604template<
class parentT,
class logFileT>
605template<
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.
iosT & logStdFormat(iosT &ios, flatlogs::bufferPtrT &buffer)
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 logShutdown(bool ls)
Set a new value of logShutdown.
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.
bool logShutdown()
Get the current value of logShutdown.
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.