/**************************************************************************/ /* */ /* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ /* Copyright (c) 2008-2017 Oleksandr Shneyder */ /* Copyright (c) 2014-2022 Ulrich Sibiller */ /* Copyright (c) 2014-2019 Mihai Moldovan */ /* Copyright (c) 2011-2022 Mike Gabriel */ /* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ /* */ /* NXCOMP, NX protocol compression and NX extensions to this software */ /* are copyright of the aforementioned persons and companies. */ /* */ /* Redistribution and use of the present software is allowed according */ /* to terms specified in the file LICENSE.nxcomp which comes in the */ /* source distribution. */ /* */ /* All rights reserved. */ /* */ /* NOTE: This software has received contributions from various other */ /* contributors, only the core maintainers and supporters are listed as */ /* copyright holders. Please contact us, if you feel you should be listed */ /* as copyright holder, as well. */ /* */ /**************************************************************************/ #include #include #include #include #include #include #include "Log.h" #include "config.h" NXLog nx_log; bool NXLog::will_log() const { std::map::const_iterator item = per_file_levels_.find(current_file()); if ( item != per_file_levels_.end() ) { return current_level() <= item->second; } else { return current_level() <= level(); } } std::string NXLog::stamp_to_string(const NXLogStamp& stamp) const { std::ostringstream oss; static const char* level_names[] = { "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG" }; if ( log_level() ) oss << ((stamp.level() >=0 && stamp.level() < NXLOG_LEVEL_COUNT ) ? level_names[stamp.level()] : "???") << " "; if ( log_time() ) { struct timeval timestamp = stamp.timestamp(); struct tm timeinfo; localtime_r(×tamp.tv_sec, &timeinfo); if ( log_unix_time() ) { oss << timestamp.tv_sec; } else { #if HAVE_STD_PUT_TIME oss << " " << std::put_time(&timeinfo, "%Y/%m/%d %H:%M:%S"); #else oss << timestamp.tv_sec; #endif } oss << "." << std::setw(3) << std::setfill('0') << (int)(timestamp.tv_usec / 1000) << " "; } if ( log_location() ) oss << stamp.file() << "/" << stamp.function() << ":" << stamp.line() << " "; if ( log_thread_id() ) { if ( thread_name().empty() ) oss << getpid() << "/" << pthread_self() << " "; else oss << "[" << thread_name() << "] "; } return oss.str(); } NXLog& operator<< (NXLog& out, const NXLogStamp& value) { /* * If appending, the file and function names must be empty and * the line set to zero. */ const bool looks_like_append = ((value.file().empty()) || (value.function().empty()) || (0 == value.line())); const bool append = ((looks_like_append) && ((value.file().empty()) && (value.function().empty()) && (0 == value.line()))); if ((looks_like_append) && (!append)) { std::cerr << "WARNING: At least one element in logstamp invalid, but this is not supposed to be an append operation. " << "Internal state error!\n" << "Log line will be discarded!" << std::endl; } else if (append) { /* Appending means that the log object's internal level and the message level must match. */ if (out.current_level() == value.level()) { /* Discard, if the message is not supposed to be written out anyway. */ if (out.will_log ()) { /* And the buffer must of course be non-empty. */ if (out.has_buffer()) { out << " (cont.) "; } else { std::cerr << "WARNING: Append operation requested, but no queued data available. " << "Internal state error!\n" << "Log line will be discarded!" << std::endl; } } } else { std::cerr << "WARNING: Append operation requested, but internal log level not matching line level. " << "Internal state error!\n" << "Log line will be discarded!" << std::endl; } } else { out.current_level( value.level() ); out.current_file( value.file() ); // Writing an NXLogStamp to the stream indicates the start of a new entry. // If there's any content in the buffer and we actually intend to keep that line, // create a new entry in the output queue. if ( out.synchronized() && out.will_log() ) out.new_stack_entry(); out << out.stamp_to_string(value); } return out; }