1 <!-- ##### SECTION Title ##### -->
4 <!-- ##### SECTION Short_Description ##### -->
5 An easy-to-use, fast and flexible message logging architecture.
7 <!-- ##### SECTION Long_Description ##### -->
9 This is an adaptation of the log4c project, which is dead upstream, and which
10 I was given the permission to fork under the LGPL licence by the authors. log4c
11 itself was loosely based on the Apache project's Log4J, Log4CC,
12 etc. project. Because C is not object oriented, a lot had to change.
16 <title>Overview</title>
19 There is 3 main concepts: category, priority and appender. These three
20 concepts work together to enable developers to log messages according to
21 message type and priority, and to control at runtime how these messages are
22 formatted and where they are reported.
27 <title>Category hierarchy</title>
30 The first and foremost advantage of any logging API over plain printf()
31 resides in its ability to disable certain log statements while allowing
32 others to print unhindered. This capability assumes that the logging space,
33 that is, the space of all possible logging statements, is categorized
34 according to some developer-chosen criteria.
38 This observation led to choosing category as the central concept of the
39 system. Every category is declared by providing a name and an optional
40 parent. If no parent is explicitly named, the root category, LOG_ROOT_CAT
41 is the category's parent.
45 A category is created by a macro call at the top level of a file. A
46 category can be created with any one of the following macros:
51 <para>@GRAS_LOG_NEW_CATEGORY(MyCat);</para>
52 <para>create a new root</para>
56 <para>@GRAS_LOG_NEW_SUBCATEGORY(MyCat, ParentCat);</para>
57 <para>Create a new category being child of the category ParentCat</para>
61 <para>@GRAS_LOG_NEW_DEFAULT_CATEGORY(MyCat);</para>
62 <para>Like GRAS_LOG_NEW_CATEGORY, but the new category is the default one
67 <para>@GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(MyCat, ParentCat);</para>
68 <para>Like GRAS_LOG_NEW_SUBCATEGORY, but the new category is the default one
74 The parent cat can be defined in the same file or in another file, but each
75 category may have only one definition.
79 Typically, there will be a Category for each module and sub-module, so you
80 can independently control logging for each module.
85 <title>Priority</title>
88 A category may be assigned a threshold priorty. The set of priorites are
89 defined by the @gras_log_priority_t enum. Their values are DEBUG, VERBOSE,
90 INFO, WARNING, ERROR and CRITICAL.
94 If a given category is not assigned a threshold priority, then it inherits
95 one from its closest ancestor with an assigned threshold.
99 To ensure that all categories can eventually inherit a threshold, the root
100 category always has an assigned threshold priority.
104 Logging requests are made by invoking a logging macro on a category. All
105 of the macros have a printf-style format string followed by arguments.
106 Because most C compilers do not support vararg macros, there is a version
107 of the macro for any number of arguments from 0 to 6. The macro name ends
108 with the total number of arguments.
112 Here is an example of the most basic type of macro:
115 <programlisting>CLOG5(MyCat, gras_log_priority_warning, "Values are: %d and '%s'", 5, "oops");</programlisting>
117 <para>This is a logging request with priority WARN.</para>
120 A logging request is said to be enabled if its priority is higher than or
121 equal to the threshold priority of its category. Otherwise, the request is
122 said to be disabled. A category without an assigned priority will inherit
123 one from the hierarchy.
127 It is possible to use any non-negative integer as a priority. If, as in the
128 example, one of the standard priorites is used, then there is a convenience
129 macro that is typically used instead. For example, the above example is
130 equivalent to the shorter:
133 <programlisting>CWARN4(MyCat, "Values are: %d and '%s'", 5, "oops");</programlisting>
137 <title>Default category</title>
140 If @GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(MyCat, Parent) or
141 @GRAS_LOG_NEW_DEFAULT_CATEGORY(MyCat) is used to create the category, then
142 the even shorter form can be used:
145 <programlisting>WARN3("Values are: %d and '%s'", 5, "oops");</programlisting>
148 Only one default category can be created per file, though multiple
149 non-defaults can be created and used.
154 <title>Example</title>
156 <para>Here is a more complete example:</para>
161 /* create a category and a default subcategory */
162 GRAS_LOG_NEW_CATEGORY(VSS);
163 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(SA, VSS);
166 /* Now set the parent's priority.
167 (the string would typcially be a runtime option) */
168 gras_log_control_set("SA.thresh=3");
170 /* This request is enabled, because WARNING >= INFO. */
171 CWARN2(VSS, "Low fuel level.");
173 /* This request is disabled, because DEBUG < INFO. */
174 CDEBUG2(VSS, "Starting search for nearest gas station.");
176 /* The default category SA inherits its priority from VSS. Thus,
177 the following request is enabled because INFO >= INFO. */
178 INFO1("Located nearest gas station.");
180 /* This request is disabled, because DEBUG < INFO. */
181 DEBUG1("Exiting gas station search");
186 <title>Configuration</title>
189 Configuration is typically done during program initialization by invoking
190 the gras_log_control_set() method. The control string passed to it
191 typically comes from the command line. Look at the doucmentation for that
192 function for the format of the control string.
197 <title>Performance</title>
200 Clever design insures efficiency. Except for the first invocation, a
201 disabled logging request requires an a single comparison of a static
202 variable to a constant.
206 There is also compile time constant, @GRAS_LOG_STATIC_THRESHOLD, which
207 causes all logging requests with a lower priority to be optimized to 0 cost
208 by the compiler. By setting it to gras_log_priority_infinite, all logging
209 requests are statically disabled and cost nothing. Released executables
210 might typically be compiled with
211 "-DGRAS_LOG_STATIC_THRESHOLD=gras_log_priority_infinite".
216 <title>Appenders</title>
219 Each category has an optional appender. An appender is a pointer to a
220 structure whcih starts with a pointer to a doAppend() function. DoAppend()
221 prints a message to a log.
225 WHen a category is passed a message by one of the logging macros, the
226 category performs the following actions:
232 if the category has an appender, the message is passed to the
233 appender's doAppend() function,
239 if 'willLogToParent' is true for the category, the message is passed
240 to the category's parent.
244 By default, all categories except root have no appender and
245 'willLogToParent' is true. This situation causes all messages to be
246 logged by the root category's appender.
250 Typically, you would only change the root category's appender when you
251 wanted, say, a different output format. Copying defaultLogAppender.c
252 would be a good start.
256 The default appender function currently prints to stderr, but more
257 would be needed, like the one able to send the logs to a remote
265 <title>Misc and Caveats</title>
268 Do not use any of the macros that start with '_'.
272 The current set of macros force each file to use categories declared in
273 that file. This is intentional. Make the category a child of the file's
278 Log4J has a 'rolling file appender' which you can select with a run-time
279 option and specify the max file size. This would be a nice default for
280 non-kernel applications.
284 Careful, category names are global variables.
288 <!-- ##### SECTION See_Also ##### -->
293 <!-- ##### MACRO CDEBUG6 ##### -->
308 <!-- ##### MACRO CVERB6 ##### -->
323 <!-- ##### MACRO CINFO6 ##### -->
338 <!-- ##### MACRO CWARN6 ##### -->
353 <!-- ##### MACRO CERROR6 ##### -->
368 <!-- ##### MACRO CCRITICAL6 ##### -->
383 <!-- ##### MACRO DEBUG6 ##### -->
397 <!-- ##### MACRO VERB6 ##### -->
411 <!-- ##### MACRO INFO6 ##### -->
425 <!-- ##### MACRO WARN6 ##### -->
439 <!-- ##### MACRO ERROR6 ##### -->
453 <!-- ##### MACRO CRITICAL6 ##### -->