Commit 2c2ac2a0 authored by Hardy Simpson's avatar Hardy Simpson

feature: add record output with dynamic path

parent 9cdc467f
AC_PREREQ(2.59)
AC_INIT([zlog], [1.1.2], [HardySimpson1984@gmail.com])
AC_INIT([zlog], [1.1.3], [HardySimpson1984@gmail.com])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AC_CONFIG_SRCDIR([libzlog/zlog.h])
AC_CONFIG_HEADER([config.h])
......
......@@ -100,7 +100,17 @@ figs-within-sections
\begin_body
\begin_layout Title
zlog使用手册
zlog
\begin_inset Foot
status collapsed
\begin_layout Plain Layout
星星之火,可以燎原——毛泽东
\end_layout
\end_inset
使用手册
\end_layout
\begin_layout Author
......@@ -119,7 +129,16 @@ status collapsed
status collapsed
\begin_layout Plain Layout
有问题,在github上开个issue,或者写邮件到
有问题,在github上
\begin_inset CommandInset href
LatexCommand href
name "开个issue"
target "https://github.com/HardySimpson/zlog/issues/new"
type "mailto:"
\end_inset
,或者写邮件到
\begin_inset CommandInset href
LatexCommand href
name "HardySimpson1984@gmail.com"
......@@ -4437,7 +4456,7 @@ $name
\begin_inset Text
\begin_layout Plain Layout
param
"path" 动态或者静态的用于record输出
\end_layout
\end_inset
......@@ -5816,19 +5835,31 @@ HDZLOG_DEBUG(buf, buf_len)
\begin_deeper
\begin_layout LyX-Code
typedef int (*zlog_record_fn)(char *
\bar under
param
\bar default
, char *
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
, size_t
\bar under
msglen
\bar default
);
);
\end_layout
\begin_layout LyX-Code
......@@ -5855,7 +5886,7 @@ zlog允许用户自定义输出函数。输出函数需要绑定到某条特殊
\end_layout
\begin_layout LyX-Code
*.* $name, param; simple
*.* $name, "record path %c %D"; simple
\end_layout
\begin_layout Standard
......@@ -5867,17 +5898,33 @@ name
\bar under
record
\bar default
。这个函数需要为zlog_record_fn的格式。
。这个函数需要为zlog_record_fn的格式。
\end_layout
\begin_layout Standard
zlog_msg_t结构的各个成员描述如下:
\end_layout
\begin_layout Standard
\bar under
path
\bar default
来自规则的逗号后的字符串,这个字符串会被动态的解析,输出当前的
\bar under
param
path
\bar default
来自规则的逗号后的字符串。
,就像动态文件路径一样。
\end_layout
\begin_layout Standard
\bar under
msg
buf
\bar default
\bar under
msglen
len
\bar default
是zlog格式化后的日志信息和长度。
\end_layout
......@@ -6951,7 +6998,7 @@ simple = "%m%n"
\end_layout
\begin_layout LyX-Code
my_cat.* $myoutput, myparam;simple
my_cat.* $myoutput, " mypath %c %D";simple
\end_layout
\end_deeper
......@@ -6969,7 +7016,7 @@ my_cat.* $myoutput, myparam;simple
\end_layout
\begin_layout LyX-Code
int output(char *str2, char *msg, size_t msg_len)
int output(zlog_msg_t *msg)
\end_layout
\begin_layout LyX-Code
......@@ -7093,7 +7140,11 @@ return 0;
\begin_deeper
\begin_layout LyX-Code
[mystd]:[myparam][hello, zlog
$ ./test_record
\end_layout
\begin_layout LyX-Code
[mystd]:[ mypath my_cat 2012-07-19 12:23:08][hello, zlog
\end_layout
\begin_layout LyX-Code
......@@ -7105,5 +7156,47 @@ return 0;
\end_layout
\end_deeper
\begin_layout Enumerate
用户自定义输出可以干很多神奇的事情,就像某个用户(flw@newsmth.net)的需求
\end_layout
\begin_deeper
\begin_layout Enumerate
日志文件名为 foo.log
\end_layout
\begin_layout Enumerate
如果 foo.log 超过 100M,则生成一个新文件,其中包含的就是 foo.log 目前的内容 而 foo.log 则变为空,重新开始增长
\end_layout
\begin_layout Enumerate
如果距离上次生成文件时已经超过 5 分钟,则即使不到 100M,也应当生成一个新文件
\end_layout
\begin_layout Enumerate
新文件名称可以自定义,比如加上设备名作为前缀、日期时间串作为后缀
\end_layout
\begin_layout Enumerate
我希望这个新文件可以被压缩,以节省磁盘空间或者网络带宽。
\end_layout
\begin_layout Standard
但愿他能顺利写出这个需求的代码!在多进程或者多线程的情况下!上帝保佑他!
\end_layout
\end_deeper
\begin_layout Chapter
尾声
\end_layout
\begin_layout Standard
好酒!所有人生问题的终极起源和终极答案。
\end_layout
\begin_layout Right Address
荷马.辛普森
\end_layout
\end_body
\end_document
......@@ -77,7 +77,17 @@ figs-within-sections
\begin_body
\begin_layout Title
zlog User's Guide
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
......@@ -86,7 +96,7 @@ by Hardy Simpson
status collapsed
\begin_layout Plain Layout
This Guide is for zlog v1.0.x
This Guide is for zlog v1.1.x
\end_layout
\end_inset
......@@ -96,8 +106,15 @@ This Guide is for zlog v1.0.x
status collapsed
\begin_layout Plain Layout
If you have comments or error corrections, post a issue on github, or write
email to
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"
\end_inset
on github, or write email to
\begin_inset CommandInset href
LatexCommand href
name "HardySimpson1984@gmail.com"
......@@ -4668,7 +4685,7 @@ $name
\begin_inset Text
\begin_layout Plain Layout
param of record function
"path" (dynamic or static) of record function
\end_layout
\end_inset
......@@ -6142,19 +6159,31 @@ SYNOPSIS
\begin_deeper
\begin_layout LyX-Code
typedef int (*zlog_record_fn)(char *
\bar under
param
\bar default
, char *
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
, size_t
\bar under
msglen
\bar default
);
);
\end_layout
\begin_layout LyX-Code
......@@ -6183,7 +6212,7 @@ zlog allows user defines his own output function.
\end_layout
\begin_layout LyX-Code
*.* $name, param; simple
*.* $name, "record path %c %D"; simple
\end_layout
\begin_layout Standard
......@@ -6199,17 +6228,30 @@ record
.
The function has the type of zlog_record_fn.
\end_layout
\begin_layout Standard
The member of struct zlog_msg_t is decribed below:
\end_layout
\begin_layout Standard
\bar under
param
path
\bar default
comes from rule.
comes from the second parm of rule after $name, which is dynamiclly generated
like dynamic file path.
\end_layout
\begin_layout Standard
\bar under
msg
buf
\bar default
and
\bar under
msglen
len
\bar default
are zlog formated log message and its length.
\end_layout
......@@ -7305,7 +7347,13 @@ name "sec:User-defined-Output"
\end_layout
\begin_layout Standard
Here I write down all steps of how user define own output function.
The goal of user-defined output is that zlog gives up all its right.
zlog is responsible for generate path and message dynamiclly as user's
configure, bug leaves the way of how log is output and rotate for user's
desire.
You can do what ever you want by set a function to special rules.
Here I write down all steps of how user define own output function.
\end_layout
\begin_layout Enumerate
......@@ -7330,7 +7378,7 @@ simple = "%m%n"
\end_layout
\begin_layout LyX-Code
my_cat.* $myoutput, myparam;simple
my_cat.* $myoutput, " mypath %c %D";simple
\end_layout
\end_deeper
......@@ -7348,27 +7396,27 @@ set a ouput function for myoutput, then using it
\end_layout
\begin_layout LyX-Code
int output(char *str2, char *msg, size_t msg_len)
int output(zlog_msg_t *msg)
\end_layout
\begin_layout LyX-Code
{
{
\end_layout
\begin_deeper
\begin_layout LyX-Code
printf("[mystd]:[%s][%s][%ld]
\backslash
n", str2, msg, (long)msg_len);
n", msg->path, msg->buf, (long)msg->len);
\end_layout
\begin_layout LyX-Code
return 0;
return 0;
\end_layout
\end_deeper
\begin_layout LyX-Code
}
}
\end_layout
\begin_layout LyX-Code
......@@ -7472,7 +7520,11 @@ Now we can see the user-defined output() works!
\begin_deeper
\begin_layout LyX-Code
[mystd]:[myparam][hello, zlog
$ ./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
......@@ -7485,5 +7537,55 @@ As you can see, msglen is 12, and msg formated by zlog contains a newline
\end_layout
\end_deeper
\begin_layout Enumerate
There are many miraculous things you can do with user-defined output functions.
As one user(flw@newsmth.net)'s desire
\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 truncate foo.log to 0 and re-append to it when 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 his own needs.
For example add device no as prefix and time string for postfix.
\end_layout
\begin_layout Enumerate
I hope the new logfile can be compressed, to save disk space and network
bandwidth.
\end_layout
\begin_layout Standard
I wish him good luck for writing such a function in case of multi-process
or multi-threads! God bless him!
\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
......@@ -26,4 +26,8 @@ default.* >stdout; simple
my_.INFO >stderr;
my_cat.!ERROR "/var/log/aa.log"
my_dog.=DEBUG >syslog, LOG_LOCAL0; simple
my_mice.* $user_define_str1 , user_define_str2 ; normal
my_mice.* $record_func , "record_path%c"; normal
......@@ -23,8 +23,13 @@
#include "zc_defs.h"
/* record is user-defined output function and it's name from configure file */
typedef struct zlog_msg_s {
char *buf;
size_t len;
char *path;
} zlog_msg_t; /* 3 of this first, see need thread or not later */
typedef int (*zlog_record_fn)(char *param, char *msg, size_t msg_len);
typedef int (*zlog_record_fn)(zlog_msg_t * msg);
typedef struct zlog_record_s {
char name[MAXLEN_PATH + 1];
......
......@@ -62,7 +62,7 @@ void zlog_rule_profile(zlog_rule_t * a_rule, int flag)
a_rule->syslog_facility,
a_rule->record_name,
a_rule->record_param,
a_rule->record_path,
a_rule->record_output,
a_rule->format);
......@@ -178,33 +178,28 @@ static int zlog_rule_output_static_file_rotate(zlog_rule_t * a_rule, zlog_thread
/* return path success
* return NULL fail
*/
static int zlog_rule_gen_path(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
{
int i;
zlog_spec_t *a_spec;
zlog_buf_restart(a_thread->path_buf);
zc_arraylist_foreach(a_rule->dynamic_file_specs, i, a_spec) {
if (zlog_spec_gen_path(a_spec, a_thread)) {
zc_error("zlog_spec_gen_path fail");
return -1;
}
}
zlog_buf_seal(a_thread->path_buf); /* path must end with \0 */
return 0;
}
#define zlog_rule_gen_path(a_rule, a_thread) do { \
int i; \
zlog_spec_t *a_spec; \
\
zlog_buf_restart(a_thread->path_buf); \
\
zc_arraylist_foreach(a_rule->dynamic_file_specs, i, a_spec) { \
zc_error("%d", i); \
if (zlog_spec_gen_path(a_spec, a_thread)) { \
zc_error("zlog_spec_gen_path fail"); \
return -1; \
} \
} \
\
zlog_buf_seal(a_thread->path_buf); \
} while(0)
static int zlog_rule_output_dynamic_file_single(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
{
int fd;
if (zlog_rule_gen_path(a_rule, a_thread)) {
zc_error("zlog_rule_gen_path fail");
return -1;
}
zlog_rule_gen_path(a_rule, a_thread);
if (zlog_format_gen_msg(a_rule->format, a_thread)) {
zc_error("zlog_format_output fail");
......@@ -242,10 +237,7 @@ static int zlog_rule_output_dynamic_file_rotate(zlog_rule_t * a_rule, zlog_threa
int fd;
size_t len;
if (zlog_rule_gen_path(a_rule, a_thread)) {
zc_error("zlog_rule_gen_path fail");
return -1;
}
zlog_rule_gen_path(a_rule, a_thread);
if (zlog_format_gen_msg(a_rule->format, a_thread)) {
zc_error("zlog_format_output fail");
......@@ -309,24 +301,57 @@ static int zlog_rule_output_syslog(zlog_rule_t * a_rule, zlog_thread_t * a_threa
return 0;
}
static int zlog_rule_output_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
static int zlog_rule_output_static_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
{
zlog_msg_t msg;
if (!a_rule->record_output) {
zc_error("user defined record funcion for [%s] not set, no output",
a_rule->record_name);
return -1;
}
if (zlog_format_gen_msg(a_rule->format, a_thread)) {
zc_error("zlog_format_gen_msg fail");
return -1;
}
zlog_buf_seal(a_thread->msg_buf);
if (a_rule->record_output) {
zlog_buf_seal(a_thread->msg_buf);
if (a_rule->record_output(a_rule->record_param,
zlog_buf_str(a_thread->msg_buf),
zlog_buf_len(a_thread->msg_buf))) {
zc_error("a_rule->record fail");
return -1;
}
} else {
zc_error("user defined record funcion for [%s,%s] not set, no output",
a_rule->record_name, a_rule->record_param);
msg.buf = zlog_buf_str(a_thread->msg_buf);
msg.len = zlog_buf_len(a_thread->msg_buf);
msg.path = a_rule->record_path;
if (a_rule->record_output(&msg)) {
zc_error("a_rule->record fail");
return -1;
}
return 0;
}
static int zlog_rule_output_dynamic_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread)
{
zlog_msg_t msg;
if (!a_rule->record_output) {
zc_error("user defined record funcion for [%s] not set, no output",
a_rule->record_name);
return -1;
}
zlog_rule_gen_path(a_rule, a_thread);
if (zlog_format_gen_msg(a_rule->format, a_thread)) {
zc_error("zlog_format_gen_msg fail");
return -1;
}
zlog_buf_seal(a_thread->msg_buf);
msg.buf = zlog_buf_str(a_thread->msg_buf);
msg.len = zlog_buf_len(a_thread->msg_buf);
msg.path = zlog_buf_str(a_thread->path_buf);
if (a_rule->record_output(&msg)) {
zc_error("a_rule->record fail");
return -1;
}
return 0;
......@@ -695,8 +720,61 @@ zlog_rule_t *zlog_rule_new(char *line,
break;
case '$' :
sscanf(file_path + 1, "%s", a_rule->record_name);
sscanf(file_limit, " %[^; ]", a_rule->record_param);
a_rule->output = zlog_rule_output_record;
p = strchr(file_limit, '"');
if (!p) {
zc_error("record_path not start with \", [%s]", file_limit);
goto err;
}
p++; /* skip 1st " */
q = strrchr(p, '"');
if (!q) {
zc_error("matching \" not found in conf line[%s]", p);
goto err;
}
len = q - p;
if (len > sizeof(a_rule->record_path) - 1) {
zc_error("record_path too long %ld > %ld", len, sizeof(a_rule->record_path) - 1);
goto err;
}
memcpy(a_rule->record_path, p, len);
/* replace any environment variables like %E(HOME) */
rc = zc_str_replace_env(a_rule->record_path, sizeof(a_rule->record_path));
if (rc) {
zc_error("zc_str_replace_env fail");
goto err;
}
/* try to figure out if the log file path is dynamic or static */
if (strchr(a_rule->record_path, '%'