]> mj.ucw.cz Git - libucw.git/blob - ucw/doc/log.txt
Logging: Precise timestamps and syslog PID flag are now configurable.
[libucw.git] / ucw / doc / log.txt
1 Logging
2 =======
3
4 LibUCW contains a powerful system for logging of messages. Depending on your
5 needs, it can be used either as a very simple logger which writes all messages
6 to stderr or to a single file, or as a multi-stream logger in which different
7 messages can be directed to different streams and the streams can be combined
8 in various ways.
9
10 Simple logging
11 --------------
12 The basic logging functions are defined in <<basics:logging,lib.h>>.
13
14 To log a message, call `msg(L_xxx,@fmt,@args)`, where `L_xxx` is a category of the log
15 message (`L_INFO`, `L_WARN`, `L_ERR` etc.), @fmt is a format string as for printf,
16 and @args are additional arguments to be substituted to the format string.
17 A newline character is automatically appended; the message should not contain
18 any control characters.
19
20 The first argument of `msg` can be OR'ed with additional flags. Most notably, you can
21 add `L_SIGHANDLER` if you wish to log a message from a signal handler (calling
22 time-related functions in libc from signal handlers is generally unsafe, so
23 `msg` does not log a timestamp in such cases).
24
25 By default, all messages are logged to stderr. If you wish to use a log file,
26 call `log_file(@name)`. All subsequent logging will use this file and stderr
27 will be redirected there, too.
28
29 Names of log files can contain strftime() escapes, which are expanded on the fly.
30 This makes it easy to start a new log file every day.
31
32 Example
33 ~~~~~~~
34         #include <ucw/lib.h>
35
36         int main(int argc, char **argv)
37         {
38           log_init(argv[0]);
39           log_file("/var/log/utterances");
40           msg(L_INFO, "This program does nothing, but successfully.");
41           return 0;
42         }
43
44 Log streams
45 -----------
46 More generally, the logger can use multiple log streams. Each stream can be directed
47 to a logging back-end (log file, syslog, ...) and equipped with a filter which
48 selects a subset of the messages received. A stream can also have substreams
49 attached, which are passed a copy of all log messages sent to the parent stream.
50
51 Streams are identified by <<struct_log_stream,struct log_stream>> and also by
52 their registration number. Messages can be directed to a stream by OR'ing the
53 registration number to the first argument of msg().
54
55 When a log stream receives a message, it is processed as follows:
56
57   1. If the log level of the message does not match the set of accepted
58      levels of the stream (@levels), the message is dropped.
59   2. The filter hook of the stream is consulted and if it returns a non-zero
60      value, the message is dropped.
61   3. The message is passed to all substreams of the stream.
62   4. The message is formatted according to the formatting flags (@msgfmt) of the stream.
63   5. The handler hook of the stream is called (if it exists).
64
65 When no stream is explicitly selected, msg() uses the default stream, which
66 has registration number 0 and which is also returned by log_default_stream().
67 This stream has no explicit destination, but it can have substreams. (When
68 a program starts, the default stream is connected to stderr; a call to log_file()
69 establishes a file logging stream and links it as the only substream of the
70 default stream.)
71
72 Streams are reference-counted. When a stream is created, it gets reference count 1.
73 When it is linked as a substream of another stream, its reference count is incremented.
74 Closing the stream by log_close_stream(), unlinking it or closing a parent stream
75 (which causes an unlink) decrements the reference count and when it drops to zero,
76 the stream is removed and all its substreams unlinked.
77
78 Example
79 ~~~~~~~
80         #include <ucw/lib.h>
81         #include <ucw/log.h>
82
83         int main(int argc, char **argv)
84         {
85           log_init(argv[0]);
86           struct log_stream *ls = log_new_file("/var/log/utterances");
87           msg(L_INFO | ls->regnum, "Aye captain, we have a log file");
88           msg(L_INFO, "Alas, stderr still works");
89           return 0;
90         }
91
92 Processes, threads and signals
93 ------------------------------
94 When you fork a new process, it automatically inherits all currently configured log
95 streams. You should however call <<log_fork()>> to update the logger's notion
96 of the current PID (at least when you use PID's in your log messages). Also, if you
97 plan to exec() a process after fork(), do not forget to call <<log_close_all()>>,
98 so that all file descriptors used for log files (except for stderr) are closed.
99
100 The <<basics:msg()>> function itself can be called from multiple threads in parallel
101 and it is atomic by design. The functions for setting up the logging machinery
102 are however not reentrant (they follow our general rule about functions that
103 affect global state).
104
105 Logging from signal handlers is problematic, as is doing almost anything in signal
106 handlers, because almost all libc functions are not signal-safe. Most importantly,
107 functions for converting time to a human-readable representation aren't safe.
108 LibUCW therefore offers only limited logging services in such situations and
109 you must use the `L_SIGHANDLER` flag to request it. Otherwise, deadlocks get
110 ready to happen.
111
112 ucw/log.h
113 ---------
114 !!ucw/log.h