final KM_log changes
[asdcplib.git] / src / KM_log.cpp
1 /*
2 Copyright (c) 2004-2007, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27   /*! \file    KM_log.cpp
28     \version $Id$
29     \brief   message logging API
30   */
31
32 #include <KM_util.h>
33 #include <KM_log.h>
34 #include <sys/types.h>
35 #include <string.h>
36 #include <stdarg.h>
37
38 #ifdef KM_WIN32
39 #define getpid GetCurrentProcessId
40 #else
41 #include <unistd.h>
42 #endif
43
44 //------------------------------------------------------------------------------------------
45 //
46
47 void
48 Kumu::ILogSink::vLogf(LogType_t type, const char* fmt, va_list* list)
49 {
50   char buf[MaxLogLength];
51   vsnprintf(buf, MaxLogLength, fmt, *list);
52
53   WriteEntry(LogEntry(getpid(), type, buf));
54 }
55
56 //------------------------------------------------------------------------------------------
57 //
58
59 static Kumu::ILogSink* s_DefaultLogSink;
60 static Kumu::StdioLogSink s_StderrLogSink;
61
62 //
63 void
64 Kumu::SetDefaultLogSink(ILogSink* Sink)
65 {
66     s_DefaultLogSink = Sink;
67 }
68
69 // Returns the internal default sink.
70 Kumu::ILogSink&
71 Kumu::DefaultLogSink()
72 {
73   if ( s_DefaultLogSink == 0 )
74     s_DefaultLogSink = &s_StderrLogSink;
75
76   return *s_DefaultLogSink;
77 }
78
79
80 //------------------------------------------------------------------------------------------
81 //
82
83 void
84 Kumu::EntryListLogSink::WriteEntry(const LogEntry& Entry)
85 {
86   AutoMutex L(m_Lock);
87
88   if ( Entry.TestFilter(m_filter) )
89     m_Target.push_back(Entry);
90 }
91
92 //------------------------------------------------------------------------------------------
93 //
94
95 void
96 Kumu::StdioLogSink::WriteEntry(const LogEntry& Entry)
97 {
98   AutoMutex L(m_Lock);
99   std::string buf;
100
101   if ( Entry.TestFilter(m_filter) )
102     {
103       Entry.CreateStringWithOptions(buf, m_options);
104       fputs(buf.c_str(), m_stream);
105     }
106 }
107
108 //---------------------------------------------------------------------------------
109
110 #ifdef KM_WIN32
111 //
112 void
113 Kumu::WinDbgLogSink::WriteEntry(const LogEntry& Entry)
114 {
115   AutoMutex L(m_Lock);
116   std::string buf;
117
118   if ( Entry.TestFilter(m_filter) )
119     {
120       Entry.CreateStringWithOptions(buf, m_options);
121       ::OutputDebugString(buf.c_str());
122     }
123 }
124 #endif
125
126 //------------------------------------------------------------------------------------------
127 //
128
129 #ifndef KM_WIN32
130 //
131 void
132 Kumu::StreamLogSink::WriteEntry(const LogEntry& Entry)
133 {
134   AutoMutex L(m_Lock);
135   std::string buf;
136
137   if ( Entry.TestFilter(m_filter) )
138     {
139       Entry.CreateStringWithOptions(buf, m_options);
140       write(m_fd, buf.c_str(), buf.size());
141     }
142 }
143 #endif
144
145 //------------------------------------------------------------------------------------------
146
147 //
148 bool
149 Kumu::LogEntry::TestFilter(i32_t filter) const
150 {
151  switch ( Type )
152     {
153     case LOG_CRIT:
154       if ( (filter & LOG_ALLOW_CRIT) == 0 )
155         return false;
156       break;
157
158     case LOG_ALERT:
159       if ( (filter & LOG_ALLOW_ALERT) == 0 )
160         return false;
161       break;
162
163     case LOG_NOTICE:
164       if ( (filter & LOG_ALLOW_NOTICE) == 0 )
165         return false;
166       break;
167
168     case LOG_ERROR:
169       if ( (filter & LOG_ALLOW_ERROR) == 0 )
170         return false;
171       break;
172
173     case LOG_WARN:
174       if ( (filter & LOG_ALLOW_WARN) == 0 )
175         return false;
176       break;
177
178     case LOG_INFO:
179       if ( (filter & LOG_ALLOW_INFO) == 0 )
180         return false;
181       break;
182
183     case LOG_DEBUG:
184       if ( (filter & LOG_ALLOW_DEBUG) == 0 )
185         return false;
186       break;
187
188     }
189
190  return true;
191 }
192
193 //
194 std::string&
195 Kumu::LogEntry::CreateStringWithOptions(std::string& out_buf, i32_t opt) const
196 {
197   out_buf.clear();
198
199   if ( opt != 0 )
200     {
201       char buf[64];
202
203       if ( (opt & LOG_OPTION_TIMESTAMP) != 0 )
204         {
205           Timestamp Now;
206           out_buf += Now.EncodeString(buf, 64);
207         }
208
209       if ( (opt & LOG_OPTION_PID) != 0 )
210         {
211           if ( ! out_buf.empty() )  out_buf += " ";
212           snprintf(buf, 64, "%d", PID);
213           out_buf += buf;
214         }
215
216       if ( (opt & LOG_OPTION_TYPE) != 0 )
217         {
218           if ( ! out_buf.empty() )  out_buf += " ";
219           
220           switch ( Type )
221             {
222             case LOG_CRIT:   out_buf += "CRT";      break;
223             case LOG_ALERT:  out_buf += "ALR";      break;
224             case LOG_NOTICE: out_buf += "NTC";      break;
225             case LOG_ERROR:  out_buf += "ERR";      break;
226             case LOG_WARN:   out_buf += "WRN";      break;
227             case LOG_INFO:   out_buf += "INF";      break;
228             case LOG_DEBUG:  out_buf += "DBG";      break;
229             default:         out_buf += "DFL";      break;
230             }
231         }
232
233       out_buf.insert(0, "[");
234       out_buf += "]: ";
235     }
236
237   out_buf += Msg;
238   return out_buf;
239 }
240
241
242 //
243 ui32_t
244 Kumu::LogEntry::ArchiveLength() const
245 {
246   return sizeof(ui32_t)
247     + EventTime.ArchiveLength()
248     + sizeof(ui32_t)
249     + sizeof(ui32_t) + Msg.size();
250 }
251
252 //
253 bool
254 Kumu::LogEntry::Archive(Kumu::MemIOWriter* Writer) const
255 {
256   if ( ! Writer->WriteUi32BE(PID) ) return false;
257   if ( ! EventTime.Archive(Writer) ) return false;
258   if ( ! Writer->WriteUi32BE(Type) ) return false;
259   if ( ! ArchiveString(*Writer, Msg) ) return false;
260   return true;
261 }
262
263 //
264 bool
265 Kumu::LogEntry::Unarchive(Kumu::MemIOReader* Reader)
266 {
267   if ( ! Reader->ReadUi32BE(&PID) ) return false;
268   if ( ! EventTime.Unarchive(Reader) ) return false;
269   if ( ! Reader->ReadUi32BE((ui32_t*)&Type) ) return false;
270   if ( ! UnarchiveString(*Reader, Msg) ) return false;
271   return true;
272 }
273
274 //
275 // end
276 //