std::ostream& MessageEventDetailsEncoder::encode(const MessageEventEphemeral& event, std::ostream &os) { static const size_t maxLogLine = 10 * 1024; char dateString[64]; curTimeString(dateString); os << dateString << ' '; StringData contextName = event.getContextName(); if (!contextName.empty()) { os << '[' << contextName << "] "; } LogSeverity severity = event.getSeverity(); if (severity >= LogSeverity::Info()) { os << severity << ": "; } StringData msg = event.getMessage(); if (msg.size() > maxLogLine) { os << "warning: log line attempted (" << msg.size() / 1024 << "k) over max size (" << maxLogLine / 1024 << "k), printing beginning and end ... "; os << msg.substr(0, maxLogLine / 3); os << " .......... "; os << msg.substr(msg.size() - (maxLogLine / 3)); } else { os << msg; } if (!msg.endsWith(StringData("\n", StringData::LiteralTag()))) os << '\n'; return os; }
/* note: can't use malloc herein - may be in signal handler. logLockless() likely does not comply and should still be fixed todo likewise class string? */ void rawOut( const string &s ) { if( s.empty() ) return; char buf[64]; curTimeString(buf); buf[23] = ' '; buf[24] = 0; Logstream::logLockless(buf); Logstream::logLockless(s); Logstream::logLockless("\n"); }
void Logstream::flush(Tee *t) { const size_t MAX_LOG_LINE = 1024 * 10; // this ensures things are sane if ( doneSetup == 1717 ) { string msg = ss.str(); string threadName = getThreadName(); const char * type = logLevelToString(logLevel); size_t msgLen = msg.size(); if ( msgLen > MAX_LOG_LINE ) msgLen = MAX_LOG_LINE; const int spaceNeeded = (int)( msgLen + 64 /* for extra info */ + threadName.size()); int bufSize = 128; while ( bufSize < spaceNeeded ) bufSize += 128; BufBuilder b(bufSize); char* dateStr = b.grow(24); curTimeString(dateStr); dateStr[23] = ' '; // change null char to space if (!threadName.empty()) { b.appendChar( '[' ); b.appendStr( threadName , false ); b.appendChar( ']' ); b.appendChar( ' ' ); } for ( int i=0; i<indent; i++ ) b.appendChar( '\t' ); if ( type[0] ) { b.appendStr( type , false ); b.appendStr( ": " , false ); } if ( msg.size() > MAX_LOG_LINE ) { stringstream sss; sss << "warning: log line attempted (" << msg.size() / 1024 << "k) over max size(" << MAX_LOG_LINE / 1024 << "k)"; sss << ", printing beginning and end ... "; b.appendStr( sss.str(), false ); const char * xx = msg.c_str(); b.appendBuf( xx , MAX_LOG_LINE / 3 ); b.appendStr( " .......... ", false ); b.appendStr( xx + msg.size() - ( MAX_LOG_LINE / 3 ) ); } else { b.appendStr( msg ); } string out( b.buf() , b.len() - 1); verify( b.len() < spaceNeeded ); scoped_lock lk(mutex); if( t ) t->write(logLevel,out); if ( globalTees ) { for ( unsigned i=0; i<globalTees->size(); i++ ) (*globalTees)[i]->write(logLevel,out); } #if defined(_WIN32) int fd = fileno( logfile ); if ( _isatty( fd ) ) { fflush( logfile ); writeUtf8ToWindowsConsole( out.data(), out.size() ); } #else if ( isSyslog ) { syslog( logLevelToSysLogLevel(logLevel) , "%s" , out.data() ); } #endif else if ( fwrite( out.data(), out.size(), 1, logfile ) ) { fflush(logfile); } else { int x = errno; cout << "Failed to write to logfile: " << errnoWithDescription(x) << ": " << out << endl; } #ifdef POSIX_FADV_DONTNEED // This only applies to pages that have already been flushed RARELY posix_fadvise(fileno(logfile), 0, 0, POSIX_FADV_DONTNEED); #endif } _init(); }