Coverage Report

Created: 2024-07-23 06:38

/src/resiprocate/rutil/Logger.hxx
Line
Count
Source (jump to first uncovered line)
1
#ifndef RESIP_Logger_hxx
2
#define RESIP_Logger_hxx
3
4
#include "rutil/Log.hxx"
5
#include "rutil/Lock.hxx"
6
#include "rutil/DataStream.hxx"
7
#include "rutil/Data.hxx"
8
#include "rutil/Subsystem.hxx"
9
10
#ifdef WIN32
11
#include <windows.h>
12
#endif 
13
14
/**
15
   @file Defines a set of logging macros, one for each level of logging.
16
17
   <h2>Simple usage</h2>
18
19
   Each source file which uses logging facilities, must set RESIPROCATE_SUBSYSTEM
20
   preprocessor define to one of resip subsystems. This define will be used by
21
   logging macros to mark log entries, generated from this source file, with
22
   appropriate subsystem tag. For the list of available resip subsystems refer
23
   to static variables list in resip::Subsystem class. Note, that those standard
24
   resip::Subsystem variables are just the most commonly used ones. Nothing
25
   prevents you from creating your own resip::Subsystem instance and set
26
   RESIPROCATE_SUBSYSTEM to point to it. That custom resip::Subsystem variable
27
   can even be local to a file or private class member variable, you just must
28
   ensure that it exist in all places you use logging this file. Creating own
29
   resip::Subsystem will allow you to create own subsystem tag and set specific
30
   logging level for it.
31
32
   Once you have RESIPROCATE_SUBSYSTEM defined you can start logging with any
33
   of StackLog(), DebugLog(), InfoLog(), WarningLog(), ErrLog(), CritLog(). These
34
   preprocessor macros provide a convenient way to log your data. Look at this
35
   piece of code as an example:
36
37
<code>
38
#include Logger.hxx
39
#define RESIPROCATE_SUBSYSTEM resip::Subsystem::SIP
40
   ...
41
   DebugLog(<< "hi there " << mix << 4 << types);  // note leading << and no endl
42
</code>
43
44
45
   <h2>Initialization</h2>
46
47
   Logging may be used without (or prior to) initialization, in which case all
48
   log data will be printed right to console (to std::cout). Likely, you will
49
   want to use more advanced logging features like output to syslog or a file.
50
   In this case you need to call Log::initialize() with appropriate parameters.
51
   E.g., following example tells logger to write data to a file with the name
52
   "resip.log". It will write only entries with logging priority Log::Info or
53
   higher. Application name is taken from argv[0], and no external logger is
54
   specified (last parameter is NULL).
55
56
<code>
57
   Log::initialize(Log::File, Log::Info, argv[0], "resip.log", NULL);
58
</code>
59
60
   Refer to Log::Type for a list of possible logging types and to Log::Level
61
   for a list of available logging levels.
62
63
64
   <h2>External loggers</h2>
65
66
   Sometimes you may need to provide your own, application specific way of
67
   logging. E.g. you may want to output log data to a GUI window. This may be
68
   implemented using external loggers. To create an external logger you just
69
   need to inherit from ExternalLogger class and pass an object of your external
70
   logger to Log::initialize() as the last parameter.
71
72
   
73
   <h2Subsystem-specific logging level></h2>
74
75
   You may set logging level to output for a specific subsystem inside resip.
76
   The recommended way to do this is with <code>Log::setLevel(level, subsystem)</code>
77
   static function. If you set a concrete logging level for the subsystem, it
78
   will be used instead of all other logging level settings, like global logging
79
   level setting and thread local logger level setting. To set subsystem-specific
80
   logging level back to default logging level, call
81
   <code>Log::setLevel(Log::None, subsystem)</code>
82
83
84
   <h2>Thread local loggers</h2>
85
86
   If your application uses several threads for resip, e.g. uses separate thread
87
   for each resip instance, then you may want to split your log streams to be
88
   separate too. E.g. you may use different log files for different instances.
89
   In this case you need to use thread local loggers.
90
91
   First, you need to create a thread local logger with Log::localLoggerCreate()
92
   static function call with desired parameters (they're closely following
93
   Log::initialize() meaning). You will receive LocalLoggerId in response which
94
   you will use later to refer to created local logger. If you need to change
95
   local logger's parameters later, you should use Log::localLoggerReinitialize()
96
   static function. And when you're done with it, free it with Log::localLoggerRemove()
97
   static function. To actually use a created local logger, you need to call
98
   Log::setThreadLocalLogger() from the target thread context. If you need to
99
   remove thread local logger from a thread, just call
100
   <code>Log::setThreadLocalLogger(0)</code>
101
102
   Note, that thread local logger may be safely used from multiple threads.
103
   So if each of your resip instances have two threads, both of them can just
104
   share the same local logger - just pass its LocalLoggerId to them both.
105
106
107
   <h2>Still not sure?</h2>
108
109
   If you still can't get something, just look how it is used in existing code.
110
   One particular place to look into is rutil/test/testLogger.cxx which is
111
   a unittest for logging facility.
112
*/
113
114
115
#define DELIM 
116
117
118
119
// unconditionally output to cerr -- easily change back and forth
120
#define CerrLog(args_)                                                  \
121
  resip::Log::tags(resip::Log::StdErr, RESIPROCATE_SUBSYSTEM,           \
122
                   __FILE__, __LINE__, __func__, resipCerr, resip::Log::Unstructured) << ' ' << '|' << ' '  \
123
          args_ << std::endl;
124
125
0
#define StackLog(args_)                                                         \
126
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Stack, args_)
127
128
0
#define DebugLog(args_) \
129
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Debug, args_)
130
131
0
#define InfoLog(args_) \
132
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Info, args_)
133
134
0
#define WarningLog(args_) \
135
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Warning, args_)
136
137
0
#define ErrLog(args_) \
138
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Err, args_)
139
140
0
#define CritLog(args_) \
141
0
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Crit, args_)
142
143
static inline bool
144
genericLogCheckLevel(resip::Log::Level level, const resip::Subsystem& sub)
145
2
{
146
2
   return resip::Log::isLogging(level, sub);
147
2
}
Unexecuted instantiation: fuzzUtil.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Unexecuted instantiation: DnsUtil.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Log.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Line
Count
Source
145
2
{
146
2
   return resip::Log::isLogging(level, sub);
147
2
}
Unexecuted instantiation: ParseBuffer.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Unexecuted instantiation: Socket.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Unexecuted instantiation: ThreadIf.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Unexecuted instantiation: BaseException.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
Unexecuted instantiation: ConfigParse.cxx:genericLogCheckLevel(resip::Log::Level, resip::Subsystem const&)
148
149
// do/while allows a {} block in an expression
150
#define GenericLog(system_, level_, args_)                              \
151
2
   do                                                                   \
152
2
   {                                                                    \
153
2
      if (genericLogCheckLevel(level_, system_))                        \
154
2
      {                                                                 \
155
0
         resip::Log::Guard _resip_log_guard(level_, system_, __FILE__, __LINE__, __func__); \
156
0
         _resip_log_guard.asStream()  args_;                            \
157
0
      }                                                                 \
158
2
   } while (false)
159
160
#ifdef NO_DEBUG
161
// Suppress debug logging at compile time
162
#undef DebugLog
163
#define DebugLog(args_)
164
#undef StackLog 
165
#define StackLog(args_)
166
#endif
167
168
namespace resip
169
{
170
/// DEPRECATED! Left for backward compatibility.
171
typedef Log GenericLogImpl;
172
}
173
174
#endif
175
176
/* ====================================================================
177
 * The Vovida Software License, Version 1.0 
178
 * 
179
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
180
 * 
181
 * Redistribution and use in source and binary forms, with or without
182
 * modification, are permitted provided that the following conditions
183
 * are met:
184
 * 
185
 * 1. Redistributions of source code must retain the above copyright
186
 *    notice, this list of conditions and the following disclaimer.
187
 * 
188
 * 2. Redistributions in binary form must reproduce the above copyright
189
 *    notice, this list of conditions and the following disclaimer in
190
 *    the documentation and/or other materials provided with the
191
 *    distribution.
192
 * 
193
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
194
 *    and "Vovida Open Communication Application Library (VOCAL)" must
195
 *    not be used to endorse or promote products derived from this
196
 *    software without prior written permission. For written
197
 *    permission, please contact vocal@vovida.org.
198
 *
199
 * 4. Products derived from this software may not be called "VOCAL", nor
200
 *    may "VOCAL" appear in their name, without prior written
201
 *    permission of Vovida Networks, Inc.
202
 * 
203
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
204
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
205
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
206
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
207
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
208
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
209
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
211
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
212
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
213
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
214
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
215
 * DAMAGE.
216
 * 
217
 * ====================================================================
218
 * 
219
 * This software consists of voluntary contributions made by Vovida
220
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
221
 * Inc.  For more information on Vovida Networks, Inc., please see
222
 * <http://www.vovida.org/>.
223
 *
224
 */