jda/external/zlog-1.2.18/doc/UsersGuide-EN.lyx
2025-04-30 15:28:08 +08:00

8540 lines
165 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#LyX 2.3 created this file. For more info see http://www.lyx.org/
\lyxformat 544
\begin_document
\begin_header
\save_transient_properties true
\origin unavailable
\textclass extbook
\use_default_options true
\begin_modules
theorems-ams
eqs-within-sections
figs-within-sections
\end_modules
\maintain_unincluded_children false
\language english
\language_package default
\inputencoding auto
\fontencoding global
\font_roman "default" "default"
\font_sans "default" "default"
\font_typewriter "default" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\use_microtype false
\use_dash_ligatures true
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\paperfontsize 12
\spacing single
\use_hyperref true
\pdf_title "zlog Users Guide EN"
\pdf_author "Hardy Simpson"
\pdf_bookmarks true
\pdf_bookmarksnumbered true
\pdf_bookmarksopen true
\pdf_bookmarksopenlevel 1
\pdf_breaklinks true
\pdf_pdfborder true
\pdf_colorlinks true
\pdf_backref false
\pdf_pdfusetitle true
\papersize default
\use_geometry true
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\biblio_style plain
\use_bibtopic false
\use_indices false
\paperorientation portrait
\suppress_date false
\justification true
\use_refstyle 0
\use_minted 0
\index 索引
\shortcut idx
\color #008000
\end_index
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\is_math_indent 0
\math_numbering_side default
\quotes_style english
\dynamic_quotes 0
\papercolumns 1
\papersides 1
\paperpagestyle default
\tracking_changes false
\output_changes false
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\end_header
\begin_body
\begin_layout Title
zlog
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
A single spark can start a prairie fire Mao Zedong
\end_layout
\end_inset
User's Guide
\end_layout
\begin_layout Author
Hardy Simpson
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
This Guide is for zlog v1.2.*
\end_layout
\end_inset
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
If you have comments or error corrections, post
\begin_inset CommandInset href
LatexCommand href
name "a issue"
target "https://github.com/HardySimpson/zlog/issues/new"
literal "false"
\end_inset
on github, or write email to
\begin_inset CommandInset href
LatexCommand href
name "HardySimpson1984@gmail.com"
target "HardySimpson1984@gmail.com"
type "mailto:"
literal "false"
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
\begin_inset CommandInset toc
LatexCommand tableofcontents
\end_inset
\end_layout
\begin_layout Chapter
What is zlog?
\end_layout
\begin_layout Standard
zlog is a reliable, high-performance, thread safe, flexible, clear-model,
pure C logging library.
\end_layout
\begin_layout Standard
Actually, in the C world there was NO good logging library for applications
like logback in java or log4cxx in c++.
printf can work, but can not be redirected easily nor be reformatted.
syslog is slow and is designed for system use.
\end_layout
\begin_layout Standard
So I wrote zlog.
\end_layout
\begin_layout Standard
It is faster, safer and more powerful than log4c.
So it can be widely used.
\end_layout
\begin_layout Standard
zlog has these features:
\end_layout
\begin_layout Itemize
syslog model, better than log4j model
\end_layout
\begin_layout Itemize
log format customization
\end_layout
\begin_layout Itemize
multiple output, include static file path, dynamic file path, stdout, stderr,
syslog, user-defined ouput
\end_layout
\begin_layout Itemize
runtime with manual or automatic refresh of configuration (done safely)
\end_layout
\begin_layout Itemize
high-performance, 250'000 logs/second on my laptop, about 1000 times faster
than syslog(3) with rsyslogd
\end_layout
\begin_layout Itemize
user-defined log level
\end_layout
\begin_layout Itemize
safely rotate log file under multiple-process or multiple-thread conditions
\end_layout
\begin_layout Itemize
accurate to microseconds
\end_layout
\begin_layout Itemize
dzlog, a default category log API for easy use
\end_layout
\begin_layout Itemize
MDC, a log4j style key-value map
\end_layout
\begin_layout Itemize
self debuggable, can output zlog's self debug and error log at runtime
\end_layout
\begin_layout Itemize
Does not depend on any other 3rd party library, just base on POSIX system
(including pthread) and a C99 compliant vsnprintf.
\end_layout
\begin_layout Standard
Links:
\end_layout
\begin_layout Standard
Homepage:
\begin_inset CommandInset href
LatexCommand href
name "http://hardysimpson.github.com/zlog"
target "http://hardysimpson.github.com/zlog"
literal "false"
\end_inset
\end_layout
\begin_layout Standard
Downloads:
\begin_inset CommandInset href
LatexCommand href
target "https://github.com/HardySimpson/zlog/releases"
literal "false"
\end_inset
\end_layout
\begin_layout Standard
Author's Email:
\begin_inset CommandInset href
LatexCommand href
name "HardySimpson1984@gmail.com"
target "HardySimpson1984@gmail.com"
type "mailto:"
literal "false"
\end_inset
\end_layout
\begin_layout Section
Compatibility Notes
\end_layout
\begin_layout Enumerate
zlog is based on POSIX-compatible systems.
I have just GNU/linux and AIX environments to compile, test and run zlog.
Still, I think zlog will work well on FreeBSD, NetBSD, OpenBSD, OpenSolaris,
Mac OS X etc.
Test runs of zlog on any system are welcome.
\end_layout
\begin_layout Enumerate
zlog uses a feature of C99 compliant vsnprintf.
That is, if the buffer size of destination is not long enough, vsnprintf
will return the number of characters (not including the trailing '
\backslash
0') which would have been written to the final string if enough space had
been available.
If the vsnprintf on your system does not work like that, zlog can not know
the right buffer size when a single log is longer than the buffer.
Fortunately, glibc 2.1, libc on AIX, and libc on freebsd work correctly,
while glibc 2.0 does not.
In this case, user should crack zlog himself with a C99 compliant vsnprintf.
I suggest
\begin_inset CommandInset href
LatexCommand href
name "ctrio"
target "http://sourceforge.net/projects/ctrio/"
literal "false"
\end_inset
, or
\begin_inset CommandInset href
LatexCommand href
name "C99-snprintf"
target "http://www.jhweiss.de/software/snprintf.html"
literal "false"
\end_inset
.
The file buf.c should be cracked, good luck!
\end_layout
\begin_layout Enumerate
Some people offer versions of zlog for other platforms.
Thanks!
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
auto tools version:
\begin_inset CommandInset href
LatexCommand href
target "https://github.com/bmanojlovic/zlog"
literal "false"
\end_inset
\end_layout
\begin_layout Standard
cmake verion:
\begin_inset CommandInset href
LatexCommand href
target "https://github.com/lisongmin/zlog"
literal "false"
\end_inset
\end_layout
\begin_layout Standard
windows version:
\begin_inset CommandInset href
LatexCommand href
target "https://github.com/lopsd07/WinZlog"
literal "false"
\end_inset
\end_layout
\end_deeper
\begin_layout Section
zlog 1.2 Release Notes
\end_layout
\begin_layout Enumerate
zlog 1.2 provides these features:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Enumerate
support for pipeline.
Now zlog can send ouput log through programs like cronolog
\end_layout
\begin_layout Enumerate
Full rotation support, see
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Rotation"
\end_inset
\end_layout
\begin_layout Enumerate
Other code compatible details, bug fixes.
\end_layout
\end_deeper
\begin_layout Enumerate
zlog 1.2 is binary compatible with zlog 1.0.
The differences are:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Enumerate
All zlog macros like ZLOG_INFO are shifted to lowercase versions, zlog_info.
This big change is because I think it is easier for people to type.
If you are using a previous version of zlog, please use a script to substitute
all macros, and re-compile your program.
Here is an example:
\end_layout
\begin_layout LyX-Code
sed -i -e 's/
\backslash
b
\backslash
w*ZLOG
\backslash
w*
\backslash
b/
\backslash
L&
\backslash
E/g' aa.c
\end_layout
\begin_layout Enumerate
Auto tools compile is abandoned.
Auto tools is ugly so I dropped it.
A simple makefile is in use, which requires gcc and gnu make.
If this makefile does not work in your environment, you will need to write
a suitable makefile for yourself.
It should be quite easy for a geek.
\end_layout
\end_deeper
\begin_layout Chapter
What zlog is not
\end_layout
\begin_layout Standard
The goal of zlog is to be a simple, fast log library for applications.
It does not support output like sending the log to another machine through
the net or saving it to database.
It will not parse content of log and filter them.
\end_layout
\begin_layout Standard
The reason is obvious: the library is called by an application, so all time
taken by the log library is part of the application's time.
And database inserting or log content parsing takes a long time.
These will slow down the application.
These operation should be done in a different process or on a different
machine.
\end_layout
\begin_layout Standard
If you want all these features, I recommend rsyslog, zLogFabric, Logstash.
These have independent processes to receive logs from another process or
machine, and to parse and store logs.
These functions are separated from the user application.
\end_layout
\begin_layout Standard
Now
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:User-defined-Output"
\end_inset
is supported by zlog.
Just one output function need to be implemented: to transfer the log to
the other process or machine.
The work of category matching and log generating is left with the zlog
library.
\end_layout
\begin_layout Standard
One possibility is to write a zlog-redis client.
It send logs to redis on local or remote machines by user defined output.
Then other processes can read logs from redis and write to disk.
What do you think about this idea? I will be happy to discuss it with you.
\end_layout
\begin_layout Chapter
Hello World
\end_layout
\begin_layout Section
Build and Installation zlog
\end_layout
\begin_layout Standard
Download:
\begin_inset CommandInset href
LatexCommand href
target "https://github.com/HardySimpson/zlog/archive/latest-stable.tar.gz"
literal "false"
\end_inset
\end_layout
\begin_layout LyX-Code
$ tar -zxvf zlog-latest-stable.tar.gz
\end_layout
\begin_layout LyX-Code
$ cd zlog-latest-stable/
\end_layout
\begin_layout LyX-Code
$ make
\end_layout
\begin_layout LyX-Code
$ sudo make install
\end_layout
\begin_layout LyX-Code
or
\end_layout
\begin_layout LyX-Code
$ sudo make PREFIX=/usr/local/ install
\end_layout
\begin_layout Standard
PREFIX indicates where zlog is installed.
After installation, change system settings to make sure your program can
find the zlog library
\end_layout
\begin_layout LyX-Code
$ sudo vi /etc/ld.so.conf
\end_layout
\begin_layout LyX-Code
/usr/local/lib
\end_layout
\begin_layout LyX-Code
$ sudo ldconfig
\end_layout
\begin_layout Standard
Before running a real program, make sure libzlog.so is in the directory where
the system's dynamic lib loader can find it.
The commands mentioned above are for linux.
Other systems will need a similar set of actions.
\end_layout
\begin_layout Itemize
Beside the normal make, these are also available:
\end_layout
\begin_layout LyX-Code
$ make 32bit # 32bit version on 64bit machine, libc6-dev-i386 is needed
\end_layout
\begin_layout LyX-Code
$ make noopt # without gcc optimization
\end_layout
\begin_layout LyX-Code
$ make doc # lyx and hevea is needed
\end_layout
\begin_layout LyX-Code
$ make test # test code, which is also good example for zlog
\end_layout
\begin_layout Itemize
makefile of zlog is written in gnu make style.
So if your platform is not linux, install a gnu make and gcc before trying
to build zlog.
Another way is to write a makefile in your platform's make style.
This should be quite easy as zlog is not complicated.
\end_layout
\begin_layout Section
Call and Link zlog in User's application
\end_layout
\begin_layout Standard
To use zlog, add one line to the source c file or cpp file:
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout Standard
zlog needs the pthread library.
The link command is:
\end_layout
\begin_layout LyX-Code
$ cc -c -o app.o app.c -I/usr/local/include
\end_layout
\begin_layout LyX-Code
# -I[where zlog.h is put]
\end_layout
\begin_layout LyX-Code
$ cc -o app app.o -L/usr/local/lib -lzlog -lpthread
\end_layout
\begin_layout LyX-Code
# -L[where libzlog.so]
\end_layout
\begin_layout Section
Hello World Example
\begin_inset CommandInset label
LatexCommand label
name "sec:Hello-World-Example"
\end_inset
\end_layout
\begin_layout Standard
This example can be found in $(top_builddir)/test/test_hello.c, test_hello.conf
\end_layout
\begin_layout Enumerate
Write a new c source file:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ vi test_hello.c
\end_layout
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
zlog_category_t *c;
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
rc = zlog_init("test_hello.conf");
\end_layout
\begin_layout LyX-Code
if (rc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
c = zlog_get_category("my_cat");
\end_layout
\begin_layout LyX-Code
if (!c) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("get cat fail
\backslash
n");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return -2;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
zlog_info(c, "hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\end_deeper
\begin_layout Enumerate
Write a configuration file in the same path as test_hello.c:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ vi test_hello.conf
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
simple = "%m%n"
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.DEBUG >stdout; simple
\end_layout
\end_deeper
\begin_layout Enumerate
Compile and run it:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ cc -c -o test_hello.o test_hello.c -I/usr/local/include
\end_layout
\begin_layout LyX-Code
$ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog
\end_layout
\begin_layout LyX-Code
$ ./test_hello
\end_layout
\begin_layout LyX-Code
hello, zlog
\end_layout
\end_deeper
\begin_layout Section
Simpler Hello World Example
\end_layout
\begin_layout Standard
This example can be found in $(top_builddir)/test/test_default.c, test_default.con
f.
The source code is
\end_layout
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
rc = dzlog_init("test_default.conf", "my_cat");
\end_layout
\begin_layout LyX-Code
if (rc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
dzlog_info("hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout Standard
The configure file test_default.conf is the same as test_hello.conf, and the
output of test_default is the same as that of test_hello.
The difference is that test_default uses the dzlog API, which has a default
\emph on
zlog_category_t
\emph default
inside and is easier to use.
See
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:dzlog-API"
\end_inset
for more details.
\end_layout
\begin_layout Chapter
Syslog model
\end_layout
\begin_layout Section
Category, Rule and Format
\end_layout
\begin_layout Standard
In zlog, there are 3 important concepts: category, rule and format.
\end_layout
\begin_layout Standard
Category specifies different kinds of log entries.
In the zlog source code, category is a (zlog_cateogory_t *) variable.
In your program, different categories for the log entries will distinguish
them from each other.
\end_layout
\begin_layout Standard
Format describes detail log patterns, such as: with or without time stamp,
source file, source line.
\end_layout
\begin_layout Standard
Rule consists of category, level, output file (or other channel) and format.
In brief, if the category string in a rule in the configuration file equals
the name of a category variable in the source, then they match.
\end_layout
\begin_layout Standard
So when this sentence in the source file is executed:
\end_layout
\begin_layout LyX-Code
zlog_category_t *c;
\end_layout
\begin_layout LyX-Code
c = zlog_get_category("my_cat");
\end_layout
\begin_layout LyX-Code
zlog_info(c, "hello, zlog");
\end_layout
\begin_layout Standard
zlog library uses the category name "my_cat" to match one rule in the configurat
ion file.
That is
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.DEBUG >stdout; simple
\end_layout
\begin_layout Standard
Then the library will check if level is correct to decide whether the log
will be output or not.
As INFO>=DEBUG the log will be output, and as the rule says, it will be
sent to stdout (standard output) in the format of simple, which is described
as
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
simple = "%m%n"
\end_layout
\begin_layout Standard
Lastly, zlog will show the zlog_info() content on the screen
\end_layout
\begin_layout LyX-Code
hello, zlog
\end_layout
\begin_layout Standard
That's the whole story.
The only thing a user need to do is to write the messages.
Where the log will be output, or in which format, is done by zlog library.
\end_layout
\begin_layout Section
Differences between syslog model and log4j model
\end_layout
\begin_layout Standard
Does zLog have anything to do with syslog? Until now, the model is more
like log4j.
As in log4j, there are concepts of logger, appender and layout.
The difference is that in log4j, each logger in source code must correspond
to one logger in the configuration file and has just one definite level.
One-to-one relationship is the only choice for log4j, log4cxx, log4cpp,
log4cplus log4net and etc...
\end_layout
\begin_layout Standard
But the log4j model is NOT flexible, they invent filters to make up for
it, and that make things more worse.
So let's get back to syslog model, which has an excellent design.
\end_layout
\begin_layout Standard
Continuing our example from the last section, if the zlog configuration
file has 2 rules:
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.DEBUG >stdout; simple
\end_layout
\begin_layout LyX-Code
my_cat.INFO >stdout;
\end_layout
\begin_layout Standard
Then they will generate 2 log outputs to stdout:
\end_layout
\begin_layout LyX-Code
hello, zlog
\end_layout
\begin_layout LyX-Code
2012-05-29 10:41:36 INFO [11288:test_hello.c:41] hello, zlog
\end_layout
\begin_layout Standard
You see that one category in the source code corresponds to two rules in
the configuration file.
Maybe log4j's user will say, "That's good, but 2 appender for one logger
will do the same thing".
So, let's see the next example of configure file:
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.WARN "/var/log/aa.log"
\end_layout
\begin_layout LyX-Code
my_cat.DEBUG "/var/log/bb.log"
\end_layout
\begin_layout Standard
And the source code is:
\end_layout
\begin_layout LyX-Code
zlog_info(c, "info, zlog");
\end_layout
\begin_layout LyX-Code
zlog_debug(c, "debug, zlog");
\end_layout
\begin_layout Standard
Then, in aa.log, there is just one log
\end_layout
\begin_layout LyX-Code
2012-05-29 10:41:36 INFO [11288:test_hello.c:41] info, zlog
\end_layout
\begin_layout Standard
But in bb.log, there will be two
\end_layout
\begin_layout LyX-Code
2012-05-29 10:41:36 INFO [11288:test_hello.c:41] info, zlog
\end_layout
\begin_layout LyX-Code
2012-05-29 10:41:36 DEBUG [11288:test_hello.c:42] debug, zlog
\end_layout
\begin_layout Standard
From this example, you see the difference.
Log4j can not do it easily.
In zlog, one category may correspond to mutiple rules, and rules can have
different level, output, and format combinations.
The user has an easy, clear way to filter and multi-ouput all logs on demand.
\end_layout
\begin_layout Section
Expand syslog model
\end_layout
\begin_layout Standard
You can see that category in zlog is more like facility in syslog.
Unfortunately, facility in sylog is an int, and the value of facility must
be chosen from a limited system-defined range.
zlog does better, making it a string variable.
\end_layout
\begin_layout Standard
In syslog, there is a special wildcard "*", which matches all facilities.
It does the same thing in zlog.
"*" matches all categories.
That is a convenient way to make all errors generated by multiple components
in your system redirect to one log file.
Just write in the configuration file like this:
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
*.error "/var/log/error.log"
\end_layout
\begin_layout Standard
A unique feature of zlog is sub-category matching.
If your source code has:
\end_layout
\begin_layout LyX-Code
c = zlog_get_category("my_cat");
\end_layout
\begin_layout Standard
And the configuration file has rules :
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.* "/var/log/my_cat.log"
\end_layout
\begin_layout LyX-Code
my_.NOTICE "/var/log/my.log"
\end_layout
\begin_layout Standard
These 2 rules match category "c" with the name "my_cat".
The wildcard "_" is the way to represent a super category.
"my_" is a super category for "my_cat" and "my_dog".
There is also another wildcard "!".
See
\begin_inset CommandInset ref
LatexCommand ref
reference "subsec:Category-Matching"
\end_inset
for more detail.
\end_layout
\begin_layout Chapter
Configure File
\end_layout
\begin_layout Standard
Most actions of zlog library are dependent upon the configuration file:
where to output the log, how to rotate the log files, how to format the
output, etc.
The configuration file uses a domain specific language to control the library
actions.
Here is an example of zlog.conf:
\end_layout
\begin_layout LyX-Code
# comments
\end_layout
\begin_layout LyX-Code
[global]
\end_layout
\begin_layout LyX-Code
strict init = true
\end_layout
\begin_layout LyX-Code
reload conf period = 1M
\end_layout
\begin_layout LyX-Code
buffer min = 1024
\end_layout
\begin_layout LyX-Code
buffer max = 2MB
\end_layout
\begin_layout LyX-Code
rotate lock file = /tmp/zlog.lock
\end_layout
\begin_layout LyX-Code
default format = "%d.%ms %-6V (%c:%F:%L) - %m%n"
\end_layout
\begin_layout LyX-Code
file perms = 600
\end_layout
\begin_layout LyX-Code
fsync period = 1K
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
[levels]
\end_layout
\begin_layout LyX-Code
TRACE = 10
\end_layout
\begin_layout LyX-Code
CRIT = 130, LOG_CRIT
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
simple = "%m%n"
\end_layout
\begin_layout LyX-Code
normal = "%d(%F %T) %m%n"
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
default.* >stdout; simple
\end_layout
\begin_layout LyX-Code
*.* "%12.2E(HOME)/log/%c.log", 1MB*12; simple
\end_layout
\begin_layout LyX-Code
my_.INFO >stderr;
\end_layout
\begin_layout LyX-Code
my_cat.!ERROR "/var/log/aa.log"
\end_layout
\begin_layout LyX-Code
my_dog.=DEBUG >syslog, LOG_LOCAL0; simple
\end_layout
\begin_layout LyX-Code
my_mice.* $user_define;
\end_layout
\begin_layout Standard
[] means a section's beginning, and the order of sections is fixed, using
the sequence global-levels-formats-rules.
\end_layout
\begin_layout Standard
Note on units: when memory size or large number is needed, it is possible
to specify it in the usual form of 1k 5GB 4M and so forth:
\end_layout
\begin_layout LyX-Code
# 1k => 1000 bytes
\end_layout
\begin_layout LyX-Code
# 1kb => 1024 bytes
\end_layout
\begin_layout LyX-Code
# 1m => 1000000 bytes
\end_layout
\begin_layout LyX-Code
# 1mb => 1024*1024 bytes
\end_layout
\begin_layout LyX-Code
# 1g => 1000000000 bytes
\end_layout
\begin_layout LyX-Code
# 1gb => 1024*1024*1024 byte
\end_layout
\begin_layout Standard
units are case insensitive so 1GB 1Gb 1gB are all the same.
\end_layout
\begin_layout Section
Global
\end_layout
\begin_layout Standard
Global section begins with [global].
This section can be omitted.The syntax is
\end_layout
\begin_layout LyX-Code
(key) = (value)
\end_layout
\begin_layout Itemize
strict init
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
If "strict init = true
\begin_inset Quotes erd
\end_inset
, zlog_init() will check syntax of all formats and rules strictly, and any
error will cause zlog_init() to fail and return -1.
When "strict init = false
\begin_inset Quotes erd
\end_inset
, zlog_init() will ignore syntax errors for formats and rules.
The default is true.
\end_layout
\end_deeper
\begin_layout Itemize
reload conf period
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
This parameter causes the zlog library to reload the configuration file
automatically after a period, which is measured by number of log times
per process.
When the number reaches the value, it calls zlog_reload() internally.
The number is reset to zero at the last zlog_reload() or zlog_init().
As zlog_reload() is atomic, if zlog_reload() fails, zlog still runs with
the current configuration.
So reloading automatically the configuration is safe.
The default is 0, which means never reload automatically.
\end_layout
\end_deeper
\begin_layout Itemize
buffer min
\end_layout
\begin_layout Itemize
buffer max
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
zlog allocates a log buffer in each thread.
"buffer min" indicates size of buffer malloc'ed at init time.
While logging, if one single log's content is longer than buffer size now,
zlog will expand buffer automatically until "buffer max".
Then, if the size is still longer than "buffer max", the log content will
be truncated.
If "buffer max" is 0, it means buffer size is unlimited, and each time
zlog will expand buffer by twice its size, until the process uses all available
memory.
The value of these 2 parameters can appended with unit KB, MB or GB suffix,
where 1024 equals 1KB.
As default, "buffer min" is 1K and "buffer max" is 2MB.
\end_layout
\end_deeper
\begin_layout Itemize
rotate lock file
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
This specifies a lock file for rotating a log safely in multi-process situations.
zlog will open the file at zlog_init() with the permission of read-write.
The pseudo-code for rotating a log file is:
\end_layout
\begin_layout LyX-Code
write(log_file, a_log)
\end_layout
\begin_layout LyX-Code
if (log_file > 1M)
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
if (pthread_mutex_lock succ && fcntl_lock(lock_file) succ)
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
if (log_file > 1M) rotate(log_file);
\end_layout
\begin_layout LyX-Code
fcntl_unlock(lock_file);
\end_layout
\begin_layout LyX-Code
pthread_mutex_unlock;
\end_layout
\end_deeper
\end_deeper
\begin_layout Standard
mutex_lock is for multi-thread and fcntl_lock is for multi-process.
fcntl_lock is the POSIX advisory record locking.
See man 3 fcntl for details.
The lock is system-wide, and when a process dies unexpectedly, the operating
system releases all locks owned by the process.
That's why I chose fcntl lock for rotating log safely.
The process needs read-write permisson for lock_file to lock it.
\end_layout
\begin_layout Standard
By default, rotate lock file = self.
This way, zlog does not create any lock file and sets the configuration
file as the lock file.
As fcntl is advisory, it does not really forbid programmers to change and
store the configuration file.
Generally speaking, one log file will not be rotated by processes run by
different operating system users, so using the configuration file as lock
file is safe.
\end_layout
\begin_layout Standard
If you choose another path as lock file, for example, /tmp/zlog.lock, zlog
will create it at zlog_init().
Make sure your program has permission to create and read-write the file.
If processes run by different operating system users need to write and
rotate the same log file, make sure that each program has permission to
create and read-write the same lock file.
\end_layout
\end_deeper
\begin_layout Itemize
default format
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
This parameter is used by rules without format specified.
The default is
\end_layout
\begin_layout LyX-Code
"%d %V [%p:%F:%L] %m%n"
\end_layout
\begin_layout Standard
It will yield output like this:
\end_layout
\begin_layout LyX-Code
2012-02-14 17:03:12 INFO [3758:test_hello.c:39] hello, zlog
\end_layout
\end_deeper
\begin_layout Itemize
file perms
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
This specifies all log file permissions when they are created.
Note that it is affected by user's umask.
The final file permission will be "file perms" & ~umask.
The default is 600, which just allows user read and write.
\end_layout
\end_deeper
\begin_layout Itemize
fsync period
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
After a number of log times per rule (to file only), zlog will call fsync(3)
after write() to tell the Operating System to write data to disk immediately
from any internal system buffers.
The number is incremented by each rule and will be reset to 0 after zlog_reload
().
Note that when the file's path is generated dynamically or is rotated,
zlog does not guarantee fsync() touch all files.
It just does fsync() against the file descriptors that have have seen write()
prior to the boundary time.
It offers a balance between speed and data safety.
An example:
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 1 10 100000
\end_layout
\begin_layout LyX-Code
real 0m1.806s
\end_layout
\begin_layout LyX-Code
user 0m3.060s
\end_layout
\begin_layout LyX-Code
sys 0m0.270s
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
$ wc -l press.log
\end_layout
\begin_layout LyX-Code
1000000 press.log
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 1 10 100000 #fsync period = 1K
\end_layout
\begin_layout LyX-Code
real 0m41.995s
\end_layout
\begin_layout LyX-Code
user 0m7.920s
\end_layout
\begin_layout LyX-Code
sys 0m0.990s
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 1 10 100000 #fsync period = 10K
\end_layout
\begin_layout LyX-Code
real 0m6.856s
\end_layout
\begin_layout LyX-Code
user 0m4.360s
\end_layout
\begin_layout LyX-Code
sys 0m0.550s
\end_layout
\begin_layout Standard
If you want extreme safety but do not care about speed, use synchronous
file I/O, see
\begin_inset CommandInset ref
LatexCommand ref
reference "ite:synchronous-I/O-file"
\end_inset
.The defualt is 0, which means let the operating system flush the output
buffer when it wants.
\end_layout
\end_deeper
\begin_layout Section
Levels
\end_layout
\begin_layout Standard
This section begins with [levels] and allows the user to define application
levels.
You should match these values with user-defined macros in the source file.
This section can be omitted.
\end_layout
\begin_layout Standard
The syntax is
\end_layout
\begin_layout LyX-Code
(level string) = (level int), (syslog level, optional)
\end_layout
\begin_layout Standard
level int should in [1,253], higher numbers mean more important.
syslog level is optional, if not set, use LOG_DEBUG
\end_layout
\begin_layout Standard
see
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:User-defined-Level"
\end_inset
for more details.
\end_layout
\begin_layout Section
Formats
\end_layout
\begin_layout Standard
This section begins with [formats], where the user can define preferred
log patterns.
The syntax is
\end_layout
\begin_layout LyX-Code
(name) = "(actual formats)"
\end_layout
\begin_layout Standard
It is easy to understand, (name) will be used in the next section [rules].
The format (name) consists of letters and digits plus underscore "_".
The (actual format) should be put in double quotes.
It can be built up with conversion patterns, as described below.
\end_layout
\begin_layout Section
Conversion pattern
\begin_inset CommandInset label
LatexCommand label
name "sec:Conversion-pattern"
\end_inset
\end_layout
\begin_layout Standard
The conversion pattern is closely related to the conversion pattern of the
C printf function.
A conversion pattern is composed of literal text and format control expressions
called conversion specifiers.
\end_layout
\begin_layout Standard
Conversion pattern is used in both filepath of rule and pattern of format.
\end_layout
\begin_layout Standard
You are free to insert any literal text within the conversion pattern.
\end_layout
\begin_layout Standard
Each conversion specifier starts with a percent sign (%) and is followed
by optional format modifiers and a conversion character.
The conversion character specifies the type of data, e.g.
category, level, date, thread id.
The format modifiers control such things as field width, padding, left
and right justification.
The following is a simple example.
\end_layout
\begin_layout Standard
Let the conversion pattern be
\end_layout
\begin_layout LyX-Code
"%d(%m-%d %T) %-5V [%p:%F:%L] %m%n".
\end_layout
\begin_layout Standard
Then the statement
\end_layout
\begin_layout LyX-Code
zlog_info(c, "hello, zlog");
\end_layout
\begin_layout Standard
would yield the output
\end_layout
\begin_layout LyX-Code
02-14 17:17:42 INFO [4935:test_hello.c:39] hello, zlog
\end_layout
\begin_layout Standard
Note that there is no explicit separator between text and conversion specifiers.
The pattern parser knows when it has reached the end of a conversion specifier
when it reads a conversion character.
In the example above the conversion specifier %-5p means the level of the
logging event should be left justified to a width of five characters.
\end_layout
\begin_layout Subsection
Conversion Characters
\end_layout
\begin_layout Standard
The recognized conversion characters are
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="23" columns="3">
<features islongtable="true" longtabularalignment="center">
<column alignment="center" valignment="top" width="10text%">
<column alignment="left" valignment="top" width="50text%">
<column alignment="left" valignment="top" width="40text%">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
conversion char
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
effect
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
example
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%c
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the category of the logging event.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa_bb
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%d()
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the date of the logging event.
The date conversion specifier may be followed by a date format specifier
enclosed between parentheses.
For example, %d(%F) or %d(%m-%d %T).
If no date format specifier is given then %d(%F %T) format is assumed.
The date format specifier permits the same syntax as the strftime(2).
see
\begin_inset CommandInset ref
LatexCommand ref
reference "subsec:Time-Character"
\end_inset
for more detail.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%d(%F) 2011-12-01
\end_layout
\begin_layout Plain Layout
%d(%m-%d %T) 12-01 17:17:42
\end_layout
\begin_layout Plain Layout
%d(%T).%ms 17:17:42.035
\end_layout
\begin_layout Plain Layout
%d 2012-02-14 17:03:12
\end_layout
\begin_layout Plain Layout
%d() 2012-02-14 17:03:12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%E()
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Value of environment variables
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%E(LOGNAME) simpson
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%ms
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The millisecond, 3-digit integer string
\end_layout
\begin_layout Plain Layout
comes from gettimeofday(2)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
013
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%us
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The microsecond, 6-digit integer string
\end_layout
\begin_layout Plain Layout
comes from gettimeofday(2)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
002323
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%F
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the file name where the logging request was issued.
The file name comes from __FILE__ macro.
Some compilers supply __FILE__ as the absolute path.
Use %f to strip path and keep the file name.
Some compilers have an option to control this feature.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
test_hello.c
\end_layout
\begin_layout Plain Layout
or, under some compiler
\end_layout
\begin_layout Plain Layout
/home/zlog/src/test/test_hello.c
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%f
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the source file name, the string after the last '/' of $F.
It will cause a little performance loss in each log event.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
test_hello.c
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%g()
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the date of the logging event in UTC in stead of local time.
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%g(%F) 2011-12-01
\end_layout
\begin_layout Plain Layout
%g(%m-%d %T) 12-01 15:17:42
\end_layout
\begin_layout Plain Layout
%g(%T.ms) 15:17:42.035
\end_layout
\begin_layout Plain Layout
%g 2012-02-14 15:03:12
\end_layout
\begin_layout Plain Layout
%g() 2012-02-14 15:03:12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%H
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the hostname of system, which is from gethostname(2)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
zlog-dev
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%k
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the kernel thread id.
On Linux, that's the LWP using syscall(SYS_gettid) and on OSX, pthread_threadid
_np.
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2136
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%L
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the line number from where the logging request was issued,
which comes from __LINE__ macro
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
135
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%m
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the application supplied message associated with the logging
event.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
hello, zlog
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%M
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the MDC (mapped diagnostic context) associated with the thread
that generated the logging event.
The M conversion character must be followed by the key for the map placed
between parenthesis, as in %M(clientNumber) where clientNumber is the key.
The value in the MDC corresponding to the key will be output.See
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:MDC"
\end_inset
for more detail.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%M(clientNumber) 12345
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%n
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Outputs unix newline character, zLog does not support the MS-Windows line
separator at this time.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\backslash
n
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%p
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the id of the process that generated the logging event, which
comes from getpid().
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2134
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%U
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the function name where the logging request was issued.
It comes from __func__(C99) or __FUNCTION__(gcc) macro, with the support
of the compiler.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
main
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%V
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the level of the logging event, uppercase.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
INFO
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%v
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the level of the logging event, lowercase.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
info
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%t
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Used to output the hexadecimal form of the thread id that generated the
logging event, which comes from pthread_self().
\end_layout
\begin_layout Plain Layout
"%x",(unsigned int) pthread_t
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
ba01e700
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%T
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Equivalent to %t, but the long form
\end_layout
\begin_layout Plain Layout
"%lu", (unsigned long) pthread_t
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
140633234859776
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%%
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
the sequence %% outputs a single percent sign.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%[other char]
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
parsed as a wrong syntax, will cause zlog_init() fail
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Subsection
Format Modifier
\end_layout
\begin_layout Standard
By default, the relevant information is output as-is.
However, with the aid of format modifiers it is possible to change the
minimum field width, the maximum field width, and justification.
It will cause a little performance loss in each log event.
\end_layout
\begin_layout Standard
The optional format modifier is placed between the percent sign and the
conversion character.
\end_layout
\begin_layout Standard
The first optional format modifier is the left justification flag which
is just the minus (-) character.
Then comes the optional minimum field width modifier.
This is a decimal constant that represents the minimum number of characters
to output.
If the data item requires fewer characters, it is padded on either the
left or the right until the minimum width is reached.
The default is to pad on the left (right justify) but you can specify right
padding with the left justification flag.
The padding character is space.
If the data item is larger than the minimum field width, the field is expanded
to accommodate the data.
The value is never truncated.
\end_layout
\begin_layout Standard
This behavior can be changed using the maximum field width modifier which
is designated by a period followed by a decimal constant.
If the data item is longer than the maximum field, then the extra characters
are removed from the beginning of the data item and not from the end.
For example, if the maximum field width is eight and the data item is ten
characters long, then the last two characters of the data item are dropped.
This behavior equals the printf function in C where truncation is done
from the end.
\end_layout
\begin_layout Standard
Below are various format modifier examples for the category conversion specifier.
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="7" columns="5">
<features tabularvalignment="middle">
<column alignment="center" valignment="top" width="9text%">
<column alignment="center" valignment="top" width="8text%">
<column alignment="center" valignment="top" width="8text%">
<column alignment="center" valignment="top" width="8text%">
<column alignment="center" valignment="top" width="60text%">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
format modifier
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
left justify
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
minimum width
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
maximum width
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
comment
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%20c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
false
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
none
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Left pad with spaces if the category name is less than 20 characters long.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%-20c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
true
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
none
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Right pad with spaces if the category name is less than 20 characters long.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%020c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
false
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
none
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Left pad with 0's if the category name is less than 20 characters long.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%.30c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
NA
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
none
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
30
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Truncate from the end if the category name is longer than 30 characters.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%20.30c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
false
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
30
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Left pad with spaces if the category name is shorter than 20 characters.
However, if category name is longer than 30 characters, then truncate from
the end.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%-20.30c
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
true
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
30
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Right pad with spaces if the category name is shorter than 20 characters.
However, if category name is longer than 30 characters, then truncate from
the end.
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Subsection
Time Character
\begin_inset CommandInset label
LatexCommand label
name "subsec:Time-Character"
\end_inset
\end_layout
\begin_layout Standard
Here is the Time Character support by Conversion Character
\emph on
d.
\emph default
\end_layout
\begin_layout Standard
All Character is supported by strftime(3) in library.
The Character supported on my linux system are
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="42" columns="3">
<features islongtable="true" longtabularalignment="center">
<column alignment="center" valignment="top" width="10text%">
<column alignment="left" valignment="top" width="60text%">
<column alignment="left" valignment="top" width="20text%">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
character
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
effect
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
example
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%a
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The abbreviated weekday name according to the current locale.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Wed
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%A
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The full weekday name according to the current locale.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Wednesday
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%b
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The abbreviated month name according to the current locale.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Mar
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%B
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The full month name according to the current locale.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
March
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%c
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The preferred date and time representation for the current locale.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Thu Feb 16 14:16:35 2012
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%C
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The century number (year/100) as a 2-digit integer.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
20
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%d
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The day of the month as a decimal number (range 01 to 31).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
06
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%D
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Equivalent to %m/%d/%y.
(for Americans only.
Americans should note that in other countries %d/%m/%y is more common.
This means that in an international context this format is ambiguous and
should not be used.) (SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
02/16/12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%e
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Like %d, the day of the month as a decimal number, but a leading zero is
replaced by a space.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
6
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%F
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Equivalent to %Y-%m-%d (the ISO 8601 date format).
(C99)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2012-02-16
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%G
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The ISO 8601 week-based year (see NOTES) with century as a decimal number.
The 4-digit year corresponding to the ISO week number (see %V).
This has the same format and value as %Y, except that if the ISO week number
belongs to the previous or next year, that year is used instead.
(TZ)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2012
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%g
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Like %G, but without century, that is, with a 2-digit year (00-99).
(TZ)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%h
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Equivalent to %b.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Feb
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%H
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The hour as a decimal number using a 24-hour clock (range 00 to 23).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
14
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%I
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The hour as a decimal number using a 12-hour clock (range 01 to 12).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
02
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%j
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The day of the year as a decimal number (range 001 to 366).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
047
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%k
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The hour (24-hour clock) as a decimal number (range 0 to 23); single digits
are preceded by a blank.
(See also %H.) (TZ)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
15
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%l
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The hour (12-hour clock) as a decimal number (range 1 to 12); single digits
are preceded by a blank.
(See also %I.) (TZ)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
3
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%m
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The month as a decimal number (range 01 to 12).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
02
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%M
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The minute as a decimal number (range 00 to 59).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
11
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%n
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
A newline character.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\backslash
n
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%p
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Either "AM" or "PM" according to the given time value, or the corresponding
strings for the current locale.
Noon is treated as "PM" and midnight as "AM".
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
PM
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%P
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Like %p but in lowercase: "am" or "pm" or a corresponding string for the
current locale.
(GNU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
pm
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%r
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The time in a.m.
or p.m.
notation.
In the POSIX locale this is equivalent to %I:%M:%S %p.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
03:11:54 PM
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%R
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The time in 24-hour notation (%H:%M).
(SU) For a version including the seconds, see %T below.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
15:11
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%s
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The number of seconds since the Epoch, that is, since 1970-01-01 00:00:00
UTC.
(TZ)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
1329376487
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%S
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The second as a decimal number (range 00 to 60).
(The range is up to 60 to allow for occasional leap seconds.)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
54
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%t
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
A tab character.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%T
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The time in 24-hour notation (%H:%M:%S).
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
15:14:47
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%u
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The day of the week as a decimal, range 1 to 7, Monday being 1.
See also %w.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
4
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%U
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The week number of the current year as a decimal number, range 00 to 53,
starting with the first Sun day as the first day of week 01.
See also %V and %W.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
07
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%V
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The ISO 8601 week number (see NOTES) of the current year as a decimal number,
range 01 to 53, where week 1 is the first week that has at least 4 days
in the new year.
See also %U and %W.
(SU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
07
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%w
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The day of the week as a decimal, range 0 to 6, Sunday being 0.
See also %u.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
4
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%W
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The week number of the current year as a decimal number, range 00 to 53,
starting with the first Mon day as the first day of week 01.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
07
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%x
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The preferred date representation for the current locale without the time.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
02/16/12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%X
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The preferred time representation for the current locale without the date.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
15:14:47
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%y
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The year as a decimal number without a century (range 00 to 99).
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
12
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%Y
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The year as a decimal number including the century.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
2012
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%z
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The time-zone as hour offset from GMT.
Required to emit RFC 822-conformant dates (using "%a, %d %b %Y %H:%M:%S
%z").
(GNU)
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
+0800
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%Z
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
The timezone or name or abbreviation.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
CST
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%%
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
A literal '%' character.
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
%
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Standard
\end_layout
\begin_layout Section
Rules
\end_layout
\begin_layout Standard
This section begins with [rules].
It decides how log actions are filtered, formatted and output.
This section can be omitted, but there will result in no log output.
The syntax is
\end_layout
\begin_layout LyX-Code
(category).(level) (output), (option,optional); (format name, optional)
\end_layout
\begin_layout Standard
When zlog_init() is called, all rules will be read into memory.
When zlog_get_category() is called, mutiple rules will be assigned to each
category, in the way
\begin_inset CommandInset ref
LatexCommand ref
reference "subsec:Category-Matching"
\end_inset
describes.
When logging is performed, the level between matched rules and INFO will
be checked to decide whether this single log will be output through the
rule.
When zlog_reload() is called, the configuration file will be re-read into
memory, including rules.
All category rules will be re-calculated.
\end_layout
\begin_layout Subsection
Level Matching
\end_layout
\begin_layout Standard
There are six default levels in zlog, "DEBUG", "INFO", "NOTICE", "WARN",
"ERROR" and "FATAL".
As in all other log libraries, aa.DEBUG means all logs of level greater
than or equal to DEBUG will be output.
Still, there are more expressions.
Levels in the configuration file are not case sensitive; both capital or
lowercase are accepted.
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="5" columns="2">
<features tabularvalignment="middle">
<column alignment="center" valignment="top">
<column alignment="center" valignment="top">
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
example expression
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
meaning
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
*
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
all [source level]
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa.debug
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
[source level]>=debug
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa.=debug
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
[source level]==debug
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa.!debug
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
[source level]!=debug
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Standard
The level strings can be defined by the user.
See
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:User-defined-Level"
\end_inset
.
\end_layout
\begin_layout Subsection
Category Matching
\begin_inset CommandInset label
LatexCommand label
name "subsec:Category-Matching"
\end_inset
\end_layout
\begin_layout Standard
Category Matching is simple.
The name of the category is made up of letters, digits, and/or the underscore
"_".
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="5" columns="4">
<features tabularvalignment="middle">
<column alignment="left" valignment="top" width="20text%">
<column alignment="left" valignment="top" width="15col%">
<column alignment="left" valignment="top" width="25col%">
<column alignment="left" valignment="top" width="20col%">
<row>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
summarize
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
category string from configure file
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
category matches
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
category not matches
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
* matches all
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
*.*
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa, aa_bb, aa_cc, xx, yy ...
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
NONE
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
string end with underline matches super-category and sub-categories
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa_.*
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa, aa_bb, aa_cc, aa_bb_cc
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
xx, yy
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
string not ending with underline accurately matches category
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa.*
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa_bb, aa_cc, aa_bb_cc
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
! matches category that has no rule matched
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
!.*
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
xx
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
aa(as it matches rules above)
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Subsection
Output Action
\end_layout
\begin_layout Standard
zlog supports various output methods.
The syntax is
\end_layout
\begin_layout LyX-Code
(output action), (output option); (format name, optional)
\end_layout
\begin_layout Standard
\begin_inset Tabular
<lyxtabular version="3" rows="8" columns="3">
<features tabularvalignment="middle">
<column alignment="left" valignment="top">
<column alignment="center" valignment="top">
<column alignment="left" valignment="top" width="30text%">
<row>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
output
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
output action
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
output option
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
to standard out
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
>stdout
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
no meaning
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
to standard error
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
>stderr
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
no meaning
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
to syslog
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
>syslog
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
syslog facility, can be: LOG_USER(default), LOG_LOCAL[0-7]
\end_layout
\begin_layout Plain Layout
This is required.
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
pipeline output
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
| cat
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
no meaning
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
to file
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
"(file path)"
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
rotation.
see
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Rotation"
\end_inset
for detail
\end_layout
\begin_layout Plain Layout
10MB * 3 ~ "press.#r.log"
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
synchronous I/O file
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
-"(file path)"
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
user-defined output
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" bottomline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
$name
\end_layout
\end_inset
</cell>
<cell alignment="left" valignment="top" topline="true" bottomline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
"path" (dynamic or static) of record function
\end_layout
\end_inset
</cell>
</row>
</lyxtabular>
\end_inset
\end_layout
\begin_layout Itemize
stdout, stderr, syslog
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
As the above table describes, only the syslog action has a meaningful output
option and it must be set.
\end_layout
\begin_layout Standard
Warning: NEVER use >stdout or >stderr when your program is a daemon process.
A daemon process always closes its first file descriptor, and when >stdout
is set, zlog will output a log like this
\end_layout
\begin_layout LyX-Code
write(STDOUT_FILENO, zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg
_buf))
\end_layout
\begin_layout Standard
What will happen then? The log will be written to the file whose fd is now
1.
I have received mail from someone who said zlog as a daemon wrote logs
to the configuration file.
So remember, daemon processes should not set any rule output to stdout,
or stderr.
It will generate undefined behavior.
If you still want output logs to console when stdout is closed, use "/dev/tty"
instead.
\end_layout
\end_deeper
\begin_layout Itemize
pipeline output
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* | /usr/bin/cronolog /www/logs/example_%Y%m%d.log ; normal
\end_layout
\begin_layout Standard
This is an example of how zlog pipelines its output to cronolog.
The implementation is simple.
popen("/usr/bin/cronolog /www/logs/example_%Y%m%d.log","w") is called at
zlog_init(), and forward logs will be written to the open descriptor in
the "normal" format.
Writing through pipeline and cronnolog is faster than dynamic file of zlog,
as there is no need to open and close file descripter each time when logs
are written to a pipe.
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
*.* "press%d(%Y%m%d).log"
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 1 10 100000
\end_layout
\begin_layout LyX-Code
real 0m4.240s
\end_layout
\begin_layout LyX-Code
user 0m2.500s
\end_layout
\begin_layout LyX-Code
sys 0m5.460s
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
*.* | /usr/bin/cronolog press%Y%m%d.log
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 1 10 100000
\end_layout
\begin_layout LyX-Code
real 0m1.911s
\end_layout
\begin_layout LyX-Code
user 0m1.980s
\end_layout
\begin_layout LyX-Code
sys 0m1.470s
\end_layout
\begin_layout Standard
There are some limitations when using pipeline output:
\end_layout
\begin_layout Itemize
POSIX.1-2001 says that write(2)s of less than PIPE_BUF bytes must be atomic,
On Linux, PIPE_BUF is 4096 bytes.
\end_layout
\begin_layout Itemize
When a single log is longer than PIPE_BUF, and multiple processes write
logs through one pipe (parent calls zlog_init(), and forks many child processes
), log interlacing will occur.
\end_layout
\begin_layout Itemize
Unrelated multiple processes can start multiple cronolog processes and write
to the same log file.
Even if a single log is not longer than PIPE_BUF, multiple cronologs will
cause log interlace.
As cronologs read log continuously, it doesn't know where is the split
between log entries.
\end_layout
\begin_layout Standard
In summary, pipeline to a single log file:
\end_layout
\begin_layout Itemize
Single process writing, no limitation for length of one log.
Multi-threads in one process, atomic writing is already assured by zlog.
\end_layout
\begin_layout Itemize
Related multiple processes, the length of one log should not longer than
PIPE_BUF.
\end_layout
\begin_layout Itemize
Unrelated multiple processes, no matter how long a single log is, will cause
interlace and is not safe.
\end_layout
\end_deeper
\begin_layout Itemize
file
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Itemize
file path
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
can be absolute file path or relative file path.
It is quoted by double quotation marks.
\emph on
Conversion pattern
\emph default
can be used in file path.
If the file path is "%E(HOME)/log/out.log" and the program environment $HOME
is /home/harry, then the log file will be /home/harry/log/output.log.
See
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Conversion-pattern"
\end_inset
for more details.
\end_layout
\begin_layout Standard
file of zlog is powerful, for example
\end_layout
\begin_layout Enumerate
output to named pipe(FIFO), which must be created by mkfifo(1) before use
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* "/tmp/pipefile"
\end_layout
\end_deeper
\begin_layout Enumerate
output to null, do nothing at all
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* "/dev/null"
\end_layout
\end_deeper
\begin_layout Enumerate
output to console, in any case
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* "/dev/tty"
\end_layout
\end_deeper
\begin_layout Enumerate
output a log to each tid, in the directory where the process running
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* "%T.log"
\end_layout
\end_deeper
\begin_layout Enumerate
output to file with pid name, every day, in $HOME/log directory, rotate
log at 1GB, keep 5 log files
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
*.* "%E(HOME)/log/aa.%p.%d(%F).log",1GB * 5
\end_layout
\end_deeper
\begin_layout Enumerate
each category of aa_ super category, output log with category name
\end_layout
\begin_layout LyX-Code
aa_.* "/var/log/%c.log"
\end_layout
\end_deeper
\begin_layout Itemize
rotate action
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
controls log file size and count.
zlog rotates the log file when the file exceeds this value.
For example, let the action be
\end_layout
\begin_layout LyX-Code
"%E(HOME)/log/out.log",1M*3
\end_layout
\begin_layout Standard
and after out.log is filled to 1M, the rotation is
\end_layout
\begin_layout LyX-Code
out.log -> out.log.1
\end_layout
\begin_layout LyX-Code
out.log(new create)
\end_layout
\begin_layout Standard
If the new log is full again, the rotation is
\end_layout
\begin_layout LyX-Code
out.log.1 -> out.log.2
\end_layout
\begin_layout LyX-Code
out.log -> out.log.1
\end_layout
\begin_layout LyX-Code
out.log(new create)
\end_layout
\begin_layout Standard
The next rotation will delete the oldest log, as *3 means just allows 3
file exist
\end_layout
\begin_layout LyX-Code
unlink(out.log.2)
\end_layout
\begin_layout LyX-Code
out.log.1 -> out.log.2
\end_layout
\begin_layout LyX-Code
out.log -> out.log.1
\end_layout
\begin_layout LyX-Code
out.log(new create)
\end_layout
\begin_layout Standard
So the oldest log has the biggest serial number.
If *3 is not specified, it means rotation will continue and no old log
will be deleted.
\end_layout
\end_deeper
\begin_layout Itemize
synchronous I/O file
\begin_inset CommandInset label
LatexCommand label
name "ite:synchronous-I/O-file"
\end_inset
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
Putting a minus sign '-' sets the synchronous I/O option.
log file is opened with O_SYNC and every single log action will wait until
the Operating System writes data to disk.
It is painfully slow:
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 100 1000
\end_layout
\begin_layout LyX-Code
real 0m0.732s
\end_layout
\begin_layout LyX-Code
user 0m1.030s
\end_layout
\begin_layout LyX-Code
sys 0m1.080s
\end_layout
\begin_layout LyX-Code
$ time ./test_press_zlog 100 1000 # synchronous I/O open
\end_layout
\begin_layout LyX-Code
real 0m20.646s
\end_layout
\begin_layout LyX-Code
user 0m2.570s
\end_layout
\begin_layout LyX-Code
sys 0m6.950s
\end_layout
\end_deeper
\end_deeper
\begin_layout Itemize
format name
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
It is optional.
If not set, use zlog default format in global setting, which is:
\end_layout
\begin_layout LyX-Code
[global]
\end_layout
\begin_layout LyX-Code
default format = "%d %V [%p:%F:%L] %m%n"
\end_layout
\end_deeper
\begin_layout Itemize
see
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:User-defined-Output"
\end_inset
for more details for $.
\end_layout
\begin_layout Section
Rotation
\begin_inset CommandInset label
LatexCommand label
name "sec:Rotation"
\end_inset
\end_layout
\begin_layout Standard
Why rotation? I have see more than once in a production environment, that
the hard disk is full of logs and causes the system to stop working, or
a single log file is too big to open or grep.
Several ways to rotate and archive log files are possible:
\end_layout
\begin_layout Enumerate
Split log by date or time.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
For example, generate one log file per day.
\end_layout
\begin_layout LyX-Code
aa.2012-08-02.log
\end_layout
\begin_layout LyX-Code
aa.2012-08-03.log
\end_layout
\begin_layout LyX-Code
aa.2012-08-04.log
\end_layout
\begin_layout Standard
In this case, the system administrator knows how much log will be produced
one day.
The sys admin is able to search log files based on the day.
The best way to make this split is to let the zlog library do it.
Another choice is using cronosplit to analyse the content of log file and
split it.
A bad way is using crontab+logrotate to daily move log files, which is
not accurate, some logs will be put into the file for the previous day.
\end_layout
\begin_layout Standard
Using zlog, there is no need for external rotate action to complete the
job.
Setting time in the log file name works:
\end_layout
\begin_layout LyX-Code
*.* "aa.%d(%F).log"
\end_layout
\begin_layout Standard
or using cronolog for faster performace:
\end_layout
\begin_layout LyX-Code
*.* | cronolog aa.%F.log
\end_layout
\end_deeper
\begin_layout Enumerate
Split log by size.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
Always suitable for development use.
In this case, the program generates a lot of logs in a short period.
But the text editor might not be able to open big files quickly.
Although the split can be done using split tools afterwards, this requires
extra steps.
So a good way is to let the logging library do the rotation.
There are two ways of rotation, as nlog describes, Sequence and Rolling.
In case of Sequence:
\end_layout
\begin_layout LyX-Code
aa.log (new)
\end_layout
\begin_layout LyX-Code
aa.log.2 (less new)
\end_layout
\begin_layout LyX-Code
aa.log.1
\end_layout
\begin_layout LyX-Code
aa.log.0 (old)
\end_layout
\begin_layout Standard
And in case of Rolling:
\end_layout
\begin_layout LyX-Code
aa.log (new)
\end_layout
\begin_layout LyX-Code
aa.log.0 (less new)
\end_layout
\begin_layout LyX-Code
aa.log.1
\end_layout
\begin_layout LyX-Code
aa.log.2 (old)
\end_layout
\begin_layout Standard
It's hard to say which one is most suitable.
\end_layout
\begin_layout Standard
If only some of the newest logs are useful to developers, logging library
should do the cleanup work and delete the old log files.
Some external tools can't find out which files are older.
\end_layout
\begin_layout Standard
The simplest rotation configuration for zlog is:
\end_layout
\begin_layout LyX-Code
*.* "aa.log", 10MB
\end_layout
\begin_layout Standard
It is Rolling.
When aa.log is larger than 10MB, zlog will rename file like this:
\end_layout
\begin_layout LyX-Code
aa.log.2 -> aa.log.3
\end_layout
\begin_layout LyX-Code
aa.log.1 -> aa.log.2
\end_layout
\begin_layout LyX-Code
aa.log.0 -> aa.log.1
\end_layout
\begin_layout LyX-Code
aa.log -> aa.log.0
\end_layout
\begin_layout Standard
The configuration can be more complex:
\end_layout
\begin_layout LyX-Code
*.* "aa.log", 10MB * 0 ~ "aa.log.#r"
\end_layout
\begin_layout Standard
The 1st argument after the file name says when rotation will be triggered,
in size.
\end_layout
\begin_layout Standard
The 2nd argument after the file name says how many archive files will be
kept, (0 means keep all).
\end_layout
\begin_layout Standard
The 3rd argument after the file name shows the archive file name.
#r is a sequence number for archive files.
r is short for Rolling, and #s is short for sequence.
Archive file name must contain one of #r or #s.
\end_layout
\end_deeper
\begin_layout Enumerate
Split log by size, and add time tag to archive file.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
aa.log
\end_layout
\begin_layout LyX-Code
aa.log-20070305.00.log
\end_layout
\begin_layout LyX-Code
aa.log-20070501.00.log
\end_layout
\begin_layout LyX-Code
aa.log-20070501.01.log
\end_layout
\begin_layout LyX-Code
aa.log-20071008.00.log
\end_layout
\begin_layout Standard
In this case, the log file is not usually viewed frequently, and is likely
checked once a day.
Of course, when one day's log is more than 100MB, you should consider storing
in two files and add postfix numbers.
For example if the date is used as part of the pattern (like 20070501):
\end_layout
\begin_layout Standard
The configuration of zlog is:
\end_layout
\begin_layout LyX-Code
*.* "aa.log", 100MB ~ "aa-%d(%Y%m%d).#2s.log"
\end_layout
\begin_layout LyX-Code
Do rotation every 100MB.
The archive file name also supports conversion strings.
#2s means the sequence number is at least 2 bytes wide.
Sequence from 00.
That's the most complex way to archive in zlog.
\end_layout
\end_deeper
\begin_layout Enumerate
Compress, move and delete old archive.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
Compress should not be done by the logging library, because compress need
time and CPU.
The mission of the logging library is to cooperate with compress programs.
\end_layout
\begin_layout Standard
For the 3 ways to split logs, way 1 and way 3 are easy to manage.
It is easy to find old log file by name or by modify time.
And then compress, move and delete old log files by crontab and shell.
\end_layout
\begin_layout Standard
For second way, compress is useless, delete is needed and zlog already supports
it.
\end_layout
\begin_layout Standard
If you really want to rotate and compress log file at the same time, I suggest
logrotate.
It is an independent program and will not confuse the situation.
\end_layout
\end_deeper
\begin_layout Enumerate
zlog support for external tools like logrotate.
\end_layout
\begin_layout Standard
The rotation support of zlog is very powerful, still there are several cases
zlog can not handle.
Like rotation by time, before or after rotation call some user-defined
shells.
That will make zlog too complex.
\end_layout
\begin_layout Standard
Under these circumstances, consider using external tools like logrotate.
On linux, the problem is that when a tool renames the log file, the working
process which uses an inode to reference the file will not automatically
reopen the new file.
The standard way is send a signal to the program and let it reopen the
file.
For syslogd the command is:
\end_layout
\begin_layout LyX-Code
kill -SIGHUP `cat /var/run/syslogd.pid`
\end_layout
\begin_layout Standard
For zlog as a library, it is not good to receive signals.
zlog provide zlog_reload(), which reloads the configuration file and reopens
all log files.
So if you write a program and want to reopen a log file manually, you can
write some code to do the job like this: after receiving a signal or command
from client, call zlog_reload().
\end_layout
\begin_layout Section
Configure File Tools
\end_layout
\begin_layout LyX-Code
$ zlog-chk-conf -h
\end_layout
\begin_layout LyX-Code
Useage: zlog-chk-conf [conf files]...
\end_layout
\begin_layout LyX-Code
-q, suppress non-error message
\end_layout
\begin_layout LyX-Code
-h, show help message
\end_layout
\begin_layout Standard
zlog-chk-conf tries to read configuration files, check their syntax, and
output to screen whether it is correct or not.
I suggest using this tool each time you create or change a configuration
file.
It will output like this
\end_layout
\begin_layout LyX-Code
$ ./zlog-chk-conf zlog.conf
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:rule.c:391) sscanf [aaa] fail, category or level
is null
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:conf.c:155) zlog_rule_new fail [aaa]
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:conf.c:258) parse configure file[zlog.conf] line[126]
fail
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:conf.c:306) zlog_conf_read_config fail
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:conf.c:366) zlog_conf_build fail
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:zlog.c:66) conf_file[zlog.conf], init conf fail
\end_layout
\begin_layout LyX-Code
03-08 15:35:44 ERROR (10595:zlog.c:131) zlog_init_inner[zlog.conf] fail
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
---[zlog.conf] syntax error, see error message above
\end_layout
\begin_layout Standard
This example tells you that [aaa] is not a correct rule and that line 126
in the configuration file is wrong.
Later failure reports result from that fundamental failure.
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout Chapter
zlog API
\end_layout
\begin_layout Standard
All zlog APIs are thread safe.
To use them, you just need to
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout Section
initialize and finish
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int zlog_init(const char *
\bar under
confpath
\bar default
);
\end_layout
\begin_layout LyX-Code
int zlog_reload(const char *
\bar under
confpath
\bar default
);
\end_layout
\begin_layout LyX-Code
void zlog_fini(void);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
zlog_init() reads configuration from the file
\bar under
confpath
\bar default
.
If
\bar under
confpath
\bar default
is NULL, it looks for the environment variable ZLOG_CONF_PATH to find the
configuration file.
If $ZLOG_CONF_PATH is NULL also, all logs will be output to stdout with
an internal format.
Only the first call to zlog_init() per process is effective, subsequent
calls will fail and do nothing.
\end_layout
\begin_layout Standard
zlog_reload() is designed to reload the configuration file.
From the
\bar under
confpath
\bar default
it re-calculates the category-rule relationships, rebuilds thread buffers,
and resets user-defined output function rules.
It can be called at runtime when the configuration file is changed or you
wish to use another configuration file.
It can be called any number of times.
If
\bar under
confpath
\bar default
is NULL, it reloads the last configuration file that zlog_init() or zlog_reload
() specified.
If zlog_reload() failed, the current configuration in memory will remain
unchanged.
So zlog_reload() is atomic.
\end_layout
\begin_layout Standard
zlog_fini() releases all zlog API
\emph on
\emph default
memory and closes opened files.
It can be called any number of times.
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
On success , zlog_init() and zlog_reload() return zero.
On error, zlog_init() and zlog_reload() return -1, and a detailed error
log will be recorded to the log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
category operation
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
typedef struct zlog_category_s zlog_category_t;
\end_layout
\begin_layout LyX-Code
zlog_category_t *zlog_get_category(const char *
\bar under
cname
\bar default
);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
zlog_get_category() gets a category from zlog's category_table for a future
log action.
If the category cname does not exist it will be created.
Then zlog goes through all rules as determined by the configuration.
It returns a pointer to matched rules corresponding to
\bar under
cname
\bar default
.
\end_layout
\begin_layout Standard
This is how category string in rules matches
\bar under
cname
\bar default
:
\end_layout
\begin_layout Enumerate
* matches all
\bar under
cname
\bar default
.
\end_layout
\begin_layout Enumerate
category string which ends with underscore "_" matches super-category and
sub-categories.
For example, "aa_" matches
\bar under
cname
\bar default
like "aa", "aa_", "aa_bb", "aa_bb_cc".
\end_layout
\begin_layout Enumerate
category string which does not end with underscore "_"matches
\bar under
cname
\bar default
accurately.
For example, "aa_bb" matches only a
\bar under
cname
\bar default
of "aa_bb".
\end_layout
\begin_layout Enumerate
! matches
\bar under
cname
\bar default
that has no rule matched.
\end_layout
\begin_layout Standard
The rules for each category will be automatically re-calculated when zlog_reload
() is called.
No need to worry about category's memory release,
\emph on
\emph default
zlog_fini() will clean up at the end.
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
On success, return the address of zlog_category_t.
On error, return NULL, and a detailed error log will be recorded to the
log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
log functions and macros
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
void zlog(zlog_category_t *
\bar under
category
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
format
\bar default
, ...);
\end_layout
\begin_layout LyX-Code
void vzlog(zlog_category_t *
\bar under
category
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
format
\bar default
, va_list
\bar under
args
\bar default
);
\end_layout
\begin_layout LyX-Code
void hzlog(zlog_category_t *
\bar under
category
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const void *
\bar under
buf
\bar default
, size_t
\bar under
buflen
\bar default
);
\end_layout
\begin_layout LyX-Code
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
These 3 functions are the real log functions producing user messages, which
correspond to %m is configuration file entries.
\bar under
category
\bar default
comes from zlog_get_category() described above.
\end_layout
\begin_layout Standard
zlog() and vzlog()
\emph on
\emph default
produce output according to a
\bar under
format
\bar default
like printf(3) and vprintf(3).
\end_layout
\begin_layout Standard
vzlog()
\emph on
\emph default
is equivalent to zlog(), except that it is called with a va_list instead
of a variable number of arguments.
vzlog() invokes the va_copy macro, the value of
\bar under
args
\bar default
remain unchanged after the call.
See stdarg(3).
\end_layout
\begin_layout Standard
hzlog()
\emph on
\emph default
is a little different, it produce output like this, the hexadecimal representati
on of
\bar under
buf
\emph on
\bar default
\emph default
and output len is
\bar under
buf_len
\end_layout
\begin_layout LyX-Code
hex_buf_len=[5365]
\end_layout
\begin_layout LyX-Code
0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDE
F
\end_layout
\begin_layout LyX-Code
0000000001 23 21 20 2f 62 69 6e 2f 62 61 73 68 0a 0a 23 20 #! /bin/bash..#
\end_layout
\begin_layout LyX-Code
0000000002 74 65 73 74 5f 68 65 78 20 2d 20 74 65 6d 70 6f test_hex
- tempo
\end_layout
\begin_layout LyX-Code
0000000003 72 61 72 79 20 77 72 61 70 70 65 72 20 73 63 72 rary wrapper
scr
\end_layout
\begin_layout Standard
The parameter
\bar under
file
\bar default
and
\bar under
line
\bar default
are usually filled by the __FILE__ and __LINE__ macros.
These indicate where the log event happened.
The parameter
\bar under
func
\bar default
is filled with __func__ or __FUNCTION__, if the compiler supports it, otherwise
it will be filled with "<unknown>".
\end_layout
\begin_layout Standard
\bar under
level
\emph on
\bar default
\emph default
is an int in the current level list, which defaults to:
\end_layout
\begin_layout LyX-Code
typedef enum {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
ZLOG_LEVEL_DEBUG = 20,
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_INFO = 40,
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_NOTICE = 60,
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_WARN = 80,
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_ERROR = 100,
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_FATAL = 120
\end_layout
\end_deeper
\begin_layout LyX-Code
} zlog_level;
\end_layout
\begin_layout Standard
Each fuction has its macros for easy use.
For example,
\end_layout
\begin_layout LyX-Code
#define zlog_fatal(cat, format, args...)
\backslash
\end_layout
\begin_layout LyX-Code
zlog(cat, __FILE__, sizeof(__FILE__)-1,
\backslash
\end_layout
\begin_layout LyX-Code
__func__, sizeof(__func__)-1, __LINE__,
\backslash
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_FATAL, format, ##args)
\end_layout
\begin_layout Standard
The full list of macros is:
\end_layout
\begin_layout LyX-Code
/* zlog macros */
\end_layout
\begin_layout LyX-Code
/* zlog macros */
\end_layout
\begin_layout LyX-Code
zlog_fatal(cat, format, ...)
\end_layout
\begin_layout LyX-Code
zlog_error(cat, format, ...)
\end_layout
\begin_layout LyX-Code
zlog_warn(cat, format, ...)
\end_layout
\begin_layout LyX-Code
zlog_notice(cat, format, ...)
\end_layout
\begin_layout LyX-Code
zlog_info(cat, format, ...)
\end_layout
\begin_layout LyX-Code
zlog_debug(cat, format, ...)
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
/* vzlog macros */
\end_layout
\begin_layout LyX-Code
vzlog_fatal(cat, format, args)
\end_layout
\begin_layout LyX-Code
vzlog_error(cat, format, args)
\end_layout
\begin_layout LyX-Code
vzlog_warn(cat, format, args)
\end_layout
\begin_layout LyX-Code
vzlog_notice(cat, format, args)
\end_layout
\begin_layout LyX-Code
vzlog_info(cat, format, args)
\end_layout
\begin_layout LyX-Code
vzlog_debug(cat, format, args)
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
/* hzlog macros */
\end_layout
\begin_layout LyX-Code
hzlog_fatal(cat, buf, buf_len)
\end_layout
\begin_layout LyX-Code
hzlog_error(cat, buf, buf_len)
\end_layout
\begin_layout LyX-Code
hzlog_warn(cat, buf, buf_len)
\end_layout
\begin_layout LyX-Code
hzlog_notice(cat, buf, buf_len)
\end_layout
\begin_layout LyX-Code
hzlog_info(cat, buf, buf_len)
\end_layout
\begin_layout LyX-Code
hzlog_debug(cat, buf, buf_len)
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
These functions return nothing.
But if anything wrong happens, a detailed error log will be recorded to
the log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
MDC operation
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int zlog_put_mdc(const char *
\bar under
key
\bar default
, const char *
\bar under
value
\bar default
);
\end_layout
\begin_layout LyX-Code
char *zlog_get_mdc(const char *
\bar under
key
\bar default
);
\end_layout
\begin_layout LyX-Code
void zlog_remove_mdc(const char *
\bar under
key
\bar default
);
\end_layout
\begin_layout LyX-Code
void zlog_clean_mdc(void);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
MDC (Mapped Diagnostic Context) is a thread key-value map, and has nothing
to do with category.
\end_layout
\begin_layout Standard
\bar under
key
\bar default
and
\bar under
value
\bar default
are all strings, which should be no longer than MAXLEN_PATH(1024).
If the input is longer than MAXLEN_PATH(1024), the input will be truncated.
\end_layout
\begin_layout Standard
One thing you should remember is that the map bonds to a thread, thus if
you set a key-value pair in one thread, it will not affect other threads.
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
zlog_put_mdc() returns 0 for success, -1 for fail.
zlog_get_mdc() returns a pointer to
\bar under
value
\bar default
for success, NULL for fail or key not exist.
If anything wrong happens, a detailed error log will be recorded to the
log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
dzlog API
\begin_inset CommandInset label
LatexCommand label
name "sec:dzlog-API"
\end_inset
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int dzlog_init(const char *
\bar under
confpath
\bar default
, const char *
\bar under
cname
\bar default
);
\end_layout
\begin_layout LyX-Code
int dzlog_set_category(const char *
\bar under
cname
\bar default
);
\end_layout
\begin_layout LyX-Code
void dzlog(const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
format
\bar default
, ...);
\end_layout
\begin_layout LyX-Code
void vdzlog(const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
format
\bar default
, va_list
\bar under
args
\bar default
);
\end_layout
\begin_layout LyX-Code
void hdzlog(const char *
\bar under
file
\bar default
, size_t
\bar under
filelen
\bar default
,
\end_layout
\begin_layout LyX-Code
const char *
\bar under
func
\bar default
, size_t
\bar under
funclen
\bar default
,
\end_layout
\begin_layout LyX-Code
long
\bar under
line
\bar default
, int
\bar under
level
\bar default
,
\end_layout
\begin_layout LyX-Code
const void *
\bar under
buf
\bar default
, size_t
\bar under
buflen
\bar default
);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
dzlog consists of simple functions that omit
\emph on
zlog_category_t
\emph default
.
It uses a default category internally and puts the category under lock
protection.
It is thread safe also.
Omitting the category means that users need not create, save, or transfer
\emph on
zlog_category_t
\emph default
variables.
Still, you can get and use other category values at the same time through
the normal API for flexibility.
\end_layout
\begin_layout Standard
dzlog_init() is just as zlog_init(), but needs a
\bar under
cname
\bar default
for the internal default category.
zlog_reload() and zlog_fini() can be used as before, to refresh conf_file,
or release all.
\end_layout
\begin_layout Standard
dzlog_set_category()
\emph on
\emph default
is designed for changing the default category.
The last default category is replaced by the new one.
Don't worry about releasing memory since all category allocations will
be cleaned up at zlog_fini().
\end_layout
\begin_layout Standard
Macros are defined in zlog.h.
They are the general way in simple logging.
\end_layout
\begin_layout LyX-Code
dzlog_fatal(format, ...)
\end_layout
\begin_layout LyX-Code
dzlog_error(format, ...)
\end_layout
\begin_layout LyX-Code
dzlog_warn(format, ...)
\end_layout
\begin_layout LyX-Code
dzlog_notice(format, ...)
\end_layout
\begin_layout LyX-Code
dzlog_info(format, ...)
\end_layout
\begin_layout LyX-Code
dezlog_debug(format, ...)
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
vdzlog_fatal(format, args)
\end_layout
\begin_layout LyX-Code
vdzlog_error(format, args)
\end_layout
\begin_layout LyX-Code
vdzlog_warn(format, args)
\end_layout
\begin_layout LyX-Code
vdzlog_notice(format, args)
\end_layout
\begin_layout LyX-Code
vdzlog_info(format, args)
\end_layout
\begin_layout LyX-Code
vdzlog_debug(format, args)
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
hdzlog_fatal(buf, buf_len)
\end_layout
\begin_layout LyX-Code
hdzlog_error(buf, buf_len)
\end_layout
\begin_layout LyX-Code
hdzlog_warn(buf, buf_len)
\end_layout
\begin_layout LyX-Code
hdzlog_noticebuf, buf_len)
\end_layout
\begin_layout LyX-Code
hdzlog_info(buf, buf_len)
\end_layout
\begin_layout LyX-Code
hdzlog_debug(buf, buf_len)
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
On success, dzlog_init() and dzlog_set_category() return zero.
On error, dzlog_init() and dzlog_set_category() return -1, and a detailed
error log will be recorded to the log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
User-defined Output
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
typedef struct zlog_msg_s {
\end_layout
\begin_layout LyX-Code
char *buf;
\end_layout
\begin_layout LyX-Code
size_t len;
\end_layout
\begin_layout LyX-Code
char *path;
\end_layout
\begin_layout LyX-Code
} zlog_msg_t;
\end_layout
\begin_layout LyX-Code
typedef int (*zlog_record_fn)(zlog_msg_t *
\bar under
msg
\bar default
);
\end_layout
\begin_layout LyX-Code
int zlog_set_record(const char *
\bar under
rname
\bar default
, zlog_record_fn
\bar under
record
\bar default
);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
zlog allows a user to define an output function.
The output function bonds to a special kind of rule in configuration file.
A typical rule is:
\end_layout
\begin_layout LyX-Code
*.* $name, "record path %c %d"; simple
\end_layout
\begin_layout Standard
zlog_set_record() does the bonding operation.
Rules with the $
\bar under
rname
\bar default
will be output through user-defined function
\bar under
record
\bar default
.
The callback function has the type of zlog_record_fn.
\end_layout
\begin_layout Standard
The members of struct zlog_msg_t are decribed below:
\end_layout
\begin_layout Standard
\bar under
path
\bar default
comes from the second parameter of rule after $name, which is generated
dynamically like the file path.
\end_layout
\begin_layout Standard
\bar under
buf
\bar default
and
\bar under
len
\bar default
are zlog formatted log message and its length.
\end_layout
\begin_layout Standard
All settings of zlog_set_record() are kept available after zlog_reload().
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
RETURN VALUE
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
On success, zlog_set_record() returns zero.
On error, it returns -1, and a detailed error log will be recorded to the
log file indicated by ZLOG_PROFILE_ERROR.
\end_layout
\end_deeper
\begin_layout Section
debug and profile
\end_layout
\begin_layout Labeling
\labelwidthstring 00.00.0000
SYNOPSIS
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
void zlog_profile(void);
\end_layout
\end_deeper
\begin_layout Labeling
\labelwidthstring 00.00.0000
DESCRIPTION
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Standard
environment variable ZLOG_PROFILE_ERROR indicates zlog's error log path.
\end_layout
\begin_layout Standard
environment variable ZLOG_PROFILE_DEBUG indicates zlog's debug log path.
\end_layout
\begin_layout Standard
zlog_profile() prints all information in memory to zlog's error log file
at runtime.
You can compare it to the configuration file to find possible errors.
\end_layout
\end_deeper
\begin_layout Chapter
Advanced Usage
\end_layout
\begin_layout Section
MDC
\begin_inset CommandInset label
LatexCommand label
name "sec:MDC"
\end_inset
\end_layout
\begin_layout Standard
What is MDC? In log4j it is short for Mapped Diagnostic Context.
That sounds like a complicated terminology.
MDC is just a key-value map.
Once you set it by function, the zlog library will print it to file every
time a log event happens, or become part of log file path.
Let's see an example in $(top_builddir)/test/test_mdc.c.
\end_layout
\begin_layout LyX-Code
$ cat test_mdc.c
\end_layout
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include <stdlib.h>
\end_layout
\begin_layout LyX-Code
#include <sys/types.h>
\end_layout
\begin_layout LyX-Code
#include <unistd.h>
\end_layout
\begin_layout LyX-Code
#include <string.h>
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
zlog_category_t *zc;
\end_layout
\begin_layout LyX-Code
rc = zlog_init("test_mdc.conf");
\end_layout
\begin_layout LyX-Code
if (rc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zc = zlog_get_category("my_cat");
\end_layout
\begin_layout LyX-Code
if (!zc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("get cat fail
\backslash
n");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return -2;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "1.hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_put_mdc("myname", "Zhang");
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "2.hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_put_mdc("myname", "Li");
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "3.hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout Standard
The configure file is
\end_layout
\begin_layout LyX-Code
$ cat test_mdc.conf
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
mdc_format= "%d.%ms %-6V (%c:%F:%L) [%M(myname)] - %m%n"
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
*.* >stdout; mdc_format
\end_layout
\begin_layout Standard
And the output is
\end_layout
\begin_layout LyX-Code
$ ./test_mdc
\end_layout
\begin_layout LyX-Code
2012-03-12 09:26:37.740 INFO (my_cat:test_mdc.c:47) [] - 1.hello, zlog
\end_layout
\begin_layout LyX-Code
2012-03-12 09:26:37.740 INFO (my_cat:test_mdc.c:51) [Zhang] - 2.hello, zlog
\end_layout
\begin_layout LyX-Code
2012-03-12 09:26:37.740 INFO (my_cat:test_mdc.c:55) [Li] - 3.hello, zlog
\end_layout
\begin_layout Standard
You can see zlog_put_mdc() function sets the map with key "myname" and value
"Zhang", and in configuration file
\emph on
%M(myname)
\emph default
indicates where the value shows in each log.
The second time, value of key "myname" is overwritten to "Li", and the
log changes also.
\end_layout
\begin_layout Standard
When should MDC be used? That mainly depends on when a user need to separate
same log action with different scenarios.
For example, in .c
\end_layout
\begin_layout LyX-Code
zlog_put_mdc("customer_name", get_customer_name_from_db() );
\end_layout
\begin_layout LyX-Code
zlog_info("get in");
\end_layout
\begin_layout LyX-Code
zlog_info("pick product");
\end_layout
\begin_layout LyX-Code
zlog_info("pay");
\end_layout
\begin_layout LyX-Code
zlog_info("get out");
\end_layout
\begin_layout Standard
in .conf
\end_layout
\begin_layout LyX-Code
&format "%M(customer_name) %m%n"
\end_layout
\begin_layout Standard
When the program processes two customers at the same time, the output could
be:
\end_layout
\begin_layout LyX-Code
Zhang get in
\end_layout
\begin_layout LyX-Code
Li get in
\end_layout
\begin_layout LyX-Code
Zhang pick product
\end_layout
\begin_layout LyX-Code
Zhang pay
\end_layout
\begin_layout LyX-Code
Li pick product
\end_layout
\begin_layout LyX-Code
Li pay
\end_layout
\begin_layout LyX-Code
Zhang get out
\end_layout
\begin_layout LyX-Code
Li get out
\end_layout
\begin_layout Standard
Now you can distinguish one customer from another, by using grep afterwards
\end_layout
\begin_layout LyX-Code
$ grep Zhang aa.log > Zhang.log
\end_layout
\begin_layout LyX-Code
$ grep Li aa.log >Li.log
\end_layout
\begin_layout Standard
Or, another way is to seperate them to different log file when log action
is taken.
In .conf
\end_layout
\begin_layout LyX-Code
*.* "mdc_%M(customer_name).log";
\end_layout
\begin_layout Standard
It will produce 3 logs
\end_layout
\begin_layout LyX-Code
mdc_.log mdc_Zhang.log mdc_Li.log
\end_layout
\begin_layout Standard
That's a quick way, if you know what you are doing.
\end_layout
\begin_layout Standard
In MDC, the map belongs to a thread and each thread has it's own map.
In one thread zlog_mdc_put() will not affect other thread's map.
Still, if you want to distinguish one thread from another, using the %t
conversion character is enough.
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout Section
Profile zlog Itself
\begin_inset CommandInset label
LatexCommand label
name "sec:Profile-zlog-Itself"
\end_inset
\end_layout
\begin_layout Standard
Until this point we have assumed that the zlog library never fails.
It helps the application to write log entries and to debug the application.
But if zlog itself has some problem, how can we find out? Other programs
debug through the log library so how can a log library debug itself? The
answer is the same, zlog library has its own log.
This profile log is usually closed, and can be opened by setting environment
variables.
\end_layout
\begin_layout LyX-Code
$ export ZLOG_PROFILE_DEBUG=/tmp/zlog.debug.log
\end_layout
\begin_layout LyX-Code
$ export ZLOG_PROFILE_ERROR=/tmp/zlog.error.log
\end_layout
\begin_layout Standard
profile log has just 2 levels, debug and error.
After setting them, run test_hello program in
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Hello-World-Example"
\end_inset
, and the debug log will be
\end_layout
\begin_layout LyX-Code
$ more zlog.debug.log
\end_layout
\begin_layout LyX-Code
03-13 09:46:56 DEBUG (7503:zlog.c:115) ------zlog_init start, compile time[Mar
13 2012 11:28:56]------
\end_layout
\begin_layout LyX-Code
03-13 09:46:56 DEBUG (7503:spec.c:825) spec:[0x7fdf96b7c010][%d(%F %T)][%F
%T 29][]
\end_layout
\begin_layout LyX-Code
03-13 09:46:56 DEBUG (7503:spec.c:825) spec:[0x7fdf96b52010][ ][ 0][]
\end_layout
\begin_layout LyX-Code
......
\end_layout
\begin_layout LyX-Code
03-13 09:52:40 DEBUG (8139:zlog.c:291) ------zlog_fini end------
\end_layout
\begin_layout Standard
zlog.error.log is not created, as no error occurs.
\end_layout
\begin_layout Standard
As you can see, debug log shows how zlog is inited and finished, but no
debug log is written when zlog_info() is executed.
That's for efficency.
\end_layout
\begin_layout Standard
If there is anything wrong with zlog library, all will show in zlog.error.log.
For example, using a wrong printf syntax in zlog()
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "%l", 1);
\end_layout
\begin_layout Standard
Then run the program, the zlog.error.log should be
\end_layout
\begin_layout LyX-Code
$ cat zlog.error.log
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:buf.c:189) vsnprintf fail, errno[0]
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:buf.c:191) nwrite[-1], size_left[1024], format[%l]
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:spec.c:329) zlog_buf_vprintf maybe fail or overflow
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:spec.c:467) a_spec->gen_buf fail
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:format.c:160) zlog_spec_gen_msg fail
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:rule.c:265) zlog_format_gen_msg fail
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:category.c:164) hzb_log_rule_output fail
\end_layout
\begin_layout LyX-Code
03-13 10:04:58 ERROR (10102:zlog.c:632) zlog_output fail, srcfile[test_hello.c],
srcline[41]
\end_layout
\begin_layout Standard
Now, you could find the reason why the expected log doesn't generate, and
fix the wrong printf syntax.
\end_layout
\begin_layout Standard
Runtime profiling causes a loss of efficency.
Normally, I keep ZLOG_PROFILE_ERROR on and ZLOG_PROFILE_DEBUG off in my
environment.
\end_layout
\begin_layout Standard
There is another way to profile the zlog library.
zlog_init() reads the configuration file into memory.
Throughout all log actions, the configure structure remains unchanged.
There is possibility that this memory is damaged by other functions in
an application, or the memory doesn't equal what the configuration file
describes.
So there is a function to show this memory at runtime and print it to ZLOG_PROF
ILE_ERROR.
\end_layout
\begin_layout Standard
see $(top_builddir)/test/test_profile.c
\end_layout
\begin_layout LyX-Code
$ cat test_profile.c
\end_layout
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
rc = dzlog_init("test_profile.conf", "my_cat");
\end_layout
\begin_layout LyX-Code
if (rc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
dzlog_info("hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_profile();
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout Standard
zlog_profile() is the function.
The configuration file is simple
\end_layout
\begin_layout LyX-Code
$ cat test_profile.conf
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
simple = "%m%n"
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.* >stdout; simple
\end_layout
\begin_layout Standard
Then zlog.error.log is
\end_layout
\begin_layout LyX-Code
$ cat /tmp/zlog.error.log
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:zlog.c:783) ------zlog_profile start------
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:zlog.c:784) init_flag:[1]
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:75) -conf[0x2333010]-
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:76) --global--
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:77) ---file[test_profile.conf],mtime[2012-06-01
11:20:44]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:78) ---strict init[1]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:79) ---buffer min[1024]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:80) ---buffer max[2097152]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:82) ---default_format---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:format.c:48) ---format[0x235ef60][default = %d(%F
%T) %V [%p:%F:%L] %m%n(0x233b810)]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:85) ---file perms[0600]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:conf.c:87) ---rotate lock file[/tmp/zlog.lock]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:rotater.c:48) --rotater[0x233b7d0][0x233b7d0,/tmp/zlog.
lock,4]--
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level_list.c:37) --level_list[0x2335490]--
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x23355c0][0,*,*,1,6]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x23375e0][20,DEBUG,debug,5,7]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x2339600][40,INFO,info,4,6]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x233b830][60,NOTICE,notice,6,5]-
--
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x233d850][80,WARN,warn,4,4]---
\end_layout
\begin_layout LyX-Code
06-01 11:21:26 WARN (7063:level.c:37) ---level[0x233fc80][100,ERROR,error,5,3]--
-
\end_layout
\begin_layout Section
User-defined Level
\begin_inset CommandInset label
LatexCommand label
name "sec:User-defined-Level"
\end_inset
\end_layout
\begin_layout Standard
Here are all the steps to define your own levels.
\end_layout
\begin_layout Enumerate
Define levels in the configuration file.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ cat $(top_builddir)/test/test_level.conf
\end_layout
\begin_layout LyX-Code
[global]
\end_layout
\begin_layout LyX-Code
default format = "%V %v %m%n"
\end_layout
\begin_layout LyX-Code
[levels]
\end_layout
\begin_layout LyX-Code
TRACE = 30, LOG_DEBUG
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.TRACE >stdout;
\end_layout
\begin_layout Standard
The internal default levels are (no need to write them in the conf file):
\end_layout
\begin_layout LyX-Code
DEBUG = 20, LOG_DEBUG
\end_layout
\begin_layout LyX-Code
INFO = 40, LOG_INFO
\end_layout
\begin_layout LyX-Code
NOTICE = 60, LOG_NOTICE
\end_layout
\begin_layout LyX-Code
WARN = 80, LOG_WARNING
\end_layout
\begin_layout LyX-Code
ERROR = 100, LOG_ERR
\end_layout
\begin_layout LyX-Code
FATAL = 120, LOG_ALERT
\end_layout
\begin_layout LyX-Code
UNKNOWN = 254, LOG_ERR
\end_layout
\begin_layout Standard
In zlog, an integer(30) and a level string(TRACE) represent a level.
Note that this integer must be in [1,253], any other number is illegal.
Higher numbers are more important.
TRACE is more important than DEBUG(30>20), and less important than INFO(30<40).
After the definition, TRACE can be used in rule of configure file.
This sentence
\end_layout
\begin_layout LyX-Code
my_cat.TRACE >stdout;
\end_layout
\begin_layout Standard
means that level >= TRACE, which is TRACE, INFO, NOTICE, WARN, ERROR, FATAL
will be written to standard output.
\end_layout
\begin_layout Standard
The conversion charactor %V of format string generates the uppercase value
of the level string and %v generates the lowercase value of the level string.
\end_layout
\begin_layout Standard
In the level definition LOG_DEBUG means when using >syslog in a rule, all
TRACE log will output as syslog' s LOG_DEBUG level.
\end_layout
\end_deeper
\begin_layout Enumerate
Using the new log level in source file, the direct way is like this
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
zlog(cat, __FILE__, sizeof(__FILE__)-1,
\backslash
\end_layout
\begin_layout LyX-Code
__func__, sizeof(__func__)-1,__LINE__,
\backslash
\end_layout
\begin_layout LyX-Code
30, "test %d", 1);
\end_layout
\begin_layout Standard
For easy use, create a .h file
\end_layout
\begin_layout LyX-Code
$ cat $(top_builddir)/test/test_level.h
\end_layout
\begin_layout LyX-Code
#ifndef __test_level_h
\end_layout
\begin_layout LyX-Code
#define __test_level_h
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
enum {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
ZLOG_LEVEL_TRACE = 30,
\end_layout
\begin_layout LyX-Code
/* must equals conf file setting */
\end_layout
\end_deeper
\begin_layout LyX-Code
};
\end_layout
\begin_layout LyX-Code
#define zlog_trace(cat, format, ...)
\backslash
\end_layout
\begin_layout LyX-Code
zlog(cat, __FILE__, sizeof(__FILE__)-1,
\backslash
\end_layout
\begin_layout LyX-Code
__func__, sizeof(__func__)-1, __LINE__,
\backslash
\end_layout
\begin_layout LyX-Code
ZLOG_LEVEL_TRACE, format, ## __VA_ARGS__)
\end_layout
\begin_layout LyX-Code
#endif
\end_layout
\end_deeper
\begin_layout Enumerate
Then zlog_trace can be used int .c file
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ cat $(top_builddir)/test/test_level.c
\end_layout
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include "test_level.h"
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
zlog_category_t *zc;
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
rc = zlog_init("test_level.conf");
\end_layout
\begin_layout LyX-Code
if (rc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zc = zlog_get_category("my_cat");
\end_layout
\begin_layout LyX-Code
if (!zc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("get cat fail
\backslash
n");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return -2;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zlog_trace(zc, "hello, zlog - trace");
\end_layout
\begin_layout LyX-Code
zlog_debug(zc, "hello, zlog - debug");
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "hello, zlog - info");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\end_deeper
\begin_layout Enumerate
Now we can see the output
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ ./test_level
\end_layout
\begin_layout LyX-Code
TRACE trace hello, zlog - trace
\end_layout
\begin_layout LyX-Code
INFO info hello, zlog - info
\end_layout
\begin_layout Standard
That's just what we expect.
The configuration file only allows >=TRACE ouput to screen.
And %V and %v work as well.
\end_layout
\end_deeper
\begin_layout Section
User-defined Output
\begin_inset CommandInset label
LatexCommand label
name "sec:User-defined-Output"
\end_inset
\end_layout
\begin_layout Standard
The goal of user-defined output is that zlog gives up some rights.
zlog is only responsible for generating path and message dynamically as
per the user's configuration, but leaves the log output, rotate and cleanup
actions for the user to specify.
You can do what ever you want by setting a function to special rules.
Here are the steps to define your own output function.
\end_layout
\begin_layout Enumerate
Define output in rules of configure file.
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ cat test_record.conf
\end_layout
\begin_layout LyX-Code
[formats]
\end_layout
\begin_layout LyX-Code
simple = "%m%n"
\end_layout
\begin_layout LyX-Code
[rules]
\end_layout
\begin_layout LyX-Code
my_cat.* $myoutput, " mypath %c %d";simple
\end_layout
\end_deeper
\begin_layout Enumerate
Set an output function for myoutput, then use it
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
#include <stdio.h>
\end_layout
\begin_layout LyX-Code
#include "zlog.h"
\end_layout
\begin_layout LyX-Code
int output(zlog_msg_t *msg)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("[mystd]:[%s][%s][%ld]
\backslash
n", msg->path, msg->buf, (long)msg->len);
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
\end_layout
\begin_layout LyX-Code
int main(int argc, char** argv)
\end_layout
\begin_layout LyX-Code
{
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
int rc;
\end_layout
\begin_layout LyX-Code
zlog_category_t *zc;
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
rc = zlog_init("test_record.conf");
\end_layout
\begin_layout LyX-Code
if (rc) {
\end_layout
\begin_layout LyX-Code
printf("init failed
\backslash
n");
\end_layout
\begin_layout LyX-Code
return -1;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zlog_set_record("myoutput", output);
\end_layout
\begin_layout LyX-Code
zc = zlog_get_category("my_cat");
\end_layout
\begin_layout LyX-Code
if (!zc) {
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("get cat fail
\backslash
n");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return -2;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\begin_layout LyX-Code
zlog_info(zc, "hello, zlog");
\end_layout
\begin_layout LyX-Code
zlog_fini();
\end_layout
\begin_layout LyX-Code
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
\end_layout
\end_deeper
\begin_layout Enumerate
Now we can see how the user-defined output() works
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout LyX-Code
$ ./test_record
\end_layout
\begin_layout LyX-Code
[mystd]:[ mypath my_cat 2012-07-19 11:01:12][hello, zlog
\end_layout
\begin_layout LyX-Code
][12]
\end_layout
\begin_layout Standard
As you can see, msglen is 12, and msg is formatted by zlog to contain a
newline character.
\end_layout
\end_deeper
\begin_layout Enumerate
There are many other things you can do with user-defined output functions.
As one user(flw@newsmth.net) provided:
\begin_inset Separator latexpar
\end_inset
\end_layout
\begin_deeper
\begin_layout Enumerate
Log name is foo.log
\end_layout
\begin_layout Enumerate
If foo.log is larger than 100M, then generate a new logfile which contains
all the contents of foo.log.
And zlog truncates foo.log to 0 and re-appends to it when the next log happens.
\end_layout
\begin_layout Enumerate
When the time is over 5 minutes after last logging, even if foo.log is not
larger than 100M, zlog still jumps to a new file.
\end_layout
\begin_layout Enumerate
The new file name should be defined by your own needs.
For example add device number as prefix and time string as postfix.
\end_layout
\begin_layout Enumerate
You might compress the new log file to save disk space and network bandwidth.
\end_layout
\begin_layout Standard
I wish him good luck trying to write such a function for multi-process or
multi-thread cases!
\end_layout
\end_deeper
\begin_layout Chapter
Epilog
\end_layout
\begin_layout Verse
Here's to alcohol, the cause of and solution to all lifes problems.
\end_layout
\begin_layout Right Address
Homer Simpson
\end_layout
\end_body
\end_document