1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
|
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_LOGGER_KERNEl_ABSTRACT_
#ifdef DLIB_LOGGER_KERNEl_ABSTRACT_
#include "../threads.h"
#include <limits>
#include <string>
#include <iostream>
#include "../uintn.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class log_level
{
/*!
WHAT THIS OBJECT REPRESENTS
This object is a simple named level to log at. It contains a numeric
priority and a name to use in the logging messages.
!*/
public:
log_level(
int priority_,
const char* name_
);
/*!
ensures
- #priority = priority_
- the first 19 characters of name_ are copied into name and name
is null terminated.
!*/
bool operator< (const log_level& rhs) const { return priority < rhs.priority; }
bool operator<=(const log_level& rhs) const { return priority <= rhs.priority; }
bool operator> (const log_level& rhs) const { return priority > rhs.priority; }
bool operator>=(const log_level& rhs) const { return priority >= rhs.priority; }
int priority;
char name[20];
};
inline std::ostream& operator<< (std::ostream& out, const log_level& item);
/*!
ensures
- performs out << item.name
- returns out
!*/
// ----------------------------------------------------------------------------------------
const log_level LALL (std::numeric_limits<int>::min(),"ALL");
const log_level LNONE (std::numeric_limits<int>::max(),"NONE");
const log_level LTRACE(-100,"TRACE");
const log_level LDEBUG(0 ,"DEBUG");
const log_level LINFO (100 ,"INFO ");
const log_level LWARN (200 ,"WARN ");
const log_level LERROR(300 ,"ERROR");
const log_level LFATAL(400 ,"FATAL");
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void set_all_logging_output_streams (
std::ostream& out
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.output_streambuf() == out.rdbuf()
- Removes any previous output hook from L. So now the logger
L will write all its messages to the given output stream.
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
typedef void (*print_header_type)(
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
void set_all_logging_headers (
const print_header_type& new_header
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.logger_header() == new_header
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
void set_all_logging_output_hooks (
T& object,
void (T::*hook)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.output_streambuf() == 0
- performs the equivalent to calling L.set_output_hook(object, hook);
(i.e. sets all loggers so that they will use the given hook function)
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_all_logging_output_hooks (
T& object
);
/*!
ensures
- calls set_all_logging_output_hooks(object, &T::log);
!*/
// ----------------------------------------------------------------------------------------
void set_all_logging_levels (
const log_level& new_level
);
/*!
ensures
- for all loggers L (even loggers not yet constructed):
- #L.level() == new_level
throws
- std::bad_alloc
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void print_default_logger_header (
std::ostream& out,
const std::string& logger_name,
const log_level& l,
const uint64 thread_id
);
/*!
requires
- is not called more than once at a time (i.e. is not called from multiple
threads at the same time).
ensures
- let MS be the number of milliseconds since program start.
- prints a string to out in the form: "MS l.name [thread_id] logger_name:"
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class logger
{
/*!
INITIAL VALUE
- name() == a user supplied value given to the constructor
- The values of level(), output_streambuf(), logger_header(), and
auto_flush() are inherited from the parent of this logger.
WHAT THIS OBJECT REPRESENTS
This object represents a logging output stream in the style of the log4j
logger available for Java.
Additionally, the logger doesn't perform any memory allocations during
each logging action. It just writes directly into the user supplied output
stream. Alternatively, if you use a logging output hook no memory allocations
are performed either. Logging just goes straight into a memory buffer
which gets passed to the user supplied logging hook.
DEFAULTS
If the user hasn't specified values for the four inherited values level(),
output_streambuf(), logger_header(), or auto_flush() then the default
values will be used. The defaults are as follows:
- level() == LERROR
- output_streambuf() == std::cout.rdbuf() (i.e. the default is to log
to standard output).
- logger_header() == print_default_logger_header
- auto_flush() == true
THREAD SAFETY
All methods of this class are thread safe. Note that it is safe to
chain calls to operator << such as:
log << LINFO << "message " << variable << " more message";
The logger ensures that the entire statement executes atomically so the
message won't be broken up by other loggers in other threads.
!*/
class logger_stream
{
public:
bool is_enabled (
) const;
/*!
ensures
- returns true if this logger stream will print out items
given to it by the << operator. returns false otherwise.
!*/
template <typename T>
logger_stream& operator << (
const T& item
);
/*!
ensures
- if (is_enabled()) then
- writes item to this output stream
- returns *this
!*/
};
public:
logger (
const std::string& name_
);
/*!
requires
- name_ != ""
ensures
- #*this is properly initialized
- #name() == name_
throws
- std::bad_alloc
- dlib::thread_error
!*/
virtual ~logger (
);
/*!
ensures
- any resources associated with *this have been released
!*/
const std::string& name (
) const;
/*!
ensures
- returns the name of this logger
!*/
logger_stream operator << (
const log_level& l
) const;
/*!
ensures
- if (l.priority >= level().priority) then
- returns a logger_stream with is_enabled() == true. I.e. this
returned stream will write its output to the I/O destination
used by this logger object.
- else
- returns a logger stream with is_enabled() == false
throws
- std::bad_alloc
!*/
bool is_child_of (
const logger& log
) const;
/*!
ensures
- if ( (name().find(log.name() + ".") == 0) || (log.name() == name()) ) then
- returns true
(i.e. if log.name() + "." is a prefix of name() or if both *this and log
have the same name then return true)
- else
- returns false
!*/
const log_level level (
) const;
/*!
ensures
- returns the current log level of this logger.
!*/
void set_level (
const log_level& new_level
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.level() == new_level
throws
- std::bad_alloc
!*/
bool auto_flush (
);
/*!
ensures
- returns true if the output stream is flushed after every logged message.
returns false otherwise. (Note that flushing only does anything if
the logger is set to use an output stream rather than a hook)
!*/
void set_auto_flush (
bool enabled
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.auto_flush() == enabled
throws
- std::bad_alloc
!*/
template <
typename T
>
void set_output_hook (
T& object,
void (T::*hook)(const std::string& logger_name,
const log_level& l,
const uint64 thread_id,
const char* message_to_log)
);
/*!
requires
- hook is a valid pointer to a member function in T
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.output_streambuf() == 0
- #L will not send its log messages to an ostream object anymore. Instead
it will call the given hook member function (i.e. (object.*hook)(name,l,id,msg) )
for each message that needs to be logged.
- The arguments to the hook function have the following meanings:
- logger_name == The name of the logger that is printing the log message.
- l == The level of the logger that is printing the log message.
- thread_id == A number that uniquely identifies the thread trying to log
the message. Note that this number is unique among all threads, past and
present. Also note that this id is not the same one returned by
get_thread_id().
- message_to_log == the actual text of the message the user is giving to
the logger object to log.
- All hook functions will also only be called one at a time. This means
that hook functions don't need to be thread safe.
!*/
std::streambuf* output_streambuf (
);
/*!
ensures
- if (an output hook isn't set) then
- returns the output stream buffer that this logger writes all
messages to.
- else
- returns 0
!*/
void set_output_stream (
std::ostream& out
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.output_streambuf() == out.rdbuf()
- Removes any previous output hook from L. So now the logger
L will write all its messages to the given output stream.
throws
- std::bad_alloc
!*/
print_header_type logger_header (
) const;
/*!
ensures
- returns the function that is called to print the header information
onto each logged message. The arguments to the function have the following
meanings:
- out == The output stream this function writes the header to.
- logger_name == The name of the logger that is printing the log message.
- l == The level of the logger that is printing the log message.
- thread_id == A number that uniquely identifies the thread trying to log
the message. Note that this number is unique among all threads, past and
present. Also note that this id is not the same one returned by
get_thread_id().
- This logger_header function will also only be called once at a time. This means
the logger_header function doesn't need to be thread safe.
- the logger_header function is only used when output_streambuf() != 0
!*/
void set_logger_header (
print_header_type print_header
);
/*!
ensures
- for all loggers L such that L.is_child_of(*this) == true:
- #L.logger_header() == print_header
throws
- std::bad_alloc
!*/
private:
// restricted functions
logger(const logger&); // copy constructor
logger& operator=(const logger&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_LOGGER_KERNEl_ABSTRACT_
|