2 Copyright (c) 2004-2011, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 \brief message logging API
35 #include <sys/types.h>
42 #define getpid GetCurrentProcessId
47 //------------------------------------------------------------------------------------------
51 Kumu::ILogSink::vLogf(LogType_t type, const char* fmt, va_list* list)
53 char buf[MaxLogLength];
54 vsnprintf(buf, MaxLogLength, fmt, *list);
56 WriteEntry(LogEntry(getpid(), type, buf));
59 //------------------------------------------------------------------------------------------
62 static Kumu::Mutex s_DefaultLogSinkLock;
63 static Kumu::ILogSink* s_DefaultLogSink = 0;
64 static Kumu::StdioLogSink s_StderrLogSink;
68 Kumu::SetDefaultLogSink(ILogSink* Sink)
70 AutoMutex L(s_DefaultLogSinkLock);
71 s_DefaultLogSink = Sink;
74 // Returns the internal default sink.
76 Kumu::DefaultLogSink()
78 AutoMutex L(s_DefaultLogSinkLock);
80 if ( s_DefaultLogSink == 0 )
81 s_DefaultLogSink = &s_StderrLogSink;
83 return *s_DefaultLogSink;
87 //------------------------------------------------------------------------------------------
91 Kumu::EntryListLogSink::WriteEntry(const LogEntry& Entry)
94 WriteEntryToListeners(Entry);
96 if ( Entry.TestFilter(m_filter) )
97 m_Target.push_back(Entry);
100 //------------------------------------------------------------------------------------------
104 Kumu::StdioLogSink::WriteEntry(const LogEntry& Entry)
108 WriteEntryToListeners(Entry);
110 if ( Entry.TestFilter(m_filter) )
112 Entry.CreateStringWithOptions(buf, m_options);
113 fputs(buf.c_str(), m_stream);
117 //---------------------------------------------------------------------------------
121 // http://www.codeguru.com/forum/showthread.php?t=231165
124 Kumu::WinDbgLogSink::WriteEntry(const LogEntry& Entry)
128 WriteEntryToListeners(Entry);
130 if ( Entry.TestFilter(m_filter) )
132 Entry.CreateStringWithOptions(buf, m_options);
133 ::OutputDebugStringA(buf.c_str());
138 //------------------------------------------------------------------------------------------
144 Kumu::StreamLogSink::WriteEntry(const LogEntry& Entry)
148 WriteEntryToListeners(Entry);
150 if ( Entry.TestFilter(m_filter) )
152 Entry.CreateStringWithOptions(buf, m_options);
153 write(m_fd, buf.c_str(), buf.size());
157 // foolin with symbols
158 //------------------------------------------------------------------------------------------
160 int const SYSLOG_ALERT = LOG_ALERT;
161 int const SYSLOG_CRIT = LOG_CRIT;
162 int const SYSLOG_ERR = LOG_ERR;
163 int const SYSLOG_WARNING = LOG_WARNING;
164 int const SYSLOG_NOTICE = LOG_NOTICE;
165 int const SYSLOG_INFO = LOG_INFO;
166 int const SYSLOG_DEBUG = LOG_DEBUG;
174 //------------------------------------------------------------------------------------------
176 Kumu::SyslogLogSink::SyslogLogSink(const std::string& source_name, int facility)
179 facility = LOG_DAEMON;
181 openlog(source_name.c_str(), LOG_CONS|LOG_NDELAY||LOG_PID, facility);
184 Kumu::SyslogLogSink::~SyslogLogSink()
191 Kumu::SyslogLogSink::WriteEntry(const LogEntry& Entry)
195 switch ( Entry.Type )
197 case Kumu::LOG_ALERT: priority = SYSLOG_ALERT; break;
198 case Kumu::LOG_CRIT: priority = SYSLOG_CRIT; break;
199 case Kumu::LOG_ERROR: priority = SYSLOG_ERR; break;
200 case Kumu::LOG_WARN: priority = SYSLOG_WARNING; break;
201 case Kumu::LOG_NOTICE: priority = SYSLOG_NOTICE; break;
202 case Kumu::LOG_INFO: priority = SYSLOG_INFO; break;
203 case Kumu::LOG_DEBUG: priority = SYSLOG_DEBUG; break;
207 WriteEntryToListeners(Entry);
209 if ( Entry.TestFilter(m_filter) )
211 syslog(priority, "%s", Entry.Msg.substr(0, Entry.Msg.size() - 1).c_str());
217 Kumu::SyslogNameToFacility(const std::string& facility_name)
219 if ( facility_name == "LOG_DAEMON" ) return LOG_DAEMON;
220 if ( facility_name == "LOG_LOCAL0" ) return LOG_LOCAL0;
221 if ( facility_name == "LOG_LOCAL1" ) return LOG_LOCAL1;
222 if ( facility_name == "LOG_LOCAL2" ) return LOG_LOCAL2;
223 if ( facility_name == "LOG_LOCAL3" ) return LOG_LOCAL3;
224 if ( facility_name == "LOG_LOCAL4" ) return LOG_LOCAL4;
225 if ( facility_name == "LOG_LOCAL5" ) return LOG_LOCAL5;
226 if ( facility_name == "LOG_LOCAL6" ) return LOG_LOCAL6;
227 if ( facility_name == "LOG_LOCAL7" ) return LOG_LOCAL7;
229 DefaultLogSink().Error("Unsupported facility name: %s, using default value LOG_DAEMON\n", facility_name.c_str());
235 //------------------------------------------------------------------------------------------
238 std::basic_ostream<char, std::char_traits<char> >&
239 Kumu::operator<<(std::basic_ostream<char, std::char_traits<char> >& strm, LogEntry const& Entry)
241 std::basic_ostringstream<char, std::char_traits<char> > s;
246 s << Entry.CreateStringWithOptions(buf, LOG_OPTION_ALL);
252 //------------------------------------------------------------------------------------------
257 Kumu::LogEntry::TestFilter(i32_t filter) const
262 if ( (filter & LOG_ALLOW_CRIT) == 0 )
267 if ( (filter & LOG_ALLOW_ALERT) == 0 )
272 if ( (filter & LOG_ALLOW_NOTICE) == 0 )
277 if ( (filter & LOG_ALLOW_ERROR) == 0 )
282 if ( (filter & LOG_ALLOW_WARN) == 0 )
287 if ( (filter & LOG_ALLOW_INFO) == 0 )
292 if ( (filter & LOG_ALLOW_DEBUG) == 0 )
303 Kumu::LogEntry::CreateStringWithOptions(std::string& out_buf, i32_t opt) const
311 if ( (opt & LOG_OPTION_TIMESTAMP) != 0 )
314 out_buf += Now.EncodeString(buf, 64);
317 if ( (opt & LOG_OPTION_PID) != 0 )
319 if ( ! out_buf.empty() ) out_buf += " ";
320 snprintf(buf, 64, "%d", PID);
324 if ( (opt & LOG_OPTION_TYPE) != 0 )
326 if ( ! out_buf.empty() ) out_buf += " ";
330 case LOG_CRIT: out_buf += "CRT"; break;
331 case LOG_ALERT: out_buf += "ALR"; break;
332 case LOG_NOTICE: out_buf += "NTC"; break;
333 case LOG_ERROR: out_buf += "ERR"; break;
334 case LOG_WARN: out_buf += "WRN"; break;
335 case LOG_INFO: out_buf += "INF"; break;
336 case LOG_DEBUG: out_buf += "DBG"; break;
337 default: out_buf += "DFL"; break;
341 out_buf.insert(0, "[");
352 Kumu::LogEntry::ArchiveLength() const
354 return sizeof(ui32_t)
355 + EventTime.ArchiveLength()
357 + sizeof(ui32_t) + Msg.size();
362 Kumu::LogEntry::Archive(Kumu::MemIOWriter* Writer) const
364 if ( ! Writer->WriteUi32BE(PID) ) return false;
365 if ( ! EventTime.Archive(Writer) ) return false;
366 if ( ! Writer->WriteUi32BE(Type) ) return false;
367 if ( ! ArchiveString(*Writer, Msg) ) return false;
373 Kumu::LogEntry::Unarchive(Kumu::MemIOReader* Reader)
375 if ( ! Reader->ReadUi32BE(&PID) ) return false;
376 if ( ! EventTime.Unarchive(Reader) ) return false;
377 if ( ! Reader->ReadUi32BE((ui32_t*)&Type) ) return false;
378 if ( ! UnarchiveString(*Reader, Msg) ) return false;