8540 lines
165 KiB
Plaintext
8540 lines
165 KiB
Plaintext
#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 life’s problems.
|
||
|
||
\end_layout
|
||
|
||
\begin_layout Right Address
|
||
Homer Simpson
|
||
\end_layout
|
||
|
||
\end_body
|
||
\end_document
|