8 #ifndef INCL_evo_logger_h 9 #define INCL_evo_logger_h 35 #define EVO_LOG_ALERT(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_ALERT)) LOGGER.log_direct(LOG_LEVEL_ALERT, MSG); } 51 #define EVO_LOG_ERROR(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_ERROR)) LOGGER.log_direct(LOG_LEVEL_ERROR, MSG); } 67 #define EVO_LOG_WARN(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_WARN)) LOGGER.log_direct(LOG_LEVEL_WARN, MSG); } 83 #define EVO_LOG_INFO(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_INFO)) LOGGER.log_direct(LOG_LEVEL_INFO, MSG); } 99 #define EVO_LOG_DEBUG(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_DEBUG)) LOGGER.log_direct(LOG_LEVEL_DEBUG, MSG); } 115 #define EVO_LOG_DEBUG_LOW(LOGGER, MSG) { if (LOGGER.check(LOG_LEVEL_DEBUG_LOW)) LOGGER.log_direct(LOG_LEVEL_DEBUG_LOW, MSG); } 166 typedef LoggerMsg<SZ> This;
168 static const uint BUF_SIZE = SZ;
177 LoggerMsg() : size(0), aux_size(0), aux_buf(NULL) {
191 const char* p =
msg.data();
192 uint32 remain_size =
msg.size();
193 if (remain_size > BUF_SIZE) {
194 ::memcpy(buf, p, BUF_SIZE);
196 remain_size -= BUF_SIZE;
198 if (aux_buf != NULL) {
199 if (remain_size > aux_size)
206 aux_size = remain_size;
207 aux_buf = (
char*)::malloc(aux_size);
211 ::memcpy(aux_buf, p, remain_size);
214 if (aux_buf != NULL) {
219 ::memcpy(buf, p, remain_size);
224 void get_buf_sizes(uint32& buf1_size, uint32& buf2_size) {
225 if (size <= BUF_SIZE) {
229 buf1_size = BUF_SIZE;
230 buf2_size = size - BUF_SIZE;
235 This& operator=(
const This& src) {
236 This& src_mutable =
const_cast<This&
>(src);
239 timestamp = src.timestamp;
245 ::memcpy(buf, src.buf, size);
246 src_mutable.size = 0;
250 swap(aux_buf, src_mutable.aux_buf);
251 swap(aux_size, src_mutable.aux_size);
336 return (level <= level_.load());
355 if (level <= level_.load()) {
356 log_direct(level, msg);
376 template<
class T=LoggerBase>
413 void set(LoggerType* newptr) {
419 return (ptr != NULL && ptr->check(level));
424 ptr->log_direct(level, msg);
429 if (ptr != NULL && ptr->check(level)) {
430 ptr->log_direct(level, msg);
508 template<u
int MSG_BUF_SIZE=512>
513 static const uint MESSAGE_BUFFER_SIZE = MSG_BUF_SIZE;
514 static const SizeT DEFAULT_QUEUE_SIZE = 256;
519 Logger(
SizeT queue_size=DEFAULT_QUEUE_SIZE) : queue_(queue_size), outfile_(
NL_SYS, false), thread_(consumer, this), local_time_(false) {
535 return MESSAGE_BUFFER_SIZE;
543 local_time_ = local_time;
561 qitem.set(level, msg);
563 if (condmutex_.trylock()) {
578 if (thread_.thread_active()) {
579 const SubString MSG(
"Logger can't open a file while thread already active");
581 errmsg_.set().reserve(MSG.
size() + filepath_.size()) << MSG << filepath_;
586 if (filepath_.empty()) {
587 errmsg_ =
"Logger can't open empty file path";
592 if (filepath_.ends(
'/') || filepath_.ends(
'\\') || filepath_.ends(
':')) {
594 if (filepath_.ends(
'/')) {
596 const SubString MSG(
"Logger can't open invalid file path, must be a file not a directory: ");
597 errmsg_.set().reserve(MSG.
size() + filepath_.size()) << MSG << filepath_;
601 if (!outfile_.open(filepath_.cstr(),
oAPPEND)) {
602 const Error err = outfile_.error();
603 errmsg_.set() <<
"Logger can't open: " << filepath_;
624 if (!thread_.thread_active()) {
627 if (!outfile_.isopen()) {
628 const SubString MSG(
"Logger file not open, must open() first before start_thread()");
629 errmsg_.set().reserve(MSG.
size() + filepath_.size()) << MSG << filepath_;
632 }
else if (!thread_.thread_start()) {
633 errmsg_ =
"Logger thread failed to start";
653 return (open(path, excep) && start_thread(excep));
658 if (thread_.thread_active()) {
660 condmutex_.lock_notify();
661 thread_.thread_join();
666 typedef impl::LoggerMsg<MSG_BUF_SIZE> Msg;
679 static void consumer(
void* arg) {
680 const char BEGIN_DELIM =
'[';
682 const char* LEVEL_STR[] = {
"ALRT",
"ERRR",
"WARN",
"INFO",
"dbug",
"dbgl" };
685 const ulong WAKE_TIMEOUT_MS = 500;
688 ulong drop_count = 0;
692 uint32 buf1_size, buf2_size;
695 while (logger.queue_.
pop(msg)) {
699 if (logger.local_time_)
700 msg.timestamp.convert_local_dt_notz(dt);
702 msg.timestamp.convert_utc_dt(dt);
705 logger.outfile_ << BEGIN_DELIM;
706 dt.
format(logger.outfile_,
':') <<
' ';
708 logger.outfile_ <<
SubString(LEVEL_STR[(
int)msg.level - 1], LEVEL_LEN);
710 logger.outfile_ <<
FmtInt(msg.level).width(LEVEL_LEN,
' ');
712 logger.outfile_ << MSG_DELIM;
715 msg.get_buf_sizes(buf1_size, buf2_size);
716 if (buf1_size > 0 && logger.outfile_.
writebin(msg.buf, buf1_size) < buf1_size)
718 else if (buf2_size > 0 && logger.outfile_.
writebin(msg.aux_buf, buf2_size) < buf2_size)
721 logger.outfile_ <<
NL;
722 if (error || !logger.outfile_) {
725 logger.outfile_.
close();
729 logger.errmsg_.
set() <<
"Logger file write error: " << logger.filepath_ <<
" -- ";
735 if (logger.shutdown_.
load())
738 if (closed || logger.rotate_.
load()) {
742 logger.outfile_.
close();
744 logger.outfile_ <<
NL;
746 logger.outfile_ <<
"[] Logger recovered from error (lost: " << drop_count <<
"): " << logger.errmsg_ <<
NL;
747 logger.errmsg_.
set();
750 }
else if (!closed) {
751 logger.errmsg_.
set() <<
"Logger can't open: " << logger.filepath_ <<
" -- ";
756 logger.rotate_.
store(0);
760 logger.condmutex_.
wait(WAKE_TIMEOUT_MS,
false);
761 logger.condmutex_.
unlock();
763 logger.shutdown_.
store(0);
Holds a system timestamp as native (platform specific) fields.
Definition: systime.h:27
Inert logger implementing the same interface as Logger.
Definition: logger.h:775
void log_direct(LogLevel level, const SubString &msg)
Log a message with given log level directly without checking the current log level.
Definition: logger.h:423
void store(T num, MemOrder mem_order=std::memory_order_seq_cst)
Store new value.
bool pop(Item &item)
Pop oldest item from queue.
Definition: atomic_buffer_queue.h:209
LoggerPtr()
Constructor sets as null.
Definition: logger.h:383
void shutdown()
Shutdown logging thread.
Definition: logger.h:657
bool open(const SubString &path, bool excep=1)
Open log file but don't start logging thread yet.
Definition: logger.h:577
void set()
Set as null (no time zone).
Definition: time.h:1164
bool get_error(String &)
Definition: logger.h:781
T & format(T &out, char dt_delim='T', char d_delim='-', char t_delim=':', char msec_delim=0, char tz_delim=':') const
Format date and time to String or Stream using given delimiters.
Definition: time.h:1724
Invalid argument or data.
Definition: sys.h:1123
TOut & errormsg_out(TOut &out)
Write error message with errno to output stream/string.
Definition: sys.h:1272
virtual void set_level(LogLevel level)
Set current log level.
Definition: logger.h:295
Evo date and time classes.
bool log(LogLevel level, const SubString &msg)
Log a message with given severity level.
Definition: logger.h:354
void set_utc()
Set to current date/time (UTC).
Definition: systime.h:149
Invalid or unsupported operation.
Definition: sys.h:1122
Logger< MSG_BUF_SIZE > This
This Logger type.
Definition: logger.h:511
T LoggerType
Logger type used from template.
Definition: logger.h:378
void set_local_time(bool local_time)
Set wheter to convert log date/time values to local time.
Definition: logger.h:542
void rotate()
Definition: logger.h:791
LoggerPtr(const LoggerPtr &src)
Copy constructor copies logger pointer.
Definition: logger.h:393
bool check(LogLevel level) const
Check whether a message with given level will actually be logged.
Definition: logger.h:335
Manages a single thread of execution.
Definition: thread.h:529
Wraps a logger pointer that can reference a logger to use or be disabled.
Definition: logger.h:377
uint get_message_buffer_size() const
Get message buffer size.
Definition: logger.h:534
const char * cstr(String &buffer) const
Get terminated string pointer, using given string buffer if needed (const).
Definition: string.h:1561
virtual bool get_error(String &msg)
Get last error that occurred.
Definition: logger.h:285
#define EVO_CREATE_EXCEPTION_IMPL(NAME, BASE)
Create an Evo exception implementation.
Definition: sys.h:1365
#define EVO_THROW_ERR_CHECK(TYPE, MSG, ERROR, COND)
Throw an Evo exception with error code if COND is true.
Definition: sys.h:1513
bool wait(ulong timeout_ms=Condition::INF, bool locked=true)
Wait for notification or timeout.
Definition: thread.h:317
Evo File I/O stream class.
static const T MAX
Maximum interger value.
Definition: type.h:996
void swap(T &a, T &b)
Swap contents of given objects.
Definition: sys.h:1602
Evo I/O streams and Console I/O.
Condition object for thread synchronization.
Definition: thread.h:243
TimeZoneOffset tz
TimeZoneOffset fields.
Definition: time.h:1370
virtual ~LoggerBase()
Destructor.
Definition: logger.h:276
Size size() const
Get size.
bool check(LogLevel) const
Definition: logger.h:793
Full calendar date and time of day with timezone offset.
Definition: time.h:1364
void log_direct(LogLevel level, const SubString &msg)
Log a message with given log level directly without checking the current log level.
Definition: logger.h:559
Evo threads implementation.
#define EVO_EXCEPTIONS
Whether to throw exceptions on error by default.
Definition: evo_config.h:35
High performance message logger.
Definition: logger.h:509
Error
General Evo error code stored in exceptions, or used directly when exceptions are disabled...
Definition: sys.h:1113
bool close()
Close stream.
Definition: iobase.h:888
LoggerPtr(LoggerType *newptr)
Constructor to set pointer.
Definition: logger.h:387
uint32 StrSizeT
Default Evo string size type.
Definition: sys.h:734
String container.
Definition: string.h:674
FmtIntT< int > FmtInt
Explicitly format an integer.
Definition: str.h:3107
bool log(LogLevel level, const SubString &msg)
Log a message with given severity level.
Definition: logger.h:428
#define EVO_ENUM_REMAP(ENUM, FIRST_VAL, LAST_VAL, UNKNOWN_VAL, REMAP_ARRAY,...)
Helper for creating enum string/value mappers with explicit first/last/unknown values, with unsorted enum remapped to sorted values.
Definition: enum.h:168
void set_level(LogLevel)
Definition: logger.h:787
Smart locking for synchronization.
Definition: lock.h:28
bool open(const char *path, Open mode=oREAD, bool flushlines=false)
Open file for read and/or writing.
Definition: file.h:124
void log_direct(LogLevel, const SubString &)
Definition: logger.h:796
File I/O stream.
Definition: file.h:77
Write/append only, created if needed.
Definition: sysio.h:198
LoggerType * ptr
Logger pointer, NULL to disable logging with this
Definition: logger.h:380
ulong writebin(const void *buf, ulong size)
Write binary output to stream.
Definition: iobase.h:946
virtual void rotate()
Set log rotation flag.
Definition: logger.h:304
Evo base exception class.
Definition: sys.h:1214
static const NewlineDefault & NL
Default newline type.
Definition: sys.h:785
Logger exception, see Exception.
Definition: logger.h:124
void unlock()
Unlock associated mutex.
Definition: thread.h:431
Evo C++ Library namespace.
Definition: alg.h:11
Logger(SizeT queue_size=DEFAULT_QUEUE_SIZE)
Constructor.
Definition: logger.h:519
bool get_error(String &msg)
Get last error that occurred.
Definition: logger.h:546
bool log(LogLevel, const SubString &)
Definition: logger.h:798
LoggerPtr & operator=(const LoggerPtr &src)
Assignment operator copies logger pointer.
Definition: logger.h:400
LoggerInert(SizeT queue_size=0)
Definition: logger.h:777
const char * msg() const
Get exception message.
Definition: sys.h:1254
static const Newline NL_SYS
Current system newline type.
Definition: sys.h:763
Operation failed.
Definition: sys.h:1124
Error error() const
Get error code from last operation.
Definition: iobase.h:66
void shutdown()
Definition: logger.h:806
bool start(const SubString &, bool excep=1)
Definition: logger.h:801
Error error() const
Get error code.
Definition: sys.h:1260
bool check(LogLevel level) const
Check whether a message with given level will actually be logged.
Definition: logger.h:418
String & set()
Set as null and empty.
Definition: string.h:995
uint get_message_buffer_size() const
Definition: logger.h:784
uint32 SizeT
Default Evo container size type.
Definition: sys.h:729
Reference and access existing string data.
Definition: substring.h:229
T load(MemOrder mem_order=std::memory_order_seq_cst) const
Load and return current value.
Base class for Logger.
Definition: logger.h:273
~Logger()
Destructor, calls shutdown().
Definition: logger.h:524
AtomicInt level_
Log level, messages less severe than this are ignored (not logged)
Definition: logger.h:363
void rotate()
Set log rotation flag.
Definition: logger.h:555
#define EVO_PARAM_UNUSED(NAME)
Mark function parameter as unused to suppress "unreferenced parameter" compiler warnings on it...
Definition: sys.h:427
bool start(const SubString &path, bool excep=1)
Open log file and start logging thread, which consumes the queue and actually writes to file...
Definition: logger.h:652
bool start_thread(bool excep=1)
Start logging thread for already open file, which consumes the queue and actually writes to file...
Definition: logger.h:623
void set_local_time(bool)
Definition: logger.h:789