/*
-Copyright (c) 2004-2008, John Hurst
+Copyright (c) 2004-2011, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include <KM_util.h>
#include <KM_log.h>
+#include <KM_mutex.h>
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
+#include <iostream>
+#include <sstream>
#ifdef KM_WIN32
#define getpid GetCurrentProcessId
//------------------------------------------------------------------------------------------
//
-static Kumu::ILogSink* s_DefaultLogSink;
+static Kumu::Mutex s_DefaultLogSinkLock;
+static Kumu::ILogSink* s_DefaultLogSink = 0;
static Kumu::StdioLogSink s_StderrLogSink;
//
void
Kumu::SetDefaultLogSink(ILogSink* Sink)
{
- s_DefaultLogSink = Sink;
+ AutoMutex L(s_DefaultLogSinkLock);
+ s_DefaultLogSink = Sink;
}
// Returns the internal default sink.
Kumu::ILogSink&
Kumu::DefaultLogSink()
{
+ AutoMutex L(s_DefaultLogSinkLock);
+
if ( s_DefaultLogSink == 0 )
s_DefaultLogSink = &s_StderrLogSink;
void
Kumu::EntryListLogSink::WriteEntry(const LogEntry& Entry)
{
- AutoMutex L(m_Lock);
+ AutoMutex L(m_lock);
+ WriteEntryToListeners(Entry);
if ( Entry.TestFilter(m_filter) )
m_Target.push_back(Entry);
void
Kumu::StdioLogSink::WriteEntry(const LogEntry& Entry)
{
- AutoMutex L(m_Lock);
std::string buf;
+ AutoMutex L(m_lock);
+ WriteEntryToListeners(Entry);
if ( Entry.TestFilter(m_filter) )
{
Entry.CreateStringWithOptions(buf, m_options);
fputs(buf.c_str(), m_stream);
+ fflush(m_stream);
}
}
#ifdef KM_WIN32
//
+// http://www.codeguru.com/forum/showthread.php?t=231165
+//
void
Kumu::WinDbgLogSink::WriteEntry(const LogEntry& Entry)
{
- AutoMutex L(m_Lock);
std::string buf;
+ AutoMutex L(m_lock);
+ WriteEntryToListeners(Entry);
if ( Entry.TestFilter(m_filter) )
{
Entry.CreateStringWithOptions(buf, m_options);
- ::OutputDebugString(buf.c_str());
+ ::OutputDebugStringA(buf.c_str());
}
}
#endif
void
Kumu::StreamLogSink::WriteEntry(const LogEntry& Entry)
{
- AutoMutex L(m_Lock);
std::string buf;
+ AutoMutex L(m_lock);
+ WriteEntryToListeners(Entry);
if ( Entry.TestFilter(m_filter) )
{
Entry.CreateStringWithOptions(buf, m_options);
- write(m_fd, buf.c_str(), buf.size());
+ ssize_t n = write(m_fd, buf.c_str(), buf.size());
+ assert(n==buf.size());
+ }
+}
+
+// foolin with symbols
+//------------------------------------------------------------------------------------------
+#include <syslog.h>
+int const SYSLOG_ALERT = LOG_ALERT;
+int const SYSLOG_CRIT = LOG_CRIT;
+int const SYSLOG_ERR = LOG_ERR;
+int const SYSLOG_WARNING = LOG_WARNING;
+int const SYSLOG_NOTICE = LOG_NOTICE;
+int const SYSLOG_INFO = LOG_INFO;
+int const SYSLOG_DEBUG = LOG_DEBUG;
+#undef LOG_ALERT
+#undef LOG_CRIT
+#undef LOG_ERR
+#undef LOG_WARNING
+#undef LOG_NOTICE
+#undef LOG_INFO
+#undef LOG_DEBUG
+//------------------------------------------------------------------------------------------
+
+Kumu::SyslogLogSink::SyslogLogSink(const std::string& source_name, int facility)
+{
+ if ( facility == 0 )
+ facility = LOG_DAEMON;
+
+ openlog(source_name.c_str(), LOG_CONS|LOG_NDELAY||LOG_PID, facility);
+}
+
+Kumu::SyslogLogSink::~SyslogLogSink()
+{
+ closelog();
+}
+
+//
+void
+Kumu::SyslogLogSink::WriteEntry(const LogEntry& Entry)
+{
+ int priority;
+
+ switch ( Entry.Type )
+ {
+ case Kumu::LOG_ALERT: priority = SYSLOG_ALERT; break;
+ case Kumu::LOG_CRIT: priority = SYSLOG_CRIT; break;
+ case Kumu::LOG_ERROR: priority = SYSLOG_ERR; break;
+ case Kumu::LOG_WARN: priority = SYSLOG_WARNING; break;
+ case Kumu::LOG_NOTICE: priority = SYSLOG_NOTICE; break;
+ case Kumu::LOG_INFO: priority = SYSLOG_INFO; break;
+ case Kumu::LOG_DEBUG: priority = SYSLOG_DEBUG; break;
+ }
+
+ AutoMutex L(m_lock);
+ WriteEntryToListeners(Entry);
+
+ if ( Entry.TestFilter(m_filter) )
+ {
+ syslog(priority, "%s", Entry.Msg.substr(0, Entry.Msg.size() - 1).c_str());
}
}
+
+//
+int
+Kumu::SyslogNameToFacility(const std::string& facility_name)
+{
+ if ( facility_name == "LOG_DAEMON" ) return LOG_DAEMON;
+ if ( facility_name == "LOG_LOCAL0" ) return LOG_LOCAL0;
+ if ( facility_name == "LOG_LOCAL1" ) return LOG_LOCAL1;
+ if ( facility_name == "LOG_LOCAL2" ) return LOG_LOCAL2;
+ if ( facility_name == "LOG_LOCAL3" ) return LOG_LOCAL3;
+ if ( facility_name == "LOG_LOCAL4" ) return LOG_LOCAL4;
+ if ( facility_name == "LOG_LOCAL5" ) return LOG_LOCAL5;
+ if ( facility_name == "LOG_LOCAL6" ) return LOG_LOCAL6;
+ if ( facility_name == "LOG_LOCAL7" ) return LOG_LOCAL7;
+
+ DefaultLogSink().Error("Unsupported facility name: %s, using default value LOG_DAEMON\n", facility_name.c_str());
+ return LOG_DAEMON;
+}
+
#endif
//------------------------------------------------------------------------------------------
+//
+std::basic_ostream<char, std::char_traits<char> >&
+Kumu::operator<<(std::basic_ostream<char, std::char_traits<char> >& strm, LogEntry const& Entry)
+{
+ std::basic_ostringstream<char, std::char_traits<char> > s;
+ s.copyfmt(strm);
+ s.width(0);
+ std::string buf;
+
+ s << Entry.CreateStringWithOptions(buf, LOG_OPTION_ALL);
+
+ strm << s.str();
+ return strm;
+}
+
+//------------------------------------------------------------------------------------------
+
+
//
bool
Kumu::LogEntry::TestFilter(i32_t filter) const
std::string&
Kumu::LogEntry::CreateStringWithOptions(std::string& out_buf, i32_t opt) const
{
- out_buf.clear();
+ out_buf.erase();
if ( opt != 0 )
{