logging re-write
[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 void
83 Kumu::StdioLogSink::WriteEntry(const LogEntry& Entry)
84 {
85   AutoMutex L(m_Lock);
86   std::string buf;
87   if ( Entry.CreateStringWithFilter(m_filter, buf) )
88     fputs(buf.c_str(), m_stream);
89 }
90
91 //---------------------------------------------------------------------------------
92
93 #ifdef KM_WIN32
94 //
95 void
96 Kumu::WinDbgLogSink::WriteEntry(const LogEntry& Entry)
97 {
98   AutoMutex L(m_Lock);
99   std::string buf;
100   if ( Entry.CreateStringWithFilter(m_filter, buf) )
101     ::OutputDebugString(buf.c_str());
102 }
103 #endif
104
105 //------------------------------------------------------------------------------------------
106 //
107
108 #ifndef KM_WIN32
109 //
110 void
111 Kumu::StreamLogSink::WriteEntry(const LogEntry& Entry)
112 {
113   AutoMutex L(m_Lock);
114   std::string buf;
115   if ( Entry.CreateStringWithFilter(m_filter, buf) )
116     write(m_fd, buf.c_str(), buf.size());
117 }
118 #endif
119
120 //------------------------------------------------------------------------------------------
121
122 bool
123 Kumu::LogEntry::CreateStringWithFilter(i32_t filter, std::string& out_buf) const
124 {
125   const char* p = 0;
126
127   switch ( Type )
128     {
129     case LOG_CRIT:
130       if ( (filter & LOG_ALLOW_CRIT) != 0 )
131         p = " CRT";
132       break;
133
134     case LOG_ALERT:
135       if ( (filter & LOG_ALLOW_ALERT) != 0 )
136         p = " ALR";
137       break;
138
139     case LOG_NOTICE:
140       if ( (filter & LOG_ALLOW_NOTICE) != 0 )
141         p = " NTC";
142       break;
143
144     case LOG_ERROR:
145       if ( (filter & LOG_ALLOW_ERROR) != 0 )
146         p = " ERR";
147       break;
148
149     case LOG_WARN:
150       if ( (filter & LOG_ALLOW_WARN) != 0 )
151         p = " WRN";
152       break;
153
154     case LOG_INFO:
155       if ( (filter & LOG_ALLOW_INFO) != 0 )
156         p = " INF";
157       break;
158
159     case LOG_DEBUG:
160       if ( (filter & LOG_ALLOW_DEBUG) != 0 )
161         p = " DBG";
162       break;
163
164     default:
165       if ( (filter & LOG_ALLOW_DEFAULT) != 0 )
166         p = " DFL";
167       break;
168     }
169
170   if ( p == 0 )
171     return false;
172
173   char buf[64];
174   out_buf = "[";
175
176   if ( (filter & LOG_ALLOW_TIMESTAMP) != 0 )
177     {
178       Timestamp Now;
179       out_buf += Now.EncodeString(buf, 64);
180
181       if ( (filter & LOG_ALLOW_PID) != 0 )
182         out_buf += " ";
183     }
184
185   if ( (filter & LOG_ALLOW_PID) != 0 )
186     {
187       snprintf(buf, 64, "%d", PID);
188       out_buf += buf;
189     }
190
191   out_buf += "] " + Msg;
192   return true;
193 }
194
195
196 //
197 ui32_t
198 Kumu::LogEntry::ArchiveLength() const
199 {
200   return sizeof(ui32_t)
201     + EventTime.ArchiveLength()
202     + sizeof(ui32_t)
203     + sizeof(ui32_t) + Msg.size();
204 }
205
206 //
207 bool
208 Kumu::LogEntry::Archive(Kumu::MemIOWriter* Writer) const
209 {
210   if ( ! Writer->WriteUi32BE(PID) ) return false;
211   if ( ! EventTime.Archive(Writer) ) return false;
212   if ( ! Writer->WriteUi32BE(Type) ) return false;
213   if ( ! ArchiveString(*Writer, Msg) ) return false;
214   return true;
215 }
216
217 //
218 bool
219 Kumu::LogEntry::Unarchive(Kumu::MemIOReader* Reader)
220 {
221   if ( ! Reader->ReadUi32BE(&PID) ) return false;
222   if ( ! EventTime.Unarchive(Reader) ) return false;
223   if ( ! Reader->ReadUi32BE((ui32_t*)&Type) ) return false;
224   if ( ! UnarchiveString(*Reader, Msg) ) return false;
225   return true;
226 }
227
228 //
229 // end
230 //