SlideShare ist ein Scribd-Unternehmen logo
1 von 21
Downloaden Sie, um offline zu lesen
Log4C Developers Guide

 1.0.6     13 Nov 2006     First Draft: pulls together information from README files and various 'how to ' documents for Log4C. This document is
                           started between the release of Log4C 1.1.0 and 1.2 so although much of it is valid for older releases it is more looking
                           towards the 1.2 release. Where you see xxx in the text this denotes an item we need to get back to.

                           This document was created with Open Office 2.0.2 .




Table of Contents
1 Introduction.............................................................................................................................................2
2 Log4C Concepts and Overview ..............................................................................................................3
3 How to download and build Log4C.......................................................................................................4
   3.1 Parsing the Log4C configuration file--the expat dependency ...................................................4
   3.2 Some comments on building Log4C in the corporate factory ..................................................5
      3.2.1 Log4C is released under the LGPL license. ................................................................ 5
      3.2.2 Building on different platforms .................................................................................... 5
         3.2.2.1 Building On Unix ............................................................................................ 5
         3.2.2.2 Building on Windows ...................................................................................... 6
         3.2.2.3 Building on MAC OS ...................................................................................... 6
      3.2.3 Packaging on different platforms ................................................................................. 6
4 Getting started--running the examples...................................................................................................6
   4.1 Running application_1 ..............................................................................................................7
   4.2 Configuring the priority for a category .....................................................................................8
   4.3 Configuring application_1 to log to a set of log files................................................................9
   4.4 What about application_2 ?.....................................................................................................10
5 Using the Log4C API...........................................................................................................................10
   5.1 The helloworld example with Log4C .....................................................................................10
      5.1.1 The helloworld code ................................................................................................... 10
      5.1.2 Configuring and running helloworld .......................................................................... 11
         5.1.2.1 Configuring helloworld with the configuration file....................................... 12
         5.1.2.2 Configuring helloworld with the environment variables............................... 12
         5.1.2.3 Configuring helloworld via the Log4C API .................................................. 13
   5.2 Comments on the the different configuration methods...........................................................13
   5.3 Interaction of the configuration methods ................................................................................14
   5.4 Including Log4C calls into your code ....................................................................................14
      5.4.1 Making it easy to remove Log4C calls from your code ............................................. 14
      5.4.2 Other useful Log4C functions .................................................................................... 16
      5.4.3 Multi threaded applications using Log4C .................................................................. 17
         5.4.3.1 Why the Log4C API is not fully MT safe ..................................................... 17
         5.4.3.2 How to use Log4C in an MT safe way .......................................................... 18
6 Extending Log4C with your own custom appender and layout types ..................................................18
7 Troubleshooting and debugging ..........................................................................................................21
8 Deployment Experience with Log4C....................................................................................................21
8.1 Blame it on the logger ..............................................................................................................21
  8.2 Preparing to move logging from development into a production
  environment....................................................................................................................................22
9 References............................................................................................................................................24


1   Introduction

Log4C is a C-based logging library. Its goal is provide the C software developer with a configurable
and efficient library for logging messages. So Log4C provides the classic logging functionality
required by most projects by default while leaving the scope for extensibility for those projects that
have special requirements.

It seems extraordinary that just about every C project ends up developing it's own logging system.
While there are environments like embedded systems or operating system kernels that may justify
customized logging technology (and there are open source projects aimed at those areas) there seems to
be no a priori reason why most user level application and server software written in C cannot share a
logging library.

Log4C may be linked with end user applications or other libraries that will eventually be linked into
applications. The library is released on SourceForge under the LGPL license.

This document is aimed at developers who wish to use Log4C to manage logging in their own project.
The kind of information you can find here includes:

           a general introduction to Log4C concepts and how Log4C can be useful to you
           how to download and build Log4C
           how to use and configure the library via examples
           how to extend Log4C with your own code for customizing, for example, where messages are
           logged and how they are formatted.
           troubleshooting and debug information
           deployment experience with Log4C
           references to useful material

For information relating to Log4C internals the intention is to create a separate documents, “Log4C
Internals”. This will help keep the size of each document reasonable and help decouple the evolution of
those documents.

2   Log4C Concepts and Overview

Log4C follows the overall style of the native Java logging and Log4j utilities. There are three
fundamental types of object in Log4C: categories, appenders and layouts.


You can think of these objects as corresponding to the what, where and how of the logging system:
categories describe what sub-system the message relates to, appenders determine where the message
goes and layouts determine how the message is formatted.
So for example a category might be named “httpd.network.connection” that may be logging messages
to the “syslog” appender using the “dated” format. The convention of using dotted names for
categories determines an obvious hierarchy which is used to determine parent and child relationships
during logging. These are used because during logging (and this is configurable) a message logged by a
category will also be logged to the appenders of any parent categories.


There is always a root category which represents a conceptual root of the hierarchy of categories.


The categorization of the system make sit easy to select which messages are logged and where—if I
configure an appender and priority for a given category then I automatically do it for all it's
descendants (unless I explicitly say not to). The extreme case of this is the root category—any
configuration positioned there will by default apply to all categories in the system. However, if I need
to drill down for finer grained control then the categorization allows me to do that.


This means that you should expect to spend some time defining the categories within your system. As
an example, if your system separates into different applications then you should have at least one
category per application. If your product ships a set of libraries, then each library probably merits it's
own category. Libraries linked in as a dependency on a given library should probably be sub-categories
of the including library. Within a library you might identify other sub categories, for example a
housekeeping category, a connection manager category, a request processor and so on that correspond
to logging messages that will come from those sections of code.


The other concept fundamental to Log4C is the logging priority: each message has an associated
priority. At a given point a given instance of Log4c has an associated configured priority--only
messages with a higher priority than the current Log4c priority are sent to an appender for processing.

3   How to download and build Log4C

The README file shipped in the workspace gives a good account of Log4C dependencies and how to
do a basic build so we will not repeat all that information here. Here we treat that information that
requires more detail than the basic build instructions.


3.1 Parsing    the Log4C configuration file--the expat dependency

“The expat dependency”--no it's not the latest Robert Ludlum novel...it refers to the fact that Log4C
can use the expat library (cf. http://expat.sourceforge.net/) as the low level xml parser for it's
configuration file. By default when you run configure, it will look for expat and if it finds it it will use
it. You can tell configure not to go looking for expat by using the --without-expat option.

In the case where you have specified --without-expat or expat is not found or is the wrong version or
fails to compile with a small test program, then Log4C will use a custom XML parser using lex/yacc
code for the lower level xml parsing. This code works ok with the current configuration file and
bundled appenders and layouts.

So why do you need to know how Log4C handles it's xml parsing ? Well, as a developer integrating
Log4C you will probably prefer the “bundled parser” option as it means you do not pull a dependency
on expat. However from the point of view of maintaining Log4C there is still a dependency on the
lex/yacc tools needed to generate the parsing code. So there is a choice to make in terms of which
dependency Log4C manages. The current consensus is that expat is now sufficiently widespread and
mature that introducing a dependency on it is a reasonable step.

So as a developer consuming Log4C you can rely on the older bundled code staying in Log4C for the
foreseeable future. But you should not expect bug fixes therein nor that that code will evolve to take
account of potential enhancements to the configuration file. So the message is that you should start to
prepare for handling the dependency on the expat library, either by bundling it in your delivery with
Log4C or ensuring that it is available natively on your supported platforms or by specifying it as a
requirement to your end users.


3.2   Some comments on building Log4C in the corporate factory

The Log4C source code is free, which is good, but there is still a cost in integrating it into your project.
Here are some points to consider on this.

3.2.1   Log4C is released under the LGPL license.

See the COPYING file in the release for the full license but this means a few things:
         you will almost certainly require a legal review inside your company to approve your use of
         Log4C.
         you are required by the LGL license to ship along with your project a copy of the Log4C source
         as used in your project. You are also required to ship a copy of the LGL license. Typically one
         ships a file called something like, ThirdPartyLicenses which lists all the open source
         components used by your project and includes all the required licenses for those open source
         components.
Ideally the changes you make to Log4C will be minor porting, bug fixes or integration issues required
to integrate with your project. Ideally, you would invest some time to work with the Log4C maintainers
to integrate your changes back into the Log4C repository in a way that was useful to the whole
community. Thus, while one might go with some 'quick fixes' in order to integrate Log4C, expect to
spend some time refactoring or generalizing the code in order to have it accepted back into the public
repository.
A general aspect of integrating an open source project is that, for various reasons, you may wish to
make it easy to remove the dependency. We discuss this in more detail in the section titled “Integrating
Log4C calls into your code”.
3.2.2   Building on different platforms
3.2.2.1 Building On Unix


On Unix systems (certainly for Linux, Solaris and HP-UX) you should be able to use the provided
autoconf tools to build Log4C as described in the README. One tip for managing different platforms
is not to compile the code in the source directories, but rather to create a directory per platform, run the
configure script therein to generate the Makefiles and then build the library, tests, examples and doc in
per-platform directory. This allows you to use the same source code to maintain binaries for multiple
platforms at the same time. So an example compile session might run:

On my Solaris x86 build machine:
         [ mySol   ar i   s x 8 6 Bu i   l   dM c hi
                                               a       ne   ] $      t a r - z x vf l og 4c - 1 . 0 . 12. t a r . gz
         [ mySol   ar i   s x 8 6 Bu i   l   dM c hi
                                               a       ne    ] $     mk d i r b ui l d - Sol a r i s - x86; c d bui l d- Sol a r i s - x86
         [ mySol   ar i   s x 8 6 Bu i   l   dM c hi
                                               a       ne     ] $    . . / l o g4 c - 1. 0. 12 / c on f i gur e - - pr e f i x=/ pa t h/ of / i ns t a l l a t i on
         [ mySol   ar i   s x 8 6 Bu i   l   dM c hi
                                               a       ne      ] $   ma k e

then on the Solaris sparc build machine:
         [ mySol a r i    s Sp a r c Bu i     l d M c h i n e ] $ mkd i r b ui l d - Sol a r i s - s pa r c ; c d bui l d- Sol a r i s - s pa r c
                                                   a
         [ mySol a r i    s Sp a r c Bu i     l d M c h i n e ] $ . . / l o g4 c - 1. 0. 12 / c onf i gur e - pr e f i x=
                                                   a
         pa t h/ of / i   ns t a l l a t i    on
         [ mySol a r i    s Sp a r c Bu i     l d M c h i n e ] $ ma k e
                                                   a

and so on.
If you need to use a compile other than gcc then use the CC environment variable as descirbed in the
README file.

3.2.2.2 Building on Windows


The build for Windows is not yet integrated into the autoconf mechanism (due to limitations in
autoconf on windows at the time the integration was done). So a makefile is provided in the msvc6
directory for building on Windows.

Note that some of the appenders are not compiled on Windows...for example the syslog appender.
See the README in the msvc6 directory for the Windows build details.

3.2.2.3 Building on MAC OS


There are some project files provided for compiling on MAC OS.
xxx Not sure of the status of the mac stuff at this time.

3.2.3   Packaging on different platforms

Using the provided makefilery as explained in the section “Building on different platforms” it should
be possible to generate the library, tests and examples. However native packaging is provided only for
Linux at this time. Even there you will probably wish to customize the naming and so on of the
generated rpms.
So you should expect to spend some time creating scripts or makefiles that will take the binaries from a
build directory and package them as required for your supported platforms.
Another solution is just to bundle the Log4C library in one of your existing packages or rpms.

4   Getting started--running the examples

Once you have built Log4C you can go into the examples directory and run the examples. There may
be additional information in the README in the examples directory.


For ease of presentation the text below tends to suppose a Unix (or cygwin) environment. We don' t
translate each command to Windows supposing that the translation of commands, pathnames and so on
are fairly obvious. However where there are significant differences for Windows then we try to
highlight them.

4.1   Running application_1

 If you have built in a directory separate from the sources, as is recommended, then you need to copy
the log4crc file from the source directory into the build directory:
        $ c d e x a mp l e s
        $ c p . . / l o g 4c / e x a mp l e s / l o g 4 c r c .



Then run the example application_1 as follows. You will need to put the Log4C library on some path
so the system can find it when application_1 starts up. If you have used the autoconf tools on Unix and
the Makefile in the msvc6 directory that will look like this:
        On Li n u x/ So l a r i s : e x p o r t LD_ LI BRARY_ PATH=. . / s r c / l og4c / . l i bs /
        On HP- UX: e xp o r t SHLI B_ PATH=. . / s r c / l og 4c / . l i bs /
        On W n d ows : s e t Pa t h =. .  l o g 4 c ; % Pa t h%
            i


Then you can run application_1 as follows:
        $ . / a p pl i c a t i o n _ 1 4

You should see this:
        [st   d ou t   ]      ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t       i o n1   - s ome   e r r or f r om a pp1 a t l i ne 79 i n
        fil   e ..     / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1.      c - l    o op 0
        [st   d ou t   ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t            i o n1   - s ome   e r r or f r om a pp1 a t l i ne 79 i n
        fil   e ..      / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1.     c - l    o op 0
        [st   d ou t    ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t           i o n1   - s ome   e r r or f r om a pp1 a t l i ne 79 i n
        fil   e ..       / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1.    c - l    o op 1
        [st   d ou t     ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t          i o n1   - s ome   e r r or f r om a pp1 a t l i ne 79 i n
        fil   e ..        / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1.   c - l    o op 1
        ../   ../l        o g 4c / e x a mp l e s / a p p l i c a t i o n _1 . c

application_1 is a simple example that loops, logging two messages on each loop. In the output above
we only see the error message logged at priority ERROR, the other message logged at priority DEBUG
is not logged with the default configuration in the l o g4 c r c file.

But why is the log message being logged twice ?

Thank you for asking. What's happening is that although the application submits the message only
once to Log4C, it is passed to all the appenders attached to the originating category
s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 AND it's ancestor categories. So, if you look in log4crc you will see
this line:
             < c a t e g or y n a me =" s i x 1 3 l o g . l o g " p r i o r i t y=" e r r o r " a ppe nde r =" s t dout " / >

So the stdout appender for the category s i x1 3l o g. l og . a pp . a pp l i c a t i o n1 is logging the message and
the stdout appender for the ancestor category s i x1 3l o g. l og is also logging it.

So why this strange behavior with respect to logging messages to multiple appenders ? Well, in this
example it's hard to see the point. But suppose we have multiple applications and associate categories
s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 2 , s i x 1 3 l o g. l o g. a p p. a ppl i c a t i on3, s i x13l og. l og. a pp. a ppl i c a t i on4
, say, with them. Then I can get very tight control over what gets logged using the categorization of the
messages: if I set an appender on s i x1 3 l o g. l og . a pp for example then I will get the messages from all
the applications. But if I am just interested in messages from a subset of categories then I can configure
an appender and logging priority just for them.

So once the application or system designer has done a good job defining the categories available for
logging then Log4C offers the administrator or end user very powerful and easy control over the
messages he chooses to log, where they get logged and the format they are logged in. Furthermore,
even if the application developer has to go back and introduce new categories then with Log4C that's
an easy task. Too often in-house logging mechanisms are hard coded for a specific domain and adding
what would amount to new categories requires significant additional coding. Not so with Log4C.

You can see that there is additional text being logged in addition to the message from the application.
This 'overhead' is added by Log4C and the various parts of the message break down like this:

[ s t d o ut ]  The name of the appender logging the message surrounded by square brackets.
ERROR The log level of the message.
s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 The name of the catgory originating the message
s o me e r r o r f r o m a p p 1 a t l i n e 7 8 i n f i l e . . / . . / l o g4c / e xa mpl e s / a ppl i c a t i on_1. c The actual log
message.

4.2    Configuring the priority for a category
Now, edit the log4crc file to change the value of the priority field from “error” to “debug”:
             < c a t e g or y n a me =" " p r i o r i t y=" d e b ug " a p pe nd e r =" s t dout " / >

Run application_1 again, you should see this:
             [st   d ou t   ]     DEBUG s i      x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - De buggi ng a pp 1      - l oop 0
             [st   d ou t   ]     DEBUG s i      x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - De buggi ng a pp 1      - l oop 0
             [st   d ou t   ] ERROR s i          x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - s ome e r r or f r om   a pp1 a t l i ne 79 i n
             fil   e ..      / . . / l og4c /    e x a mp l e s / a p p l i c a t i o n_ 1.     c - l    o op 0
             [st   d ou t    ] ERROR s i         x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - s ome e r r or f r om   a pp1 a t l i ne 79 i n
             fil   e ..       / . . / l og4c /   e x a mp l e s / a p p l i c a t i o n_ 1.     c - l    o op 0
             [st   d ou t     ] DEBUG s i        x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - De buggi ng a pp 1      - l oop 1
[st   d ou t    ]    DEBUG s i      x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - De buggi ng a pp 1 - l oop 1
         [st   d ou t    ]    ERROR s i      x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - s ome e r r or f r om a pp1 a t l i ne 79 i n
         fil   e ..      / . . / l og4c /    e x a mp l e s / a p p l i c a t i o n_ 1.     c - l    o op 1
         [st   d ou t    ] ERROR s i         x 1 3 l o g . l o g . a p p . a p pl i c a t   i o n1   - s ome e r r or f r om a pp1 a t l i ne 79 i n
         fil   e ..       / . . / l og4c /   e x a mp l e s / a p p l i c a t i o n_ 1.     c - l    o op 1

What's happening now is that because the priority of the category has been lowered to DEBUG, the
debug message in the application is now appearing. And, for the reasons explained above for the
ERROR message, it appears twice.

4.3   Configuring application_1 to log to a set of log files
Logging to stdout is fine but suppose we wish to trap all the messages for
s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 to a set of log files. To do this we can use the rolling file appender.



Edit this line in log4crc to replace stdout with myrollingfileappender:
         < c a t e g or y n a me =" s i x 1 3 l o g . l o g . a p p . a pp l i c a t i on 1" p r i or i t y=" de bug" a ppe nde r =" s t dout " / >



Run application_1 again. This time on stdout you will see:
         [s t d o ut ]       DEBUG s i x 1 3 l o g . l og . a p p . a pp l i c a t i on 1 - De buggi ng a pp 1 - l oop 0
         [ s t d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n
         f i l e . . / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0
         [ s t d ou t ]      DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 1
         [ s t d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n
         f i l e . . / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1



The other copies of the log messages are no longer being sent to stdout but rather to the
myrollingfileappender appender, which is logging them to a set of log files in the current directory of
the form myprefix.*. Verify this by dumping one of the log files:
         $ c a t myp r e f i x . 0
           20 0 61 10 5 1 6 : 2 9 : 3 3 . 5 3 0 DEBUG s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- De buggi ng a pp 1 - l oop 0
           20 0 61 10 5 1 6 : 2 9 : 3 3 . 6 0 4 ERROR s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- s ome e r r or f r om a pp1 a t
         l i n e 7 9i n f i l e . . / . . / l o g 4c / e x a mp l e s / a p pl i c a t i o n_ 1. c - l oop 0
           20 0 61 10 5 1 6 : 2 9 : 3 6 . 6 0 5 DEBUG s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- De buggi ng a pp 1 - l oop 1
           20 0 61 10 5 1 6 : 2 9 : 3 6 . 6 0 5 ERROR s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- s ome e r r or f r om a pp1 a t
         l i n e 7 9 i n f i l e . . / . . / l o g4 c / e x a mpl e s / a pp l i c a t i on _1. c - l oop 1



You will notice that these log messages also have a date stamp on them. This is because
myrollingfileappender has been configured in log4crc to use the dated layout (rather than the basic
layout) and this layout inserts a date stamp in the message before logging it.


You will also notice that the unlike the stream appender which is logging to stdout, the rollingfile
appender does not prefix it's messages with the name of the appender enclosed in square brackets. The
reason for the change is twofold: first we did not see a real need to log the appender name in each
message and secondly it seems better from a design point of view if it is only the layout code which
determines the format of the message.
4.4   What about application_2 ?
As an application application_2 does the same thing as application_1—it loops logging a few
messages. However the interesting thing about application_2 is that it links with a library where new
appenders and layouts have been defined. So we leave this more advanced topic to a later section.

5   Using the Log4C API
In the last section we saw how to control the logging output from a Log4C enabled example using the
configuration file. In this section we see how to “Log4C enable” your applications using the Log4C
API.


At the top of the main Log4C home page you will see links to the API documentation for the latest
released Log4C, for example here: http://log4c.sourceforge.net/files.html. You should keep a reference
to this documentation when working with Log4C—it documents parameters, call conventions, return
codes, issues and sometimes has code snippets. If you have checked out the workspace from CVS you
will need to have added –enable-doc to build the documentation, which gets put into the doc directory
where you build. You are strongly recommended to build and view (and improve!!) the API
documentation.


Depending on the utilities available (dyoxygen, latex,...) on your system the API documentation can be
generated in html, pdf and man page format. See 'configure –help' and the README for details on
this.

5.1   The helloworld example with Log4C

As tradition dictates we provide a hello world example to illustrate the bare bones of Log4C. The hello
world code looks as follows:

5.1.1   The helloworld code

         # i n c l u de < s t d i o . h >
         # i n c l u de " l o g 4 c . h "
         i nt ma i n ( i n t a r g c , c h a r * * a r g v ) {
         i nt r c = 0;
         l og 4 c _ c a t e g o r y_ t * myc a t = NULL;
         i f ( l o g4 c _i n i t ( ) ) {
                     p r i n t f ( " l og 4 c _ i n i t ( ) f a i l e d" ) ;
                     r c = 1;
         } el s e{
         myc a t = l og 4 c _ c a t e g o r y_ g e t ( " l o g 4 c . e x a mpl e s . h e l l o wor l d" ) ;
         l og 4 c _ c a t e g o r y_ l o g ( myc a t , LOG4 C_ PRI ORI TY_ERROR, " He l l o W l d! " ) ;
                                                                                             or
         / * Exp l i c i t l y c a l l t h e l og 4 c c l e a n up r ou t i ne * /
                     i f ( l og4c _f i ni ( ) ) {
p r i n t f ( " l o g 4c _ f i n i ( ) f a i l e d" ) ;
                        }
         }
         r e t ur n 0;
         }

As you can see there are four calls to the Log4C API here.
    1. The l og 4 c _ i ni t ( ) call initializes the library, and reads the configuration files (if any) and
       environment variables. We will see more about the configuration mechanisms below.
    2. The l og 4 c _ c a t e g or y_ g e t ( ) function returns a reference to a category required for logging.
    3. The l og 4 c _ c a t e g or y_ l o g ( ) function logs the age old message .
    4. The l og 4 c _ f i n i ( ) tells Log4C to cleanup, freeing memory, closing files and so on.

5.1.2   Configuring and running helloworld

See the section “Running application_1” for information on setting the environment before running
helloworld. If you have compiled and run the helloworld example as is you will see...no output :-(.


This is because although we have done all the right things, we have not as yet configured an appender
for our helloworld category. It will be instructive to visit each of the three ways Log4C provides to
configure it's behavior.


For information, the command line on Linux to compile a Log4C example, supposing that the log4c
library is already compiled, looks like this:
         $ g c c - I . . / . . / l o g 4 c / s r c - I . . / s r c . . / . . / l og 4c / e xa mpl e s / he l l owor l d/ he l l owor l d. c - L
         . . / s r c / l o g4 c / . l i b s / - l l o g4 c

5.1.2.1 Configuring helloworld with the configuration file
Copy the log4crc file into the helloworld directory and edit it to add this line:
         < c a t e g or y n a me =" l o g 4 c . e x a mp l e s . h e l l o wo r l d" p r i or i t y=" de bug" a ppe nde r =" s t dout " / >



For completeness we cite here the two other lines relevant to the configuration for helloworld, which
are already in the file:
             < a p p e n d e r n a me =" s t d o u t " t yp e =" s t r e a m" l a yo ut =" ba s i c " / >
             < l a you t n a me =" b a s i c " t yp e =" b a s i c " / >



Run the helloworld program again. You will now see:
         [ s t d ou t ]     ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d!
                                                                                            or



Cool. What has happened is that we have configured Log4C to send messages for our helloworld
example, logged with priority DEBUG or above to go to the appender called “stdout”. This appender
is a stream based appender with name stdout, which means the messages will go to...well, stdout. The
appender called “stdout” also specifies it's layout, which is the basic layout type. Of course we could
configure the messages to go to any of the existing Log4C appenders and use any of the layouts to
format the message.


By way of building a mental model of what is happening inside the Log4C library note that the fact
that the helloworld category is mentioned in the configuration file means that after the call to
lo g4 c _i ni t ( ) , a nicely configured instance of that category already exists inside the library. In the case
where that category is not mentioned in the configuration file then it is the call to
l o g4 c _c a t e g or y_ g e t ( " l o g 4 c . e x a mp l e s . h e l l o wo r l d" ) that creates the (unconfigured) instance on this
category.

5.1.2.2 Configuring helloworld with the environment variables
Log4C provides a minimal configuration ability via two environment variables: LOG4C_APPENDER
and LOG4C_PRIORITY. Both these variables act only on the root category but provide a quick way to
globally enable logging . This can be useful to take a look at log messages before drilling down into a
finer grained logging using the categorization to focus on messages of particular interest.


So, remove the line from the configuration file you added above:
         < c a t e g or y n a me =" l o g 4 c . e x a mp l e s . h e l l o wo r l d" p r i or i t y=" de bug" a ppe nde r =" s t dout " / >



Rerun helloworld to confirm you have no output then rerun the program as follows:
         e xp o r t LOG4 C_ APPENDER=s t do u t ; h e l l owor l d



You will now see the log message as before:
         [ s t d ou t ]   ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d!
                                                                                          or



What is happening here is that at init time Log4C is reading the LOG4C_APPENDER environment
variable and configuring the stdout appender for the root category as a result. Thus all messages logged
to this instance of the library, at a priority higher than NOTICE (for that is the priority set on the root
category in the configuration file) will be sent to stdout.
We could just as well have set LOG4C_APPENDER to be myrollingfileappender, as defined in the
configuration file, in which case the helloworld message would have been logged to the myprefix.0
file. Go on, give it a lash, it works!

5.1.2.3 Configuring helloworld via the Log4C API
The configuration achieved in the above sections via the configuration file or the environment
variables can also be done manually using the Log4C API. Add the following call to set the appender
for the helloworld category:
         myc a t = l og 4 c _ c a t e g o r y_ g e t ( " l o g 4 c . e x a mpl e s . h e l l o wor l d" ) ;
         l og 4 c _ c a t e g o r y_ s e t _ a p p e n de r ( myc a t , l og 4c _a pp e n de r _ge t ( " s t dout " ) ) ; / * ADD THI S LI NE */
         l og 4 c _ c a t e g o r y_ l o g ( myc a t , LOG4 C_ PRI ORI TY_ERROR, " He l l o W l d! " ) ;
                                                                                             or
Recompile and rerun helloworld to see the output:
         [ s t d ou t ]   ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d!
                                                                                          or


5.2   Comments on the the different configuration methods
The three configuration methods demonstrated above are likely to be of more or less interest depending
on the nature of your project. Far be it from Log4C developers to adopt the arms dealer pattern of
technology development, so here are some general observations to help you think about which method
or methods are most appropriate for your scenario:


         The environment variables seem to be generally useful as a quick way to get your application or
         system outputting messages.
         The configuration file is certainly a very powerful way and easy way to configure logging. It is
         probably of most utility in those cases where you are quite close to the final application
         development as this gives you more say in the nature of the configuration requirements you
         introduce to application users.
         Using the API to configure Log4C is probably of use to those projects delivering some
         intermediate technology or framework to other application developers. This is because as a
         framework or library provider you probably do not wish to contribute to a kind of
         “configuration file proliferation”. You probably would rather take configuration from your own
         configuration files, or even programmatically from your application developers and then
         configure Log4C programmatically. If you use the Log4C configuration file and your
         framework has it's own configuration file and your application has it's own configuration file
         then it's getting a bit hard for your administrator to keep track of all these configuration files.

5.3   Interaction of the configuration methods

The l og 4 c _ i n i t ( ) function looks for a configuration file first and then reads the environment variables,
so for defining the priority and appender for the root category the environment variables take
precedence. The order that Log4C (up to version 1.0.12) searches for the configuration file is
“$LOG4C_RCPATH/log4crc", "$HOME/.log4crc", "./log4crc" . This seems wrong and will probably
be changed or made configurable. Also, it is not clear if there is a well defined design decision about
what happens when loading fails in a file or if, once a file is loaded successfully, we should then stop
trying to load other files. xxx revisit this on the list.
If you configure Log4C objects after the call to l o g4 c _i ni t ( ) then the new settings you configure take
precedence.

5.4   Including Log4C calls into your code

5.4.1   Making it easy to remove Log4C calls from your code

For various reasons you may wish to wrap calls to the Log4C API either in macros or function calls.
We list some of these here to help you decide if you want to use wrapped or naked calls to Log4C.
         You may wish to do this in order, for example, to do some generic preparation of your logging
         messages.
Another reason might be to define some smaller subset of the Log4C API that you wish all your
            library writers or application developers to use—by using the interface you define you can
            ensure a consistent usage of Log4C across your system.
            Another reason might be that, Log4C being an external open source project, you may wish to
            make it easy to remove Log4C from your project, for fear of API stability, quality or licensing
            issues that may arise later in your project.


As an example, we present one way of wrapping the Log4C calls here. We will modify the
helloworld.c file to remove the hard coded dependency on Log4C and introduce a level of indirection
that allows an easy decoupling of helloworld from Log4C.


We simply introduce functions that wrap the required Log4C functions: myl o g_i ni t ( ) for
l o g4 c _i ni t ( ) , myl o g _f i n i ( ) for l o g4 c _ f i n i ( ) and so on. We also need to define our own copies of the
logging priorities. See the file mylog.h for the full definitions. So, for logging single strings we can use
a function like this:
        s t a t i c LOG4C_ I NLI NE v o i d myl o g_ ms g( c h a r * c a t Na me , i n t a _pr i or i t y, c ha r *ms g) {
        # i f n de f W THOUT_ LOG4 C
                      I
                    l o g 4 c _c a t e g o r y_ l o g ( l o g 4 c _c a t e g or y_ ge t ( c a t Na me ) , a _pr i or i t y, ms g) ;
        # el s e
                    p r i n t f ( ms g) ;
        # e ndi f
        }

You can see that if this code is compiled with -DWITHOUT_LOG4C then Log4C is totally removed.


To use this code, rather than directly calling l o g4 c _c a t e go r y_l og ( ) we would do this:
        myl o g_ ms g ( " l o g 4 c . e x a mp l e s . h e l l o wor l d " , MYLOG_PRI ORI TY_ERROR, " He l l o W l d! " ) ;
                                                                                                                 or



One suggestion by this writer http://jefficus.usask.ca/article.php?story=20040613140849924 is to
define a macro for the logging call which means you need only mention hte category name for your
subsystem in one place, typically in some include file used by all files in that subsytem.


So your simplified logging call actually looks like this:
        MYLOG_ MSG( MYLOG_ PRI ORI TY_ERROR, " He l l o W l d ! " ) ;
                                                         or



but at the start of the helloworld.c file you define the category name to use, which is picked up by the
MYLOG_MSG macro:
        # de f i n e MYLOG_ CATEGORY_ NAM " l o g 4c . e xa mp l e s . he l l owor l d"
                                         E



The MYLOG_MSG macro is defined such that if you do not define a category name then it defaults to
the root category. This means it is safe and, if you want to be lazy, easy to get logging.
The only comment on this handy technique is that if you are paranoid about performance then you may
not want to have the lookup call based on the logger name at each logging call. In this case you would
do the call to l o g4 c _ c a t e g or y_ g e t ( ) (or the wrapped equivalent) at the initialize time of your
subsystem and then use the actual reference to the category object rather than the category name.


The code to wrap the log call to take a variable number of arguments is a bit more complex than the
code used to log one string shown here—see the function myl o g_l og ( ) defined in mylog.h for way to
do that. The code discussed above is included in helloworld1.c and the file mylog.h. The full code of
helloworld1.c is included here for convenience:

         # i n c l u de < s t d i o . h >
         # de f i n e MYLOG_ CATEGORY_ NAM " l o g 4c . e xa mp l e s . he l l owor l d"
                                          E
         # i n c l u de " myl o g . h "
         i nt ma i n ( i n t a r g c , c h a r * * a r g v ) {
         i nt r c = 0;
         i f ( myl o g _i n i t ( ) ) {
                     p r i n t f ( " myl o g _ i n i t ( ) f a i l e d" ) ;
                     r c = 1;
         } el s e{
                     MYLOGMSG( LOG4 C_ PRI ORI TY_ERROR, " He l l o W r l d! " ) ;
                                                                     o
                     / * Ex pl i c i t l y c a l l t h e l og 4c c l e a n up r ou t i ne * /
                     i f ( myl o g_ f i n i ( ) ) {
                                 p r i n t f ( " myl og _ f i n i ( ) f a i l e d" ) ;
                                 r c = 1;
                     }
         }
         r e t ur n r c ;
         }


5.4.2   Other useful Log4C functions

See the Log4C API documentation in your workspace (as generated by make if you have done
'configure –enable-doc') or here for the last release: http://log4c.sourceforge.net/files.html.


Log4C provides some convenience functions that mean you do not have to specify the logging priority
in the logging call—for example l o g4 c _ c a t e g or y_ f a t a l ( ) , l o g4 c _c a t e go r y_e r r or ( ) and so on. These
are documented here for the last release: http://log4c.sourceforge.net/category_8h.html.


You can test to see the logging priority of a given category using the
lo g4 c _c a t e g or y_ i s _ p r i o r i t y_ e n a b l e d ( ) function.
Browse the documentation and examples and tests source to see other usage of the Log4C API.

5.4.3   Multi threaded applications using Log4C

Log4C is not Multi thread safe (MT safe). xxx This topic should be discussed on the mailing list and
revisited systematically to see what can be done and to document the MT status of the various API
calls.


In the meantime, it is possible to use Log4C safely provided you follow some rules related to
initialization and provided the appenders and layouts you use are themselves MT safe.

5.4.3.1 Why the Log4C API is not fully MT safe


A fully MT safe library would be such that multiple threads in the application could safely call any of
the LOG4C API functions without any need for synchronization on the part of the application. There
are several places where Log4C does not satisfy this:
                         This function must be called successfully just once by the application. If two
         l og 4 c _ i ni t ( )
         threads call this at the same time the behavior is undefined. The problem is that both threads
         will start to initialize global objects and the behavior is this case is undefined.
                         The same is true of l og 4c _f i ni ( ) —this function can safely be called by only one
         l og 4 c _ f i n i ( )
         thread at a time. Furthermore when you call l o g4 c _f i n i ( ) you must be sure that there are no
         calls to the logging API in flight—if there are then l o g4 c _f i n i ( ) goes ahead freeing up Log4C
         objects (like categories, appenders and layouts) so this will probably crash your application.
         Readonly type Log4C calls like l og 4c _c a t e g or y_ i s _p r i or i t y_e na bl e d ( ) and so on are MT safe
         between themselves and calls to logging functions like l o g4 c _c a t e go r y_l og ( ) but are not MT
         safe with respect to l o g4 c _ i ni t ( ) and l o g4 c _f i n i ( ) .
         Issues related to lazy creation and intialization of objects.
                     Lookup and creation type calls like l o g4 c _c a t e go r y_g e t ( ) , l o g4 c _a pp e nd e r _g e t ( ) ,
                     l o g4 c _ l a yo u t _ g e t ( ) and so on are not MT safe, even between themselves. The problem
                     is that if two threads call l o g4 c _c a t e go r y_g e t ( ) at the same time then, if the category
                     instances do not yet exist in the internal store of category instances, then the threads
                     may clash as they write to the shared hash that stores the instance references. This is
                     because no synchronization is provided on the shared instance hash.
                     Calls to l o g4 c _ c a t e g or y_ l o g( ) are not MT safe when called on the same categories. The
                     problem is that log4c_category_log() eventually calls l o g4 c _a pp e nd e r _a pp e n d( ) to log
                     the message. However, if the appender has not already been opened then it calls
                     l o g4 c _ a pp e n de r _ o p e n ( ) , which is not MT safe. The result could be that the two threads
                     will to open the appender at the same time which will give rise to undefined behavior.


The calls to the currently shipped basic and dated layouts all work in the context of a logging event
object which is allocated by the l o g4 c _ c a t e go r y_l og ( ) call on the stack. Thus the current usage of the
layout interface is in fact MT-safe.

5.4.3.2 How to use Log4C in an MT safe way


It can be seen from the last section that if you can ensure the following two conditions then you should
be able to use Log4C safely in an MT environment:


    1. perform the initialization of Log4C and the creation and intialization of all the log4C logging
       objects before before starting up the multiple threads that call Log4C.
        In reality this can be problematic as in order to ensure that “open” has been called on all the
        appenders in your system you will need to know the appender names up front at init time. For
        developers configuring Log4C programatically then this may work—by definition they will
        have the names of all the Log4C objects available, otherwise they could not configure then
        programmatically. For those using the Log4C configuration file where the Log4C init time code
        takes care of the creation of the objects there is currently no way to tell that code “call open at
        init time”. There seem to be a few possibilities here that require some development work in
        Log4C xxx:
                A way to do that could be to provide an option 'call open at init time' in the
                configuration file.
                Provide a function like l o g4c _a p pe n de r _ op e n _a l l ( ) that would call open on all
                appenders in Log4C. This way the application writer could call that routine to explicitly
                open all the appenders and avoid race conditions as various threads try to open them.
                A third solution would be that log4c guarantees that the open call on an appender is
                called only once in a critical section.
    2. Ensure that there are no logging calls in flight when l o g4 c _f i n i ( ) is called.

6Extending Log4C with your own custom appender and layout
types

The application_2 program in the examples shows how to define your own appender and layout types.


First a short word on Log4C terminology. The Log4C library ships with a set of “base types”. These
base types are category, appender, layout and rollingpolicy. These base types are hard coded into the
library—there is no run time way to control the creation or deletion of these base types (which perhaps
there should be). The base types all define an interface which one can use to create new types from the
base type. For example the stream appender, the stream2 appender and the rollingfile appender are all
types of appender. The basic and dated layouts are both type of layout. The only rollingpolicy currently
supplied with Log4C is sizewin, which is a type of rollingpolicy.


Once a base type exists in Log4C it is very easy to add new types—the application_2 example shows
how to do this for appenders and layouts. Of course it is possible to add new base types to Log4C but
we leave that more as a topic for the “Log4C Internals” document as it is less common to need to do
that.


Note that it is not possible to extend the set of priorities defined by Log4C. These follow the syslog(3)
model and are defined as follows:
    t yp e de f e n um {
        / ** f a t a l * /                    LOG4 C_ PRI ORI TY_FATAL                    = 000,
        / ** a l e r t * /                    LOG4 C_ PRI ORI TY_ALERT                    = 100,
        / ** c r i t * /                      LOG4 C_ PRI ORI TY_CRI T                    = 200,
        / ** e r r or * /                     LOG4 C_ PRI ORI TY_ERROR                    = 300,
        / ** wa r n * /                       LOG4 C_ PRI ORI TY_WARN                     = 400,
        / ** n ot i c e * /                   LOG4 C_ PRI ORI TY_NOTI CE                  = 500,
        / ** i nf o * /                       LOG4 C_ PRI ORI TY_I NFO                    = 600,
        / ** d e b ug * /                     LOG4 C_ PRI ORI TY_DEBUG                    = 700,
        / ** t r a c e * /                    LOG4 C_ PRI ORI TY_TRACE                    = 800,
        / ** n ot s e t * /                   LOG4 C_ PRI ORI TY_NOTSET                   = 900,
        / ** u nk no wn * /                   LOG4 C_ PRI ORI TY_UNKNOWN                  = 1000
}    l o g 4c _p r i or i t y_ l e v e l _ t ;



So, turning to application_2...if you look at application_2.c you will see that it is very similar to
application_1.c—it loops logging two messages at each loop. However, it includes an additional call
before the call to l o g4 c _ i ni t ( ) :
             i ni t _e xa mpl e s _ l i b ( ) ;



This function is defining some new appender and layout types that can be accessed in the configuration
file or programatically. It eventually calls i n i t _e x a mpl e _a pp e n de r s ( ) . A key code snippet from that file
looks like this:

             s t a t i c c o ns t l o g 4 c _ a p p e n de r _ t yp e _t * c on s t a pp e n de r _t ype s [ ]   = {
             # i f d e f HAVE_ SYSLOG_ H
                         & l o g 4 c _ a p pe n d e r _ t yp e _ s ys l og _l oc a l 0,
                         & l o g 4 c _ a p pe n d e r _ t yp e _ s ys l og _u s e r ,
             # e ndi f
             & l o g 4c _a p pe n d e r _ t yp e _ s 1 3 _f i l e ,
             & l o g 4c _a p pe n d e r _ t yp e _ s 1 3 _s t d e r r
             } ;
             s t a t i c s i z e _ t n a p p e n d e r _ t yp e s =
             s i z e of ( a p pe n d e r _ t yp e s ) / s i z e o f ( a p pe nd e r _t yp e s [ 0 ] ) ;
             i nt i n i t _ e x a mp l e _ a p p e n d e r s ( ) {
             i nt r c = 0; i n t i = 0 ;
f or ( i = 0; i <                   n a p p e n d e r _ t yp e s ; i ++)
                            l o g 4 c _a p p e n d e r _ t yp e _ s e t ( a p pe nd e r _t yp e s [ i ] ) ;
            r e t ur n( r c ) ;
            }



The key call is to the (somewhat badly named) l o g4 c _a pp e nd e r _t yp e _ s e t ( ) function. This function is
registering the appender types defined here with the Log4C code. Thereafter they are available for use
in the configuration file or accessible programmatically.


We list here the complete code fragment that deals with the l o g4 c _a pp e nd e r _t yp e _ s 1 3_ f i l e type:
/ * ** * ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * ** ** ** ** ** ** ********************************/
/*
* Th e l og 4c s t d e r r a d d s a " [ s t d e r r ]                 " i n f r o nt o f t he me s s a ge
* i t i s l og gi n g . t h i s o n e d o e s n ' t , a nd l e a ve s t h e f or ma t t i ng
* de s c i s i on s u p t o t h e f o r ma t t e r
*/
s t a t i c i n t s 1 3 _ s t d e r r _ a p p e n d ( l o g 4 c _ a pp e n de r _ t * t hi s , c ons t l og4c _l oggi ng_e ve nt _t * a _e ve nt )
{
            r e t ur n f pr i nt f ( s t de r r , " % s  n" ,
            a _e v e n t - > e v t _ r e n d e r e d _ ms g) ;
}
s t a t i c i n t s 1 3 _ s t d e r r _ o p e n ( l o g 4 c _ a p p e n de r _ t * t hi s )
{
            / * f pr i n t f ( s t d e r r , " r u n n i n g s 1 3 _ s t de r r a pp e n de r ope n c omma nd now n" ) ; */
            r e t ur n 0;
}
c o ns t l og 4c _a p p e n d e r _ t yp e _ t l o g 4 c _ a p pe nd e r _t yp e _ s 13_s t de r r = {
                " s 1 3 _s t de r r " ,
                s 13 _ s t d e r r _ op e n ,
                1 3_ s t d e r r _ a pp e n d ,
                NULL,
} ;
/ * ** * ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * ** ** ** ** ** ** ********************************/

The l og 4 c _ a p pe n de r _ t yp e _ s 1 3 _ s t d e r r object is defining the interface that the core Log4C code will use
to open, append and close this appender. As you can see this appender is pretty simple. It's close
function is NULL—it is safe to do this the core Log4C code will not try to call a NULL function. The
name of this appender is defined in the first field of it's interface object and is ”s 1 3_ s t d e r r " . It is this
name that can be used either in the configuration file or programatically in the l o g4 c _a pp e nd e r _ ge t ( )
call to obtain a reference to the actual object.


Defining new layout types follows a similar pattern. See the example_formatters.c file for some
example code. Defining new rollingpolicy types--which are used to tell rollingfile appenders under
which conditions rollover events should occur—proceeds in the same way. Other types of
rollingpolicy it would be interesting to add would be a policy that triggered rollover based on a time
period or fixed time basis.

7   Troubleshooting and debugging
If you have run configure with the –enable-debug option then by setting the environment variables
SD_DEBUG and SD_ERROR to the value “1” you should see some useful internal Log4C trace
messages. The traces are useful for watching how Log4C initializes itself, how it looks for and handles
configuration files and environment variables, how it intializes and configures internal objects and for
log time events like rollover events in the rollingfile appender, for example.

Also keep in mind that using the Log4C configuration file allows you complete control over which
appender and layout your categories use. So if you are having problems with some specific appender
or layout you can easily change those to compare the behavior with other appenders or layouts.


8   Deployment Experience with Log4C

This idea of this section is to gather any deployment experience or tips with deploying Log4C in
projects.


8.1 Blame   it on the logger

Here is some experience we had integrating Log4C into a new project. By it's nature a new project has
bugs and also makes heavy use of logging to help with the development and debugging phase. What I
observed was that on at least four occasions our system was crashing with a stack that led to some
Log4C code. In none of these cases did the root cause turn out to be Log4C. After the fourth time
debugging someone else's code I thought it worth while to look at the bugs to understand why there
was a tendency to have the core stack terminate (misleadingly) in Log4C. Here are some observations
that help explain that:

       logging messages is relatively expensive--so once you turn on, especially heavy logging, then
       your code spends a lot of it time in there. It would be interesting to run a collector/analyzer to
       quantify that. So, in the case where there is general memory corruption in your system it is
       quite likely that when it does crash, it will be in your logging code. This accounts for 2 of the 4
       bugs I mention that crashed Log4C

       Often folks will put debug log statements (good!) without ever testing them (bad!). So some
       errors of the form of a mismatch between the format string and the parameter list can easily
       arise. These bugs at least have the merit of being easy to spot once they do occur. That was
       one of the 4 bugs.

       Enabling logging calls obviously triggers an extra depth in the call stack--in the case of Log4C
       using the stream appender this can be up to 10 deep by the time you hit the base write() call to
       write to the file. So watch out if your stack size is small, especially if you are on a 64 bit
system (where you double the memory consumed by pointer types) and especially if your code
       is already stack hungry. This of course describes exactly the scenario of the 4th bug that
       crashed Log4C. For information, on HP-UX, where we saw this problem, the default stack
       size for threads is 64K, which is pretty small compared with defaults of 1M on Solaris and
       Windows and 2M on Linux.

Another Log4C integrator shared this relevant experience:

       on some Operating Systems there will be a maximum file size limit. If
       log4c gets deployed in a production environment and no one watches and
       rotates the log files, a crash and stackdump eventually results from the
       standard C library routines that write to a file. This stack dump always
       traces back through log4c and log4c can get blamed as the cause of the
       crashes. Use rotating file appenders or tell your operations team to put
       their own rotators on the files.


8.2 Preparing
           to move logging from development into a production
environment.

At some point your project will actually be ready to ship and run. Here are
some considerations as you migrate logging from a development role to an
operations role. Operators will need to be able to debug problems without recompiling code.
This is the most critical difference in how logging will be used once your
code ships. Here are some tips.

   1. Use the configuration file for configuration of categories and appenders, not the API.
      Operators will want do things like add additional appenders, redirect
      categories to different appenders etc. They will not be able to just
      recompile the code they way you do as a developer. If the configuration is
      done by API then they cannot change anything. If the configuration is done
      by the log4crc file then they can change things as needed.

   2. Plan ahead for runtime debugging. Remember that once it ships, you
      won't be able to just recompile to change or add logging. Make careful use
      of the different log levels. Keep use of the ERROR level down to the
      minimum, and use WARNING, INFO, and DEBUG as you get to messages that are
      more verbose and less related to known bugs or problems. But don't hesitate
      to put in lots of DEBUG statements. Your application will be run at ERROR
      level in production until it has a problem. Picture yourself on the phone
      telling someone how to change the level to DEBUG in the log4crc and they are
      in a different city than you. If you have lots of extra DEBUG statements
      available, it can mean the different between finding the problem just by
      looking at logs, or having to reproduce the entire bug from inputs on a
      system that simulates production. The first is quick, the second can
      involve many days of setup before you can even properly simulate the
      problem.
3. Use a logging hierarchy wisely to aid in pinpoint debugging.
       Say that you have shipped several program that work together on and end
       system. You can choose a logging hierarchy that makes it easy and flexible
       to manage your logging. Say your company name is initech. And that you
       have three applications that work together. And in each of these
       applications you have input handling, business logic, and database access
       logic. By using a hierarchy for your categories you can get great runtime
       flexibility.
       "company.program.subsystem"
       Using this you would have logging to categories like
       initech.prog1.dal
       initech.prog2.blogic
       initech.prog2.ilogic
       This allows tremendous runtime flexibility so that operations can manage the
       logging in many different ways without asking for recompiles and changes to
       your code. In the above example the top level category "initech" would be
       the main logging and would remain at ERROR level. If program 3 was having a
       lot of difficulties and crashes, an additional logging would be added
       mapping category initech.prog3 to a separate file at DEBUG level until the
       problems could be solved. If program 2 was extremely slow and database
       access was suspected, logging could be added to category initech.prog2.dal
       at DEBUG level and put into its own file.


9   References
http://log4c.sf.net/ This SourceForge site is now the main log4c site.
http://expat.sourceforge.net/
http://gcc.gnu.org
http://www.sunfreeware.com/
http://hpux.connect.org.uk/
Log4c developer mailing list
Nice 'How to get developing with log4c' article
Log4j
Pantheios - "The C++ Logging Sweetspot"
http://sourceforge.net/projects/log4cpp/

Weitere ähnliche Inhalte

Was ist angesagt?

Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...
Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...
Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...InfluxData
 
Splunk Enterprise for IT Troubleshooting
Splunk Enterprise for IT TroubleshootingSplunk Enterprise for IT Troubleshooting
Splunk Enterprise for IT TroubleshootingSplunk
 
Microservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaMicroservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaAraf Karsh Hamid
 
Juraci Paixão Kröhling - All you need to know about OpenTelemetry
Juraci Paixão Kröhling - All you need to know about OpenTelemetryJuraci Paixão Kröhling - All you need to know about OpenTelemetry
Juraci Paixão Kröhling - All you need to know about OpenTelemetryJuliano Costa
 
Deconstructing Monoliths with Domain Driven Design
Deconstructing Monoliths with Domain Driven DesignDeconstructing Monoliths with Domain Driven Design
Deconstructing Monoliths with Domain Driven DesignVMware Tanzu
 
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパス
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパスコーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパス
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパスyasuimao
 
Parallel SQL and Streaming Expressions in Apache Solr 6
Parallel SQL and Streaming Expressions in Apache Solr 6Parallel SQL and Streaming Expressions in Apache Solr 6
Parallel SQL and Streaming Expressions in Apache Solr 6Shalin Shekhar Mangar
 
2.0~2.2~2.4~3.0 zabbixの進化を紐解く zabbix便利機能紹介-
2.0~2.2~2.4~3.0  zabbixの進化を紐解く  zabbix便利機能紹介-2.0~2.2~2.4~3.0  zabbixの進化を紐解く  zabbix便利機能紹介-
2.0~2.2~2.4~3.0 zabbixの進化を紐解く zabbix便利機能紹介-Daisuke Ikeda
 
Opentelemetry - From frontend to backend
Opentelemetry - From frontend to backendOpentelemetry - From frontend to backend
Opentelemetry - From frontend to backendSebastian Poxhofer
 
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...Edureka!
 
NServiceBus - building a distributed system based on a messaging infrastructure
NServiceBus - building a distributed system based on a messaging infrastructureNServiceBus - building a distributed system based on a messaging infrastructure
NServiceBus - building a distributed system based on a messaging infrastructureMauro Servienti
 
Monitoring and observability
Monitoring and observabilityMonitoring and observability
Monitoring and observabilityDanylenko Max
 
所属しているグループをすべて取得する
所属しているグループをすべて取得する所属しているグループをすべて取得する
所属しているグループをすべて取得するMichio Koyama
 
Oracle Supply Chain Management
Oracle Supply Chain ManagementOracle Supply Chain Management
Oracle Supply Chain ManagementNAVIN AGARWAL
 
Operating a payables shared service organization in oracle cloud oow 2019_v4
Operating a payables shared service organization in oracle cloud oow 2019_v4Operating a payables shared service organization in oracle cloud oow 2019_v4
Operating a payables shared service organization in oracle cloud oow 2019_v4Mahesh Vallampati
 
Continuous Integration & Continuous Delivery
Continuous Integration & Continuous DeliveryContinuous Integration & Continuous Delivery
Continuous Integration & Continuous DeliveryDatabricks
 

Was ist angesagt? (20)

Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...
Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...
Reduce SRE Stress: Minimizing Service Downtime with Grafana, InfluxDB and Tel...
 
Splunk Enterprise for IT Troubleshooting
Splunk Enterprise for IT TroubleshootingSplunk Enterprise for IT Troubleshooting
Splunk Enterprise for IT Troubleshooting
 
Microservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and SagaMicroservices Architecture Part 2 Event Sourcing and Saga
Microservices Architecture Part 2 Event Sourcing and Saga
 
Juraci Paixão Kröhling - All you need to know about OpenTelemetry
Juraci Paixão Kröhling - All you need to know about OpenTelemetryJuraci Paixão Kröhling - All you need to know about OpenTelemetry
Juraci Paixão Kröhling - All you need to know about OpenTelemetry
 
Deconstructing Monoliths with Domain Driven Design
Deconstructing Monoliths with Domain Driven DesignDeconstructing Monoliths with Domain Driven Design
Deconstructing Monoliths with Domain Driven Design
 
Oracle Assets Period Closing
Oracle Assets Period ClosingOracle Assets Period Closing
Oracle Assets Period Closing
 
Distributed Tracing
Distributed TracingDistributed Tracing
Distributed Tracing
 
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパス
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパスコーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパス
コーパス分析ツールの選択肢の一つとしての CasualConc - 2015 英語コーパス学会@愛知大学名古屋キャンパス
 
Parallel SQL and Streaming Expressions in Apache Solr 6
Parallel SQL and Streaming Expressions in Apache Solr 6Parallel SQL and Streaming Expressions in Apache Solr 6
Parallel SQL and Streaming Expressions in Apache Solr 6
 
2.0~2.2~2.4~3.0 zabbixの進化を紐解く zabbix便利機能紹介-
2.0~2.2~2.4~3.0  zabbixの進化を紐解く  zabbix便利機能紹介-2.0~2.2~2.4~3.0  zabbixの進化を紐解く  zabbix便利機能紹介-
2.0~2.2~2.4~3.0 zabbixの進化を紐解く zabbix便利機能紹介-
 
Opentelemetry - From frontend to backend
Opentelemetry - From frontend to backendOpentelemetry - From frontend to backend
Opentelemetry - From frontend to backend
 
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...
Spring Framework Tutorial | Spring Tutorial For Beginners With Examples | Jav...
 
SonarQube Presentation.pptx
SonarQube Presentation.pptxSonarQube Presentation.pptx
SonarQube Presentation.pptx
 
NServiceBus - building a distributed system based on a messaging infrastructure
NServiceBus - building a distributed system based on a messaging infrastructureNServiceBus - building a distributed system based on a messaging infrastructure
NServiceBus - building a distributed system based on a messaging infrastructure
 
Monitoring and observability
Monitoring and observabilityMonitoring and observability
Monitoring and observability
 
Domain Driven Design
Domain Driven Design Domain Driven Design
Domain Driven Design
 
所属しているグループをすべて取得する
所属しているグループをすべて取得する所属しているグループをすべて取得する
所属しているグループをすべて取得する
 
Oracle Supply Chain Management
Oracle Supply Chain ManagementOracle Supply Chain Management
Oracle Supply Chain Management
 
Operating a payables shared service organization in oracle cloud oow 2019_v4
Operating a payables shared service organization in oracle cloud oow 2019_v4Operating a payables shared service organization in oracle cloud oow 2019_v4
Operating a payables shared service organization in oracle cloud oow 2019_v4
 
Continuous Integration & Continuous Delivery
Continuous Integration & Continuous DeliveryContinuous Integration & Continuous Delivery
Continuous Integration & Continuous Delivery
 

Ähnlich wie Log4c developersguide

Ähnlich wie Log4c developersguide (20)

Log4 C Developers Guide
Log4 C Developers GuideLog4 C Developers Guide
Log4 C Developers Guide
 
Ppdg Robust File Replication
Ppdg Robust File ReplicationPpdg Robust File Replication
Ppdg Robust File Replication
 
Ppdg Robust File Replication
Ppdg Robust File ReplicationPpdg Robust File Replication
Ppdg Robust File Replication
 
Mongo db reference-manual
Mongo db reference-manualMongo db reference-manual
Mongo db reference-manual
 
Mongo db reference manual
Mongo db reference manualMongo db reference manual
Mongo db reference manual
 
TechDoc - WMB - Administration - Logs
TechDoc - WMB - Administration - LogsTechDoc - WMB - Administration - Logs
TechDoc - WMB - Administration - Logs
 
Subversion howto
Subversion howtoSubversion howto
Subversion howto
 
Introduction tococoon2 (1)
Introduction tococoon2 (1)Introduction tococoon2 (1)
Introduction tococoon2 (1)
 
16.7_Release_Notes.pdf
16.7_Release_Notes.pdf16.7_Release_Notes.pdf
16.7_Release_Notes.pdf
 
Consumer centric api design v0.4.0
Consumer centric api design v0.4.0Consumer centric api design v0.4.0
Consumer centric api design v0.4.0
 
Getting started with libfabric
Getting started with libfabricGetting started with libfabric
Getting started with libfabric
 
ROS ROS
ROS ROSROS ROS
ROS ROS
 
textconfig
textconfigtextconfig
textconfig
 
Adobe Flex 3 - Compiler API
Adobe Flex 3 - Compiler APIAdobe Flex 3 - Compiler API
Adobe Flex 3 - Compiler API
 
Create a PHP Library the right way
Create a PHP Library the right wayCreate a PHP Library the right way
Create a PHP Library the right way
 
Understand
UnderstandUnderstand
Understand
 
tutorialSCE
tutorialSCEtutorialSCE
tutorialSCE
 
[EN] PLC programs development guidelines
[EN] PLC programs development guidelines[EN] PLC programs development guidelines
[EN] PLC programs development guidelines
 
manual
manualmanual
manual
 
manual
manualmanual
manual
 

Mehr von hik_lhz

D bus specification
D bus specificationD bus specification
D bus specificationhik_lhz
 
自动生成 Makefile 的全过程详解!
自动生成 Makefile 的全过程详解!自动生成 Makefile 的全过程详解!
自动生成 Makefile 的全过程详解!hik_lhz
 
Developments in linux
Developments in linuxDevelopments in linux
Developments in linuxhik_lhz
 
Larena3 0架构与关键技术
Larena3 0架构与关键技术Larena3 0架构与关键技术
Larena3 0架构与关键技术hik_lhz
 
Considerations when implementing_ha_in_dmf
Considerations when implementing_ha_in_dmfConsiderations when implementing_ha_in_dmf
Considerations when implementing_ha_in_dmfhik_lhz
 
8 集群
8 集群8 集群
8 集群hik_lhz
 
0 mq the guide
0 mq   the guide0 mq   the guide
0 mq the guidehik_lhz
 
Memcached内存分析、调优、集群
Memcached内存分析、调优、集群Memcached内存分析、调优、集群
Memcached内存分析、调优、集群hik_lhz
 
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)hik_lhz
 

Mehr von hik_lhz (9)

D bus specification
D bus specificationD bus specification
D bus specification
 
自动生成 Makefile 的全过程详解!
自动生成 Makefile 的全过程详解!自动生成 Makefile 的全过程详解!
自动生成 Makefile 的全过程详解!
 
Developments in linux
Developments in linuxDevelopments in linux
Developments in linux
 
Larena3 0架构与关键技术
Larena3 0架构与关键技术Larena3 0架构与关键技术
Larena3 0架构与关键技术
 
Considerations when implementing_ha_in_dmf
Considerations when implementing_ha_in_dmfConsiderations when implementing_ha_in_dmf
Considerations when implementing_ha_in_dmf
 
8 集群
8 集群8 集群
8 集群
 
0 mq the guide
0 mq   the guide0 mq   the guide
0 mq the guide
 
Memcached内存分析、调优、集群
Memcached内存分析、调优、集群Memcached内存分析、调优、集群
Memcached内存分析、调优、集群
 
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)
Linux集群应用实战 通过lvs+keepalived搭建高可用的负载均衡集群系统(第二讲)
 

Kürzlich hochgeladen

AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 

Kürzlich hochgeladen (20)

AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 

Log4c developersguide

  • 1. Log4C Developers Guide 1.0.6 13 Nov 2006 First Draft: pulls together information from README files and various 'how to ' documents for Log4C. This document is started between the release of Log4C 1.1.0 and 1.2 so although much of it is valid for older releases it is more looking towards the 1.2 release. Where you see xxx in the text this denotes an item we need to get back to. This document was created with Open Office 2.0.2 . Table of Contents 1 Introduction.............................................................................................................................................2 2 Log4C Concepts and Overview ..............................................................................................................3 3 How to download and build Log4C.......................................................................................................4 3.1 Parsing the Log4C configuration file--the expat dependency ...................................................4 3.2 Some comments on building Log4C in the corporate factory ..................................................5 3.2.1 Log4C is released under the LGPL license. ................................................................ 5 3.2.2 Building on different platforms .................................................................................... 5 3.2.2.1 Building On Unix ............................................................................................ 5 3.2.2.2 Building on Windows ...................................................................................... 6 3.2.2.3 Building on MAC OS ...................................................................................... 6 3.2.3 Packaging on different platforms ................................................................................. 6 4 Getting started--running the examples...................................................................................................6 4.1 Running application_1 ..............................................................................................................7 4.2 Configuring the priority for a category .....................................................................................8 4.3 Configuring application_1 to log to a set of log files................................................................9 4.4 What about application_2 ?.....................................................................................................10 5 Using the Log4C API...........................................................................................................................10 5.1 The helloworld example with Log4C .....................................................................................10 5.1.1 The helloworld code ................................................................................................... 10 5.1.2 Configuring and running helloworld .......................................................................... 11 5.1.2.1 Configuring helloworld with the configuration file....................................... 12 5.1.2.2 Configuring helloworld with the environment variables............................... 12 5.1.2.3 Configuring helloworld via the Log4C API .................................................. 13 5.2 Comments on the the different configuration methods...........................................................13 5.3 Interaction of the configuration methods ................................................................................14 5.4 Including Log4C calls into your code ....................................................................................14 5.4.1 Making it easy to remove Log4C calls from your code ............................................. 14 5.4.2 Other useful Log4C functions .................................................................................... 16 5.4.3 Multi threaded applications using Log4C .................................................................. 17 5.4.3.1 Why the Log4C API is not fully MT safe ..................................................... 17 5.4.3.2 How to use Log4C in an MT safe way .......................................................... 18 6 Extending Log4C with your own custom appender and layout types ..................................................18 7 Troubleshooting and debugging ..........................................................................................................21 8 Deployment Experience with Log4C....................................................................................................21
  • 2. 8.1 Blame it on the logger ..............................................................................................................21 8.2 Preparing to move logging from development into a production environment....................................................................................................................................22 9 References............................................................................................................................................24 1 Introduction Log4C is a C-based logging library. Its goal is provide the C software developer with a configurable and efficient library for logging messages. So Log4C provides the classic logging functionality required by most projects by default while leaving the scope for extensibility for those projects that have special requirements. It seems extraordinary that just about every C project ends up developing it's own logging system. While there are environments like embedded systems or operating system kernels that may justify customized logging technology (and there are open source projects aimed at those areas) there seems to be no a priori reason why most user level application and server software written in C cannot share a logging library. Log4C may be linked with end user applications or other libraries that will eventually be linked into applications. The library is released on SourceForge under the LGPL license. This document is aimed at developers who wish to use Log4C to manage logging in their own project. The kind of information you can find here includes: a general introduction to Log4C concepts and how Log4C can be useful to you how to download and build Log4C how to use and configure the library via examples how to extend Log4C with your own code for customizing, for example, where messages are logged and how they are formatted. troubleshooting and debug information deployment experience with Log4C references to useful material For information relating to Log4C internals the intention is to create a separate documents, “Log4C Internals”. This will help keep the size of each document reasonable and help decouple the evolution of those documents. 2 Log4C Concepts and Overview Log4C follows the overall style of the native Java logging and Log4j utilities. There are three fundamental types of object in Log4C: categories, appenders and layouts. You can think of these objects as corresponding to the what, where and how of the logging system: categories describe what sub-system the message relates to, appenders determine where the message goes and layouts determine how the message is formatted.
  • 3. So for example a category might be named “httpd.network.connection” that may be logging messages to the “syslog” appender using the “dated” format. The convention of using dotted names for categories determines an obvious hierarchy which is used to determine parent and child relationships during logging. These are used because during logging (and this is configurable) a message logged by a category will also be logged to the appenders of any parent categories. There is always a root category which represents a conceptual root of the hierarchy of categories. The categorization of the system make sit easy to select which messages are logged and where—if I configure an appender and priority for a given category then I automatically do it for all it's descendants (unless I explicitly say not to). The extreme case of this is the root category—any configuration positioned there will by default apply to all categories in the system. However, if I need to drill down for finer grained control then the categorization allows me to do that. This means that you should expect to spend some time defining the categories within your system. As an example, if your system separates into different applications then you should have at least one category per application. If your product ships a set of libraries, then each library probably merits it's own category. Libraries linked in as a dependency on a given library should probably be sub-categories of the including library. Within a library you might identify other sub categories, for example a housekeeping category, a connection manager category, a request processor and so on that correspond to logging messages that will come from those sections of code. The other concept fundamental to Log4C is the logging priority: each message has an associated priority. At a given point a given instance of Log4c has an associated configured priority--only messages with a higher priority than the current Log4c priority are sent to an appender for processing. 3 How to download and build Log4C The README file shipped in the workspace gives a good account of Log4C dependencies and how to do a basic build so we will not repeat all that information here. Here we treat that information that requires more detail than the basic build instructions. 3.1 Parsing the Log4C configuration file--the expat dependency “The expat dependency”--no it's not the latest Robert Ludlum novel...it refers to the fact that Log4C can use the expat library (cf. http://expat.sourceforge.net/) as the low level xml parser for it's configuration file. By default when you run configure, it will look for expat and if it finds it it will use it. You can tell configure not to go looking for expat by using the --without-expat option. In the case where you have specified --without-expat or expat is not found or is the wrong version or fails to compile with a small test program, then Log4C will use a custom XML parser using lex/yacc
  • 4. code for the lower level xml parsing. This code works ok with the current configuration file and bundled appenders and layouts. So why do you need to know how Log4C handles it's xml parsing ? Well, as a developer integrating Log4C you will probably prefer the “bundled parser” option as it means you do not pull a dependency on expat. However from the point of view of maintaining Log4C there is still a dependency on the lex/yacc tools needed to generate the parsing code. So there is a choice to make in terms of which dependency Log4C manages. The current consensus is that expat is now sufficiently widespread and mature that introducing a dependency on it is a reasonable step. So as a developer consuming Log4C you can rely on the older bundled code staying in Log4C for the foreseeable future. But you should not expect bug fixes therein nor that that code will evolve to take account of potential enhancements to the configuration file. So the message is that you should start to prepare for handling the dependency on the expat library, either by bundling it in your delivery with Log4C or ensuring that it is available natively on your supported platforms or by specifying it as a requirement to your end users. 3.2 Some comments on building Log4C in the corporate factory The Log4C source code is free, which is good, but there is still a cost in integrating it into your project. Here are some points to consider on this. 3.2.1 Log4C is released under the LGPL license. See the COPYING file in the release for the full license but this means a few things: you will almost certainly require a legal review inside your company to approve your use of Log4C. you are required by the LGL license to ship along with your project a copy of the Log4C source as used in your project. You are also required to ship a copy of the LGL license. Typically one ships a file called something like, ThirdPartyLicenses which lists all the open source components used by your project and includes all the required licenses for those open source components. Ideally the changes you make to Log4C will be minor porting, bug fixes or integration issues required to integrate with your project. Ideally, you would invest some time to work with the Log4C maintainers to integrate your changes back into the Log4C repository in a way that was useful to the whole community. Thus, while one might go with some 'quick fixes' in order to integrate Log4C, expect to spend some time refactoring or generalizing the code in order to have it accepted back into the public repository. A general aspect of integrating an open source project is that, for various reasons, you may wish to make it easy to remove the dependency. We discuss this in more detail in the section titled “Integrating Log4C calls into your code”.
  • 5. 3.2.2 Building on different platforms 3.2.2.1 Building On Unix On Unix systems (certainly for Linux, Solaris and HP-UX) you should be able to use the provided autoconf tools to build Log4C as described in the README. One tip for managing different platforms is not to compile the code in the source directories, but rather to create a directory per platform, run the configure script therein to generate the Makefiles and then build the library, tests, examples and doc in per-platform directory. This allows you to use the same source code to maintain binaries for multiple platforms at the same time. So an example compile session might run: On my Solaris x86 build machine: [ mySol ar i s x 8 6 Bu i l dM c hi a ne ] $ t a r - z x vf l og 4c - 1 . 0 . 12. t a r . gz [ mySol ar i s x 8 6 Bu i l dM c hi a ne ] $ mk d i r b ui l d - Sol a r i s - x86; c d bui l d- Sol a r i s - x86 [ mySol ar i s x 8 6 Bu i l dM c hi a ne ] $ . . / l o g4 c - 1. 0. 12 / c on f i gur e - - pr e f i x=/ pa t h/ of / i ns t a l l a t i on [ mySol ar i s x 8 6 Bu i l dM c hi a ne ] $ ma k e then on the Solaris sparc build machine: [ mySol a r i s Sp a r c Bu i l d M c h i n e ] $ mkd i r b ui l d - Sol a r i s - s pa r c ; c d bui l d- Sol a r i s - s pa r c a [ mySol a r i s Sp a r c Bu i l d M c h i n e ] $ . . / l o g4 c - 1. 0. 12 / c onf i gur e - pr e f i x= a pa t h/ of / i ns t a l l a t i on [ mySol a r i s Sp a r c Bu i l d M c h i n e ] $ ma k e a and so on. If you need to use a compile other than gcc then use the CC environment variable as descirbed in the README file. 3.2.2.2 Building on Windows The build for Windows is not yet integrated into the autoconf mechanism (due to limitations in autoconf on windows at the time the integration was done). So a makefile is provided in the msvc6 directory for building on Windows. Note that some of the appenders are not compiled on Windows...for example the syslog appender. See the README in the msvc6 directory for the Windows build details. 3.2.2.3 Building on MAC OS There are some project files provided for compiling on MAC OS. xxx Not sure of the status of the mac stuff at this time. 3.2.3 Packaging on different platforms Using the provided makefilery as explained in the section “Building on different platforms” it should be possible to generate the library, tests and examples. However native packaging is provided only for Linux at this time. Even there you will probably wish to customize the naming and so on of the generated rpms.
  • 6. So you should expect to spend some time creating scripts or makefiles that will take the binaries from a build directory and package them as required for your supported platforms. Another solution is just to bundle the Log4C library in one of your existing packages or rpms. 4 Getting started--running the examples Once you have built Log4C you can go into the examples directory and run the examples. There may be additional information in the README in the examples directory. For ease of presentation the text below tends to suppose a Unix (or cygwin) environment. We don' t translate each command to Windows supposing that the translation of commands, pathnames and so on are fairly obvious. However where there are significant differences for Windows then we try to highlight them. 4.1 Running application_1 If you have built in a directory separate from the sources, as is recommended, then you need to copy the log4crc file from the source directory into the build directory: $ c d e x a mp l e s $ c p . . / l o g 4c / e x a mp l e s / l o g 4 c r c . Then run the example application_1 as follows. You will need to put the Log4C library on some path so the system can find it when application_1 starts up. If you have used the autoconf tools on Unix and the Makefile in the msvc6 directory that will look like this: On Li n u x/ So l a r i s : e x p o r t LD_ LI BRARY_ PATH=. . / s r c / l og4c / . l i bs / On HP- UX: e xp o r t SHLI B_ PATH=. . / s r c / l og 4c / . l i bs / On W n d ows : s e t Pa t h =. . l o g 4 c ; % Pa t h% i Then you can run application_1 as follows: $ . / a p pl i c a t i o n _ 1 4 You should see this: [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1 ../ ../l o g 4c / e x a mp l e s / a p p l i c a t i o n _1 . c application_1 is a simple example that loops, logging two messages on each loop. In the output above we only see the error message logged at priority ERROR, the other message logged at priority DEBUG
  • 7. is not logged with the default configuration in the l o g4 c r c file. But why is the log message being logged twice ? Thank you for asking. What's happening is that although the application submits the message only once to Log4C, it is passed to all the appenders attached to the originating category s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 AND it's ancestor categories. So, if you look in log4crc you will see this line: < c a t e g or y n a me =" s i x 1 3 l o g . l o g " p r i o r i t y=" e r r o r " a ppe nde r =" s t dout " / > So the stdout appender for the category s i x1 3l o g. l og . a pp . a pp l i c a t i o n1 is logging the message and the stdout appender for the ancestor category s i x1 3l o g. l og is also logging it. So why this strange behavior with respect to logging messages to multiple appenders ? Well, in this example it's hard to see the point. But suppose we have multiple applications and associate categories s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 2 , s i x 1 3 l o g. l o g. a p p. a ppl i c a t i on3, s i x13l og. l og. a pp. a ppl i c a t i on4 , say, with them. Then I can get very tight control over what gets logged using the categorization of the messages: if I set an appender on s i x1 3 l o g. l og . a pp for example then I will get the messages from all the applications. But if I am just interested in messages from a subset of categories then I can configure an appender and logging priority just for them. So once the application or system designer has done a good job defining the categories available for logging then Log4C offers the administrator or end user very powerful and easy control over the messages he chooses to log, where they get logged and the format they are logged in. Furthermore, even if the application developer has to go back and introduce new categories then with Log4C that's an easy task. Too often in-house logging mechanisms are hard coded for a specific domain and adding what would amount to new categories requires significant additional coding. Not so with Log4C. You can see that there is additional text being logged in addition to the message from the application. This 'overhead' is added by Log4C and the various parts of the message break down like this: [ s t d o ut ] The name of the appender logging the message surrounded by square brackets. ERROR The log level of the message. s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 The name of the catgory originating the message s o me e r r o r f r o m a p p 1 a t l i n e 7 8 i n f i l e . . / . . / l o g4c / e xa mpl e s / a ppl i c a t i on_1. c The actual log message. 4.2 Configuring the priority for a category Now, edit the log4crc file to change the value of the priority field from “error” to “debug”: < c a t e g or y n a me =" " p r i o r i t y=" d e b ug " a p pe nd e r =" s t dout " / > Run application_1 again, you should see this: [st d ou t ] DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 0 [st d ou t ] DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 0 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l og4c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l og4c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0 [st d ou t ] DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 1
  • 8. [st d ou t ] DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 1 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l og4c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1 [st d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n fil e .. / . . / l og4c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1 What's happening now is that because the priority of the category has been lowered to DEBUG, the debug message in the application is now appearing. And, for the reasons explained above for the ERROR message, it appears twice. 4.3 Configuring application_1 to log to a set of log files Logging to stdout is fine but suppose we wish to trap all the messages for s i x1 3 l o g. l o g. a p p . a p p l i c a t i o n 1 to a set of log files. To do this we can use the rolling file appender. Edit this line in log4crc to replace stdout with myrollingfileappender: < c a t e g or y n a me =" s i x 1 3 l o g . l o g . a p p . a pp l i c a t i on 1" p r i or i t y=" de bug" a ppe nde r =" s t dout " / > Run application_1 again. This time on stdout you will see: [s t d o ut ] DEBUG s i x 1 3 l o g . l og . a p p . a pp l i c a t i on 1 - De buggi ng a pp 1 - l oop 0 [ s t d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n f i l e . . / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 0 [ s t d ou t ] DEBUG s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - De buggi ng a pp 1 - l oop 1 [ s t d ou t ] ERROR s i x 1 3 l o g . l o g . a p p . a p pl i c a t i o n1 - s ome e r r or f r om a pp1 a t l i ne 79 i n f i l e . . / . . / l o g 4 c / e x a mp l e s / a p p l i c a t i o n_ 1. c - l o op 1 The other copies of the log messages are no longer being sent to stdout but rather to the myrollingfileappender appender, which is logging them to a set of log files in the current directory of the form myprefix.*. Verify this by dumping one of the log files: $ c a t myp r e f i x . 0 20 0 61 10 5 1 6 : 2 9 : 3 3 . 5 3 0 DEBUG s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- De buggi ng a pp 1 - l oop 0 20 0 61 10 5 1 6 : 2 9 : 3 3 . 6 0 4 ERROR s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- s ome e r r or f r om a pp1 a t l i n e 7 9i n f i l e . . / . . / l o g 4c / e x a mp l e s / a p pl i c a t i o n_ 1. c - l oop 0 20 0 61 10 5 1 6 : 2 9 : 3 6 . 6 0 5 DEBUG s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- De buggi ng a pp 1 - l oop 1 20 0 61 10 5 1 6 : 2 9 : 3 6 . 6 0 5 ERROR s i x 13 l o g. l o g. a p p. a p pl i c a t i on1- s ome e r r or f r om a pp1 a t l i n e 7 9 i n f i l e . . / . . / l o g4 c / e x a mpl e s / a pp l i c a t i on _1. c - l oop 1 You will notice that these log messages also have a date stamp on them. This is because myrollingfileappender has been configured in log4crc to use the dated layout (rather than the basic layout) and this layout inserts a date stamp in the message before logging it. You will also notice that the unlike the stream appender which is logging to stdout, the rollingfile appender does not prefix it's messages with the name of the appender enclosed in square brackets. The reason for the change is twofold: first we did not see a real need to log the appender name in each message and secondly it seems better from a design point of view if it is only the layout code which determines the format of the message.
  • 9. 4.4 What about application_2 ? As an application application_2 does the same thing as application_1—it loops logging a few messages. However the interesting thing about application_2 is that it links with a library where new appenders and layouts have been defined. So we leave this more advanced topic to a later section. 5 Using the Log4C API In the last section we saw how to control the logging output from a Log4C enabled example using the configuration file. In this section we see how to “Log4C enable” your applications using the Log4C API. At the top of the main Log4C home page you will see links to the API documentation for the latest released Log4C, for example here: http://log4c.sourceforge.net/files.html. You should keep a reference to this documentation when working with Log4C—it documents parameters, call conventions, return codes, issues and sometimes has code snippets. If you have checked out the workspace from CVS you will need to have added –enable-doc to build the documentation, which gets put into the doc directory where you build. You are strongly recommended to build and view (and improve!!) the API documentation. Depending on the utilities available (dyoxygen, latex,...) on your system the API documentation can be generated in html, pdf and man page format. See 'configure –help' and the README for details on this. 5.1 The helloworld example with Log4C As tradition dictates we provide a hello world example to illustrate the bare bones of Log4C. The hello world code looks as follows: 5.1.1 The helloworld code # i n c l u de < s t d i o . h > # i n c l u de " l o g 4 c . h " i nt ma i n ( i n t a r g c , c h a r * * a r g v ) { i nt r c = 0; l og 4 c _ c a t e g o r y_ t * myc a t = NULL; i f ( l o g4 c _i n i t ( ) ) { p r i n t f ( " l og 4 c _ i n i t ( ) f a i l e d" ) ; r c = 1; } el s e{ myc a t = l og 4 c _ c a t e g o r y_ g e t ( " l o g 4 c . e x a mpl e s . h e l l o wor l d" ) ; l og 4 c _ c a t e g o r y_ l o g ( myc a t , LOG4 C_ PRI ORI TY_ERROR, " He l l o W l d! " ) ; or / * Exp l i c i t l y c a l l t h e l og 4 c c l e a n up r ou t i ne * / i f ( l og4c _f i ni ( ) ) {
  • 10. p r i n t f ( " l o g 4c _ f i n i ( ) f a i l e d" ) ; } } r e t ur n 0; } As you can see there are four calls to the Log4C API here. 1. The l og 4 c _ i ni t ( ) call initializes the library, and reads the configuration files (if any) and environment variables. We will see more about the configuration mechanisms below. 2. The l og 4 c _ c a t e g or y_ g e t ( ) function returns a reference to a category required for logging. 3. The l og 4 c _ c a t e g or y_ l o g ( ) function logs the age old message . 4. The l og 4 c _ f i n i ( ) tells Log4C to cleanup, freeing memory, closing files and so on. 5.1.2 Configuring and running helloworld See the section “Running application_1” for information on setting the environment before running helloworld. If you have compiled and run the helloworld example as is you will see...no output :-(. This is because although we have done all the right things, we have not as yet configured an appender for our helloworld category. It will be instructive to visit each of the three ways Log4C provides to configure it's behavior. For information, the command line on Linux to compile a Log4C example, supposing that the log4c library is already compiled, looks like this: $ g c c - I . . / . . / l o g 4 c / s r c - I . . / s r c . . / . . / l og 4c / e xa mpl e s / he l l owor l d/ he l l owor l d. c - L . . / s r c / l o g4 c / . l i b s / - l l o g4 c 5.1.2.1 Configuring helloworld with the configuration file Copy the log4crc file into the helloworld directory and edit it to add this line: < c a t e g or y n a me =" l o g 4 c . e x a mp l e s . h e l l o wo r l d" p r i or i t y=" de bug" a ppe nde r =" s t dout " / > For completeness we cite here the two other lines relevant to the configuration for helloworld, which are already in the file: < a p p e n d e r n a me =" s t d o u t " t yp e =" s t r e a m" l a yo ut =" ba s i c " / > < l a you t n a me =" b a s i c " t yp e =" b a s i c " / > Run the helloworld program again. You will now see: [ s t d ou t ] ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d! or Cool. What has happened is that we have configured Log4C to send messages for our helloworld example, logged with priority DEBUG or above to go to the appender called “stdout”. This appender
  • 11. is a stream based appender with name stdout, which means the messages will go to...well, stdout. The appender called “stdout” also specifies it's layout, which is the basic layout type. Of course we could configure the messages to go to any of the existing Log4C appenders and use any of the layouts to format the message. By way of building a mental model of what is happening inside the Log4C library note that the fact that the helloworld category is mentioned in the configuration file means that after the call to lo g4 c _i ni t ( ) , a nicely configured instance of that category already exists inside the library. In the case where that category is not mentioned in the configuration file then it is the call to l o g4 c _c a t e g or y_ g e t ( " l o g 4 c . e x a mp l e s . h e l l o wo r l d" ) that creates the (unconfigured) instance on this category. 5.1.2.2 Configuring helloworld with the environment variables Log4C provides a minimal configuration ability via two environment variables: LOG4C_APPENDER and LOG4C_PRIORITY. Both these variables act only on the root category but provide a quick way to globally enable logging . This can be useful to take a look at log messages before drilling down into a finer grained logging using the categorization to focus on messages of particular interest. So, remove the line from the configuration file you added above: < c a t e g or y n a me =" l o g 4 c . e x a mp l e s . h e l l o wo r l d" p r i or i t y=" de bug" a ppe nde r =" s t dout " / > Rerun helloworld to confirm you have no output then rerun the program as follows: e xp o r t LOG4 C_ APPENDER=s t do u t ; h e l l owor l d You will now see the log message as before: [ s t d ou t ] ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d! or What is happening here is that at init time Log4C is reading the LOG4C_APPENDER environment variable and configuring the stdout appender for the root category as a result. Thus all messages logged to this instance of the library, at a priority higher than NOTICE (for that is the priority set on the root category in the configuration file) will be sent to stdout. We could just as well have set LOG4C_APPENDER to be myrollingfileappender, as defined in the configuration file, in which case the helloworld message would have been logged to the myprefix.0 file. Go on, give it a lash, it works! 5.1.2.3 Configuring helloworld via the Log4C API The configuration achieved in the above sections via the configuration file or the environment variables can also be done manually using the Log4C API. Add the following call to set the appender for the helloworld category: myc a t = l og 4 c _ c a t e g o r y_ g e t ( " l o g 4 c . e x a mpl e s . h e l l o wor l d" ) ; l og 4 c _ c a t e g o r y_ s e t _ a p p e n de r ( myc a t , l og 4c _a pp e n de r _ge t ( " s t dout " ) ) ; / * ADD THI S LI NE */ l og 4 c _ c a t e g o r y_ l o g ( myc a t , LOG4 C_ PRI ORI TY_ERROR, " He l l o W l d! " ) ; or
  • 12. Recompile and rerun helloworld to see the output: [ s t d ou t ] ERROR l o g 4 c . e x a mp l e s . h e l l owor l d - He l l o W l d! or 5.2 Comments on the the different configuration methods The three configuration methods demonstrated above are likely to be of more or less interest depending on the nature of your project. Far be it from Log4C developers to adopt the arms dealer pattern of technology development, so here are some general observations to help you think about which method or methods are most appropriate for your scenario: The environment variables seem to be generally useful as a quick way to get your application or system outputting messages. The configuration file is certainly a very powerful way and easy way to configure logging. It is probably of most utility in those cases where you are quite close to the final application development as this gives you more say in the nature of the configuration requirements you introduce to application users. Using the API to configure Log4C is probably of use to those projects delivering some intermediate technology or framework to other application developers. This is because as a framework or library provider you probably do not wish to contribute to a kind of “configuration file proliferation”. You probably would rather take configuration from your own configuration files, or even programmatically from your application developers and then configure Log4C programmatically. If you use the Log4C configuration file and your framework has it's own configuration file and your application has it's own configuration file then it's getting a bit hard for your administrator to keep track of all these configuration files. 5.3 Interaction of the configuration methods The l og 4 c _ i n i t ( ) function looks for a configuration file first and then reads the environment variables, so for defining the priority and appender for the root category the environment variables take precedence. The order that Log4C (up to version 1.0.12) searches for the configuration file is “$LOG4C_RCPATH/log4crc", "$HOME/.log4crc", "./log4crc" . This seems wrong and will probably be changed or made configurable. Also, it is not clear if there is a well defined design decision about what happens when loading fails in a file or if, once a file is loaded successfully, we should then stop trying to load other files. xxx revisit this on the list. If you configure Log4C objects after the call to l o g4 c _i ni t ( ) then the new settings you configure take precedence. 5.4 Including Log4C calls into your code 5.4.1 Making it easy to remove Log4C calls from your code For various reasons you may wish to wrap calls to the Log4C API either in macros or function calls. We list some of these here to help you decide if you want to use wrapped or naked calls to Log4C. You may wish to do this in order, for example, to do some generic preparation of your logging messages.
  • 13. Another reason might be to define some smaller subset of the Log4C API that you wish all your library writers or application developers to use—by using the interface you define you can ensure a consistent usage of Log4C across your system. Another reason might be that, Log4C being an external open source project, you may wish to make it easy to remove Log4C from your project, for fear of API stability, quality or licensing issues that may arise later in your project. As an example, we present one way of wrapping the Log4C calls here. We will modify the helloworld.c file to remove the hard coded dependency on Log4C and introduce a level of indirection that allows an easy decoupling of helloworld from Log4C. We simply introduce functions that wrap the required Log4C functions: myl o g_i ni t ( ) for l o g4 c _i ni t ( ) , myl o g _f i n i ( ) for l o g4 c _ f i n i ( ) and so on. We also need to define our own copies of the logging priorities. See the file mylog.h for the full definitions. So, for logging single strings we can use a function like this: s t a t i c LOG4C_ I NLI NE v o i d myl o g_ ms g( c h a r * c a t Na me , i n t a _pr i or i t y, c ha r *ms g) { # i f n de f W THOUT_ LOG4 C I l o g 4 c _c a t e g o r y_ l o g ( l o g 4 c _c a t e g or y_ ge t ( c a t Na me ) , a _pr i or i t y, ms g) ; # el s e p r i n t f ( ms g) ; # e ndi f } You can see that if this code is compiled with -DWITHOUT_LOG4C then Log4C is totally removed. To use this code, rather than directly calling l o g4 c _c a t e go r y_l og ( ) we would do this: myl o g_ ms g ( " l o g 4 c . e x a mp l e s . h e l l o wor l d " , MYLOG_PRI ORI TY_ERROR, " He l l o W l d! " ) ; or One suggestion by this writer http://jefficus.usask.ca/article.php?story=20040613140849924 is to define a macro for the logging call which means you need only mention hte category name for your subsystem in one place, typically in some include file used by all files in that subsytem. So your simplified logging call actually looks like this: MYLOG_ MSG( MYLOG_ PRI ORI TY_ERROR, " He l l o W l d ! " ) ; or but at the start of the helloworld.c file you define the category name to use, which is picked up by the MYLOG_MSG macro: # de f i n e MYLOG_ CATEGORY_ NAM " l o g 4c . e xa mp l e s . he l l owor l d" E The MYLOG_MSG macro is defined such that if you do not define a category name then it defaults to the root category. This means it is safe and, if you want to be lazy, easy to get logging.
  • 14. The only comment on this handy technique is that if you are paranoid about performance then you may not want to have the lookup call based on the logger name at each logging call. In this case you would do the call to l o g4 c _ c a t e g or y_ g e t ( ) (or the wrapped equivalent) at the initialize time of your subsystem and then use the actual reference to the category object rather than the category name. The code to wrap the log call to take a variable number of arguments is a bit more complex than the code used to log one string shown here—see the function myl o g_l og ( ) defined in mylog.h for way to do that. The code discussed above is included in helloworld1.c and the file mylog.h. The full code of helloworld1.c is included here for convenience: # i n c l u de < s t d i o . h > # de f i n e MYLOG_ CATEGORY_ NAM " l o g 4c . e xa mp l e s . he l l owor l d" E # i n c l u de " myl o g . h " i nt ma i n ( i n t a r g c , c h a r * * a r g v ) { i nt r c = 0; i f ( myl o g _i n i t ( ) ) { p r i n t f ( " myl o g _ i n i t ( ) f a i l e d" ) ; r c = 1; } el s e{ MYLOGMSG( LOG4 C_ PRI ORI TY_ERROR, " He l l o W r l d! " ) ; o / * Ex pl i c i t l y c a l l t h e l og 4c c l e a n up r ou t i ne * / i f ( myl o g_ f i n i ( ) ) { p r i n t f ( " myl og _ f i n i ( ) f a i l e d" ) ; r c = 1; } } r e t ur n r c ; } 5.4.2 Other useful Log4C functions See the Log4C API documentation in your workspace (as generated by make if you have done 'configure –enable-doc') or here for the last release: http://log4c.sourceforge.net/files.html. Log4C provides some convenience functions that mean you do not have to specify the logging priority in the logging call—for example l o g4 c _ c a t e g or y_ f a t a l ( ) , l o g4 c _c a t e go r y_e r r or ( ) and so on. These are documented here for the last release: http://log4c.sourceforge.net/category_8h.html. You can test to see the logging priority of a given category using the lo g4 c _c a t e g or y_ i s _ p r i o r i t y_ e n a b l e d ( ) function.
  • 15. Browse the documentation and examples and tests source to see other usage of the Log4C API. 5.4.3 Multi threaded applications using Log4C Log4C is not Multi thread safe (MT safe). xxx This topic should be discussed on the mailing list and revisited systematically to see what can be done and to document the MT status of the various API calls. In the meantime, it is possible to use Log4C safely provided you follow some rules related to initialization and provided the appenders and layouts you use are themselves MT safe. 5.4.3.1 Why the Log4C API is not fully MT safe A fully MT safe library would be such that multiple threads in the application could safely call any of the LOG4C API functions without any need for synchronization on the part of the application. There are several places where Log4C does not satisfy this: This function must be called successfully just once by the application. If two l og 4 c _ i ni t ( ) threads call this at the same time the behavior is undefined. The problem is that both threads will start to initialize global objects and the behavior is this case is undefined. The same is true of l og 4c _f i ni ( ) —this function can safely be called by only one l og 4 c _ f i n i ( ) thread at a time. Furthermore when you call l o g4 c _f i n i ( ) you must be sure that there are no calls to the logging API in flight—if there are then l o g4 c _f i n i ( ) goes ahead freeing up Log4C objects (like categories, appenders and layouts) so this will probably crash your application. Readonly type Log4C calls like l og 4c _c a t e g or y_ i s _p r i or i t y_e na bl e d ( ) and so on are MT safe between themselves and calls to logging functions like l o g4 c _c a t e go r y_l og ( ) but are not MT safe with respect to l o g4 c _ i ni t ( ) and l o g4 c _f i n i ( ) . Issues related to lazy creation and intialization of objects. Lookup and creation type calls like l o g4 c _c a t e go r y_g e t ( ) , l o g4 c _a pp e nd e r _g e t ( ) , l o g4 c _ l a yo u t _ g e t ( ) and so on are not MT safe, even between themselves. The problem is that if two threads call l o g4 c _c a t e go r y_g e t ( ) at the same time then, if the category instances do not yet exist in the internal store of category instances, then the threads may clash as they write to the shared hash that stores the instance references. This is because no synchronization is provided on the shared instance hash. Calls to l o g4 c _ c a t e g or y_ l o g( ) are not MT safe when called on the same categories. The problem is that log4c_category_log() eventually calls l o g4 c _a pp e nd e r _a pp e n d( ) to log the message. However, if the appender has not already been opened then it calls l o g4 c _ a pp e n de r _ o p e n ( ) , which is not MT safe. The result could be that the two threads will to open the appender at the same time which will give rise to undefined behavior. The calls to the currently shipped basic and dated layouts all work in the context of a logging event
  • 16. object which is allocated by the l o g4 c _ c a t e go r y_l og ( ) call on the stack. Thus the current usage of the layout interface is in fact MT-safe. 5.4.3.2 How to use Log4C in an MT safe way It can be seen from the last section that if you can ensure the following two conditions then you should be able to use Log4C safely in an MT environment: 1. perform the initialization of Log4C and the creation and intialization of all the log4C logging objects before before starting up the multiple threads that call Log4C. In reality this can be problematic as in order to ensure that “open” has been called on all the appenders in your system you will need to know the appender names up front at init time. For developers configuring Log4C programatically then this may work—by definition they will have the names of all the Log4C objects available, otherwise they could not configure then programmatically. For those using the Log4C configuration file where the Log4C init time code takes care of the creation of the objects there is currently no way to tell that code “call open at init time”. There seem to be a few possibilities here that require some development work in Log4C xxx: A way to do that could be to provide an option 'call open at init time' in the configuration file. Provide a function like l o g4c _a p pe n de r _ op e n _a l l ( ) that would call open on all appenders in Log4C. This way the application writer could call that routine to explicitly open all the appenders and avoid race conditions as various threads try to open them. A third solution would be that log4c guarantees that the open call on an appender is called only once in a critical section. 2. Ensure that there are no logging calls in flight when l o g4 c _f i n i ( ) is called. 6Extending Log4C with your own custom appender and layout types The application_2 program in the examples shows how to define your own appender and layout types. First a short word on Log4C terminology. The Log4C library ships with a set of “base types”. These base types are category, appender, layout and rollingpolicy. These base types are hard coded into the library—there is no run time way to control the creation or deletion of these base types (which perhaps there should be). The base types all define an interface which one can use to create new types from the base type. For example the stream appender, the stream2 appender and the rollingfile appender are all types of appender. The basic and dated layouts are both type of layout. The only rollingpolicy currently supplied with Log4C is sizewin, which is a type of rollingpolicy. Once a base type exists in Log4C it is very easy to add new types—the application_2 example shows how to do this for appenders and layouts. Of course it is possible to add new base types to Log4C but
  • 17. we leave that more as a topic for the “Log4C Internals” document as it is less common to need to do that. Note that it is not possible to extend the set of priorities defined by Log4C. These follow the syslog(3) model and are defined as follows: t yp e de f e n um { / ** f a t a l * / LOG4 C_ PRI ORI TY_FATAL = 000, / ** a l e r t * / LOG4 C_ PRI ORI TY_ALERT = 100, / ** c r i t * / LOG4 C_ PRI ORI TY_CRI T = 200, / ** e r r or * / LOG4 C_ PRI ORI TY_ERROR = 300, / ** wa r n * / LOG4 C_ PRI ORI TY_WARN = 400, / ** n ot i c e * / LOG4 C_ PRI ORI TY_NOTI CE = 500, / ** i nf o * / LOG4 C_ PRI ORI TY_I NFO = 600, / ** d e b ug * / LOG4 C_ PRI ORI TY_DEBUG = 700, / ** t r a c e * / LOG4 C_ PRI ORI TY_TRACE = 800, / ** n ot s e t * / LOG4 C_ PRI ORI TY_NOTSET = 900, / ** u nk no wn * / LOG4 C_ PRI ORI TY_UNKNOWN = 1000 } l o g 4c _p r i or i t y_ l e v e l _ t ; So, turning to application_2...if you look at application_2.c you will see that it is very similar to application_1.c—it loops logging two messages at each loop. However, it includes an additional call before the call to l o g4 c _ i ni t ( ) : i ni t _e xa mpl e s _ l i b ( ) ; This function is defining some new appender and layout types that can be accessed in the configuration file or programatically. It eventually calls i n i t _e x a mpl e _a pp e n de r s ( ) . A key code snippet from that file looks like this: s t a t i c c o ns t l o g 4 c _ a p p e n de r _ t yp e _t * c on s t a pp e n de r _t ype s [ ] = { # i f d e f HAVE_ SYSLOG_ H & l o g 4 c _ a p pe n d e r _ t yp e _ s ys l og _l oc a l 0, & l o g 4 c _ a p pe n d e r _ t yp e _ s ys l og _u s e r , # e ndi f & l o g 4c _a p pe n d e r _ t yp e _ s 1 3 _f i l e , & l o g 4c _a p pe n d e r _ t yp e _ s 1 3 _s t d e r r } ; s t a t i c s i z e _ t n a p p e n d e r _ t yp e s = s i z e of ( a p pe n d e r _ t yp e s ) / s i z e o f ( a p pe nd e r _t yp e s [ 0 ] ) ; i nt i n i t _ e x a mp l e _ a p p e n d e r s ( ) { i nt r c = 0; i n t i = 0 ;
  • 18. f or ( i = 0; i < n a p p e n d e r _ t yp e s ; i ++) l o g 4 c _a p p e n d e r _ t yp e _ s e t ( a p pe nd e r _t yp e s [ i ] ) ; r e t ur n( r c ) ; } The key call is to the (somewhat badly named) l o g4 c _a pp e nd e r _t yp e _ s e t ( ) function. This function is registering the appender types defined here with the Log4C code. Thereafter they are available for use in the configuration file or accessible programmatically. We list here the complete code fragment that deals with the l o g4 c _a pp e nd e r _t yp e _ s 1 3_ f i l e type: / * ** * ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * ** ** ** ** ** ** ********************************/ /* * Th e l og 4c s t d e r r a d d s a " [ s t d e r r ] " i n f r o nt o f t he me s s a ge * i t i s l og gi n g . t h i s o n e d o e s n ' t , a nd l e a ve s t h e f or ma t t i ng * de s c i s i on s u p t o t h e f o r ma t t e r */ s t a t i c i n t s 1 3 _ s t d e r r _ a p p e n d ( l o g 4 c _ a pp e n de r _ t * t hi s , c ons t l og4c _l oggi ng_e ve nt _t * a _e ve nt ) { r e t ur n f pr i nt f ( s t de r r , " % s n" , a _e v e n t - > e v t _ r e n d e r e d _ ms g) ; } s t a t i c i n t s 1 3 _ s t d e r r _ o p e n ( l o g 4 c _ a p p e n de r _ t * t hi s ) { / * f pr i n t f ( s t d e r r , " r u n n i n g s 1 3 _ s t de r r a pp e n de r ope n c omma nd now n" ) ; */ r e t ur n 0; } c o ns t l og 4c _a p p e n d e r _ t yp e _ t l o g 4 c _ a p pe nd e r _t yp e _ s 13_s t de r r = { " s 1 3 _s t de r r " , s 13 _ s t d e r r _ op e n , 1 3_ s t d e r r _ a pp e n d , NULL, } ; / * ** * ** ** ** ** * * * * * * * * * * * * * * * * * * * * * * * ** ** ** ** ** ** ********************************/ The l og 4 c _ a p pe n de r _ t yp e _ s 1 3 _ s t d e r r object is defining the interface that the core Log4C code will use to open, append and close this appender. As you can see this appender is pretty simple. It's close function is NULL—it is safe to do this the core Log4C code will not try to call a NULL function. The name of this appender is defined in the first field of it's interface object and is ”s 1 3_ s t d e r r " . It is this name that can be used either in the configuration file or programatically in the l o g4 c _a pp e nd e r _ ge t ( ) call to obtain a reference to the actual object. Defining new layout types follows a similar pattern. See the example_formatters.c file for some
  • 19. example code. Defining new rollingpolicy types--which are used to tell rollingfile appenders under which conditions rollover events should occur—proceeds in the same way. Other types of rollingpolicy it would be interesting to add would be a policy that triggered rollover based on a time period or fixed time basis. 7 Troubleshooting and debugging If you have run configure with the –enable-debug option then by setting the environment variables SD_DEBUG and SD_ERROR to the value “1” you should see some useful internal Log4C trace messages. The traces are useful for watching how Log4C initializes itself, how it looks for and handles configuration files and environment variables, how it intializes and configures internal objects and for log time events like rollover events in the rollingfile appender, for example. Also keep in mind that using the Log4C configuration file allows you complete control over which appender and layout your categories use. So if you are having problems with some specific appender or layout you can easily change those to compare the behavior with other appenders or layouts. 8 Deployment Experience with Log4C This idea of this section is to gather any deployment experience or tips with deploying Log4C in projects. 8.1 Blame it on the logger Here is some experience we had integrating Log4C into a new project. By it's nature a new project has bugs and also makes heavy use of logging to help with the development and debugging phase. What I observed was that on at least four occasions our system was crashing with a stack that led to some Log4C code. In none of these cases did the root cause turn out to be Log4C. After the fourth time debugging someone else's code I thought it worth while to look at the bugs to understand why there was a tendency to have the core stack terminate (misleadingly) in Log4C. Here are some observations that help explain that: logging messages is relatively expensive--so once you turn on, especially heavy logging, then your code spends a lot of it time in there. It would be interesting to run a collector/analyzer to quantify that. So, in the case where there is general memory corruption in your system it is quite likely that when it does crash, it will be in your logging code. This accounts for 2 of the 4 bugs I mention that crashed Log4C Often folks will put debug log statements (good!) without ever testing them (bad!). So some errors of the form of a mismatch between the format string and the parameter list can easily arise. These bugs at least have the merit of being easy to spot once they do occur. That was one of the 4 bugs. Enabling logging calls obviously triggers an extra depth in the call stack--in the case of Log4C using the stream appender this can be up to 10 deep by the time you hit the base write() call to write to the file. So watch out if your stack size is small, especially if you are on a 64 bit
  • 20. system (where you double the memory consumed by pointer types) and especially if your code is already stack hungry. This of course describes exactly the scenario of the 4th bug that crashed Log4C. For information, on HP-UX, where we saw this problem, the default stack size for threads is 64K, which is pretty small compared with defaults of 1M on Solaris and Windows and 2M on Linux. Another Log4C integrator shared this relevant experience: on some Operating Systems there will be a maximum file size limit. If log4c gets deployed in a production environment and no one watches and rotates the log files, a crash and stackdump eventually results from the standard C library routines that write to a file. This stack dump always traces back through log4c and log4c can get blamed as the cause of the crashes. Use rotating file appenders or tell your operations team to put their own rotators on the files. 8.2 Preparing to move logging from development into a production environment. At some point your project will actually be ready to ship and run. Here are some considerations as you migrate logging from a development role to an operations role. Operators will need to be able to debug problems without recompiling code. This is the most critical difference in how logging will be used once your code ships. Here are some tips. 1. Use the configuration file for configuration of categories and appenders, not the API. Operators will want do things like add additional appenders, redirect categories to different appenders etc. They will not be able to just recompile the code they way you do as a developer. If the configuration is done by API then they cannot change anything. If the configuration is done by the log4crc file then they can change things as needed. 2. Plan ahead for runtime debugging. Remember that once it ships, you won't be able to just recompile to change or add logging. Make careful use of the different log levels. Keep use of the ERROR level down to the minimum, and use WARNING, INFO, and DEBUG as you get to messages that are more verbose and less related to known bugs or problems. But don't hesitate to put in lots of DEBUG statements. Your application will be run at ERROR level in production until it has a problem. Picture yourself on the phone telling someone how to change the level to DEBUG in the log4crc and they are in a different city than you. If you have lots of extra DEBUG statements available, it can mean the different between finding the problem just by looking at logs, or having to reproduce the entire bug from inputs on a system that simulates production. The first is quick, the second can involve many days of setup before you can even properly simulate the problem.
  • 21. 3. Use a logging hierarchy wisely to aid in pinpoint debugging. Say that you have shipped several program that work together on and end system. You can choose a logging hierarchy that makes it easy and flexible to manage your logging. Say your company name is initech. And that you have three applications that work together. And in each of these applications you have input handling, business logic, and database access logic. By using a hierarchy for your categories you can get great runtime flexibility. "company.program.subsystem" Using this you would have logging to categories like initech.prog1.dal initech.prog2.blogic initech.prog2.ilogic This allows tremendous runtime flexibility so that operations can manage the logging in many different ways without asking for recompiles and changes to your code. In the above example the top level category "initech" would be the main logging and would remain at ERROR level. If program 3 was having a lot of difficulties and crashes, an additional logging would be added mapping category initech.prog3 to a separate file at DEBUG level until the problems could be solved. If program 2 was extremely slow and database access was suspected, logging could be added to category initech.prog2.dal at DEBUG level and put into its own file. 9 References http://log4c.sf.net/ This SourceForge site is now the main log4c site. http://expat.sourceforge.net/ http://gcc.gnu.org http://www.sunfreeware.com/ http://hpux.connect.org.uk/ Log4c developer mailing list Nice 'How to get developing with log4c' article Log4j Pantheios - "The C++ Logging Sweetspot" http://sourceforge.net/projects/log4cpp/