1 /*
2  * syslog.h
3  *
4  * System Logging class.
5  *
6  * Portable Tools Library
7  *
8  * Copyright (c) 2009 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Contributor(s): ______________________________________.
25  *
26  * $Revision: 24994 $
27  * $Author: rjongbloed $
28  * $Date: 2011-01-04 17:13:51 -0600 (Tue, 04 Jan 2011) $
29  */
30 
31 #ifndef _PSYSTEMLOG
32 #define _PSYSTEMLOG
33 
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37 
38 #include "ptlib/udpsock.h"
39 
40 class PSystemLogTarget;
41 
42 
43 /** This class abstracts the operating system dependent error logging facility.
44     To send messages to the system error log, the PSYSTEMLOG macro should be used.
45   */
46 
47 class PSystemLog : public PObject, public iostream
48 {
49     PCLASSINFO(PSystemLog, PObject);
50   public:
51   /**@name Construction */
52   //@{
53     /// define the different error log levels
54     enum Level {
55       /// Log from standard error stream
56       StdError = -1,
57       /// Log a fatal error
58       Fatal,
59       /// Log a non-fatal error
60       Error,
61       /// Log a warning
62       Warning,
63       /// Log general information
64       Info,
65       /// Log debugging information
66       Debug,
67       /// Log more debugging information
68       Debug2,
69       /// Log even more debugging information
70       Debug3,
71       /// Log a lot of debugging information
72       Debug4,
73       /// Log a real lot of debugging information
74       Debug5,
75       /// Log a bucket load of debugging information
76       Debug6,
77 
78       NumLogLevels
79     };
80 
81     /// Create a system log stream
82     PSystemLog(
83      Level level   ///< only messages at this level or higher will be logged
84     );
85 
86     /// Destroy the string stream, deleting the stream buffer
~PSystemLog()87     ~PSystemLog() { flush(); }
88   //@}
89 
90   /**@name Miscellaneous functions */
91   //@{
92     /** Get the current target/destination for system logging.
93       */
94     static PSystemLogTarget & GetTarget();
95 
96     /** Set the current target/destination for system logging.
97       */
98     static void SetTarget(
99       PSystemLogTarget * target,  ///< New target/destination for logging.
100       bool autoDelete = true      ///< Indicate target is to be deleted when no longer in use.
101     );
102   //@}
103 
104   private:
105     PSystemLog(const PSystemLog & other);
106     PSystemLog & operator=(const PSystemLog &);
107 
108     class Buffer : public streambuf {
109       public:
110         Buffer();
111         virtual int_type overflow(int_type=EOF);
112         virtual int_type underflow();
113         virtual int sync();
114         PSystemLog * m_log;
115         PString      m_string;
116     } m_buffer;
117     friend class Buffer;
118 
119     Level m_logLevel;
120 
121   friend class PSystemLogTarget;
122 };
123 
124 
125 class PSystemLogTarget : public PObject
126 {
127     PCLASSINFO(PSystemLogTarget, PObject);
128   public:
129   /**@name Construction */
130   //@{
131     PSystemLogTarget();
132   //@}
133 
134   /**@name Miscellaneous functions */
135   //@{
136     /** Set the level at which errors are logged. Only messages higher than or
137        equal to the specified level will be logged.
138       */
SetThresholdLevel(PSystemLog::Level level)139     void SetThresholdLevel(
140       PSystemLog::Level level  ///< New log level
141     ) { m_thresholdLevel = level; }
142 
143     /** Get the current level for logging.
144 
145        @return
146        Log level.
147      */
GetThresholdLevel()148     PSystemLog::Level GetThresholdLevel() const { return m_thresholdLevel; }
149   //@}
150 
151   protected:
152   /**@name Output functions */
153   //@{
154     /** Log an error into the system log.
155      */
156     virtual void Output(
157       PSystemLog::Level level,  ///< Level of this message
158       const char * msg          ///< Message to be logged
159     ) = 0;
160 
161     /** Log an error into the specified stream.
162      */
163     void OutputToStream(
164       ostream & strm,           ///< Stream to output
165       PSystemLog::Level level,  ///< Level of this message
166       const char * msg          ///< Message to be logged
167     );
168   //@}
169 
170   protected:
171     PSystemLog::Level m_thresholdLevel;
172 
173   private:
174     PSystemLogTarget(const PSystemLogTarget & other);
175     PSystemLogTarget & operator=(const PSystemLogTarget &);
176 
177   friend class PSystemLog::Buffer;
178 };
179 
180 
181 /** Log system output to nowhere.
182   */
183 class PSystemLogToNowhere : public PSystemLogTarget
184 {
185     PCLASSINFO(PSystemLogToNowhere, PSystemLogTarget);
186   public:
Output(PSystemLog::Level,const char *)187     virtual void Output(PSystemLog::Level, const char *)
188     {
189     }
190 };
191 
192 
193 /** Log system output to stderr.
194   */
195 class PSystemLogToStderr : public PSystemLogTarget
196 {
197     PCLASSINFO(PSystemLogToStderr, PSystemLogTarget);
198   public:
199   /**@name Overrides of PSystemLogTarget */
200   //@{
201     /** Log an error into the system log.
202      */
203     virtual void Output(
204       PSystemLog::Level level,  ///< Level of this message
205       const char * msg          ///< Message to be logged
206     );
207   //@}
208 };
209 
210 
211 /** Log system output to a file.
212   */
213 class PSystemLogToFile : public PSystemLogTarget
214 {
215     PCLASSINFO(PSystemLogToFile, PSystemLogTarget);
216   public:
217   /**@name Construction */
218   //@{
219     PSystemLogToFile(
220       const PString & filename
221     );
222   //@}
223 
224   /**@name Overrides of PSystemLogTarget */
225   //@{
226     /** Log an error into the system log.
227      */
228     virtual void Output(
229       PSystemLog::Level level,  ///< Level of this message
230       const char * msg          ///< Message to be logged
231     );
232   //@}
233 
234   /**@name Miscellaneous functions */
235   //@{
236     /**Get the path to the file being logged to.
237       */
GetFilePath()238     const PFilePath & GetFilePath() const { return m_file.GetFilePath(); }
239   //@}
240 
241   protected:
242     PTextFile m_file;
243 };
244 
245 
246 /** Log system output to the network using RFC 3164 BSD syslog protocol.
247   */
248 class PSystemLogToNetwork : public PSystemLogTarget
249 {
250     PCLASSINFO(PSystemLogToNetwork, PSystemLogTarget);
251   public:
252     enum { RFC3164_Port = 514 };
253 
254   /**@name Construction */
255   //@{
256     PSystemLogToNetwork(
257       const PIPSocket::Address & address, ///< Host to send data to
258       WORD port = RFC3164_Port,           ///< Port for UDP packet
259       unsigned facility = 16              ///< facility code
260     );
261     PSystemLogToNetwork(
262       const PString & hostname, ///< Host to send data to
263       WORD port = RFC3164_Port,           ///< Port for UDP packet
264       unsigned facility = 16              ///< facility code
265     );
266   //@}
267 
268   /**@name Overrides of PSystemLogTarget */
269   //@{
270     /** Log an error into the system log.
271      */
272     virtual void Output(
273       PSystemLog::Level level,  ///< Level of this message
274       const char * msg          ///< Message to be logged
275     );
276   //@}
277 
278   protected:
279     PIPSocket::Address m_host;
280     WORD               m_port;
281     unsigned           m_facility;
282     PUDPSocket         m_socket;
283 };
284 
285 
286 #ifdef WIN32
287 /** Log system output to the Windows OutputDebugString() function.
288   */
289 class PSystemLogToDebug : public PSystemLogTarget
290 {
291     PCLASSINFO(PSystemLogToDebug, PSystemLogTarget);
292   public:
293   /**@name Overrides of PSystemLogTarget */
294   //@{
295     /** Log an error into the system log.
296      */
297     virtual void Output(
298       PSystemLog::Level level,  ///< Level of this message
299       const char * msg          ///< Message to be logged
300     );
301   //@}
302 };
303 #elif !defined(P_VXWORKS)
304 /** Log system output to the Posix syslog() function.
305   */
306 class PSystemLogToSyslog : public PSystemLogTarget
307 {
308     PCLASSINFO(PSystemLogToSyslog, PSystemLogTarget);
309   public:
310   /**@name Construction */
311   //@{
312     PSystemLogToSyslog();
313     ~PSystemLogToSyslog();
314   //@}
315 
316   /**@name Overrides of PSystemLogTarget */
317   //@{
318     /** Log an error into the system log.
319      */
320     virtual void Output(
321       PSystemLog::Level level,  ///< Level of this message
322       const char * msg          ///< Message to be logged
323     );
324   //@}
325 };
326 #endif
327 
328 
329 /** Log a message to the system log.
330 The current log level is checked and if allowed, the second argument is evaluated
331 as a stream output sequence which is them output to the system log.
332 */
333 #define PSYSTEMLOG(level, variables) \
334   if (PSystemLog::GetTarget().GetThresholdLevel() >= PSystemLog::level) { \
335     PSystemLog P_systemlog(PSystemLog::level); \
336     P_systemlog << variables; \
337   } else (void)0
338 
339 
340 #endif
341 
342 
343 // End Of File ///////////////////////////////////////////////////////////////
344