├── INSTALL ├── cpack ├── zlog │ ├── prerm │ ├── preinst │ ├── postinst │ ├── postrm │ └── CMakeLists.txt ├── CMakeLists.txt └── CPackConfig.cmake ├── src ├── version.h ├── zlog-chk-conf.1 ├── zc_defs.h ├── zc_util.h ├── record_table.h ├── level.h ├── fmacros.h ├── format.h ├── record.h ├── level_list.h ├── category_table.h ├── mdc.h ├── lockfile.h ├── thread.h ├── conf.h ├── Makefile.am ├── category.h ├── rotater.h ├── zc_arraylist.h ├── record.c ├── zlog-chk-conf.c ├── zc_profile.h ├── record_table.c ├── lockfile.c ├── spec.h ├── CMakeLists.txt ├── zc_xplatform.h ├── buf.h ├── zc_hashtable.h ├── zlog_win.c ├── rule.h ├── event.h ├── zc_profile.c ├── zc_util.c ├── zlog_win.h ├── zc_arraylist.c ├── mdc.c ├── level.c ├── category_table.c ├── level_list.c ├── format.c ├── thread.c ├── event.c ├── category.c ├── zc_hashtable.c ├── makefile └── zlog.h ├── tools ├── Makefile.am └── mk_targz.sh ├── test ├── test_hex.conf ├── test_default.conf ├── test_profile.conf ├── test_record.conf ├── test_pipe.conf ├── test_category.conf ├── test_mdc.conf ├── test_enabled.conf ├── test_level.conf ├── test_leak.2.conf ├── val.sh ├── test_hello.conf ├── test_init.conf ├── test_init.2.conf ├── test_prompt.conf ├── test_longlog.conf ├── test_leak.conf ├── test_tmp.conf ├── test_syslog.conf ├── test_press_zlog2.conf ├── test_default.c ├── test_multithread.conf ├── test_profile.c ├── Makefile.am ├── fuzzers │ └── zlog_init_fuzzer.c ├── test_press_zlog.conf ├── test_pipe.c ├── test_hello.c ├── test_syslog.c ├── test_level.c ├── makefile ├── test_record.c ├── test_conf.c ├── test_category.c ├── test_tmp.c ├── test_conf2.c ├── test_mdc.c ├── test_enabled.c ├── test_bitmap.c ├── test_prompt.c ├── test_conf2.conf.h ├── test_leak.c ├── test_init.c ├── test_level.h ├── test_press_syslog.c ├── test_conf.conf ├── test_enabled.h ├── test_longlog.c ├── test_hashtable.c ├── CMakeLists.txt ├── test_press_zlog.c ├── test_press_zlog2.c ├── test_press_write2.c ├── test_press_write.c ├── test_hex.c ├── test_buf.c └── test_multithread.c ├── Makefile.am ├── TODO ├── makefile ├── doc ├── makefile ├── Makefile.am ├── zlog.conf ├── performence.txt ├── GettingStart-CN.txt └── GettingStart-EN.txt ├── cmake ├── LoadLibraries.cmake ├── FindUnixem.cmake └── toolchain-mingw64.cmake ├── .gitignore ├── zlog.spec ├── autogen.sh ├── configure.ac ├── CMakeLists.txt ├── Changelog └── README.md /INSTALL: -------------------------------------------------------------------------------- 1 | README.md -------------------------------------------------------------------------------- /cpack/zlog/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | -------------------------------------------------------------------------------- /cpack/zlog/preinst: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | #define ZLOG_VERSION "1.2.12" 2 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = mk_targz.sh 2 | -------------------------------------------------------------------------------- /test/test_hex.conf: -------------------------------------------------------------------------------- 1 | [rules] 2 | *.* "hex.log"; 3 | -------------------------------------------------------------------------------- /cpack/zlog/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ldconfig 4 | 5 | -------------------------------------------------------------------------------- /test/test_default.conf: -------------------------------------------------------------------------------- 1 | [rules] 2 | my_cat.* >stdout 3 | -------------------------------------------------------------------------------- /cpack/zlog/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ldconfig 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/test_profile.conf: -------------------------------------------------------------------------------- 1 | [formats] 2 | simple="%m%n" 3 | [rules] 4 | my_cat.* >stdout; simple 5 | -------------------------------------------------------------------------------- /test/test_record.conf: -------------------------------------------------------------------------------- 1 | [formats] 2 | simple = "%m%n" 3 | [rules] 4 | my_cat.* $myoutput, " mypath %c %d";simple 5 | -------------------------------------------------------------------------------- /test/test_pipe.conf: -------------------------------------------------------------------------------- 1 | [formats] 2 | simple = "%m%n" 3 | [rules] 4 | my_cat.* |/usr/bin/cronolog test_pipe_%Y%m%d.log; 5 | -------------------------------------------------------------------------------- /test/test_category.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | default format = "%V %v %m%n" 3 | [rules] 4 | my_cat.* >stdout; 5 | my-cat.* >stdout; 6 | -------------------------------------------------------------------------------- /test/test_mdc.conf: -------------------------------------------------------------------------------- 1 | [formats] 2 | mdc_format= "%d(%F %X.%ms) %-6V (%c:%F:%L) [%M(myname)] - %m%n" 3 | [rules] 4 | *.* >stdout; mdc_format 5 | -------------------------------------------------------------------------------- /test/test_enabled.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | default format = "%V %v %m%n" 3 | [levels] 4 | TRACE = 30, LOG_DEBUG 5 | [rules] 6 | my_cat.TRACE >stdout; 7 | -------------------------------------------------------------------------------- /test/test_level.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | default format = "%V %v %m%n" 3 | [levels] 4 | TRACE = 30, LOG_DEBUG 5 | [rules] 6 | my_cat.TRACE >stdout; 7 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | SUBDIRS = doc src tools test 3 | dist_doc_DATA = COPYING INSTALL README.md TODO 4 | EXTRA_DIST = autogen.sh 5 | -------------------------------------------------------------------------------- /test/test_leak.2.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min = 100 4 | buffer max = 200 5 | default format = "%m%n" 6 | 7 | [rules ] 8 | *.* >stdout; 9 | -------------------------------------------------------------------------------- /test/val.sh: -------------------------------------------------------------------------------- 1 | unset ZLOG_PROFILE_ERROR 2 | unset ZLOG_PROFILE_DEBUG_LOG 3 | 4 | rm -f press*log 5 | 6 | valgrind --tool=callgrind ./test_press_zlog 1 10 10000 7 | -------------------------------------------------------------------------------- /test/test_hello.conf: -------------------------------------------------------------------------------- 1 | [formats] 2 | simple = "%d.%ms %m%n" 3 | simple2 = "%d.%us %m%n" 4 | [rules] 5 | my_cat.* >stderr; 6 | my_cat.* >stdout;simple 7 | my_cat.* >stdout;simple2 8 | -------------------------------------------------------------------------------- /test/test_init.conf: -------------------------------------------------------------------------------- 1 | [ global ] 2 | strict init = true 3 | buffer min = 1024 4 | buffer max = 2MB 5 | rotate lock file= /tmp/zlog.lock 6 | 7 | [ rules ] 8 | my_cat.* >stderr; 9 | -------------------------------------------------------------------------------- /test/test_init.2.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | buffer min = 2048 3 | buffer max = 4096 4 | default format = "%V %m%n" 5 | [levels] 6 | TEST = 40, LOG_INFO 7 | 8 | 9 | [formats] 10 | simple = "%m%n" 11 | [rules] 12 | my_cat.* >stderr; 13 | -------------------------------------------------------------------------------- /test/test_prompt.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min = 1024 4 | buffer max = 0 5 | 6 | [formats] 7 | simple = "%r%d %V %m%n" 8 | prompt = "%r%d(%T)>%m" 9 | 10 | [rules ] 11 | !.* >stdout;simple 12 | prompt.* >stdout;prompt 13 | -------------------------------------------------------------------------------- /test/test_longlog.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | #buffer min = 1024 4 | #buffer max = 0 5 | rotate lock file = /tmp/zlog.lock 6 | 7 | [formats] 8 | simple = "%d %V %m%n" 9 | simple2 = "%d %V %m%n" 10 | 11 | [rules ] 12 | *.* "test_longlog.log" 13 | -------------------------------------------------------------------------------- /test/test_leak.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min = 2048 4 | buffer max = 4096 5 | rotate lock file = /tmp/zlog.lock 6 | default format = "%d(%F %T).%ms %-6V (%c:%F:%L) - %m%n" 7 | 8 | [ levels ] 9 | TEST = 40, LOG_INFO 10 | 11 | [rules ] 12 | *.* >stderr; 13 | -------------------------------------------------------------------------------- /test/test_tmp.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min = 1024 4 | buffer max = 0 5 | rotate lock file = /tmp/zlog.lock 6 | 7 | [formats] 8 | simple = "%d %V %m%n" 9 | simple2 = "%d %V %m%n" 10 | 11 | [rules ] 12 | *.=debug >stdout;simple 13 | *.=info >stdout;simple2 14 | -------------------------------------------------------------------------------- /src/zlog-chk-conf.1: -------------------------------------------------------------------------------- 1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.10. 2 | .TH ZLOG-CHK-CONF: "1" "" "zlog logging library" "User Commands" 3 | .SH NAME 4 | zlog-chk-conf 5 | .SH DESCRIPTION 6 | zlog\-chk\-conf [conf files]... 7 | .TP 8 | \fB\-q\fR, 9 | suppress non\-error message 10 | .TP 11 | \fB\-h\fR, 12 | show help message 13 | .PP 14 | -------------------------------------------------------------------------------- /test/test_syslog.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min= 1024 4 | buffer max= 2MB 5 | rotate lock file = /tmp/zlog.lock 6 | default format = "default - %d(%F %X.%ms) %-6V (%c:%F:%U:%L) - %m%n" 7 | 8 | [formats] 9 | null = "%n" 10 | print = "print - [%-10.3d(%F)]%n" 11 | 12 | simple = "simple - %m%n" 13 | 14 | [rules] 15 | *.* >syslog , LOG_LOCAL0 16 | my_cat.* >stdout;simple 17 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | [p] 使用valgrind测试性能 2 | [ ] 更好的错误展现,当系统出问题的时候直接报错 3 | [ ] hzlog的可定制 4 | [ ] hex那段重写,内置到buf内,参考od的设计 5 | [ ] 分类匹配的可定制化, rcat 6 | [ ] 自行管理文件缓存,替代stdio 7 | [ ] 减少dynamic文件名open的次数,通过日期改变智能推断, file_table? 8 | [ ] async file输出的增加 9 | [ ] 兼容性问题 zlog.h内 10 | [ ] 增加trace级别 11 | [ ] gettid() 12 | [ ] 性能对比, log4x, pantheios, glog 13 | [ ] perl, python, go, c++支持 14 | [ ] redis对接,协议设计 15 | [ ] 和rsyslog对接的问题 16 | [x] linux fsync->fdatasync, open.. 17 | 18 | -------------------------------------------------------------------------------- /src/zc_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zc_defs_h 10 | #define __zc_defs_h 11 | 12 | #include "zc_profile.h" 13 | #include "zc_arraylist.h" 14 | #include "zc_hashtable.h" 15 | #include "zc_xplatform.h" 16 | #include "zc_util.h" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /test/test_press_zlog2.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | default format = "%d.%us %-6V %p:%T:%F:%L %m%n" 3 | 4 | [rules] 5 | cat0.* "press.0.log" 6 | cat1.* "press.1.log" 7 | cat2.* "press.2.log" 8 | cat3.* "press.3.log" 9 | cat4.* "press.4.log" 10 | cat5.* "press.5.log" 11 | cat6.* "press.6.log" 12 | cat7.* "press.7.log" 13 | cat8.* "press.8.log" 14 | cat9.* "press.9.log" 15 | -------------------------------------------------------------------------------- /src/zc_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | #ifndef __zc_util_h 9 | #define __zc_util_h 10 | 11 | size_t zc_parse_byte_size(char *astring); 12 | int zc_str_replace_env(char *str, size_t str_size); 13 | 14 | #define zc_max(a,b) ((a) > (b) ? (a) : (b)) 15 | #define zc_min(a,b) ((a) < (b) ? (a) : (b)) 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/record_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_record_table_h 10 | #define __zlog_record_table_h 11 | 12 | #include "zc_defs.h" 13 | #include "record.h" 14 | 15 | zc_hashtable_t *zlog_record_table_new(void); 16 | void zlog_record_table_del(zc_hashtable_t * records); 17 | void zlog_record_table_profile(zc_hashtable_t * records, int flag); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tools/mk_targz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$1" = "" ] 4 | then 5 | echo "Usage: mk_targz.sh " 6 | echo "Example: mk_targz.sh 1.2.7" 7 | exit 1 8 | fi 9 | 10 | if [ ! -d .git ] 11 | then 12 | echo "Must run at git home directory" 13 | exit 2 14 | fi 15 | 16 | HASH=`git show-ref --hash=8 refs/tags/${1}` 17 | PREFIX="zlog-${1}-${HASH}/" 18 | TARBALL="/tmp/zlog-${1}-${HASH}.tar.gz" 19 | git archive --format=tar -v --prefix=$PREFIX $1 | gzip -c > $TARBALL 20 | cp ${TARBALL} /tmp/zlog-latest-stable.tar.gz 21 | echo "File created: $TARBALL" 22 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | # Top level makefile, the real shit is at src/makefile 2 | 3 | TARGETS=noopt 32bit 4 | 5 | all: 6 | cd src && $(MAKE) $@ 7 | 8 | install: 9 | cd src && $(MAKE) $@ 10 | 11 | $(TARGETS): 12 | cd src && $(MAKE) $@ 13 | 14 | doc: 15 | cd doc && $(MAKE) 16 | 17 | test: 18 | cd test && $(MAKE) 19 | 20 | TAGS: 21 | find . -type f -name "*.[ch]" | xargs etags - 22 | 23 | clean: 24 | cd src && $(MAKE) $@ 25 | cd test && $(MAKE) $@ 26 | cd doc && $(MAKE) $@ 27 | rm -f TAGS 28 | 29 | distclean: clean 30 | 31 | dummy: 32 | 33 | .PHONY: doc install test TAGS 34 | -------------------------------------------------------------------------------- /test/test_default.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | 16 | rc = dzlog_init("test_default.conf", "my_cat"); 17 | if (rc) { 18 | printf("init failed\n"); 19 | return -1; 20 | } 21 | 22 | dzlog_info("hello, zlog"); 23 | 24 | zlog_fini(); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /doc/makefile: -------------------------------------------------------------------------------- 1 | doc = \ 2 | UsersGuide-EN.pdf \ 3 | UsersGuide-CN.pdf \ 4 | UsersGuide-EN.tex \ 5 | UsersGuide-CN.tex \ 6 | UsersGuide-EN.html \ 7 | UsersGuide-CN.html \ 8 | GettingStart-EN.txt \ 9 | GettingStart-CN.txt 10 | 11 | all : $(doc) 12 | 13 | UsersGuide-EN.pdf : UsersGuide-EN.lyx 14 | lyx -f -e pdf2 $^ 15 | 16 | UsersGuide-CN.pdf : UsersGuide-CN.lyx 17 | lyx -f -e pdf4 $^ 18 | 19 | %.tex : %.lyx 20 | lyx -f -e pdflatex $< 21 | 22 | %.html : %.tex 23 | hevea book.hva -s $< 24 | hevea book.hva -s $< 25 | 26 | clean : 27 | -rm -f *.pdf *.haux *.html *.htoc *.tex *.lyx~ 28 | -------------------------------------------------------------------------------- /test/test_multithread.conf: -------------------------------------------------------------------------------- 1 | [levels] 2 | TRACE = 10, LOG_DEBUG 3 | SECURITY = 150, LOG_ALERT 4 | [formats] 5 | simple = "%d(%m%d%H%M%S).%us %-6c %-10V [%06k] %m%n" 6 | security = "%d(%m%d%H%M%S).%us %-6c [%-8V] %m%n" 7 | developer = "%d(%m%d%H%M%S).%us %-6c %-10V [%t] %F(%L)/%U() - %m%n" 8 | csv = "%d.%ms;%m%n [%08t] [%T] [%06k] " 9 | [rules] 10 | clsn.ERROR >stdout; developer 11 | high.ERROR >stdout; security 12 | main.* >stdout; simple 13 | main.* "./test_multithread-logs.txt"; simple 14 | thrd.* "./test_multithread-logs/threadslog.csv", 20KB * 30 ~ "./test_multithread-logs/threadslog#r.csv"; csv 15 | -------------------------------------------------------------------------------- /test/test_profile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | 16 | rc = dzlog_init("test_profile.conf", "my_cat"); 17 | if (rc) { 18 | printf("init failed\n"); 19 | return -1; 20 | } 21 | 22 | dzlog_info("hello, zlog"); 23 | 24 | zlog_profile(); 25 | 26 | zlog_fini(); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | LDADD = $(top_builddir)/src/libzlog.la 2 | AM_CFLAGS = -I$(top_srcdir)/src 3 | test_level_SOURCES = test_level.c test_level.h 4 | check_PROGRAMS = test_bitmap \ 5 | test_buf \ 6 | test_conf \ 7 | test_default \ 8 | test_enabled \ 9 | test_hashtable \ 10 | test_hello \ 11 | test_hex \ 12 | test_init \ 13 | test_leak \ 14 | test_level \ 15 | test_mdc \ 16 | test_pipe \ 17 | test_press_syslog \ 18 | test_press_write2 \ 19 | test_press_write \ 20 | test_press_zlog2 \ 21 | test_press_zlog \ 22 | test_profile \ 23 | test_record \ 24 | test_syslog \ 25 | test_tmp 26 | 27 | EXTRA_DIST = *.conf 28 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | if HAVE_LYX 2 | LYX_PDFS = \ 3 | UsersGuide-EN.pdf \ 4 | UsersGuide-CN.pdf 5 | 6 | UsersGuide-EN.pdf : UsersGuide-EN.lyx 7 | lyx -f -e pdf2 $^ 8 | 9 | UsersGuide-CN.pdf : UsersGuide-CN.lyx 10 | lyx -f -e pdf4 $^ 11 | 12 | %.tex : %.lyx 13 | lyx -f -e pdflatex $< 14 | endif 15 | 16 | if HAVE_HEVEA 17 | LYX_HTML = \ 18 | UsersGuide-EN.html \ 19 | UsersGuide-CN.html 20 | 21 | %.html : %.tex 22 | hevea book.hva -s $< 23 | hevea book.hva -s $< 24 | endif 25 | 26 | dist_doc_DATA = GettingStart-CN.txt \ 27 | GettingStart-EN.txt \ 28 | performence.txt \ 29 | zlog.conf \ 30 | $(LYX_PDFS) \ 31 | $(LYX_HTML) 32 | -------------------------------------------------------------------------------- /test/fuzzers/zlog_init_fuzzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "zlog.h" 5 | 6 | int 7 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) 8 | { 9 | char filename[256]; 10 | sprintf(filename, "/tmp/libfuzzer.%d", getpid()); 11 | 12 | FILE *fp = fopen(filename, "wb"); 13 | if (!fp) 14 | return 0; 15 | fwrite(data, size, 1, fp); 16 | fclose(fp); 17 | 18 | int rc = zlog_init(filename); 19 | if (rc == 0) 20 | { 21 | zlog_fini(); 22 | } 23 | unlink(filename); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /test/test_press_zlog.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | #default format = "%d(%F %T).%us %-6V %p:%T:%F:%L %m%n" 3 | 4 | default format = "%d.%us %-6V %p:%T:%F:%L %m%n" 5 | 6 | [rules] 7 | # time ./test_press_zlog 1 10 100000 real user sys 8 | 9 | #*.* | /usr/bin/cronolog press%Y%m%d.log #1.632s 2.010s 1.100s 10 | *.* "press.log" #2.364s 2.090s 2.460s 11 | #*.* "press.log",10M #4.644s 2.540s 6.260s 12 | #*.* "press%d(%Y%m%d).log" #4.132s 2.910s 5.030s 13 | #*.* "press%d(%Y%m%d).log",1M*5 #4.713s 2.740s 6.310s 14 | #*.* "press.%d(%F).log",1MB ~ "press.#2r.log"#4.730s 2.690s 6.360s 15 | -------------------------------------------------------------------------------- /test/test_pipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_pipe.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | zlog_info(zc, "hello, zlog"); 31 | zlog_fini(); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /src/level.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_level_h 10 | #define __zlog_level_h 11 | 12 | #include "zc_defs.h" 13 | 14 | typedef struct zlog_level_s { 15 | int int_level; 16 | char str_uppercase[MAXLEN_PATH + 1]; 17 | char str_lowercase[MAXLEN_PATH + 1]; 18 | size_t str_len; 19 | int syslog_level; 20 | } zlog_level_t; 21 | 22 | zlog_level_t *zlog_level_new(char *line); 23 | void zlog_level_del(zlog_level_t *a_level); 24 | void zlog_level_profile(zlog_level_t *a_level, int flag); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /cmake/LoadLibraries.cmake: -------------------------------------------------------------------------------- 1 | #======================================================= 2 | # 支持多线程 3 | # 对于需要多线程的库,使用以下命令包含连接库: 4 | # target_link_libraries(xxx ${CMAKE_THREAD_PREFER_PTHREAD}) 5 | #======================================================= 6 | if(Need_THREAD) 7 | find_package(Threads REQUIRED) 8 | if(NOT CMAKE_THREAD_PREFER_PTHREAD) 9 | set(CMAKE_THREAD_PREFER_PTHREAD ${CMAKE_THREAD_LIBS_INIT}) 10 | endif() 11 | message(STATUS "thread lib : ${CMAKE_THREAD_PREFER_PTHREAD}") 12 | endif(Need_THREAD) 13 | 14 | if(Need_UNIXEM) 15 | find_package(Unixem) 16 | if (NOT UNIXEM_FOUND) 17 | message(FATAL_ERROR "unixem lib not found!") 18 | endif() 19 | endif() 20 | -------------------------------------------------------------------------------- /test/test_hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_hello.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | zlog_info(zc, "hello, zlog"); 31 | 32 | zlog_fini(); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/test_syslog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_syslog.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | zlog_info(zc, "hello, zlog -- info"); 31 | zlog_error(zc, "hello, zlog -- error"); 32 | 33 | zlog_fini(); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/test_level.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "test_level.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_level.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | zlog_trace(zc, "hello, zlog - trace"); 31 | zlog_debug(zc, "hello, zlog - debug"); 32 | zlog_info(zc, "hello, zlog - info"); 33 | 34 | zlog_fini(); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | 4 | *.o 5 | *.lo 6 | *.la 7 | *.gcda 8 | *.gcno 9 | aclocal.m4 10 | autom4te.cache 11 | build 12 | compile 13 | config.guess 14 | config.h 15 | config.h.in 16 | config.h.in~ 17 | config.log 18 | config.status 19 | config.sub 20 | configure 21 | depcomp 22 | .deps 23 | install-sh 24 | .libs 25 | libtool 26 | libzlog.so* 27 | libzlog.a* 28 | ltmain.sh 29 | Makefile 30 | Makefile.in 31 | missing 32 | stamp-h1 33 | tags 34 | TAGS 35 | zlog-chk-conf 36 | zlog-*.tar.gz 37 | zlog.pc 38 | callgrind* 39 | err.log 40 | test_* 41 | !test_*.c 42 | !test_*.conf 43 | !test_*.h 44 | doc/*.lyx~ 45 | doc/*.pdf 46 | doc/obj.think 47 | doc/zlog.3 48 | doc/zlogtest.xls 49 | doc/*.haux 50 | doc/*.html 51 | doc/*.htoc 52 | doc/*.tex 53 | test/press* 54 | test/*.png 55 | cscope* 56 | release.h 57 | *.pyc 58 | 59 | *.dylib 60 | -------------------------------------------------------------------------------- /cmake/FindUnixem.cmake: -------------------------------------------------------------------------------- 1 | # FindUnixem.cmake 2 | # author lsm 3 | 4 | if (NOT UNIXEM_FOUND) 5 | if (NOT UNIXEM_INCLUDE_DIR) 6 | find_path(UNIXEM_INCLUDE_DIR 7 | NAMES 8 | unixem/unixem.h 9 | ONLY_CMAKE_FIND_ROOT_PATH 10 | ) 11 | endif() 12 | 13 | if (NOT UNIXEM_LIBRARY) 14 | find_library(UNIXEM_LIBRARY 15 | NAMES unixem 16 | ONLY_CMAKE_FIND_ROOT_PATH 17 | ) 18 | endif (NOT UNIXEM_LIBRARY) 19 | 20 | message(STATUS " UNIXEM_INCLUDE_DIR = ${UNIXEM_INCLUDE_DIR}") 21 | message(STATUS " UNIXEM_LIBRARY = ${UNIXEM_LIBRARY}") 22 | 23 | if (UNIXEM_INCLUDE_DIR AND UNIXEM_LIBRARY) 24 | set(UNIXEM_FOUND TRUE) 25 | endif (UNIXEM_INCLUDE_DIR AND UNIXEM_LIBRARY) 26 | endif() 27 | 28 | -------------------------------------------------------------------------------- /doc/zlog.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | reload conf period = 10M 4 | 5 | buffer min = 1024 6 | buffer max = 2MB 7 | 8 | #rotate lock file = /tmp/zlog.lock 9 | rotate lock file = self 10 | default format = "%d(%F %T.%l) %-6V (%c:%F:%L) - %m%n" 11 | 12 | file perms = 600 13 | fsync period = 1K 14 | 15 | [levels] 16 | TRACE = 10 17 | CRIT = 130, LOG_CRIT 18 | 19 | [formats] 20 | simple = "%m%n" 21 | normal = "%d(%F %T.%l) %m%n" 22 | 23 | [rules] 24 | default.* >stdout; simple 25 | 26 | *.* -"%12.2E(HOME)/log/%c.log", \ 27 | 1MB * 12 ~ "%E(HOME)/log/%c.%D(%F) #2r #3s.log"; \ 28 | simple 29 | 30 | my_.INFO >stderr; 31 | my_cat.!ERROR "aa.log" 32 | my_dog.=DEBUG >syslog, LOG_LOCAL0; simple 33 | my_dog.=DEBUG | /usr/bin/cronolog /www/logs/example_%Y%m%d.log ; normal 34 | my_mice.* $record_func , "record_path%c"; normal 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/makefile: -------------------------------------------------------------------------------- 1 | exe = \ 2 | test_tmp \ 3 | test_longlog \ 4 | test_buf \ 5 | test_bitmap \ 6 | test_conf \ 7 | test_conf2 \ 8 | test_hashtable \ 9 | test_hello \ 10 | test_hex \ 11 | test_init \ 12 | test_level \ 13 | test_leak \ 14 | test_mdc \ 15 | test_multithread \ 16 | test_record \ 17 | test_pipe \ 18 | test_press_zlog \ 19 | test_press_zlog2 \ 20 | test_press_write \ 21 | test_press_write2 \ 22 | test_press_syslog \ 23 | test_syslog \ 24 | test_default \ 25 | test_profile \ 26 | test_category \ 27 | test_prompt \ 28 | test_enabled 29 | 30 | all : $(exe) 31 | 32 | $(exe) : %:%.o 33 | gcc -O2 -g -o $@ $^ -L../src -lzlog -lpthread -Wl,-rpath ../src 34 | 35 | .c.o : 36 | gcc -O2 -g -Wall -D_GNU_SOURCE -o $@ -c $< -I. -I../src 37 | 38 | clean : 39 | rm -f press.log* *.o $(exe) 40 | 41 | .PHONY : clean all 42 | -------------------------------------------------------------------------------- /test/test_record.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int output(zlog_msg_t *msg) 13 | { 14 | printf("[mystd]:[%s][%s][%ld]\n", msg->path, msg->buf, (long)msg->len); 15 | return 0; 16 | } 17 | 18 | int main(int argc, char** argv) 19 | { 20 | int rc; 21 | zlog_category_t *zc; 22 | 23 | rc = zlog_init("test_record.conf"); 24 | if (rc) { 25 | printf("init failed\n"); 26 | return -1; 27 | } 28 | 29 | zlog_set_record("myoutput", output); 30 | 31 | zc = zlog_get_category("my_cat"); 32 | if (!zc) { 33 | printf("get cat fail\n"); 34 | zlog_fini(); 35 | return -2; 36 | } 37 | 38 | zlog_info(zc, "hello, zlog"); 39 | zlog_fini(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /src/fmacros.h: -------------------------------------------------------------------------------- 1 | #ifndef __zlog_fmacro_h 2 | #define __zlog_fmacro_h 3 | 4 | #ifndef _BSD_SOURCE 5 | #define _BSD_SOURCE 6 | #endif 7 | 8 | #ifndef _DEFAULT_SOURCE 9 | #define _DEFAULT_SOURCE 10 | #endif 11 | 12 | #if defined(__linux__) || defined(__OpenBSD__) || defined(_AIX) 13 | #ifndef _XOPEN_SOURCE 14 | #define _XOPEN_SOURCE 700 15 | #endif 16 | #ifndef _XOPEN_SOURCE_EXTENDED 17 | #define _XOPEN_SOURCE_EXTENDED 18 | #endif 19 | #if defined(__APPLE__) 20 | #include 21 | #else 22 | #ifndef _POSIX_C_SOURCE 23 | #define _POSIX_C_SOURCE 200809L 24 | #endif 25 | #endif 26 | #ifndef _XOPEN_SOURCE 27 | #define _XOPEN_SOURCE 28 | #endif 29 | #endif 30 | 31 | #ifndef _LARGEFILE_SOURCE 32 | #define _LARGEFILE_SOURCE 33 | #endif 34 | 35 | #ifndef _LARGEFILE_SOURCE 36 | #define _LARGEFILE_SOURCE 37 | #endif 38 | #ifndef _FILE_OFFSET_BITS 39 | #define _FILE_OFFSET_BITS 64 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /test/test_conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | 17 | int main(int argc, char** argv) 18 | { 19 | int rc; 20 | zlog_category_t *zc; 21 | 22 | 23 | rc = zlog_init("test_conf.conf"); 24 | if (rc) { 25 | printf("init failed, try zlog-chk-conf test_conf.conf for more detail\n"); 26 | return -1; 27 | } 28 | 29 | zc = zlog_get_category("my_cat"); 30 | if (!zc) { 31 | printf("get cat fail\n"); 32 | zlog_fini(); 33 | return -2; 34 | } 35 | 36 | zlog_info(zc, "hello, zlog"); 37 | 38 | zlog_fini(); 39 | printf("log end\n"); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /test/test_category.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_category.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | zlog_debug(zc, "hello, zlog - debug"); 31 | 32 | zc = zlog_get_category("my-cat"); 33 | if (!zc) { 34 | printf("get cat fail\n"); 35 | zlog_fini(); 36 | return -2; 37 | } 38 | 39 | zlog_info(zc, "hello, zlog - info"); 40 | 41 | zlog_fini(); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /test/test_tmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | #include 12 | 13 | int main(int argc, char** argv) 14 | { 15 | int rc; 16 | zlog_category_t *zc; 17 | 18 | rc = zlog_init("test_tmp.conf"); 19 | if (rc) { 20 | printf("init failed\n"); 21 | return -1; 22 | } 23 | 24 | zc = zlog_get_category("my_cat"); 25 | if (!zc) { 26 | printf("get cat fail\n"); 27 | zlog_fini(); 28 | return -2; 29 | } 30 | 31 | zlog_debug(zc, "%s%d", "hello, zlog ", 1); 32 | zlog_info(zc, "hello, zlog 2"); 33 | 34 | sleep(1); 35 | 36 | zlog_info(zc, "hello, zlog 3"); 37 | zlog_debug(zc, "hello, zlog 4"); 38 | 39 | // zlog_profile(); 40 | 41 | zlog_fini(); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/format.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_format_h 10 | #define __zlog_format_h 11 | 12 | #include "thread.h" 13 | #include "zc_defs.h" 14 | 15 | typedef struct zlog_format_s zlog_format_t; 16 | 17 | struct zlog_format_s { 18 | char name[MAXLEN_CFG_LINE + 1]; 19 | char pattern[MAXLEN_CFG_LINE + 1]; 20 | zc_arraylist_t *pattern_specs; 21 | }; 22 | 23 | zlog_format_t *zlog_format_new(char *line, int * time_cache_count); 24 | void zlog_format_del(zlog_format_t * a_format); 25 | void zlog_format_profile(zlog_format_t * a_format, int flag); 26 | 27 | int zlog_format_gen_msg(zlog_format_t * a_format, zlog_thread_t * a_thread); 28 | 29 | #define zlog_format_has_name(a_format, fname) \ 30 | STRCMP(a_format->name, ==, fname) 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/record.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_record_h 10 | #define __zlog_record_h 11 | 12 | #include "zc_defs.h" 13 | 14 | /* record is user-defined output function and it's name from configure file */ 15 | typedef struct zlog_msg_s { 16 | char *buf; 17 | size_t len; 18 | char *path; 19 | } zlog_msg_t; /* 3 of this first, see need thread or not later */ 20 | 21 | typedef int (*zlog_record_fn)(zlog_msg_t * msg); 22 | 23 | typedef struct zlog_record_s { 24 | char name[MAXLEN_PATH + 1]; 25 | zlog_record_fn output; 26 | } zlog_record_t; 27 | 28 | zlog_record_t *zlog_record_new(const char *name, zlog_record_fn output); 29 | void zlog_record_del(zlog_record_t *a_record); 30 | void zlog_record_profile(zlog_record_t *a_record, int flag); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /test/test_conf2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | #include "test_conf2.conf.h" 17 | 18 | int main(int argc, char** argv) 19 | { 20 | int rc; 21 | zlog_category_t *zc; 22 | 23 | rc = zlog_init(test_conf2_conf); 24 | if (rc) { 25 | printf("init failed, save [] in a config file and try zlog-chk-conf for more detail [%s]\n", test_conf2_conf); 26 | return -1; 27 | } 28 | 29 | zc = zlog_get_category("my_cat"); 30 | if (!zc) { 31 | printf("get cat fail\n"); 32 | zlog_fini(); 33 | return -2; 34 | } 35 | 36 | zlog_info(zc, "hello, zlog"); 37 | 38 | zlog_fini(); 39 | printf("log end\n"); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /zlog.spec: -------------------------------------------------------------------------------- 1 | Name: zlog 2 | Version: 1.2.8 3 | Release: 1 4 | Summary: zlog logger framework 5 | 6 | License: LGPL 7 | URL: http://hardysimpson.github.io/zlog/ 8 | 9 | BuildRequires: gcc make 10 | 11 | %define _builddir %(echo $PWD) 12 | 13 | %description 14 | AIRTAME Web Service is powering the setup page. 15 | 16 | %build 17 | 18 | make clean all 19 | 20 | %install 21 | install -d '%{buildroot}/usr/include' 22 | install -d '%{buildroot}/usr/lib' 23 | cp src/zlog.h '%{buildroot}/usr/include/zlog.h' 24 | cp src/libzlog.a '%{buildroot}/usr/lib/libzlog.a' 25 | cp src/libzlog.so.1.2 '%{buildroot}/usr/lib/libzlog.so.1.2' 26 | ln -sf /usr/lib/libzlog.so.1.2 '%{buildroot}/usr/lib/libzlog.so.1' 27 | ln -sf /usr/lib/libzlog.so.1.2 '%{buildroot}/usr/lib/libzlog.so' 28 | 29 | %clean 30 | 31 | %files 32 | /usr/include/zlog.h 33 | /usr/lib/libzlog.a 34 | /usr/lib/libzlog.so 35 | /usr/lib/libzlog.so.1 36 | /usr/lib/libzlog.so.1.2 37 | 38 | 39 | -------------------------------------------------------------------------------- /test/test_mdc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | 17 | int main(int argc, char** argv) 18 | { 19 | int rc; 20 | zlog_category_t *zc; 21 | 22 | rc = zlog_init("test_mdc.conf"); 23 | if (rc) { 24 | printf("init failed\n"); 25 | return -1; 26 | } 27 | 28 | zc = zlog_get_category("my_cat"); 29 | if (!zc) { 30 | printf("get cat fail\n"); 31 | zlog_fini(); 32 | return -2; 33 | } 34 | 35 | 36 | zlog_info(zc, "1.hello, zlog"); 37 | 38 | zlog_put_mdc("myname", "Zhang"); 39 | 40 | zlog_info(zc, "2.hello, zlog"); 41 | 42 | zlog_put_mdc("myname", "Li"); 43 | 44 | zlog_info(zc, "3.hello, zlog"); 45 | 46 | zlog_fini(); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /src/level_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_level_list_h 10 | #define __zlog_level_list_h 11 | 12 | #include "zc_defs.h" 13 | #include "level.h" 14 | 15 | zc_arraylist_t *zlog_level_list_new(void); 16 | void zlog_level_list_del(zc_arraylist_t *levels); 17 | void zlog_level_list_profile(zc_arraylist_t *levels, int flag); 18 | 19 | /* conf init use, slow */ 20 | /* if l is wrong or str=="", return -1 */ 21 | int zlog_level_list_set(zc_arraylist_t *levels, char *line); 22 | 23 | /* spec output use, fast */ 24 | /* rule output use, fast */ 25 | /* if not found, return levels[254] */ 26 | zlog_level_t *zlog_level_list_get(zc_arraylist_t *levels, int l); 27 | 28 | /* rule init use, slow */ 29 | /* if not found, return -1 */ 30 | int zlog_level_list_atoi(zc_arraylist_t *levels, char *str); 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/category_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_category_table_h 10 | #define __zlog_category_table_h 11 | 12 | #include "zc_defs.h" 13 | #include "category.h" 14 | 15 | zc_hashtable_t *zlog_category_table_new(void); 16 | void zlog_category_table_del(zc_hashtable_t * categories); 17 | void zlog_category_table_profile(zc_hashtable_t * categories, int flag); 18 | 19 | /* if none, create new and return */ 20 | zlog_category_t *zlog_category_table_fetch_category( 21 | zc_hashtable_t * categories, 22 | const char *category_name, zc_arraylist_t * rules); 23 | 24 | int zlog_category_table_update_rules(zc_hashtable_t * categories, zc_arraylist_t * new_rules); 25 | void zlog_category_table_commit_rules(zc_hashtable_t * categories); 26 | void zlog_category_table_rollback_rules(zc_hashtable_t * categories); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /cpack/zlog/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # create by lsm 2 | 3 | #=============================== 4 | # package info setting 5 | #=============================== 6 | SET(CPACK_PACKAGE_NAME "zlog") 7 | SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "log component for Linux/Unix/AIX") 8 | SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_HOME_DIRECTORY}/README") 9 | SET(CPACK_INSTALL_CMAKE_PROJECTS "${zlog_BINARY_DIR};zlog;zlog;/") 10 | 11 | #================================= 12 | # dependency setting 13 | #================================= 14 | #SET(CPACK_RPM_PACKAGE_REQUIRES "") 15 | #SET(CPACK_DEBIAN_PACKAGE_DEPENDS "") 16 | 17 | #=============================== 18 | # copy file to build directory. 19 | #=============================== 20 | SET(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/CPackConfig.cmake") 21 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../CPackConfig.cmake CPackConfig.cmake) 22 | 23 | file(COPY 24 | . 25 | 26 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR} 27 | 28 | PATTERN CMakeLists.txt EXCLUDE 29 | ) 30 | 31 | -------------------------------------------------------------------------------- /src/mdc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_mdc_h 10 | #define __zlog_mdc_h 11 | 12 | #include "zc_defs.h" 13 | 14 | typedef struct zlog_mdc_s zlog_mdc_t; 15 | struct zlog_mdc_s { 16 | zc_hashtable_t *tab; 17 | }; 18 | 19 | zlog_mdc_t *zlog_mdc_new(void); 20 | void zlog_mdc_del(zlog_mdc_t * a_mdc); 21 | void zlog_mdc_profile(zlog_mdc_t *a_mdc, int flag); 22 | 23 | void zlog_mdc_clean(zlog_mdc_t * a_mdc); 24 | int zlog_mdc_put(zlog_mdc_t * a_mdc, const char *key, const char *value); 25 | char *zlog_mdc_get(zlog_mdc_t * a_mdc, const char *key); 26 | void zlog_mdc_remove(zlog_mdc_t * a_mdc, const char *key); 27 | 28 | typedef struct zlog_mdc_kv_s { 29 | char key[MAXLEN_PATH + 1]; 30 | char value[MAXLEN_PATH + 1]; 31 | size_t value_len; 32 | } zlog_mdc_kv_t; 33 | 34 | zlog_mdc_kv_t *zlog_mdc_get_kv(zlog_mdc_t * a_mdc, const char *key); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/lockfile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * 4 | * \file lockfile.h 5 | * \breif 6 | * \version 1.0 7 | * \date 2013-07-07 12:34:20 8 | * \author Song min.Li (Li), lisongmin@126.com 9 | * \copyright Copyright (c) 2013, skybility 10 | * 11 | * ============================================================================= 12 | */ 13 | 14 | #ifndef __ZLOG_LOCK_FILE_H__ 15 | #define __ZLOG_LOCK_FILE_H__ 16 | 17 | #ifdef _WIN32 18 | #include 19 | #include 20 | #define LOCK_FD HANDLE 21 | #define INVALID_LOCK_FD INVALID_HANDLE_VALUE 22 | #else //_WIN32 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #define LOCK_FD int 30 | #define INVALID_LOCK_FD -1 31 | #endif 32 | #include 33 | 34 | /** 35 | * lock file. 36 | */ 37 | LOCK_FD lock_file(char* path); 38 | 39 | /** 40 | * unlock file. 41 | */ 42 | bool unlock_file(LOCK_FD fd); 43 | 44 | #endif //__ZLOG_LOCK_FILE_H__ 45 | 46 | -------------------------------------------------------------------------------- /test/test_enabled.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2018 by Teracom Telemática S/A 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "test_enabled.h" 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc; 16 | 17 | rc = zlog_init("test_enabled.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | if (!zc) { 25 | printf("get cat fail\n"); 26 | zlog_fini(); 27 | return -2; 28 | } 29 | 30 | if (zlog_trace_enabled(zc)) { 31 | /* do something heavy to collect data */ 32 | zlog_trace(zc, "hello, zlog - trace"); 33 | } 34 | 35 | if (zlog_debug_enabled(zc)) { 36 | /* do something heavy to collect data */ 37 | zlog_debug(zc, "hello, zlog - debug"); 38 | } 39 | 40 | if (zlog_info_enabled(zc)) { 41 | /* do something heavy to collect data */ 42 | zlog_info(zc, "hello, zlog - info"); 43 | } 44 | 45 | zlog_fini(); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /test/test_bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "zlog.h" 13 | 14 | int main(int argc, char** argv) 15 | { 16 | unsigned char aa[32]; 17 | int i, j; 18 | 19 | if (argc != 3) { 20 | printf("useage: test_bitmap i j\n"); 21 | exit(1); 22 | } 23 | 24 | dzlog_init(NULL, "AA"); 25 | 26 | 27 | i = atoi(argv[1]); 28 | j = atoi(argv[2]); 29 | 30 | memset(aa, 0x00, sizeof(aa)); 31 | 32 | /* 32 byte, 256 bit 33 | * [11111..1100...00] 34 | * i 35 | */ 36 | aa[i/8] |= ~(0xFF << (8 - i % 8)); 37 | memset(aa + i/8 + 1, 0xFF, sizeof(aa) - i/8 - 1); 38 | 39 | hdzlog_info(aa, sizeof(aa)); 40 | 41 | dzlog_info("%0x", aa[j/8]); 42 | dzlog_info("%0x", aa[j/8] >> 6); 43 | 44 | /* see j of bits fits */ 45 | dzlog_info("%0x", ~((aa[j/8] >> (7 - j % 8)) & 0x01) ); 46 | 47 | zlog_fini(); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test/test_prompt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2020 by Bjoern Riemer 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | #include 9 | #include "zlog.h" 10 | #include 11 | 12 | int main(int argc, char** argv) 13 | { 14 | int rc; 15 | zlog_category_t *zc,*pzc; 16 | 17 | rc = zlog_init("test_prompt.conf"); 18 | if (rc) { 19 | printf("init failed\n"); 20 | return -1; 21 | } 22 | 23 | zc = zlog_get_category("my_cat"); 24 | pzc = zlog_get_category("prompt"); 25 | if (!zc || !pzc) { 26 | printf("get cat fail\n"); 27 | zlog_fini(); 28 | return -2; 29 | } 30 | 31 | zlog_debug(zc, "%s%d", "hello, zlog ", 1); 32 | zlog_info(zc, "hello, zlog 2"); 33 | 34 | for (int i =0; i<15;i++){ 35 | zlog_info(pzc, "prompt>"); 36 | sleep(1); 37 | if (! (i%3)) 38 | zlog_debug(zc, "dummy log entry %d",i); 39 | if (! (i%5)) 40 | zlog_info(zc, "hello, zlog %d",i); 41 | } 42 | zlog_info(zc, "done"); 43 | 44 | // zlog_profile(); 45 | 46 | zlog_fini(); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | function good_or_bad { 5 | if [ $? -eq 0 ]; then 6 | echo OK 7 | else 8 | echo FAILED 9 | fi 10 | } 11 | 12 | function rename_makefile { 13 | if [ -f $1 ]; then 14 | mv $1 $1.old_static 15 | else 16 | echo 17 | echo "Already renamed?" 18 | fi 19 | } 20 | 21 | echo -n "Finding version and setting it up for autoconf.... " 22 | VERSION_STRING=$(sed -e 's/.*ZLOG_VERSION.*"\(.*\)"/\1/g' src/version.h) 23 | sed -i "s/\[VERSION\]/[${VERSION_STRING}]/g" configure.ac 24 | good_or_bad 25 | 26 | echo -n "Renaming original static makefiles.... " 27 | rename_makefile test/makefile && \ 28 | rename_makefile src/makefile && \ 29 | rename_makefile doc/makefile && \ 30 | rename_makefile makefile 31 | good_or_bad 32 | 33 | 34 | echo -n "Running aclocal ..... " 35 | aclocal 36 | good_or_bad 37 | 38 | echo -n "Run libtoolize ..... " 39 | libtoolize -fc 40 | good_or_bad 41 | 42 | echo -n "Running autoconf ..... " 43 | autoconf 44 | good_or_bad 45 | 46 | echo -n "Running automake ..... " 47 | automake -afic 48 | good_or_bad 49 | 50 | echo "Now run ./configure to configure application" 51 | -------------------------------------------------------------------------------- /src/thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_thread_h 10 | #define __zlog_thread_h 11 | 12 | #include "zc_defs.h" 13 | #include "event.h" 14 | #include "buf.h" 15 | #include "mdc.h" 16 | 17 | typedef struct { 18 | int init_version; 19 | zlog_mdc_t *mdc; 20 | zlog_event_t *event; 21 | 22 | zlog_buf_t *pre_path_buf; 23 | zlog_buf_t *path_buf; 24 | zlog_buf_t *archive_path_buf; 25 | zlog_buf_t *pre_msg_buf; 26 | zlog_buf_t *msg_buf; 27 | } zlog_thread_t; 28 | 29 | 30 | void zlog_thread_del(zlog_thread_t * a_thread); 31 | void zlog_thread_profile(zlog_thread_t * a_thread, int flag); 32 | zlog_thread_t *zlog_thread_new(int init_version, 33 | size_t buf_size_min, size_t buf_size_max, int time_cache_count); 34 | 35 | int zlog_thread_rebuild_msg_buf(zlog_thread_t * a_thread, size_t buf_size_min, size_t buf_size_max); 36 | int zlog_thread_rebuild_event(zlog_thread_t * a_thread, int time_cache_count); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /test/test_conf2.conf.h: -------------------------------------------------------------------------------- 1 | #define test_conf2_conf "[global]\nstrict init = true\nbuffer min= 1024\nbuffer max= 2MB\nrotate lock file = /tmp/zlog.lock\ndefault format = \"defalut - %d(%F %X.%ms) %-6V (%c:%F:%U:%L) - %m%n\"\n\n[formats]\nnull = \"%n\"\nprint = \"print - [%-10.3d(%F)]%n\"\n\ndate = \"date start%n%d(%a--Wed)%n%d(%A--Wednesday)%n%d(%b--Mar)%n%d(%B--March)%n%d(%c--WedMar211:45:262011)%n%d(%C--20)%n%d(%d--02)%n%d(%D--03/02/11)%n%d(%e--2)%n%d(%F--2011-03-02)%n%d(%g--11)%n%d(%G--2011)%n%d(%h--Mar)%n%d(%H--11)%n%d(%I--11)%n%d(%j--061)%n%d(%k-k)%n%d(%l-l)%n%d(%ms--500)%n%d(%m--03)%n%d(%M--45)%n%d(%us--500730)%n%d(%p--AM)%n%d(%r--11:45:26AM)%n%d(%R--11:45)%n%d(%s--epoch)%n%d(%S--26)%n%d(%t--)%n%d(%T--11:45:26)%n%d(%u--3)%n%d(%U--09)%n%d(%V--09)%n%d(%w--3)%n%d(%W--09)%n%d(%x--03/02/11)%n%d(%X--11:45:26)%n%d(%y--11)%n%d(%Y--2011)%n%d(%z--+0800)%n%d(%Z--CST)%n%d(%%--%)%n%d(%J--%J)%ndate end%n\"\n\nsimple = \"simple - %m%n\"\n\ntext = \"text - text%n\"\n\nms = \"ms - %d(%a--Wed)[%d(%ms)]%n\"\n\nmsus = \"msus - %d(%ms,%us,%ms,%us)%n\"\n\n[rules]\n*.* >stderr;\n*.* >stderr; null\n*.* >stderr; print\n*.* >stderr; date\n*.* >stderr; simple\n*.* >stderr; text\n*.* >stderr; ms\n*.* >stderr; msus" 2 | -------------------------------------------------------------------------------- /test/test_leak.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | 17 | int main(int argc, char** argv) 18 | { 19 | int rc; 20 | int k; 21 | int i; 22 | 23 | if (argc != 2) { 24 | printf("test_leak ntime\n"); 25 | return -1; 26 | } 27 | 28 | rc = zlog_init("test_leak.conf"); 29 | 30 | k = atoi(argv[1]); 31 | while (k-- > 0) { 32 | i = rand(); 33 | switch (i % 4) { 34 | case 0: 35 | rc = dzlog_init("test_leak.conf", "xxx"); 36 | dzlog_info("init, rc=[%d]", rc); 37 | break; 38 | case 1: 39 | rc = zlog_reload(NULL); 40 | dzlog_info("reload null, rc=[%d]", rc); 41 | break; 42 | case 2: 43 | rc = zlog_reload("test_leak.2.conf"); 44 | dzlog_info("reload 2, rc=[%d]", rc); 45 | break; 46 | case 3: 47 | zlog_fini(); 48 | printf("fini\n"); 49 | // printf("zlog_finish\tj=[%d], rc=[%d]\n", j, rc); 50 | break; 51 | } 52 | } 53 | 54 | zlog_fini(); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /test/test_init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | 17 | int main(int argc, char** argv) 18 | { 19 | int rc; 20 | 21 | zlog_category_t *zc; 22 | 23 | rc = zlog_init("test_init.conf"); 24 | if (rc) { 25 | printf("init fail"); 26 | return -2; 27 | } 28 | zc = zlog_get_category("my_cat"); 29 | if (!zc) { 30 | printf("zlog_get_category fail\n"); 31 | zlog_fini(); 32 | return -1; 33 | } 34 | zlog_info(zc, "before update"); 35 | sleep(1); 36 | rc = zlog_reload("test_init.2.conf"); 37 | if (rc) { 38 | printf("update fail\n"); 39 | } 40 | zlog_info(zc, "after update"); 41 | zlog_profile(); 42 | zlog_fini(); 43 | 44 | sleep(1); 45 | zlog_init("test_init.conf"); 46 | zc = zlog_get_category("my_cat"); 47 | if (!zc) { 48 | printf("zlog_get_category fail\n"); 49 | zlog_fini(); 50 | return -1; 51 | } 52 | zlog_info(zc, "init again"); 53 | zlog_fini(); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /test/test_level.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * The zlog Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * The zlog Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with the zlog Library. If not, see . 18 | */ 19 | 20 | #ifndef __test_level_h 21 | #define __test_level_h 22 | 23 | #include "zlog.h" 24 | 25 | enum { 26 | ZLOG_LEVEL_TRACE = 30, 27 | /* must equals conf file setting */ 28 | }; 29 | 30 | #define zlog_trace(cat, format, args...) \ 31 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 32 | ZLOG_LEVEL_TRACE, format, ##args) 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /test/test_press_syslog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int work(long loop_count) 17 | { 18 | while(loop_count-- > 0) { 19 | syslog(LOG_INFO, "loglog"); 20 | } 21 | return 0; 22 | } 23 | 24 | 25 | int test(long process_count, long loop_count) 26 | { 27 | long i; 28 | pid_t pid; 29 | 30 | for (i = 0; i < process_count; i++) { 31 | pid = fork(); 32 | if (pid < 0) { 33 | printf("fork fail\n"); 34 | } else if(pid == 0) { 35 | work(loop_count); 36 | return 0; 37 | } 38 | } 39 | 40 | for (i = 0; i < process_count; i++) { 41 | pid = wait(NULL); 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | 48 | int main(int argc, char** argv) 49 | { 50 | 51 | if (argc != 3) { 52 | fprintf(stderr, "test nprocess nloop"); 53 | exit(1); 54 | } 55 | 56 | openlog(NULL, LOG_NDELAY|LOG_NOWAIT|LOG_PID, LOG_LOCAL0); 57 | 58 | test(atol(argv[1]), atol(argv[2])); 59 | 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /test/test_conf.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | strict init = true 3 | buffer min= 1024 4 | buffer max= 2MB 5 | rotate lock file = /tmp/zlog.lock 6 | default format = "defalut - %d(%F %X.%ms) %-6V (%c:%F:%U:%L) - %m%n" 7 | 8 | [formats] 9 | null = "%n" 10 | print = "print - [%-10.3d(%F)]%n" 11 | 12 | date = "date start%n%d(%a--Wed)%n%d(%A--Wednesday)%n%d(%b--Mar)%n%d(%B--March)%n%d(%c--WedMar211:45:262011)%n%d(%C--20)%n%d(%d--02)%n%d(%D--03/02/11)%n%d(%e--2)%n%d(%F--2011-03-02)%n%d(%g--11)%n%d(%G--2011)%n%d(%h--Mar)%n%d(%H--11)%n%d(%I--11)%n%d(%j--061)%n%d(%k-k)%n%d(%l-l)%n%d(%ms--500)%n%d(%m--03)%n%d(%M--45)%n%d(%us--500730)%n%d(%p--AM)%n%d(%r--11:45:26AM)%n%d(%R--11:45)%n%d(%s--epoch)%n%d(%S--26)%n%d(%t--)%n%d(%T--11:45:26)%n%d(%u--3)%n%d(%U--09)%n%d(%V--09)%n%d(%w--3)%n%d(%W--09)%n%d(%x--03/02/11)%n%d(%X--11:45:26)%n%d(%y--11)%n%d(%Y--2011)%n%d(%z--+0800)%n%d(%Z--CST)%n%d(%%--%)%n%d(%J--%J)%ndate end%n" 13 | 14 | simple = "simple - %m%n" 15 | 16 | text = "text - text%n" 17 | 18 | ms = "ms - %d(%a--Wed)[%d(%ms)]%n" 19 | 20 | msus = "msus - %d(%ms,%us,%ms,%us)%n" 21 | 22 | [rules] 23 | *.* >stderr; 24 | *.* >stderr; null 25 | *.* >stderr; print 26 | *.* >stderr; date 27 | *.* >stderr; simple 28 | *.* >stderr; text 29 | *.* >stderr; ms 30 | *.* >stderr; msus 31 | -------------------------------------------------------------------------------- /src/conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_conf_h 10 | #define __zlog_conf_h 11 | 12 | #include "zc_defs.h" 13 | #include "format.h" 14 | #include "rotater.h" 15 | 16 | typedef struct zlog_conf_s { 17 | char file[MAXLEN_PATH + 1]; 18 | char cfg_ptr[MAXLEN_CFG_LINE*MAXLINES_NO]; 19 | char mtime[20 + 1]; 20 | 21 | int strict_init; 22 | size_t buf_size_min; 23 | size_t buf_size_max; 24 | 25 | char rotate_lock_file[MAXLEN_CFG_LINE + 1]; 26 | zlog_rotater_t *rotater; 27 | 28 | char default_format_line[MAXLEN_CFG_LINE + 1]; 29 | zlog_format_t *default_format; 30 | 31 | unsigned int file_perms; 32 | size_t fsync_period; 33 | size_t reload_conf_period; 34 | 35 | zc_arraylist_t *levels; 36 | zc_arraylist_t *formats; 37 | zc_arraylist_t *rules; 38 | int time_cache_count; 39 | } zlog_conf_t; 40 | 41 | extern zlog_conf_t * zlog_env_conf; 42 | 43 | zlog_conf_t *zlog_conf_new(const char *config); 44 | zlog_conf_t *zlog_conf_new_from_string(const char *config_string); 45 | void zlog_conf_del(zlog_conf_t * a_conf); 46 | void zlog_conf_profile(zlog_conf_t * a_conf, int flag); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /test/test_enabled.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2018 by Teracom Telemática S/A 5 | * 6 | * The zlog Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * The zlog Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with the zlog Library. If not, see . 18 | */ 19 | 20 | #ifndef __test_level_h 21 | #define __test_level_h 22 | 23 | #include "zlog.h" 24 | 25 | enum { 26 | ZLOG_LEVEL_TRACE = 30, 27 | /* must equals conf file setting */ 28 | }; 29 | 30 | #define zlog_trace(cat, format, args...) \ 31 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 32 | ZLOG_LEVEL_TRACE, format, ##args) 33 | 34 | #define zlog_trace_enabled(cat) zlog_level_enabled(cat, ZLOG_LEVEL_TRACE) 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | NAME=zlog 2 | 3 | lib_LTLIBRARIES = libzlog.la 4 | 5 | # Version info is a bit crazy but for more info 6 | # https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html 7 | # value bellow is used for current soname compatibility but in future version 8 | # should be changed depending on interface changes look here for info 9 | # https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html 10 | libzlog_la_LDFLAGS =-version-info 2:0:1 11 | libzlog_la_CFLAGS = -I. 12 | libzlog_la_SOURCES = buf.c buf.h \ 13 | category.c category.h \ 14 | category_table.c category_table.h \ 15 | conf.c conf.h \ 16 | event.c event.h \ 17 | fmacros.h version.h \ 18 | format.c format.h \ 19 | level.c level.h \ 20 | level_list.c level_list.h \ 21 | mdc.c mdc.h \ 22 | record.c record.h \ 23 | record_table.c record_table.h \ 24 | rotater.c rotater.h \ 25 | rule.c rule.h \ 26 | spec.c spec.h \ 27 | thread.c thread.h \ 28 | zc_arraylist.c zc_arraylist.h \ 29 | zc_hashtable.c zc_hashtable.h \ 30 | zc_profile.c zc_profile.h \ 31 | zc_util.c zc_util.h \ 32 | zc_xplatform.h \ 33 | zc_defs.h \ 34 | zlog.c zlog.h 35 | 36 | include_HEADERS = zlog.h 37 | 38 | bin_PROGRAMS = zlog-chk-conf 39 | zlog_chk_conf_CFLAGS = -I. 40 | zlog_chk_conf_LDADD = libzlog.la 41 | 42 | dist_man_MANS = zlog-chk-conf.1 43 | -------------------------------------------------------------------------------- /src/category.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_category_h 10 | #define __zlog_category_h 11 | 12 | #include "zc_defs.h" 13 | #include "thread.h" 14 | 15 | typedef struct zlog_category_s { 16 | char name[MAXLEN_PATH + 1]; 17 | size_t name_len; 18 | unsigned char level_bitmap[32]; 19 | unsigned char level_bitmap_backup[32]; 20 | zc_arraylist_t *fit_rules; 21 | zc_arraylist_t *fit_rules_backup; 22 | } zlog_category_t; 23 | 24 | zlog_category_t *zlog_category_new(const char *name, zc_arraylist_t * rules); 25 | void zlog_category_del(zlog_category_t * a_category); 26 | void zlog_category_profile(zlog_category_t *a_category, int flag); 27 | 28 | int zlog_category_update_rules(zlog_category_t * a_category, zc_arraylist_t * new_rules); 29 | void zlog_category_commit_rules(zlog_category_t * a_category); 30 | void zlog_category_rollback_rules(zlog_category_t * a_category); 31 | 32 | int zlog_category_output(zlog_category_t * a_category, zlog_thread_t * a_thread); 33 | 34 | #define zlog_category_needless_level(a_category, lv) \ 35 | (a_category && !((a_category->level_bitmap[lv/8] >> (7 - lv % 8)) & 0x01)) 36 | 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/rotater.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_rotater_h 10 | #define __zlog_rotater_h 11 | 12 | #include "zc_defs.h" 13 | #include "lockfile.h" 14 | 15 | typedef struct zlog_rotater_s { 16 | pthread_mutex_t lock_mutex; 17 | char *lock_file; 18 | LOCK_FD lock_fd; 19 | 20 | /* single-use members */ 21 | char *base_path; /* aa.log */ 22 | char *archive_path; /* aa.#5i.log */ 23 | char glob_path[MAXLEN_PATH + 1]; /* aa.*.log */ 24 | size_t num_start_len; /* 3, offset to glob_path */ 25 | size_t num_end_len; /* 6, offset to glob_path */ 26 | int num_width; /* 5 */ 27 | int mv_type; /* ROLLING or SEQUENCE */ 28 | int max_count; 29 | zc_arraylist_t *files; 30 | } zlog_rotater_t; 31 | 32 | zlog_rotater_t *zlog_rotater_new(char *lock_file); 33 | void zlog_rotater_del(zlog_rotater_t *a_rotater); 34 | 35 | /* 36 | * return 37 | * -1 fail 38 | * 0 no rotate, or rotate and success 39 | */ 40 | int zlog_rotater_rotate(zlog_rotater_t *a_rotater, 41 | char *base_path, size_t msg_len, 42 | char *archive_path, long archive_max_size, int archive_max_count); 43 | 44 | void zlog_rotater_profile(zlog_rotater_t *a_rotater, int flag); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/zc_arraylist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zc_arraylist_h 10 | #define __zc_arraylist_h 11 | 12 | #define ARRAY_LIST_DEFAULT_SIZE 32 13 | 14 | typedef void (*zc_arraylist_del_fn) (void *data); 15 | typedef int (*zc_arraylist_cmp_fn) (void *data1, void *data2); 16 | 17 | /* make zc_arraylist_foreach speed up, so keep struct defination here */ 18 | typedef struct { 19 | void **array; 20 | int len; 21 | int size; 22 | zc_arraylist_del_fn del; 23 | } zc_arraylist_t; 24 | 25 | zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del); 26 | void zc_arraylist_del(zc_arraylist_t * a_list); 27 | 28 | int zc_arraylist_set(zc_arraylist_t * a_list, int i, void *data); 29 | int zc_arraylist_add(zc_arraylist_t * a_list, void *data); 30 | int zc_arraylist_sortadd(zc_arraylist_t * a_list, zc_arraylist_cmp_fn cmp, 31 | void *data); 32 | 33 | #define zc_arraylist_len(a_list) (a_list->len) 34 | 35 | #define zc_arraylist_get(a_list, i) \ 36 | ((i >= a_list->len) ? NULL : a_list->array[i]) 37 | 38 | #define zc_arraylist_foreach(a_list, i, a_unit) \ 39 | for(i = 0, a_unit = a_list->array[0]; (i < a_list->len) && (a_unit = a_list->array[i], 1) ; i++) 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/record.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | #include "errno.h" 9 | #include "zc_defs.h" 10 | #include "record.h" 11 | 12 | void zlog_record_profile(zlog_record_t *a_record, int flag) 13 | { 14 | zc_assert(a_record,); 15 | zc_profile(flag, "--record:[%p][%s:%p]--", a_record, a_record->name, a_record->output); 16 | return; 17 | } 18 | 19 | void zlog_record_del(zlog_record_t *a_record) 20 | { 21 | zc_assert(a_record,); 22 | zc_debug("zlog_record_del[%p]", a_record); 23 | free(a_record); 24 | return; 25 | } 26 | 27 | zlog_record_t *zlog_record_new(const char *name, zlog_record_fn output) 28 | { 29 | zlog_record_t *a_record; 30 | 31 | zc_assert(name, NULL); 32 | zc_assert(output, NULL); 33 | 34 | a_record = calloc(1, sizeof(zlog_record_t)); 35 | if (!a_record) { 36 | zc_error("calloc fail, errno[%d]", errno); 37 | return NULL; 38 | } 39 | 40 | if (strlen(name) > sizeof(a_record->name) - 1) { 41 | zc_error("name[%s] is too long", name); 42 | goto err; 43 | } 44 | 45 | strcpy(a_record->name, name); 46 | a_record->output = output; 47 | 48 | zlog_record_profile(a_record, ZC_DEBUG); 49 | return a_record; 50 | err: 51 | zlog_record_del(a_record); 52 | return NULL; 53 | } 54 | -------------------------------------------------------------------------------- /test/test_longlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zlog.h" 11 | #include 12 | #include 13 | 14 | #define str "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 15 | #define str2 str str 16 | #define str4 str2 str2 17 | #define str8 str4 str4 18 | #define str16 str8 str8 19 | #define str32 str16 str16 20 | #define str64 str32 str32 21 | 22 | int main(int argc, char** argv) 23 | { 24 | int i, k; 25 | int rc; 26 | zlog_category_t *zc; 27 | 28 | if (argc != 2) { 29 | printf("useage: test_longlog [count]\n"); 30 | exit(1); 31 | } 32 | 33 | rc = zlog_init("test_longlog.conf"); 34 | if (rc) { 35 | printf("init failed\n"); 36 | return -1; 37 | } 38 | 39 | zc = zlog_get_category("my_cat"); 40 | if (!zc) { 41 | printf("get cat fail\n"); 42 | zlog_fini(); 43 | return -2; 44 | } 45 | 46 | k = atoi(argv[1]); 47 | while (k-- > 0) { 48 | i = rand(); 49 | switch (i % 3) { 50 | case 0: 51 | zlog_info(zc, str32); 52 | break; 53 | case 1: 54 | zlog_info(zc, str64); 55 | break; 56 | case 2: 57 | zlog_info(zc, str16); 58 | break; 59 | } 60 | } 61 | 62 | 63 | zlog_fini(); 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /test/test_hashtable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zc_profile.c" 16 | #include "zc_hashtable.h" 17 | #include "zc_hashtable.c" 18 | 19 | void myfree(void *kv) 20 | { 21 | } 22 | 23 | int main(void) 24 | { 25 | zc_hashtable_t *a_table; 26 | zc_hashtable_entry_t *a_entry; 27 | 28 | a_table = zc_hashtable_new(20, 29 | zc_hashtable_str_hash, 30 | zc_hashtable_str_equal, 31 | myfree, myfree); 32 | 33 | zc_hashtable_put(a_table, "aaa", "bnbb"); 34 | zc_hashtable_put(a_table, "bbb", "bnbb"); 35 | zc_hashtable_put(a_table, "ccc", "bnbb"); 36 | 37 | zc_hashtable_put(a_table, "aaa", "123"); 38 | 39 | zc_hashtable_foreach(a_table, a_entry) { 40 | printf("k[%s],v[%s]\n", (char*)a_entry->key, (char*)a_entry->value); 41 | } 42 | 43 | printf("getv[%s]\n", (char*)zc_hashtable_get(a_table, "ccc")); 44 | 45 | zc_hashtable_remove(a_table, "ccc"); 46 | 47 | zc_hashtable_foreach(a_table, a_entry) { 48 | printf("k[%s],v[%s]\n", (char*)a_entry->key, (char*)a_entry->value); 49 | } 50 | 51 | 52 | zc_hashtable_remove(a_table, NULL); 53 | zc_hashtable_del(NULL); 54 | 55 | zc_hashtable_del(a_table); 56 | return 0; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([zlog], [1.2.7], [HardySimpson1984@gmail.com]) 6 | AC_CONFIG_SRCDIR([src/version.h]) 7 | AC_CONFIG_MACRO_DIR([m4]) 8 | # Checks for programs. 9 | AC_PROG_CC 10 | AM_PROG_CC_C_O 11 | AC_PROG_INSTALL 12 | AC_PROG_LN_S 13 | AC_PROG_MAKE_SET 14 | LT_INIT 15 | AM_INIT_AUTOMAKE([foreign dist-bzip2]) 16 | 17 | # Checks for libraries. 18 | AC_CHECK_LIB([pthread], [pthread_create]) 19 | 20 | # Checks for header files. 21 | AC_CHECK_HEADERS([fcntl.h limits.h stdint.h stdlib.h string.h strings.h sys/time.h syslog.h unistd.h]) 22 | 23 | # Checks for programs 24 | AC_CHECK_PROG([VAR_LYX], [lyx], [true], [false]) 25 | AC_CHECK_PROG([VAR_HEVEA], [hevea], [true], [false]) 26 | AM_CONDITIONAL([HAVE_LYX], [$VAR_LYX]) 27 | AM_CONDITIONAL([HAVE_HEVEA], [$VAR_HEVEA]) 28 | 29 | 30 | # Checks for typedefs, structures, and compiler characteristics. 31 | AC_TYPE_PID_T 32 | AC_TYPE_SIZE_T 33 | AC_TYPE_UINT32_T 34 | AC_TYPE_UINT64_T 35 | 36 | # Checks for library functions. 37 | AC_FUNC_FORK 38 | AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK 39 | AC_FUNC_REALLOC 40 | AC_CHECK_FUNCS([atexit gethostname gettimeofday localtime_r memmove memset setenv strchr strrchr strtol]) 41 | 42 | AC_CONFIG_FILES([doc/Makefile 43 | Makefile 44 | src/Makefile 45 | test/Makefile 46 | tools/Makefile]) 47 | AC_OUTPUT 48 | -------------------------------------------------------------------------------- /src/zlog-chk-conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include "fmacros.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "zlog.h" 19 | #include "version.h" 20 | 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | int rc = 0; 25 | int op; 26 | int quiet = 0; 27 | static const char *help = 28 | "usage: zlog-chk-conf [conf files]...\n" 29 | "\t-q,\tsuppress non-error message\n" 30 | "\t-h,\tshow help message\n" 31 | "zlog version: " ZLOG_VERSION "\n"; 32 | 33 | while((op = getopt(argc, argv, "qhv")) > 0) { 34 | if (op == 'h') { 35 | fputs(help, stdout); 36 | return 0; 37 | } else if (op == 'q') { 38 | quiet = 1; 39 | } 40 | } 41 | 42 | argc -= optind; 43 | argv += optind; 44 | 45 | if (argc == 0) { 46 | fputs(help, stdout); 47 | return -1; 48 | } 49 | 50 | setenv("ZLOG_PROFILE_ERROR", "/dev/stderr", 1); 51 | setenv("ZLOG_CHECK_FORMAT_RULE", "1", 1); 52 | 53 | while (argc > 0) { 54 | rc = zlog_init(*argv); 55 | if (rc) { 56 | printf("\n---[%s] syntax error, see error message above\n", 57 | *argv); 58 | exit(2); 59 | } else { 60 | zlog_fini(); 61 | if (!quiet) { 62 | printf("--[%s] syntax right\n", *argv); 63 | } 64 | } 65 | argc--; 66 | argv++; 67 | } 68 | 69 | exit(0); 70 | } 71 | -------------------------------------------------------------------------------- /cmake/toolchain-mingw64.cmake: -------------------------------------------------------------------------------- 1 | 2 | # this one is important 3 | SET(CMAKE_SYSTEM_NAME Windows) 4 | 5 | # specify the cross compiler 6 | find_path(MINGW_BIN_PATH gcc.exe PATHS c:/mingw64 d:/mingw64 c:/mingw-build/mingw64 d:/mingw-build/mingw64 PATH_SUFFIXES bin) 7 | 8 | if (MINGW_PATH_NOTFOUND) 9 | message(FATAL "mingw64 not found!") 10 | endif() 11 | 12 | get_filename_component(MINGW_PATH ${MINGW_BIN_PATH} PATH) 13 | 14 | SET(CMAKE_GENERATOR "MinGW Makefiles") 15 | 16 | SET(CMAKE_C_COMPILER gcc) 17 | SET(CMAKE_CXX_COMPILER g++) 18 | 19 | SET(CMAKE_RC_COMPILER windres) 20 | set(CMAKE_RC_COMPILE_OBJECT " -O coff -i -o ") 21 | 22 | #SET(_CMAKE_TOOLCHAIN_PREFIX x86_64-w64-mingw32-) 23 | SET(_CMAKE_TOOLCHAIN_LOCATION ${MINGW_BIN_PATH}) 24 | 25 | # where is the target environment 26 | SET(CMAKE_FIND_ROOT_PATH ${MINGW_PATH} ${MINGW_PATH}/x86_64-w64-mingw32) 27 | 28 | SET(CMAKE_SYSTEM_INCLUDE_PATH "${CMAKE_SYSTEM_INCLUDE_PATH} ${MINGW_PATH}/include ${MINGW_PATH}/x86_64-w64-mingw32/include") 29 | SET(CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_SYSTEM_LIBRARY_PATH} ${MINGW_PATH}/lib ${MINGW_PATH}/x86_64-w64-mingw32/lib") 30 | SET(CMAKE_SYSTEM_PROGRAM_PATH "${CMAKE_SYSTEM_PROGRAM_PATH} ${MINGW_PATH}/bin ${MINGW_PATH}/x86_64-w64-mingw32/bin") 31 | 32 | # printf support %sz format. 33 | add_definitions("-D_POSIX") 34 | 35 | # search for programs in the build host directories 36 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 37 | # for libraries and headers in the target directories 38 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 39 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 40 | 41 | -------------------------------------------------------------------------------- /src/zc_profile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zc_profile_h 10 | #define __zc_profile_h 11 | 12 | #include 13 | 14 | #define EMPTY() 15 | #define zc_assert(expr, rv) \ 16 | if(!(expr)) { \ 17 | zc_error(#expr" is null or 0"); \ 18 | return rv; \ 19 | } 20 | 21 | enum zc_profile_flag { 22 | ZC_DEBUG = 0, 23 | ZC_WARN = 1, 24 | ZC_ERROR = 2 25 | }; 26 | 27 | 28 | #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L 29 | #define zc_debug(...) \ 30 | zc_profile_inner(ZC_DEBUG, __FILE__, __LINE__, __VA_ARGS__) 31 | #define zc_warn(...) \ 32 | zc_profile_inner(ZC_WARN, __FILE__, __LINE__, __VA_ARGS__) 33 | #define zc_error(...) \ 34 | zc_profile_inner(ZC_ERROR, __FILE__, __LINE__, __VA_ARGS__) 35 | #define zc_profile(flag, ...) \ 36 | zc_profile_inner(flag, __FILE__, __LINE__, __VA_ARGS__) 37 | #elif defined __GNUC__ 38 | #define zc_debug(fmt, args...) \ 39 | zc_profile_inner(ZC_DEBUG, __FILE__, __LINE__, fmt, ## args) 40 | #define zc_warn(fmt, args...) \ 41 | zc_profile_inner(ZC_WARN, __FILE__, __LINE__, fmt, ## args) 42 | #define zc_error(fmt, args...) \ 43 | zc_profile_inner(ZC_ERROR, __FILE__, __LINE__, fmt, ## args) 44 | #define zc_profile(flag, fmt, args...) \ 45 | zc_profile_inner(flag, __FILE__, __LINE__, fmt, ## args) 46 | #endif 47 | 48 | 49 | int zc_profile_inner(int flag, 50 | const char *file, const long line, 51 | const char *fmt, ...); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/record_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "zc_defs.h" 14 | #include "record_table.h" 15 | 16 | void zlog_record_table_profile(zc_hashtable_t * records, int flag) 17 | { 18 | zc_hashtable_entry_t *a_entry; 19 | zlog_record_t *a_record; 20 | 21 | zc_assert(records,); 22 | zc_profile(flag, "-record_table[%p]-", records); 23 | zc_hashtable_foreach(records, a_entry) { 24 | a_record = (zlog_record_t *) a_entry->value; 25 | zlog_record_profile(a_record, flag); 26 | } 27 | return; 28 | } 29 | 30 | /*******************************************************************************/ 31 | 32 | void zlog_record_table_del(zc_hashtable_t * records) 33 | { 34 | zc_assert(records,); 35 | zc_hashtable_del(records); 36 | zc_debug("zlog_record_table_del[%p]", records); 37 | return; 38 | } 39 | 40 | zc_hashtable_t *zlog_record_table_new(void) 41 | { 42 | zc_hashtable_t *records; 43 | 44 | records = zc_hashtable_new(20, 45 | (zc_hashtable_hash_fn) zc_hashtable_str_hash, 46 | (zc_hashtable_equal_fn) zc_hashtable_str_equal, 47 | NULL, (zc_hashtable_del_fn) zlog_record_del); 48 | if (!records) { 49 | zc_error("zc_hashtable_new fail"); 50 | return NULL; 51 | } else { 52 | zlog_record_table_profile(records, ZC_DEBUG); 53 | return records; 54 | } 55 | } 56 | /*******************************************************************************/ 57 | -------------------------------------------------------------------------------- /src/lockfile.c: -------------------------------------------------------------------------------- 1 | /** 2 | * ============================================================================= 3 | * 4 | * \file lockfile.c 5 | * \breif 6 | * \version 1.0 7 | * \date 2013-07-07 11:55:38 8 | * \author Song min.Li (Li), lisongmin@126.com 9 | * \copyright Copyright (c) 2013, skybility 10 | * 11 | * ============================================================================= 12 | */ 13 | 14 | #include "lockfile.h" 15 | #include "zc_profile.h" 16 | 17 | LOCK_FD lock_file(char* path) 18 | { 19 | if (!path || strlen(path) <= 0) 20 | { 21 | return INVALID_LOCK_FD; 22 | } 23 | #ifdef _WIN32 24 | LOCK_FD fd = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 25 | if (fd == INVALID_LOCK_FD) 26 | { 27 | DWORD err = GetLastError(); 28 | zc_error("lock file error : %d ", err); 29 | } 30 | #else 31 | LOCK_FD fd = open(path, O_RDWR | O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO); 32 | if (fd == INVALID_LOCK_FD) 33 | { 34 | zc_error("lock file error : %s ", strerror(errno)); 35 | } 36 | #endif 37 | return fd; 38 | } 39 | 40 | bool unlock_file(LOCK_FD fd) 41 | { 42 | if (fd == INVALID_LOCK_FD) 43 | { 44 | return true; 45 | } 46 | #ifdef _WIN32 47 | bool ret = CloseHandle(fd); 48 | if (ret == false) 49 | { 50 | DWORD err = GetLastError(); 51 | zc_error("unlock file error : %d ", err); 52 | } 53 | #else 54 | bool ret = close(fd) == 0; 55 | if (ret == false) 56 | { 57 | zc_error("unlock file error : %s ", strerror(errno)); 58 | } 59 | #endif 60 | return ret; 61 | } 62 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | include_directories("${CMAKE_HOME_DIRECTORY}/src") 3 | 4 | aux_source_directory(. SRCS) 5 | 6 | if (WIN32) 7 | #message(STATUS ${SRCS}) 8 | list(REMOVE_ITEM SRCS ./test_press_syslog.c) 9 | list(REMOVE_ITEM SRCS ./test_syslog.c) 10 | list(REMOVE_ITEM SRCS ./test_press_write.c) 11 | list(REMOVE_ITEM SRCS ./test_press_write2.c) 12 | list(REMOVE_ITEM SRCS ./test_press_zlog.c) 13 | list(REMOVE_ITEM SRCS ./test_press_zlog2.c) 14 | #message(STATUS ${SRCS}) 15 | endif() 16 | 17 | set(not_auto_add_test 18 | test_hello 19 | test_bitmap 20 | test_hex 21 | test_leak 22 | test_press_write 23 | test_press_write2 24 | test_press_zlog 25 | test_press_zlog2 26 | test_press_syslog 27 | test_syslog 28 | test_longlog 29 | ) 30 | 31 | foreach(test_src ${SRCS}) 32 | string(REGEX MATCH "^.*/([^/]+)[.]c$" test_name ${test_src}) 33 | set(test_name ${CMAKE_MATCH_1}) 34 | 35 | message(STATUS "${test_name} ${test_src}") 36 | 37 | add_executable("${test_name}" "${test_src}") 38 | target_link_libraries(${test_name} zlog) 39 | 40 | list(FIND not_auto_add_test ${test_name} not_auto_test) 41 | if (not_auto_test EQUAL -1) 42 | add_test("${test_name}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test_name}") 43 | endif() 44 | endforeach(test_src) 45 | 46 | add_test(test_hello "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_hello" hello_output 3) 47 | add_test(test_longlog "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_longlog" 2222) 48 | add_test(test_bitmap "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_bitmap" 0xaa55 0x66) 49 | 50 | file(GLOB CONF_FILES . *.conf) 51 | file(COPY 52 | ${CONF_FILES} hello_output 53 | DESTINATION ${CMAKE_CURRENT_BINARY_DIR} 54 | ) 55 | 56 | -------------------------------------------------------------------------------- /src/spec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_spec_h 10 | #define __zlog_spec_h 11 | 12 | #include "event.h" 13 | #include "buf.h" 14 | #include "thread.h" 15 | 16 | typedef struct zlog_spec_s zlog_spec_t; 17 | 18 | /* write buf, according to each spec's Conversion Characters */ 19 | typedef int (*zlog_spec_write_fn) (zlog_spec_t * a_spec, 20 | zlog_thread_t * a_thread, 21 | zlog_buf_t * a_buf); 22 | 23 | /* gen a_thread->msg or gen a_thread->path by using write_fn */ 24 | typedef int (*zlog_spec_gen_fn) (zlog_spec_t * a_spec, 25 | zlog_thread_t * a_thread); 26 | 27 | struct zlog_spec_s { 28 | char *str; 29 | int len; 30 | 31 | char time_fmt[MAXLEN_CFG_LINE + 1]; 32 | int time_cache_index; 33 | char mdc_key[MAXLEN_PATH + 1]; 34 | 35 | char print_fmt[MAXLEN_CFG_LINE + 1]; 36 | int left_adjust; 37 | int left_fill_zeros; 38 | size_t max_width; 39 | size_t min_width; 40 | 41 | zlog_spec_write_fn write_buf; 42 | zlog_spec_gen_fn gen_msg; 43 | zlog_spec_gen_fn gen_path; 44 | zlog_spec_gen_fn gen_archive_path; 45 | }; 46 | 47 | zlog_spec_t *zlog_spec_new(char *pattern_start, char **pattern_end, int * time_cache_count); 48 | void zlog_spec_del(zlog_spec_t * a_spec); 49 | void zlog_spec_profile(zlog_spec_t * a_spec, int flag); 50 | 51 | #define zlog_spec_gen_msg(a_spec, a_thread) \ 52 | a_spec->gen_msg(a_spec, a_thread) 53 | 54 | #define zlog_spec_gen_path(a_spec, a_thread) \ 55 | a_spec->gen_path(a_spec, a_thread) 56 | 57 | #define zlog_spec_gen_archive_path(a_spec, a_thread) \ 58 | a_spec->gen_archive_path(a_spec, a_thread) 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | #================================================================ 3 | # generate zlog lib 4 | #================================================================ 5 | aux_source_directory(. SRCS) 6 | if (NOT WIN32) 7 | list(REMOVE_ITEM SRCS ./zlog_win.c) 8 | endif() 9 | 10 | list(REMOVE_ITEM SRCS ./zlog-chk-conf.c) 11 | 12 | add_library(zlog 13 | SHARED 14 | ${SRCS} 15 | ) 16 | target_link_libraries(zlog 17 | ${CMAKE_THREAD_PREFER_PTHREAD} 18 | ) 19 | 20 | if (WIN32) 21 | target_link_libraries(zlog 22 | ${UNIXEM_LIBRARY} 23 | Ws2_32 24 | ) 25 | endif() 26 | 27 | set_target_properties(zlog PROPERTIES VERSION ${zlog_ver} SOVERSION ${zlog_so_ver}) 28 | 29 | add_library(zlog_s 30 | STATIC 31 | ${SRCS} 32 | ) 33 | target_link_libraries(zlog_s 34 | ${CMAKE_THREAD_PREFER_PTHREAD} 35 | ) 36 | 37 | if (WIN32) 38 | target_link_libraries(zlog_s 39 | ${UNIXEM_LIBRARY} 40 | Ws2_32 41 | ) 42 | endif() 43 | 44 | set_target_properties(zlog_s PROPERTIES OUTPUT_NAME zlog) 45 | 46 | #================================================================ 47 | # generate zlog-chk-conf 48 | #================================================================ 49 | add_executable(zlog-chk-conf zlog-chk-conf.c) 50 | target_link_libraries(zlog-chk-conf zlog) 51 | 52 | #================================================================ 53 | # install 54 | #================================================================ 55 | install(TARGETS 56 | zlog zlog_s zlog-chk-conf 57 | COMPONENT zlog 58 | ARCHIVE DESTINATION lib 59 | LIBRARY DESTINATION lib 60 | RUNTIME DESTINATION bin 61 | ) 62 | 63 | install(FILES 64 | zlog.h 65 | COMPONENT zlog 66 | DESTINATION include 67 | ) 68 | -------------------------------------------------------------------------------- /src/zc_xplatform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | #ifndef __zc_xplatform_h 9 | #define __zc_xplatform_h 10 | 11 | #include 12 | 13 | #define ZLOG_INT32_LEN sizeof("-2147483648") - 1 14 | #define ZLOG_INT64_LEN sizeof("-9223372036854775808") - 1 15 | 16 | #if ((__GNU__ == 2) && (__GNUC_MINOR__ < 8)) 17 | #define ZLOG_MAX_UINT32_VALUE (uint32_t) 0xffffffffLL 18 | #else 19 | #define ZLOG_MAX_UINT32_VALUE (uint32_t) 0xffffffff 20 | #endif 21 | 22 | #define ZLOG_MAX_INT32_VALUE (uint32_t) 0x7fffffff 23 | 24 | #define MAXLEN_PATH 1024 25 | #define MAXLEN_CFG_LINE (MAXLEN_PATH * 4) 26 | #define MAXLINES_NO 128 27 | 28 | #define FILE_NEWLINE "\n" 29 | #define FILE_NEWLINE_LEN 1 30 | 31 | #include 32 | #include 33 | 34 | #define STRCMP(_a_,_C_,_b_) ( strcmp(_a_,_b_) _C_ 0 ) 35 | #define STRNCMP(_a_,_C_,_b_,_n_) ( strncmp(_a_,_b_,_n_) _C_ 0 ) 36 | #define STRICMP(_a_,_C_,_b_) ( strcasecmp(_a_,_b_) _C_ 0 ) 37 | #define STRNICMP(_a_,_C_,_b_,_n_) ( strncasecmp(_a_,_b_,_n_) _C_ 0 ) 38 | 39 | 40 | #ifdef __APPLE__ 41 | #include 42 | #endif 43 | 44 | /* Define zlog_fstat to fstat or fstat64() */ 45 | #if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6) 46 | #define zlog_fstat fstat64 47 | #define zlog_stat stat64 48 | #elif defined(_WIN32) 49 | #define zlog_fstat _fstat 50 | #define zlog_stat _stat 51 | #else 52 | #define zlog_fstat fstat 53 | #define zlog_stat stat 54 | #endif 55 | 56 | /* Define zlog_fsync to fdatasync() in Linux and fsync() for all the rest */ 57 | #ifdef __linux__ 58 | #define zlog_fsync fdatasync 59 | #else 60 | #define zlog_fsync fsync 61 | #endif 62 | 63 | 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /test/test_press_zlog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "zlog.h" 17 | 18 | static zlog_category_t *zc; 19 | static long loop_count; 20 | 21 | void * work(void *ptr) 22 | { 23 | long j = loop_count; 24 | while(j-- > 0) { 25 | zlog_info(zc, "loglog"); 26 | } 27 | return 0; 28 | } 29 | 30 | 31 | int test(long process_count, long thread_count) 32 | { 33 | long i; 34 | pid_t pid; 35 | long j; 36 | 37 | for (i = 0; i < process_count; i++) { 38 | pid = fork(); 39 | if (pid < 0) { 40 | printf("fork fail\n"); 41 | } else if(pid == 0) { 42 | pthread_t tid[thread_count]; 43 | for (j = 0; j < thread_count; j++) { 44 | pthread_create(&(tid[j]), NULL, work, NULL); 45 | } 46 | for (j = 0; j < thread_count; j++) { 47 | pthread_join(tid[j], NULL); 48 | } 49 | return 0; 50 | } 51 | } 52 | 53 | for (i = 0; i < process_count; i++) { 54 | pid = wait(NULL); 55 | } 56 | 57 | return 0; 58 | } 59 | 60 | 61 | int main(int argc, char** argv) 62 | { 63 | int rc; 64 | 65 | if (argc != 4) { 66 | fprintf(stderr, "test nprocess nthreads nloop\n"); 67 | exit(1); 68 | } 69 | 70 | rc = zlog_init("test_press_zlog.conf"); 71 | if (rc) { 72 | printf("init failed\n"); 73 | return 2; 74 | } 75 | 76 | zc = zlog_get_category("my_cat"); 77 | if (!zc) { 78 | printf("get cat failed\n"); 79 | zlog_fini(); 80 | return 3; 81 | } 82 | 83 | loop_count = atol(argv[3]); 84 | test(atol(argv[1]), atol(argv[2])); 85 | 86 | zlog_fini(); 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_buf_h 10 | #define __zlog_buf_h 11 | 12 | /* buf, is a dynamic expand buffer for one single log, 13 | * as one single log will interlace if use multiple write() to file. 14 | * and buf is always keep in a thread, to make each thread has its 15 | * own buffer to avoid lock. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | typedef struct zlog_buf_s { 22 | char *start; 23 | char *tail; 24 | char *end; 25 | char *end_plus_1; 26 | 27 | size_t size_min; 28 | size_t size_max; 29 | size_t size_real; 30 | 31 | char truncate_str[MAXLEN_PATH + 1]; 32 | size_t truncate_str_len; 33 | } zlog_buf_t; 34 | 35 | 36 | zlog_buf_t *zlog_buf_new(size_t min, size_t max, const char *truncate_str); 37 | void zlog_buf_del(zlog_buf_t * a_buf); 38 | void zlog_buf_profile(zlog_buf_t * a_buf, int flag); 39 | 40 | int zlog_buf_vprintf(zlog_buf_t * a_buf, const char *format, va_list args); 41 | int zlog_buf_append(zlog_buf_t * a_buf, const char *str, size_t str_len); 42 | int zlog_buf_adjust_append(zlog_buf_t * a_buf, const char *str, size_t str_len, 43 | int left_adjust, int zero_pad, size_t in_width, size_t out_width); 44 | int zlog_buf_printf_dec32(zlog_buf_t * a_buf, uint32_t ui32, int width); 45 | int zlog_buf_printf_dec64(zlog_buf_t * a_buf, uint64_t ui64, int width); 46 | int zlog_buf_printf_hex(zlog_buf_t * a_buf, uint32_t ui32, int width); 47 | 48 | #define zlog_buf_restart(a_buf) do { \ 49 | a_buf->tail = a_buf->start; \ 50 | } while(0) 51 | 52 | #define zlog_buf_len(a_buf) (a_buf->tail - a_buf->start) 53 | #define zlog_buf_str(a_buf) (a_buf->start) 54 | #define zlog_buf_seal(a_buf) do {*(a_buf)->tail = '\0';} while (0) 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /test/test_press_zlog2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "zlog.h" 19 | 20 | static long loop_count; 21 | 22 | 23 | void * work(void *ptr) 24 | { 25 | long j = loop_count; 26 | char category[20]; 27 | sprintf(category, "cat%ld", (long)ptr); 28 | zlog_category_t *zc; 29 | 30 | zc = zlog_get_category(category); 31 | 32 | while(j-- > 0) { 33 | zlog_info(zc, "loglog"); 34 | } 35 | return 0; 36 | } 37 | 38 | 39 | int test(long process_count, long thread_count) 40 | { 41 | long i; 42 | pid_t pid; 43 | long j; 44 | 45 | for (i = 0; i < process_count; i++) { 46 | pid = fork(); 47 | if (pid < 0) { 48 | printf("fork fail\n"); 49 | } else if(pid == 0) { 50 | pthread_t tid[thread_count]; 51 | 52 | for (j = 0; j < thread_count; j++) { 53 | pthread_create(&(tid[j]), NULL, work, (void*)j); 54 | } 55 | for (j = 0; j < thread_count; j++) { 56 | pthread_join(tid[j], NULL); 57 | } 58 | return 0; 59 | } 60 | } 61 | 62 | for (i = 0; i < process_count; i++) { 63 | pid = wait(NULL); 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | 70 | int main(int argc, char** argv) 71 | { 72 | int rc = 0; 73 | if (argc != 4) { 74 | fprintf(stderr, "test nprocess nthreads nloop\n"); 75 | exit(1); 76 | } 77 | 78 | rc = zlog_init("test_press_zlog2.conf"); 79 | if (rc) { 80 | printf("init failed\n"); 81 | return 2; 82 | } 83 | 84 | loop_count = atol(argv[3]); 85 | test(atol(argv[1]), atol(argv[2])); 86 | 87 | zlog_fini(); 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/zc_hashtable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zc_hashtalbe_h 10 | #define __zc_hashtalbe_h 11 | 12 | #include 13 | 14 | typedef struct zc_hashtable_entry_s { 15 | unsigned int hash_key; 16 | void *key; 17 | void *value; 18 | struct zc_hashtable_entry_s *prev; 19 | struct zc_hashtable_entry_s *next; 20 | } zc_hashtable_entry_t; 21 | 22 | typedef struct zc_hashtable_s zc_hashtable_t; 23 | 24 | typedef unsigned int (*zc_hashtable_hash_fn) (const void *key); 25 | typedef int (*zc_hashtable_equal_fn) (const void *key1, const void *key2); 26 | typedef void (*zc_hashtable_del_fn) (void *kv); 27 | 28 | zc_hashtable_t *zc_hashtable_new(size_t a_size, 29 | zc_hashtable_hash_fn hash_fn, 30 | zc_hashtable_equal_fn equal_fn, 31 | zc_hashtable_del_fn key_del_fn, 32 | zc_hashtable_del_fn value_del_fn); 33 | 34 | void zc_hashtable_del(zc_hashtable_t * a_table); 35 | void zc_hashtable_clean(zc_hashtable_t * a_table); 36 | int zc_hashtable_put(zc_hashtable_t * a_table, void *a_key, void *a_value); 37 | zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t * a_table, const void *a_key); 38 | void *zc_hashtable_get(zc_hashtable_t * a_table, const void *a_key); 39 | void zc_hashtable_remove(zc_hashtable_t * a_table, const void *a_key); 40 | zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t * a_table); 41 | zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t * a_table, zc_hashtable_entry_t * a_entry); 42 | 43 | #define zc_hashtable_foreach(a_table, a_entry) \ 44 | for(a_entry = zc_hashtable_begin(a_table); a_entry; a_entry = zc_hashtable_next(a_table, a_entry)) 45 | 46 | unsigned int zc_hashtable_str_hash(const void *str); 47 | int zc_hashtable_str_equal(const void *key1, const void *key2); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /test/test_press_write2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "zlog.h" 19 | 20 | static long loop_count; 21 | 22 | 23 | void * work(void *ptr) 24 | { 25 | long j = loop_count; 26 | static char log[] = "2012-06-14 20:30:38.481187 INFO 24536:140716226213632:test_press_zlog.c:36 loglog\n"; 27 | char file[20]; 28 | 29 | sprintf(file, "press.%ld.log", (long)ptr); 30 | 31 | int fd; 32 | fd = open(file, O_CREAT | O_WRONLY | O_APPEND , 0644); 33 | //FILE *fp; 34 | 35 | while(j-- > 0) { 36 | write(fd, log, sizeof(log)-1); 37 | //fwrite(log, sizeof(log)-1, 1, fp); 38 | } 39 | //fclose(fp); 40 | close(fd); 41 | return 0; 42 | } 43 | 44 | 45 | int test(long process_count, long thread_count) 46 | { 47 | long i; 48 | pid_t pid; 49 | long j; 50 | 51 | for (i = 0; i < process_count; i++) { 52 | pid = fork(); 53 | if (pid < 0) { 54 | printf("fork fail\n"); 55 | } else if(pid == 0) { 56 | pthread_t tid[thread_count]; 57 | 58 | for (j = 0; j < thread_count; j++) { 59 | pthread_create(&(tid[j]), NULL, work, (void*)j); 60 | } 61 | for (j = 0; j < thread_count; j++) { 62 | pthread_join(tid[j], NULL); 63 | } 64 | return 0; 65 | } 66 | } 67 | 68 | for (i = 0; i < process_count; i++) { 69 | pid = wait(NULL); 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | 76 | int main(int argc, char** argv) 77 | { 78 | if (argc != 4) { 79 | fprintf(stderr, "test nprocess nthreads nloop\n"); 80 | exit(1); 81 | } 82 | 83 | 84 | loop_count = atol(argv[3]); 85 | test(atol(argv[1]), atol(argv[2])); 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /test/test_press_write.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | #include "zlog.h" 20 | 21 | int fd; 22 | static long loop_count; 23 | 24 | 25 | void * work(void *ptr) 26 | { 27 | long j = loop_count; 28 | static char aa[] = "2012-06-14 20:30:38.481187 INFO 24536:140716226213632:test_press_zlog.c:36 loglog\n"; 29 | 30 | while(j-- > 0) { 31 | // fprintf(fp, "2012-05-16 17:24:58.282603 INFO 22471:test_press_zlog.c:33 loglog\n"); 32 | // fwrite(aa, sizeof(aa)-1, 1, fp); 33 | write(fd, aa, sizeof(aa)-1); 34 | } 35 | return 0; 36 | } 37 | 38 | 39 | int test(long process_count, long thread_count) 40 | { 41 | long i; 42 | pid_t pid; 43 | long j; 44 | 45 | for (i = 0; i < process_count; i++) { 46 | pid = fork(); 47 | if (pid < 0) { 48 | printf("fork fail\n"); 49 | } else if(pid == 0) { 50 | pthread_t tid[thread_count]; 51 | 52 | for (j = 0; j < thread_count; j++) { 53 | pthread_create(&(tid[j]), NULL, work, NULL); 54 | } 55 | for (j = 0; j < thread_count; j++) { 56 | pthread_join(tid[j], NULL); 57 | } 58 | return 0; 59 | } 60 | } 61 | 62 | for (i = 0; i < process_count; i++) { 63 | pid = wait(NULL); 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | 70 | int main(int argc, char** argv) 71 | { 72 | if (argc != 4) { 73 | fprintf(stderr, "test nprocess nthreads nloop\n"); 74 | exit(1); 75 | } 76 | 77 | 78 | fd = open("press.log", O_CREAT | O_WRONLY | O_APPEND, 0644); 79 | //fp = fdopen(fd, "a"); 80 | loop_count = atol(argv[3]); 81 | test(atol(argv[1]), atol(argv[2])); 82 | //fclose(fp); 83 | close(fd); 84 | 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/zlog_win.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "zlog_win.h" 8 | #include 9 | #include 10 | 11 | int gethostname_w(char *name, size_t len) 12 | { 13 | int rc = gethostname(name, len); 14 | DWORD newlen = len; 15 | 16 | if (rc != 0) { 17 | rc = GetComputerNameEx(ComputerNameDnsHostname, name, &newlen); 18 | if (rc == 0) { 19 | sprintf(name, "noname"); 20 | } 21 | } 22 | return 0; 23 | } 24 | #ifndef strcasecmp 25 | int strcasecmp (const char *sz1, const char *sz2) 26 | { 27 | return stricmp (sz1, sz2); 28 | } 29 | #endif 30 | #ifndef localtime_r 31 | struct tm *localtime_r(const time_t *timep, struct tm *result) 32 | { 33 | struct tm *ret = localtime(timep); 34 | if (ret) 35 | { 36 | memcpy(result, ret, sizeof(struct tm)); 37 | } 38 | return ret; 39 | } 40 | #endif 41 | int fsync (int fd) 42 | { 43 | HANDLE h = (HANDLE) _get_osfhandle (fd); 44 | DWORD err; 45 | 46 | if (h == INVALID_HANDLE_VALUE) 47 | { 48 | errno = EBADF; 49 | return -1; 50 | } 51 | 52 | if (!FlushFileBuffers (h)) 53 | { 54 | /* Translate some Windows errors into rough approximations of Unix 55 | * errors. MSDN is useless as usual - in this case it doesn't 56 | * document the full range of errors. 57 | */ 58 | err = GetLastError (); 59 | switch (err) 60 | { 61 | /* eg. Trying to fsync a tty. */ 62 | case ERROR_INVALID_HANDLE: 63 | errno = EINVAL; 64 | break; 65 | default: 66 | errno = EIO; 67 | } 68 | return -1; 69 | } 70 | return 0; 71 | } 72 | 73 | void setenv(const char *name, const char *value) 74 | { 75 | #ifdef HAVE_SETENV 76 | setenv(name, value, 1); 77 | #else 78 | int len = strlen(value)+1+strlen(value)+1; 79 | char *str = malloc(len); 80 | sprintf(str, "%s=%s", name, value); 81 | putenv(str); 82 | #endif 83 | } 84 | -------------------------------------------------------------------------------- /cpack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # create by lsm 2 | 3 | #====================================== 4 | # vendor info 5 | #====================================== 6 | SET(CPACK_PACKAGE_VENDOR "zlog") 7 | SET(CPACK_PACKAGE_CONTACT "HardySimpson1984@gmail.com") 8 | SET(CPACK_RPM_PACKAGE_LICENSE "LGPL") 9 | 10 | #====================================== 11 | # default install prefix. 12 | #====================================== 13 | SET(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local") 14 | SET(CPACK_RPM_PACKAGE_GROUP "System Environment/Base") 15 | 16 | #================================= 17 | # set platform. 18 | #================================= 19 | message(STATUS "system process is ${CMAKE_HOST_SYSTEM_PROCESSOR}") 20 | message(STATUS "system process is ${CMAKE_SYSTEM_PROCESSOR}") 21 | 22 | IF (NOT CMAKE_SYSTEM_PROCESSOR) 23 | set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) 24 | endif() 25 | 26 | IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64|amd64") 27 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 28 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE amd64) 29 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") 30 | ELSEIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc64|ppc64") 31 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE powerpc64) 32 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE "ppc64") 33 | ELSEIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc|ppc") 34 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE powerpc) 35 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE "ppc") 36 | ELSE() 37 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386) 38 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE i386) 39 | ENDIF() 40 | SET(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") 41 | SET(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") 42 | 43 | #====================================== 44 | # generator setting. 45 | #====================================== 46 | SET(CPACK_CMAKE_GENERATOR "Unix Makefiles") 47 | if (WIN32) 48 | SET(CPACK_GENERATOR "NSIS") 49 | else() 50 | SET(CPACK_GENERATOR "RPM;DEB") 51 | endif() 52 | 53 | #====================================== 54 | # package. 55 | #====================================== 56 | add_subdirectory(zlog) 57 | -------------------------------------------------------------------------------- /doc/performence.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------------- 2 | using makefile.linux for test, libzlog compile in O2 3 | ------------------------------------------------- 4 | [direct write, no logging library] - The Sky! 5 | $ time ./test_press_write 1 10 100000 6 | real 0m1.872s 7 | user 0m0.140s 8 | sys 0m3.290s 9 | 10 | $ time ./test_press_write2 1 10 100000 11 | real 0m0.909s 12 | user 0m0.080s 13 | sys 0m1.710s 14 | ------------------------------------------------- 15 | v1.1.1 (fwrite is not atomic, so backup to write) 16 | $ time ./test_press_zlog 1 10 100000 17 | real 0m2.334s 18 | user 0m1.780s 19 | sys 0m2.710s 20 | 21 | $ time ./test_press_zlog2 1 10 100000 22 | real 0m2.134s 23 | user 0m1.840s 24 | sys 0m1.990s 25 | ------------------------------------------------- 26 | v1.1.0 27 | $ time ./test_press_zlog 1 10 100000 28 | real 0m1.107s 29 | user 0m1.500s 30 | sys 0m0.340s 31 | 32 | $ time ./test_press_zlog2 1 10 100000 33 | real 0m0.898s 34 | user 0m1.480s 35 | sys 0m0.150s 36 | ------------------------------------------------- 37 | v1.0.7 38 | $ time ./test_press_zlog 1 10 100000 39 | real 0m1.783s 40 | user 0m3.000s 41 | sys 0m0.300s 42 | 43 | $ time ./test_press_zlog2 1 10 100000 44 | real 0m1.621s 45 | user 0m2.980s 46 | sys 0m0.120s 47 | ------------------------------------------------- 48 | v1.0.6 49 | $ time ./test_press_zlog 1 10 100000 50 | real 0m1.814s 51 | user 0m3.060s 52 | sys 0m0.270s 53 | 54 | $ time ./test_press_zlog2 1 10 100000 55 | real 0m1.605s 56 | user 0m2.990s 57 | sys 0m0.140s 58 | ------------------------------------------------- 59 | v1.0.5 60 | $ time ./test_press_zlog 1 10 100000 61 | real 0m2.779s 62 | user 0m4.170s 63 | sys 0m0.560s 64 | 65 | $ time ./test_press_zlog2 1 10 100000 66 | real 0m2.713s 67 | user 0m4.410s 68 | sys 0m0.900s 69 | ------------------------------------------------- 70 | v1.0.3 71 | $ time ./test_press_zlog 1 10 100000 72 | 73 | real 0m6.349s 74 | user 0m6.300s 75 | sys 0m5.950s 76 | 77 | $ time ./test_press_zlog2 1 10 100000 78 | real 0m6.377s 79 | user 0m6.240s 80 | sys 0m6.090s 81 | ------------------------------------------------- 82 | v1.0.0 83 | $ time ./test_press_zlog 1 10 100000 84 | real 0m6.364s 85 | user 0m6.040s 86 | sys 0m6.270s 87 | 88 | $ time ./test_press_zlog2 1 10 100000 89 | real 0m6.361s 90 | user 0m6.150s 91 | sys 0m6.020s 92 | ------------------------------------------------- 93 | -------------------------------------------------------------------------------- /src/rule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | /** 10 | * @file rule.h 11 | * @brief rule decide to output in format by category & level 12 | */ 13 | 14 | #ifndef __zlog_rule_h 15 | #define __zlog_rule_h 16 | 17 | #include 18 | #include 19 | 20 | #include "zc_defs.h" 21 | #include "format.h" 22 | #include "thread.h" 23 | #include "rotater.h" 24 | #include "record.h" 25 | 26 | typedef struct zlog_rule_s zlog_rule_t; 27 | 28 | typedef int (*zlog_rule_output_fn) (zlog_rule_t * a_rule, zlog_thread_t * a_thread); 29 | 30 | struct zlog_rule_s { 31 | char category[MAXLEN_CFG_LINE + 1]; 32 | char compare_char; 33 | /* 34 | * [*] log all level 35 | * [.] log level >= rule level, default 36 | * [=] log level == rule level 37 | * [!] log level != rule level 38 | */ 39 | int level; 40 | unsigned char level_bitmap[32]; /* for category determine whether output or not */ 41 | 42 | unsigned int file_perms; 43 | int file_open_flags; 44 | 45 | char file_path[MAXLEN_PATH + 1]; 46 | zc_arraylist_t *dynamic_specs; 47 | int static_fd; 48 | dev_t static_dev; 49 | ino_t static_ino; 50 | 51 | long archive_max_size; 52 | int archive_max_count; 53 | char archive_path[MAXLEN_PATH + 1]; 54 | zc_arraylist_t *archive_specs; 55 | 56 | FILE *pipe_fp; 57 | int pipe_fd; 58 | 59 | size_t fsync_period; 60 | size_t fsync_count; 61 | 62 | zc_arraylist_t *levels; 63 | int syslog_facility; 64 | 65 | zlog_format_t *format; 66 | zlog_rule_output_fn output; 67 | 68 | char record_name[MAXLEN_PATH + 1]; 69 | char record_path[MAXLEN_PATH + 1]; 70 | zlog_record_fn record_func; 71 | }; 72 | 73 | zlog_rule_t *zlog_rule_new(char * line, 74 | zc_arraylist_t * levels, 75 | zlog_format_t * default_format, 76 | zc_arraylist_t * formats, 77 | unsigned int file_perms, 78 | size_t fsync_period, 79 | int * time_cache_count); 80 | 81 | void zlog_rule_del(zlog_rule_t * a_rule); 82 | void zlog_rule_profile(zlog_rule_t * a_rule, int flag); 83 | int zlog_rule_match_category(zlog_rule_t * a_rule, char *category); 84 | int zlog_rule_is_wastebin(zlog_rule_t * a_rule); 85 | int zlog_rule_set_record(zlog_rule_t * a_rule, zc_hashtable_t *records); 86 | int zlog_rule_output(zlog_rule_t * a_rule, zlog_thread_t * a_thread); 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_event_h 10 | #define __zlog_event_h 11 | 12 | #include /* for pid_t */ 13 | #include /* for struct timeval */ 14 | #include /* for pthread_t */ 15 | #include /* for va_list */ 16 | #include "zc_defs.h" 17 | 18 | typedef enum { 19 | ZLOG_FMT = 0, 20 | ZLOG_HEX = 1, 21 | } zlog_event_cmd; 22 | 23 | typedef struct zlog_time_cache_s { 24 | char str[MAXLEN_CFG_LINE + 1]; 25 | size_t len; 26 | time_t sec; 27 | } zlog_time_cache_t; 28 | 29 | typedef struct { 30 | char *category_name; 31 | size_t category_name_len; 32 | char host_name[256 + 1]; 33 | size_t host_name_len; 34 | 35 | const char *file; 36 | size_t file_len; 37 | const char *func; 38 | size_t func_len; 39 | long line; 40 | int level; 41 | 42 | const void *hex_buf; 43 | size_t hex_buf_len; 44 | const char *str_format; 45 | va_list str_args; 46 | zlog_event_cmd generate_cmd; 47 | 48 | struct timeval time_stamp; 49 | 50 | time_t time_utc_sec; 51 | struct tm time_utc; 52 | time_t time_local_sec; 53 | struct tm time_local; 54 | 55 | zlog_time_cache_t *time_caches; 56 | int time_cache_count; 57 | 58 | pid_t pid; 59 | pid_t last_pid; 60 | char pid_str[30 + 1]; 61 | size_t pid_str_len; 62 | 63 | pthread_t tid; 64 | char tid_str[30 + 1]; 65 | size_t tid_str_len; 66 | 67 | char tid_hex_str[30 + 1]; 68 | size_t tid_hex_str_len; 69 | 70 | #if defined __linux__ || __APPLE__ 71 | pid_t ktid; 72 | char ktid_str[30+1]; 73 | size_t ktid_str_len; 74 | #endif 75 | } zlog_event_t; 76 | 77 | 78 | zlog_event_t *zlog_event_new(int time_cache_count); 79 | void zlog_event_del(zlog_event_t * a_event); 80 | void zlog_event_profile(zlog_event_t * a_event, int flag); 81 | 82 | void zlog_event_set_fmt(zlog_event_t * a_event, 83 | char *category_name, size_t category_name_len, 84 | const char *file, size_t file_len, const char *func, size_t func_len, long line, int level, 85 | const char *str_format, va_list str_args); 86 | 87 | void zlog_event_set_hex(zlog_event_t * a_event, 88 | char *category_name, size_t category_name_len, 89 | const char *file, size_t file_len, const char *func, size_t func_len, long line, int level, 90 | const void *hex_buf, size_t hex_buf_len); 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /src/zc_profile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include "fmacros.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "zc_profile.h" 21 | #include "zc_xplatform.h" 22 | 23 | static void zc_time(char *time_str, size_t time_str_size) 24 | { 25 | time_t tt; 26 | 27 | time(&tt); 28 | #ifdef _WIN32 29 | struct tm *local_time; 30 | local_time = localtime(&tt); 31 | strftime(time_str, time_str_size, "%m-%d %H:%M:%S", local_time); 32 | #else 33 | struct tm local_time; 34 | localtime_r(&tt, &local_time); 35 | strftime(time_str, time_str_size, "%m-%d %H:%M:%S", &local_time); 36 | #endif 37 | 38 | return; 39 | } 40 | 41 | int zc_profile_inner(int flag, const char *file, const long line, const char *fmt, ...) 42 | { 43 | va_list args; 44 | char time_str[20 + 1]; 45 | FILE *fp = NULL; 46 | 47 | static char *debug_log = NULL; 48 | static char *error_log = NULL; 49 | static size_t init_flag = 0; 50 | 51 | if (!init_flag) { 52 | init_flag = 1; 53 | debug_log = getenv("ZLOG_PROFILE_DEBUG"); 54 | error_log = getenv("ZLOG_PROFILE_ERROR"); 55 | } 56 | 57 | switch (flag) { 58 | case ZC_DEBUG: 59 | if (debug_log == NULL) return 0; 60 | fp = fopen(debug_log, "a"); 61 | if (!fp) return -1; 62 | zc_time(time_str, sizeof(time_str)); 63 | fprintf(fp, "%s DEBUG (%d:%s:%ld) ", time_str, getpid(), file, line); 64 | break; 65 | case ZC_WARN: 66 | if (error_log == NULL) return 0; 67 | fp = fopen(error_log, "a"); 68 | if (!fp) return -1; 69 | zc_time(time_str, sizeof(time_str)); 70 | fprintf(fp, "%s WARN (%d:%s:%ld) ", time_str, getpid(), file, line); 71 | break; 72 | case ZC_ERROR: 73 | if (error_log == NULL) return 0; 74 | fp = fopen(error_log, "a"); 75 | if (!fp) return -1; 76 | zc_time(time_str, sizeof(time_str)); 77 | fprintf(fp, "%s ERROR (%d:%s:%ld) ", time_str, getpid(), file, line); 78 | break; 79 | } 80 | 81 | /* writing file twice(time & msg) is not atomic 82 | * may cause cross 83 | * but avoid log size limit */ 84 | va_start(args, fmt); 85 | vfprintf(fp, fmt, args); 86 | va_end(args); 87 | fprintf(fp, "\n"); 88 | 89 | fclose(fp); 90 | return 0; 91 | } 92 | 93 | -------------------------------------------------------------------------------- /test/test_hex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zlog.h" 16 | #include "stdlib.h" 17 | 18 | static int ReadTotalFile( FILE * fp , char ** ptr , long * len ) 19 | { 20 | long fileLen ; 21 | int nret ; 22 | char * pStart ; 23 | 24 | *ptr = NULL; 25 | 26 | nret = fseek( fp , 0L , SEEK_END ); 27 | if( nret ) 28 | { 29 | return -1; 30 | } 31 | 32 | fileLen = ftell( fp ); 33 | if( fileLen < 0 ) 34 | { 35 | return -2; 36 | } 37 | 38 | if( ( pStart = calloc(1, fileLen+1) ) == NULL ) 39 | { 40 | return -3; 41 | } 42 | 43 | nret = fseek( fp , 0L , SEEK_SET ); 44 | if( nret ) 45 | { 46 | free( pStart ); 47 | return -4; 48 | } 49 | 50 | nret = fread( pStart , fileLen , 1 , fp ); 51 | if( ferror( fp ) ) 52 | { 53 | free( pStart ); 54 | return -5; 55 | } 56 | 57 | *ptr = pStart; 58 | *len = fileLen; 59 | 60 | return 0; 61 | } 62 | 63 | int main(int argc, char** argv) 64 | { 65 | int rc; 66 | 67 | FILE *fp; 68 | char *dmp; 69 | long dmp_len = 0; 70 | int ntimes; 71 | 72 | if (argc != 3) { 73 | printf("useage: test_hex [file] [ntimes]\n"); 74 | exit(1); 75 | } 76 | 77 | fp = fopen(argv[1], "r"); 78 | if (!fp) { 79 | printf("fopen[%s] fail\n", argv[1]); 80 | exit(1); 81 | } 82 | 83 | ntimes = atoi(argv[2]); 84 | 85 | zlog_category_t *zc; 86 | 87 | rc = zlog_init("test_hex.conf"); 88 | if (rc) { 89 | printf("init failed\n"); 90 | return -1; 91 | } 92 | 93 | zc = zlog_get_category("my_cat"); 94 | if (!zc) { 95 | printf("get category failed\n"); 96 | zlog_fini(); 97 | return -2; 98 | } 99 | 100 | 101 | rc = ReadTotalFile(fp, &dmp, &dmp_len); 102 | 103 | while(ntimes--) hzlog_debug(zc, dmp, dmp_len); 104 | 105 | fclose(fp); 106 | free(dmp); 107 | 108 | zlog_fini(); 109 | printf("hex log end\n"); 110 | 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # create by lsm 2 | # cmake 3 | 4 | cmake_minimum_required(VERSION 2.8.5) 5 | 6 | message(STATUS "path : ${CMAKE_FIND_ROOT_PATH}") 7 | project(zlog) 8 | message(STATUS "path : ${CMAKE_FIND_ROOT_PATH}") 9 | 10 | set(CMAKE_MODULE_PATH ${zlog_SOURCE_DIR}/cmake) 11 | 12 | #===================================== 13 | # version of zlog 14 | #===================================== 15 | SET(CPACK_PACKAGE_VERSION_MAJOR "1") 16 | SET(CPACK_PACKAGE_VERSION_MINOR "2") 17 | SET(CPACK_PACKAGE_VERSION_PATCH "12") 18 | SET(CPACK_RPM_PACKAGE_RELEASE 1) #release version. 19 | SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") 20 | SET(zlog_ver ${CPACK_PACKAGE_VERSION}) 21 | SET(zlog_so_ver ${CPACK_PACKAGE_VERSION_MAJOR}) 22 | 23 | #======================================================= 24 | 25 | message(STATUS "plateform : ${CMAKE_SYSTEM}") 26 | 27 | add_definitions("-g -Wall -Wstrict-prototypes") 28 | set(CMAKE_C_FLAGS "-std=c99 -pedantic -D_DEFAULT_SOURCE") 29 | set(CMAKE_C_FLAGS_DEBUG "-ggdb3 -DDEBUG") 30 | set(CMAKE_C_FLAGS_RELEASE "-O2") 31 | 32 | if (WIN32) 33 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 ") 34 | endif() 35 | 36 | #===================================================== 37 | # include dir 38 | # include_directories(include) 39 | #===================================================== 40 | 41 | #===================================================== 42 | # lib output path. 43 | cmake_policy(SET CMP0015 NEW) 44 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${zlog_BINARY_DIR}/lib") 45 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${zlog_BINARY_DIR}/lib") 46 | # bin output path. 47 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${zlog_BINARY_DIR}/bin") 48 | #===================================================== 49 | 50 | #===================================================== 51 | # link path. 52 | link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) 53 | #===================================================== 54 | 55 | #===================================================== 56 | # library depend. 57 | set(Need_THREAD 1) 58 | if (WIN32) 59 | set(Need_UNIXEM 1) 60 | endif() 61 | 62 | include(cmake/LoadLibraries.cmake) 63 | #===================================================== 64 | 65 | #======================================================== 66 | # sub dir 67 | add_subdirectory(src) 68 | add_subdirectory(cpack) 69 | #======================================================== 70 | 71 | #======================================================== 72 | # for unittest, call "cmake .. -DUNIT_TEST=on" 73 | if(UNIT_TEST) 74 | enable_testing() 75 | add_subdirectory(test) 76 | endif() 77 | #======================================================== 78 | 79 | -------------------------------------------------------------------------------- /test/test_buf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include "zc_defs.h" 11 | #include "buf.h" 12 | 13 | int main(int argc, char** argv) 14 | { 15 | zlog_buf_t *a_buf; 16 | char *aa; 17 | 18 | a_buf = zlog_buf_new(10, 20, "ABC"); 19 | if (!a_buf) { 20 | zc_error("zlog_buf_new fail"); 21 | return -1; 22 | } 23 | 24 | aa = "123456789"; 25 | zlog_buf_append(a_buf, aa, strlen(aa)); 26 | zc_error("a_buf->start[%s]", a_buf->start); 27 | fwrite(a_buf->start, zlog_buf_len(a_buf), 1, stdout); 28 | zc_error("------------"); 29 | 30 | aa = "0"; 31 | zlog_buf_append(a_buf, aa, strlen(aa)); 32 | zc_error("a_buf->start[%s]", a_buf->start); 33 | zc_error("------------"); 34 | 35 | aa = "12345"; 36 | zlog_buf_append(a_buf, aa, strlen(aa)); 37 | zc_error("a_buf->start[%s]", a_buf->start); 38 | zc_error("------------"); 39 | 40 | aa = "6789"; 41 | zlog_buf_append(a_buf, aa, strlen(aa)); 42 | zc_error("a_buf->start[%s]", a_buf->start); 43 | zc_error("------------"); 44 | 45 | aa = "0"; 46 | zlog_buf_append(a_buf, aa, strlen(aa)); 47 | zc_error("a_buf->start[%s]", a_buf->start); 48 | zc_error("------------"); 49 | 50 | aa = "22345"; 51 | zlog_buf_append(a_buf, aa, strlen(aa)); 52 | zc_error("a_buf->start[%s]", a_buf->start); 53 | zc_error("------------"); 54 | 55 | 56 | aa = "abc"; 57 | int i,j; 58 | for (i = 0; i <= 5; i++) { 59 | for (j = 0; j <= 5; j++) { 60 | zlog_buf_restart(a_buf); 61 | zc_error("left[1],max[%d],min[%d]", i, j); 62 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 1, 0, i, j); 63 | zc_error("a_buf->start[%s]", a_buf->start); 64 | 65 | zc_error("-----"); 66 | 67 | zlog_buf_restart(a_buf); 68 | zc_error("left[0],max[%d],min[%d]", i, j); 69 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, i, j); 70 | zc_error("a_buf->start[%s]", a_buf->start); 71 | zc_error("------------"); 72 | } 73 | } 74 | 75 | aa = "1234567890"; 76 | zc_error("left[0],max[%d],min[%d]", 15, 5); 77 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 15, 5); 78 | zc_error("a_buf->start[%s]", a_buf->start); 79 | zc_error("------------"); 80 | 81 | aa = "1234567890"; 82 | zlog_buf_restart(a_buf); 83 | zc_error("left[0],max[%d],min[%d]", 25, 5); 84 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 1, 0, 25, 5); 85 | zc_error("a_buf->start[%s]", a_buf->start); 86 | zc_error("------------"); 87 | 88 | zlog_buf_restart(a_buf); 89 | zc_error("left[0],max[%d],min[%d]", 19, 5); 90 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 19, 5); 91 | zc_error("a_buf->start[%s]", a_buf->start); 92 | zc_error("------------"); 93 | 94 | zlog_buf_restart(a_buf); 95 | zc_error("left[0],max[%d],min[%d]", 20, 5); 96 | zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 20, 5); 97 | zc_error("a_buf->start[%s]", a_buf->start); 98 | zc_error("------------"); 99 | 100 | zlog_buf_del(a_buf); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /cpack/CPackConfig.cmake: -------------------------------------------------------------------------------- 1 | #===================================================# 2 | # pack config. 3 | #===================================================# 4 | SET(CPACK_CMAKE_GENERATOR "${CPACK_CMAKE_GENERATOR}") 5 | SET(CPACK_GENERATOR "${CPACK_GENERATOR}") 6 | SET(CPACK_OUTPUT_CONFIG_FILE "${CPACK_OUTPUT_CONFIG_FILE}") 7 | SET(CPACK_INSTALL_CMAKE_PROJECTS "${CPACK_INSTALL_CMAKE_PROJECTS}") 8 | 9 | SET(CPACK_PACKAGE_VERSION_MAJOR "${CPACK_PACKAGE_VERSION_MAJOR}") 10 | SET(CPACK_PACKAGE_VERSION_MINOR "${CPACK_PACKAGE_VERSION_MINOR}") 11 | SET(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}") 12 | SET(CPACK_RPM_PACKAGE_RELEASE "${CPACK_RPM_PACKAGE_RELEASE}") #release version. 13 | SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}") 14 | 15 | SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}" ) 16 | SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}" ) 17 | SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CPACK_PACKAGE_DESCRIPTION_FILE}" ) 18 | 19 | SET(CPACK_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}" ) 20 | SET(CPACK_PACKAGING_INSTALL_PREFIX "${CPACK_PACKAGING_INSTALL_PREFIX}" ) 21 | SET(CPACK_PACKAGE_CONTACT "${CPACK_PACKAGE_CONTACT}" ) 22 | 23 | SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}") 24 | 25 | SET(CPACK_SYSTEM_NAME "${CPACK_SYSTEM_NAME}") 26 | SET(CPACK_TOPLEVEL_TAG "${CPACK_TOPLEVEL_TAG}") 27 | SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}-${CPACK_TOPLEVEL_TAG}") 28 | 29 | #SET(CPACK_PACKAGE_EXECUTABLES "ccmake;CMake") 30 | #SET(CPACK_STRIP_FILES "bin/ccmake;bin/cmake;bin/cpack;bin/ctest") 31 | 32 | set (CPACK_NSIS_MODIFY_PATH, ON) 33 | 34 | #================================= 35 | # set platform. 36 | #================================= 37 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}" ) 38 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE "${CPACK_RPM_PACKAGE_ARCHITECTURE}" ) 39 | 40 | #================================= 41 | # set dependency. 42 | #================================= 43 | SET(CPACK_RPM_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" ) 44 | SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" ) 45 | 46 | #================================= 47 | # set control script. 48 | #================================= 49 | SET(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA 50 | "${CMAKE_CURRENT_BINARY_DIR}/preinst;${CMAKE_CURRENT_BINARY_DIR}/postinst;${CMAKE_CURRENT_BINARY_DIR}/prerm;${CMAKE_CURRENT_BINARY_DIR}/postrm") 51 | 52 | SET(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/preinst") 53 | SET(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/postinst") 54 | SET(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/prerm") 55 | SET(CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE "${CMAKE_CURRENT_BINARY_DIR}/postrm") 56 | 57 | #===================================================# 58 | # set license 59 | #===================================================# 60 | SET(CPACK_RPM_PACKAGE_LICENSE "${CPACK_RPM_PACKAGE_LICENSE}") 61 | 62 | #===================================================# 63 | # others. 64 | #===================================================# 65 | SET(CPACK_RPM_PACKAGE_GROUP "${CPACK_RPM_PACKAGE_GROUP}") 66 | 67 | -------------------------------------------------------------------------------- /doc/GettingStart-CN.txt: -------------------------------------------------------------------------------- 1 | 0. zlog是什么? 2 | 3 | zlog是一个高可靠性、高性能、线程安全、灵活、概念清晰的纯C日志函数库。 4 | 5 | 事实上,在C的世界里面没有特别好的日志函数库(就像JAVA里面的的log4j,或者C++的log4cxx)。C程序员都喜欢用自己的轮子。printf就是个挺好的轮子,但没办法通过配置改变日志的格式或者输出文件。syslog是个系统级别的轮子,不过速度慢,而且功能比较单调。 6 | 所以我写了zlog。 7 | zlog在效率、功能、安全性上大大超过了log4c,并且是用c写成的,具有比较好的通用性。 8 | 9 | 1.安装 10 | 11 | 下载:https://github.com/HardySimpson/zlog/releases 12 | 13 | $ tar -zxvf zlog-latest-stable.tar.gz 14 | $ cd zlog-latest-stable/ 15 | $ make 16 | $ sudo make install 17 | or 18 | $ make PREFIX=/usr/local/ 19 | $ sudo make PREFIX=/usr/local/ install 20 | 21 | PREFIX指明了安装的路径,安转完之后为了让你的程序能找到zlog动态库 22 | 23 | $ sudo vi /etc/ld.so.conf 24 | /usr/local/lib 25 | $ sudo ldconfig 26 | 27 | 在你的程序运行之前,保证libzlog.so在系统的动态链接库加载器可以找到的目录下。上面的命令适用于linux,别的系统自己想办法。 28 | 29 | 30 | 2.介绍一下配置文件 31 | 32 | zlog里面有三个重要的概念,category,format,rule 33 | 34 | 分类(Category)用于区分不同的输入,代码中的分类变量的名字是一个字符串,在一个程序里面可以通过获取不同的分类名的category用来后面输出不同分类的日志,用于不同的目的。 35 | 36 | 格式(Format)是用来描述输出日志的格式,比如是否有带有时间戳, 是否包含文件位置信息等,上面的例子里面的格式simple就配置成简单的用户输入的信息+换行符。 37 | 38 | 规则(Rule)则是把分类、级别、输出文件、格式组合起来,决定一条代码中的日志是否输出,输出到哪里,以什么格式输出。简单而言,规则里面的分类字符串和代码里面的分类变量的名字一样就匹配,当然还有更高级的纲目分类匹配。规则彻底解耦了各个元素之间的强绑定,例如log4j就必须为每个分类指定一个级别(或者从父分类那里继承),这在多层系统需要每一层都有自己的级别要求的时候非常不方便。 39 | 40 | 现在试着写配置文件,配置文件名无所谓,放在哪里也无所谓,反正在zlog_init()的时候可以指定 41 | $ cat /etc/zlog.conf 42 | 43 | [formats] 44 | simple = "%m%n" 45 | [rules] 46 | my_cat.DEBUG >stdout; simple 47 | 48 | 在目前的配置文件的例子里面,可以看到my_cat分类,>=debug等级的日志会被输出到stdout(标准输出),并且输出的格式是simple这个格式,也就是用户输入信息+换行符。如果要输出到文件并控制文件大小为1兆,规则的配置应该是 49 | my_cat.DEBUG "/var/log/aa.log", 1M; simple 50 | 51 | 3.在代码中使用 52 | $ vi test_hello.c 53 | 54 | #include 55 | 56 | #include "zlog.h" 57 | 58 | int main(int argc, char** argv) 59 | { 60 | int rc; 61 | zlog_category_t *c; 62 | 63 | rc = zlog_init("/etc/zlog.conf"); 64 | if (rc) { 65 | printf("init failed\n"); 66 | return -1; 67 | } 68 | 69 | c = zlog_get_category("my_cat"); 70 | if (!c) { 71 | printf("get cat fail\n"); 72 | zlog_fini(); 73 | return -2; 74 | } 75 | 76 | zlog_info(c, "hello, zlog"); 77 | 78 | zlog_fini(); 79 | 80 | return 0; 81 | } 82 | 83 | 4.编译、然后运行! 84 | 85 | $ cc -c -o test_hello.o test_hello.c -I/usr/local/include 86 | $ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread 87 | $ ./test_hello 88 | hello, zlog 89 | 90 | 5.高级使用 91 | * syslog分类模型,比log4j模型更加直接了当 92 | * 日志格式定制,类似于log4j的pattern layout 93 | * 多种输出,包括动态文件、静态文件、stdout、stderr、syslog、用户自定义输出函数 94 | * 运行时手动、自动刷新配置文件(同时保证安全) 95 | * 高性能,在我的笔记本上达到25万条日志每秒, 大概是syslog(3)配合rsyslogd的1000倍速度 96 | * 用户自定义等级 97 | * 多线程和多进程环境下保证安全转档 98 | * 精确到微秒 99 | * 简单调用包装dzlog(一个程序默认只用一个分类) 100 | * MDC,线程键-值对的表,可以扩展用户自定义的字段 101 | * 自诊断,可以在运行时输出zlog自己的日志和配置状态 102 | * 不依赖其他库,只要是个POSIX系统就成(当然还要一个C99兼容的vsnprintf) 103 | 104 | 6.相关链接 105 | 主页:http://hardysimpson.github.com/zlog/ 106 | 软件下载:https://github.com/HardySimpson/zlog/releases 107 | 作者邮箱:HardySimpson1984@gmail.com 108 | 109 | auto tools版本: https://github.com/bmanojlovic/zlog 110 | cmake版本: https://github.com/lisongmin/zlog 111 | windows版本: https://github.com/lopsd07/WinZlog 112 | -------------------------------------------------------------------------------- /src/zc_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "zc_defs.h" 16 | 17 | size_t zc_parse_byte_size(char *astring) 18 | { 19 | /* Parse size in bytes depending on the suffix. Valid suffixes are KB, MB and GB */ 20 | char *p; 21 | char *q; 22 | size_t sz; 23 | long res; 24 | int c, m; 25 | 26 | zc_assert(astring, 0); 27 | 28 | /* clear space */ 29 | for (p = q = astring; *p != '\0'; p++) { 30 | if (isspace(*p)) { 31 | continue; 32 | } else { 33 | *q = *p; 34 | q++; 35 | } 36 | } 37 | *q = '\0'; 38 | 39 | sz = strlen(astring); 40 | res = strtol(astring, (char **)NULL, 10); 41 | 42 | if (res <= 0) 43 | return 0; 44 | 45 | if (astring[sz - 1] == 'B' || astring[sz - 1] == 'b') { 46 | c = astring[sz - 2]; 47 | m = 1024; 48 | } else { 49 | c = astring[sz - 1]; 50 | m = 1000; 51 | } 52 | 53 | switch (c) { 54 | case 'K': 55 | case 'k': 56 | res *= m; 57 | break; 58 | case 'M': 59 | case 'm': 60 | res *= m * m; 61 | break; 62 | case 'G': 63 | case 'g': 64 | res *= m * m * m; 65 | break; 66 | default: 67 | if (!isdigit(c)) { 68 | zc_error("Wrong suffix parsing " "size in bytes for string [%s], ignoring suffix", 69 | astring); 70 | } 71 | break; 72 | } 73 | 74 | return (res); 75 | } 76 | 77 | /*******************************************************************************/ 78 | int zc_str_replace_env(char *str, size_t str_size) 79 | { 80 | char *p; 81 | char *q; 82 | char fmt[MAXLEN_CFG_LINE + 1]; 83 | char env_key[MAXLEN_CFG_LINE + 1]; 84 | char env_value[MAXLEN_CFG_LINE + 1]; 85 | int str_len; 86 | int env_value_len; 87 | int nscan; 88 | int nread; 89 | 90 | str_len = strlen(str); 91 | q = str; 92 | 93 | do { 94 | p = strchr(q, '%'); 95 | if (!p) { 96 | /* can't find more % */ 97 | break; 98 | } 99 | 100 | memset(fmt, 0x00, sizeof(fmt)); 101 | memset(env_key, 0x00, sizeof(env_key)); 102 | memset(env_value, 0x00, sizeof(env_value)); 103 | nread = 0; 104 | nscan = sscanf(p + 1, "%[.0-9-]%n", fmt + 1, &nread); 105 | if (nscan == 1) { 106 | fmt[0] = '%'; 107 | fmt[nread + 1] = 's'; 108 | } else { 109 | nread = 0; 110 | strcpy(fmt, "%s"); 111 | } 112 | 113 | q = p + 1 + nread; 114 | 115 | nscan = sscanf(q, "E(%[^)])%n", env_key, &nread); 116 | if (nscan == 0) { 117 | continue; 118 | } 119 | 120 | q += nread; 121 | 122 | if (*(q - 1) != ')') { 123 | zc_error("in string[%s] can't find match )", p); 124 | return -1; 125 | } 126 | 127 | env_value_len = snprintf(env_value, sizeof(env_value), fmt, getenv(env_key)); 128 | if (env_value_len < 0 || env_value_len >= sizeof(env_value)) { 129 | zc_error("snprintf fail, errno[%d], evn_value_len[%d]", 130 | errno, env_value_len); 131 | return -1; 132 | } 133 | 134 | str_len = str_len - (q - p) + env_value_len; 135 | if (str_len > str_size - 1) { 136 | zc_error("repalce env_value[%s] cause overlap", env_value); 137 | return -1; 138 | } 139 | 140 | memmove(p + env_value_len, q, strlen(q) + 1); 141 | memcpy(p, env_value, env_value_len); 142 | 143 | } while (1); 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /src/zlog_win.h: -------------------------------------------------------------------------------- 1 | #ifndef _ZLOG_WIN_H_ 2 | #define _ZLOG_WIN_H_ 3 | 4 | #include 5 | 6 | #ifndef localtime_r 7 | struct tm *localtime_r(const time_t *timep, struct tm *result); 8 | #endif 9 | #ifndef strcasecmp 10 | int strcasecmp (const char *sz1, const char *sz2); 11 | #endif 12 | int fsync (int fd); 13 | void setenv(const char *name, const char *value); 14 | int gethostname_w(char *name, size_t len); 15 | 16 | /* facility codes */ 17 | #define LOG_KERN (0<<3) /* kernel messages */ 18 | #define LOG_USER (1<<3) /* random user-level messages */ 19 | #define LOG_MAIL (2<<3) /* mail system */ 20 | #define LOG_DAEMON (3<<3) /* system daemons */ 21 | #define LOG_AUTH (4<<3) /* authorization messages */ 22 | #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ 23 | #define LOG_LPR (6<<3) /* line printer subsystem */ 24 | #define LOG_NEWS (7<<3) /* network news subsystem */ 25 | #define LOG_UUCP (8<<3) /* UUCP subsystem */ 26 | #define LOG_CRON (9<<3) /* clock daemon */ 27 | #define LOG_AUTHPRIV (10<<3) /* authorization messages (private) */ 28 | /* Facility #10 clashes in DEC UNIX, where */ 29 | /* it's defined as LOG_MEGASAFE for AdvFS */ 30 | /* event logging. */ 31 | #define LOG_FTP (11<<3) /* ftp daemon */ 32 | #define LOG_NTP (12<<3) /* NTP subsystem */ 33 | #define LOG_SECURITY (13<<3) /* security subsystems (firewalling, etc.) */ 34 | #define LOG_CONSOLE (14<<3) /* /dev/console output */ 35 | 36 | /* other codes through 15 reserved for system use */ 37 | #define LOG_LOCAL0 (16<<3) /* reserved for local use */ 38 | #define LOG_LOCAL1 (17<<3) /* reserved for local use */ 39 | #define LOG_LOCAL2 (18<<3) /* reserved for local use */ 40 | #define LOG_LOCAL3 (19<<3) /* reserved for local use */ 41 | #define LOG_LOCAL4 (20<<3) /* reserved for local use */ 42 | #define LOG_LOCAL5 (21<<3) /* reserved for local use */ 43 | #define LOG_LOCAL6 (22<<3) /* reserved for local use */ 44 | #define LOG_LOCAL7 (23<<3) /* reserved for local use */ 45 | 46 | /* 47 | * Option flags for openlog. 48 | * 49 | * LOG_ODELAY no longer does anything. 50 | * LOG_NDELAY is the inverse of what it used to be. 51 | */ 52 | #define LOG_PID 0x01 /* log the pid with each message */ 53 | #define LOG_CONS 0x02 /* log on the console if errors in sending */ 54 | #define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ 55 | #define LOG_NDELAY 0x08 /* don't delay open */ 56 | #define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ 57 | #define LOG_PERROR 0x20 /* log to stderr as well */ 58 | 59 | /* 60 | * priorities/facilities are encoded into a single 32-bit quantity, where the 61 | * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility 62 | * (0-big number). Both the priorities and the facilities map roughly 63 | * one-to-one to strings in the syslogd(8) source code. This mapping is 64 | * included in this file. 65 | * 66 | * priorities (these are ordered) 67 | */ 68 | #define LOG_EMERG 0 /* system is unusable */ 69 | #define LOG_ALERT 1 /* action must be taken immediately */ 70 | #define LOG_CRIT 2 /* critical conditions */ 71 | #define LOG_ERR 3 /* error conditions */ 72 | #define LOG_WARNING 4 /* warning conditions */ 73 | #define LOG_NOTICE 5 /* normal but significant condition */ 74 | #define LOG_INFO 6 /* informational */ 75 | #define LOG_DEBUG 7 /* debug-level messages */ 76 | 77 | #define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ 78 | /* extract priority */ 79 | #define LOG_PRI(p) ((p) & LOG_PRIMASK) 80 | #define LOG_MAKEPRI(fac, pri) ((fac) | (pri)) 81 | 82 | #endif -------------------------------------------------------------------------------- /src/zc_arraylist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "zc_defs.h" 15 | 16 | zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del) 17 | { 18 | zc_arraylist_t *a_list; 19 | 20 | a_list = (zc_arraylist_t *) calloc(1, sizeof(zc_arraylist_t)); 21 | if (!a_list) { 22 | zc_error("calloc fail, errno[%d]", errno); 23 | return NULL; 24 | } 25 | a_list->size = ARRAY_LIST_DEFAULT_SIZE; 26 | a_list->len = 0; 27 | 28 | /* this could be NULL */ 29 | a_list->del = del; 30 | a_list->array = (void **)calloc(a_list->size, sizeof(void *)); 31 | if (!a_list->array) { 32 | zc_error("calloc fail, errno[%d]", errno); 33 | free(a_list); 34 | return NULL; 35 | } 36 | 37 | return a_list; 38 | } 39 | 40 | void zc_arraylist_del(zc_arraylist_t * a_list) 41 | { 42 | int i; 43 | 44 | if (!a_list) 45 | return; 46 | if (a_list->del) { 47 | for (i = 0; i < a_list->len; i++) { 48 | if (a_list->array[i]) 49 | a_list->del(a_list->array[i]); 50 | } 51 | } 52 | if (a_list->array) 53 | free(a_list->array); 54 | free(a_list); 55 | return; 56 | } 57 | 58 | static int zc_arraylist_expand_inner(zc_arraylist_t * a_list, int max) 59 | { 60 | void *tmp; 61 | int new_size; 62 | int diff_size; 63 | 64 | new_size = zc_max(a_list->size * 2, max); 65 | tmp = realloc(a_list->array, new_size * sizeof(void *)); 66 | if (!tmp) { 67 | zc_error("realloc fail, errno[%d]", errno); 68 | return -1; 69 | } 70 | a_list->array = (void **)tmp; 71 | diff_size = new_size - a_list->size; 72 | if (diff_size) memset(a_list->array + a_list->size, 0x00, diff_size * sizeof(void *)); 73 | a_list->size = new_size; 74 | return 0; 75 | } 76 | 77 | int zc_arraylist_set(zc_arraylist_t * a_list, int idx, void *data) 78 | { 79 | if (idx > a_list->size - 1) { 80 | if (zc_arraylist_expand_inner(a_list, idx)) { 81 | zc_error("expand_internal fail"); 82 | return -1; 83 | } 84 | } 85 | if (a_list->array[idx] && a_list->del) a_list->del(a_list->array[idx]); 86 | a_list->array[idx] = data; 87 | if (a_list->len <= idx) 88 | a_list->len = idx + 1; 89 | return 0; 90 | } 91 | 92 | int zc_arraylist_add(zc_arraylist_t * a_list, void *data) 93 | { 94 | return zc_arraylist_set(a_list, a_list->len, data); 95 | } 96 | 97 | /* assum idx < len */ 98 | static int zc_arraylist_insert_inner(zc_arraylist_t * a_list, int idx, 99 | void *data) 100 | { 101 | if (a_list->array[idx] == NULL) { 102 | a_list->array[idx] = data; 103 | return 0; 104 | } 105 | if (a_list->len > a_list->size - 1) { 106 | if (zc_arraylist_expand_inner(a_list, 0)) { 107 | zc_error("expand_internal fail"); 108 | return -1; 109 | } 110 | } 111 | memmove(a_list->array + idx + 1, a_list->array + idx, 112 | (a_list->len - idx) * sizeof(void *)); 113 | a_list->array[idx] = data; 114 | a_list->len++; 115 | return 0; 116 | } 117 | 118 | int zc_arraylist_sortadd(zc_arraylist_t * a_list, zc_arraylist_cmp_fn cmp, 119 | void *data) 120 | { 121 | int i; 122 | 123 | for (i = 0; i < a_list->len; i++) { 124 | if ((*cmp) (a_list->array[i], data) > 0) 125 | break; 126 | } 127 | 128 | if (i == a_list->len) 129 | return zc_arraylist_add(a_list, data); 130 | else 131 | return zc_arraylist_insert_inner(a_list, i, data); 132 | } 133 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | --- 1.2.12 --- 2 | [o] bugfix for avoid segmentation fault if call zlog_init() many times 3 | [o] static file rule to emulate python's WatchedFileHandler mode when used with external log rotation 4 | --- 1.2.10 --- 5 | [o] bugfix, LGPL v3 -> LGPL v2.1 6 | --- 1.2.8 --- 7 | [o] gcc __attribute__宏,用于检查zlog的format输出格式 8 | [o] 支持配置文件行中带#注释 9 | --- 1.2.5 --- 10 | [o] 保证在单个线程退出的时候自动删除thread, 用atexit来注册函数解决主线程退出的问题 11 | [o] 缓存多个时间,保证所有的%d在strftime的时候都能每秒缓存,达到和原先%D一样的速度 12 | [o] 鉴于上面那点,去掉%D的使用,虽然库还支持,但文档和实例代码都用%d 13 | [o] 修复makefile静态链接zlog-chk-conf 14 | --- 1.2.4 --- 15 | [o] 不再维持thread_list链表,每次写日志时判断配置有无更新,来刷新每线程的缓存大小 16 | --- 1.2.0 --- 17 | [o] rotate和zip的方案 18 | [o] 把一部分static变量化为全局变量,减少接口参数 19 | [o] fstat64 20 | [o] pipe, cronolog 21 | [o] record忽略第二参数 22 | [o] __VA_ARGS__的跨平台 23 | [o] 增加git/版本在代码中的标志(redis) 24 | [o] 去除auto tools的使用,自行makefile[redis] 25 | [o] 宏都小写化 26 | [o] const 27 | [x] 每线程内置rule-> file fd write time 28 | [x] 用时间作为判断重载配置reload conf period,而不是次数,需要每次取时间计算,暂不考虑 29 | [x] zlog_set_conf("section", "command"); 30 | [x] format,spec,level采用直接数组的方式重写,性能提高不大 31 | [x] 增加manpage, df, 案例 32 | --- 1.1.3 --- 33 | [o] zlog_record动态一点 34 | --- 1.1.2 --- 35 | [o] 修正rule.c, path_buf封顶 36 | --- 1.1.1 --- 37 | [o] 修正rule.c, 不使用FILE*, 避免日志交错 38 | --- 1.1.0 --- 39 | [x] spec改为switch循环, 如果可能的话rule也照样--发现switch的效率不如函数指针 40 | [x] 把__LINE__ 变成string--需要改接口 41 | [o] 建立bit位来判断,无锁判断 42 | [o] 寻找快速的方法把us, srcline变成字符串 43 | [o] 在一开始就判断是否需要输出, 44 | [o] 使用pthread_key_t线程私有变量来存储zlog_thread_t,仅有1%不到的提高 45 | [o] 增加%D,缓存strftime的结果 46 | [o] 缓存pid, tid的字符串形式 47 | [o] 去掉rc的使用[redis] 48 | [o] 对ZLOG_FMT和ZLOG_HEX清算,部分成功 49 | --- 1.0.7 --- 50 | [x] 自己实现部分的strftime,进一步提高效率--替换后发现vsnprintf消耗增加,未能超越原有strftime的效率 51 | [o] %t显示为16进制 52 | [o] 零碎的性能优化,10%把 53 | --- 1.0.6 --- 54 | [o] 每秒取一次localtime_r,加速1倍以上 55 | --- 1.0.5 --- 56 | [o] 修复1.0.4的问题,reopen文件时用读写锁保护 57 | --- 1.0.4 --- 58 | [o] 测试多线程的效率 59 | [o] 缓存静态文件的FILE*和fd,优化,加速3倍 60 | --- 1.0.3 --- 61 | [o] 基于日志笔数自动刷新配置 62 | [o] 基于日志笔数自动做sync到硬盘操作 63 | --- 1.0.2 --- 64 | [o] 增加同步写入到硬盘选项,打开后极为费时 65 | --- 1.0.1 --- 66 | [o] 采用配置文件作为锁文件 67 | --- 1.0.0 --- 68 | [o] 改变配置文件的布局,去掉@ &这种符号,改用[global],[format]这样的形式来 69 | [o] 把reload改成原子性的,失败用旧的 70 | [o] 优化spec_gen_msg部分, spec内采用自己写的buf_append对齐来代替buf_sprintf 71 | [o] 引入__func__ 72 | [o] 文件的权限设置 73 | [o] 输出函数自定义 74 | --- 0.9 --- 75 | [o] 采用更加面向对象的方法来写 76 | [o] 使用arraylist来代替linklist为内部数据结构 77 | [o] 改进配置文件的格式 78 | [o] 打造线程安全的日志函数库 79 | [o] 解决微秒毫秒在配置中的表示 80 | [o] 把event并到thread内避免开内存 81 | [o] 增加init读取配置文件的api 82 | [o] default] format的解析,初始化全无的时候的输出,zlog_chk_conf的编写 83 | [o] 把category独立出来 84 | [o] 增加update接口 85 | [o] buf的大小无法通过zlog_init动态的改变,可以zlog_update重建所有缓存解决,呵呵 86 | [o] 调整文件创建权限,采用类似fopen的办法,为0666&(~umask) 87 | [o] syslog输出,搞定但发现syslog暴慢 88 | [o] 转档的模式,是否需要轮询等,解决为传统模式 89 | [o] 增加zlog_profile接口,诊断配置内存 90 | [o] 增加MDC,可配置的增加字段 91 | [o] 测试buf被重写的时候,是否会导致后面的\0没加 92 | [o] xlog要改名为zlog.... 93 | [o] 取一次ZLOG_ERROR_LOG和ZLOG_DEBUG_LOG,避免多次getenv 94 | [o] zc_assert一般关闭,调试打开 95 | [o] 增加!.*, 匹配未被匹配的分类 96 | [o] priority->level 97 | [o] level自定义 98 | [o] rule syslog open 99 | [o] default format移到全局配置 100 | [o] reset level, 用arraylist来做试试看 101 | [o] ylog, 更简单的接口, 改名为dzlog的一堆接口来解决 102 | [o] zlog-gen-conf 103 | [o] rotate控制个数 104 | --- 废弃想法 --- 105 | [x] 使用writev来写日志,提高效率,达到一次形成,多次输出的目的, writev内部也是开buffermemcpy 106 | [x] 尝试信号量的方法来打成线程安全的转档互斥问题 107 | [x] zlog.h变长参数宏的问题(参考glib的log解决) 108 | [x] rule的dynamic] file可以从format获取 109 | [x] 修改arraylist的读取长度,循环等 110 | [x] 运行期间指定是否采用线程 111 | [x] buf_append 优化——为了安全,不优化这个 112 | [x] 用某种自动编译器以及文档生成器 113 | [x] 输出到管道,有名管道和文件一样 114 | [x] 打印堆栈。。可能需要语言支持 115 | [x] zlog-input -c category -p priority -f conf 116 | [x] 采用精细的reo en方法来建立用fo en来智能判断需不需要重开文件,操作系统本身已经做得够好,无须做 117 | 118 | -------------------------------------------------------------------------------- /src/mdc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "mdc.h" 14 | #include "zc_defs.h" 15 | 16 | void zlog_mdc_profile(zlog_mdc_t *a_mdc, int flag) 17 | { 18 | zc_hashtable_entry_t *a_entry; 19 | zlog_mdc_kv_t *a_mdc_kv; 20 | 21 | zc_assert(a_mdc,); 22 | zc_profile(flag, "---mdc[%p]---", a_mdc); 23 | 24 | zc_hashtable_foreach(a_mdc->tab, a_entry) { 25 | a_mdc_kv = a_entry->value; 26 | zc_profile(flag, "----mdc_kv[%p][%s]-[%s]----", 27 | a_mdc_kv, 28 | a_mdc_kv->key, a_mdc_kv->value); 29 | } 30 | return; 31 | } 32 | /*******************************************************************************/ 33 | void zlog_mdc_del(zlog_mdc_t * a_mdc) 34 | { 35 | zc_assert(a_mdc,); 36 | if (a_mdc->tab) zc_hashtable_del(a_mdc->tab); 37 | zc_debug("zlog_mdc_del[%p]", a_mdc); 38 | free(a_mdc); 39 | return; 40 | } 41 | 42 | static void zlog_mdc_kv_del(zlog_mdc_kv_t * a_mdc_kv) 43 | { 44 | zc_debug("zlog_mdc_kv_del[%p]", a_mdc_kv); 45 | free(a_mdc_kv); 46 | } 47 | 48 | static zlog_mdc_kv_t *zlog_mdc_kv_new(const char *key, const char *value) 49 | { 50 | zlog_mdc_kv_t *a_mdc_kv; 51 | 52 | a_mdc_kv = calloc(1, sizeof(zlog_mdc_kv_t)); 53 | if (!a_mdc_kv) { 54 | zc_error("calloc fail, errno[%d]", errno); 55 | return NULL; 56 | } 57 | 58 | snprintf(a_mdc_kv->key, sizeof(a_mdc_kv->key), "%s", key); 59 | a_mdc_kv->value_len = snprintf(a_mdc_kv->value, sizeof(a_mdc_kv->value), "%s", value); 60 | return a_mdc_kv; 61 | } 62 | 63 | zlog_mdc_t *zlog_mdc_new(void) 64 | { 65 | zlog_mdc_t *a_mdc; 66 | 67 | a_mdc = calloc(1, sizeof(zlog_mdc_t)); 68 | if (!a_mdc) { 69 | zc_error("calloc fail, errno[%d]", errno); 70 | return NULL; 71 | } 72 | 73 | a_mdc->tab = zc_hashtable_new(20, 74 | zc_hashtable_str_hash, 75 | zc_hashtable_str_equal, NULL, 76 | (zc_hashtable_del_fn) zlog_mdc_kv_del); 77 | if (!a_mdc->tab) { 78 | zc_error("zc_hashtable_new fail"); 79 | goto err; 80 | } 81 | 82 | //zlog_mdc_profile(a_mdc, ZC_DEBUG); 83 | return a_mdc; 84 | err: 85 | zlog_mdc_del(a_mdc); 86 | return NULL; 87 | } 88 | 89 | /*******************************************************************************/ 90 | int zlog_mdc_put(zlog_mdc_t * a_mdc, const char *key, const char *value) 91 | { 92 | zlog_mdc_kv_t *a_mdc_kv; 93 | 94 | a_mdc_kv = zlog_mdc_kv_new(key, value); 95 | if (!a_mdc_kv) { 96 | zc_error("zlog_mdc_kv_new failed"); 97 | return -1; 98 | } 99 | 100 | if (zc_hashtable_put(a_mdc->tab, a_mdc_kv->key, a_mdc_kv)) { 101 | zc_error("zc_hashtable_put fail"); 102 | zlog_mdc_kv_del(a_mdc_kv); 103 | return -1; 104 | } 105 | 106 | return 0; 107 | } 108 | 109 | void zlog_mdc_clean(zlog_mdc_t * a_mdc) 110 | { 111 | zc_hashtable_clean(a_mdc->tab); 112 | return; 113 | } 114 | 115 | char *zlog_mdc_get(zlog_mdc_t * a_mdc, const char *key) 116 | { 117 | zlog_mdc_kv_t *a_mdc_kv; 118 | 119 | a_mdc_kv = zc_hashtable_get(a_mdc->tab, key); 120 | if (!a_mdc_kv) { 121 | zc_error("zc_hashtable_get fail"); 122 | return NULL; 123 | } else { 124 | return a_mdc_kv->value; 125 | } 126 | } 127 | 128 | zlog_mdc_kv_t *zlog_mdc_get_kv(zlog_mdc_t * a_mdc, const char *key) 129 | { 130 | zlog_mdc_kv_t *a_mdc_kv; 131 | 132 | a_mdc_kv = zc_hashtable_get(a_mdc->tab, key); 133 | if (!a_mdc_kv) { 134 | zc_error("zc_hashtable_get fail"); 135 | return NULL; 136 | } else { 137 | return a_mdc_kv; 138 | } 139 | } 140 | 141 | void zlog_mdc_remove(zlog_mdc_t * a_mdc, const char *key) 142 | { 143 | zc_hashtable_remove(a_mdc->tab, key); 144 | return; 145 | } 146 | -------------------------------------------------------------------------------- /src/level.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #ifndef _WIN32 13 | #include 14 | #else 15 | #include "zlog_win.h" 16 | #endif 17 | 18 | #include "zc_defs.h" 19 | #include "level.h" 20 | 21 | void zlog_level_profile(zlog_level_t *a_level, int flag) 22 | { 23 | zc_assert(a_level,); 24 | zc_profile(flag, "---level[%p][%d,%s,%s,%d,%d]---", 25 | a_level, 26 | a_level->int_level, 27 | a_level->str_uppercase, 28 | a_level->str_lowercase, 29 | (int) a_level->str_len, 30 | a_level->syslog_level); 31 | return; 32 | } 33 | 34 | /*******************************************************************************/ 35 | void zlog_level_del(zlog_level_t *a_level) 36 | { 37 | zc_assert(a_level,); 38 | zc_debug("zlog_level_del[%p]", a_level); 39 | free(a_level); 40 | return; 41 | } 42 | 43 | static int syslog_level_atoi(char *str) 44 | { 45 | /* guess no unix system will choose -187 46 | * as its syslog level, so it is a safe return value 47 | */ 48 | zc_assert(str, -187); 49 | 50 | if (STRICMP(str, ==, "LOG_EMERG")) 51 | return LOG_EMERG; 52 | if (STRICMP(str, ==, "LOG_ALERT")) 53 | return LOG_ALERT; 54 | if (STRICMP(str, ==, "LOG_CRIT")) 55 | return LOG_CRIT; 56 | if (STRICMP(str, ==, "LOG_ERR")) 57 | return LOG_ERR; 58 | if (STRICMP(str, ==, "LOG_WARNING")) 59 | return LOG_WARNING; 60 | if (STRICMP(str, ==, "LOG_NOTICE")) 61 | return LOG_NOTICE; 62 | if (STRICMP(str, ==, "LOG_INFO")) 63 | return LOG_INFO; 64 | if (STRICMP(str, ==, "LOG_DEBUG")) 65 | return LOG_DEBUG; 66 | 67 | zc_error("wrong syslog level[%s]", str); 68 | return -187; 69 | } 70 | 71 | /* line: TRACE = 10, LOG_ERR */ 72 | zlog_level_t *zlog_level_new(char *line) 73 | { 74 | zlog_level_t *a_level = NULL; 75 | int i; 76 | int nscan; 77 | char str[MAXLEN_CFG_LINE + 1]; 78 | int l = 0; 79 | char sl[MAXLEN_CFG_LINE + 1]; 80 | 81 | zc_assert(line, NULL); 82 | 83 | memset(str, 0x00, sizeof(str)); 84 | memset(sl, 0x00, sizeof(sl)); 85 | 86 | nscan = sscanf(line, " %[^= \t] = %d ,%s", str, &l, sl); 87 | if (nscan < 2) { 88 | zc_error("level[%s], syntax wrong", line); 89 | return NULL; 90 | } 91 | 92 | /* check level and str */ 93 | if ((l < 0) || (l > 255)) { 94 | zc_error("l[%d] not in [0,255], wrong", l); 95 | return NULL; 96 | } 97 | 98 | if (str[0] == '\0') { 99 | zc_error("str[0] = 0"); 100 | return NULL; 101 | } 102 | 103 | a_level = calloc(1, sizeof(zlog_level_t)); 104 | if (!a_level) { 105 | zc_error("calloc fail, errno[%d]", errno); 106 | return NULL; 107 | } 108 | 109 | a_level->int_level = l; 110 | 111 | /* fill syslog level */ 112 | if (sl[0] == '\0') { 113 | a_level->syslog_level = LOG_DEBUG; 114 | } else { 115 | a_level->syslog_level = syslog_level_atoi(sl); 116 | if (a_level->syslog_level == -187) { 117 | zc_error("syslog_level_atoi fail"); 118 | goto err; 119 | } 120 | } 121 | 122 | /* strncpy and toupper(str) */ 123 | for (i = 0; (i < sizeof(a_level->str_uppercase) - 1) && str[i] != '\0'; i++) { 124 | (a_level->str_uppercase)[i] = toupper(str[i]); 125 | (a_level->str_lowercase)[i] = tolower(str[i]); 126 | } 127 | 128 | if (str[i] != '\0') { 129 | /* overflow */ 130 | zc_error("not enough space for str, str[%s] > %d", str, i); 131 | goto err; 132 | } else { 133 | (a_level->str_uppercase)[i] = '\0'; 134 | (a_level->str_lowercase)[i] = '\0'; 135 | } 136 | 137 | a_level->str_len = i; 138 | 139 | //zlog_level_profile(a_level, ZC_DEBUG); 140 | return a_level; 141 | err: 142 | zc_error("line[%s]", line); 143 | zlog_level_del(a_level); 144 | return NULL; 145 | } 146 | -------------------------------------------------------------------------------- /src/category_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "zc_defs.h" 14 | #include "category_table.h" 15 | 16 | void zlog_category_table_profile(zc_hashtable_t * categories, int flag) 17 | { 18 | zc_hashtable_entry_t *a_entry; 19 | zlog_category_t *a_category; 20 | 21 | zc_assert(categories,); 22 | zc_profile(flag, "-category_table[%p]-", categories); 23 | zc_hashtable_foreach(categories, a_entry) { 24 | a_category = (zlog_category_t *) a_entry->value; 25 | zlog_category_profile(a_category, flag); 26 | } 27 | return; 28 | } 29 | 30 | /*******************************************************************************/ 31 | 32 | void zlog_category_table_del(zc_hashtable_t * categories) 33 | { 34 | zc_assert(categories,); 35 | zc_hashtable_del(categories); 36 | zc_debug("zlog_category_table_del[%p]", categories); 37 | return; 38 | } 39 | 40 | zc_hashtable_t *zlog_category_table_new(void) 41 | { 42 | zc_hashtable_t *categories; 43 | 44 | categories = zc_hashtable_new(20, 45 | (zc_hashtable_hash_fn) zc_hashtable_str_hash, 46 | (zc_hashtable_equal_fn) zc_hashtable_str_equal, 47 | NULL, (zc_hashtable_del_fn) zlog_category_del); 48 | if (!categories) { 49 | zc_error("zc_hashtable_new fail"); 50 | return NULL; 51 | } else { 52 | zlog_category_table_profile(categories, ZC_DEBUG); 53 | return categories; 54 | } 55 | } 56 | /*******************************************************************************/ 57 | int zlog_category_table_update_rules(zc_hashtable_t * categories, zc_arraylist_t * new_rules) 58 | { 59 | zc_hashtable_entry_t *a_entry; 60 | zlog_category_t *a_category; 61 | 62 | zc_assert(categories, -1); 63 | zc_hashtable_foreach(categories, a_entry) { 64 | a_category = (zlog_category_t *) a_entry->value; 65 | if (zlog_category_update_rules(a_category, new_rules)) { 66 | zc_error("zlog_category_update_rules fail, try rollback"); 67 | return -1; 68 | } 69 | } 70 | return 0; 71 | } 72 | 73 | void zlog_category_table_commit_rules(zc_hashtable_t * categories) 74 | { 75 | zc_hashtable_entry_t *a_entry; 76 | zlog_category_t *a_category; 77 | 78 | zc_assert(categories,); 79 | zc_hashtable_foreach(categories, a_entry) { 80 | a_category = (zlog_category_t *) a_entry->value; 81 | zlog_category_commit_rules(a_category); 82 | } 83 | return; 84 | } 85 | 86 | void zlog_category_table_rollback_rules(zc_hashtable_t * categories) 87 | { 88 | zc_hashtable_entry_t *a_entry; 89 | zlog_category_t *a_category; 90 | 91 | zc_assert(categories,); 92 | zc_hashtable_foreach(categories, a_entry) { 93 | a_category = (zlog_category_t *) a_entry->value; 94 | zlog_category_rollback_rules(a_category); 95 | } 96 | return; 97 | } 98 | 99 | /*******************************************************************************/ 100 | zlog_category_t *zlog_category_table_fetch_category(zc_hashtable_t * categories, 101 | const char *category_name, zc_arraylist_t * rules) 102 | { 103 | zlog_category_t *a_category; 104 | 105 | zc_assert(categories, NULL); 106 | 107 | /* 1st find category in global category map */ 108 | a_category = zc_hashtable_get(categories, category_name); 109 | if (a_category) return a_category; 110 | 111 | /* else not found, create one */ 112 | a_category = zlog_category_new(category_name, rules); 113 | if (!a_category) { 114 | zc_error("zc_category_new fail"); 115 | return NULL; 116 | } 117 | 118 | if(zc_hashtable_put(categories, a_category->name, a_category)) { 119 | zc_error("zc_hashtable_put fail"); 120 | goto err; 121 | } 122 | 123 | return a_category; 124 | err: 125 | zlog_category_del(a_category); 126 | return NULL; 127 | } 128 | 129 | /*******************************************************************************/ 130 | -------------------------------------------------------------------------------- /src/level_list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #ifdef _WIN32 13 | #include "zlog_win.h" 14 | #endif 15 | 16 | #include "zc_defs.h" 17 | #include "level.h" 18 | #include "level_list.h" 19 | 20 | /* zlog_level_list == zc_arraylist_t */ 21 | 22 | void zlog_level_list_profile(zc_arraylist_t *levels, int flag) 23 | { 24 | int i; 25 | zlog_level_t *a_level; 26 | 27 | zc_assert(levels,); 28 | zc_profile(flag, "--level_list[%p]--", levels); 29 | zc_arraylist_foreach(levels, i, a_level) { 30 | /* skip empty slots */ 31 | if (a_level) zlog_level_profile(a_level, flag); 32 | } 33 | return; 34 | } 35 | 36 | /*******************************************************************************/ 37 | void zlog_level_list_del(zc_arraylist_t *levels) 38 | { 39 | zc_assert(levels,); 40 | zc_arraylist_del(levels); 41 | zc_debug("zc_level_list_del[%p]", levels); 42 | return; 43 | } 44 | 45 | static int zlog_level_list_set_default(zc_arraylist_t *levels) 46 | { 47 | return zlog_level_list_set(levels, "* = 0, LOG_INFO") 48 | || zlog_level_list_set(levels, "DEBUG = 20, LOG_DEBUG") 49 | || zlog_level_list_set(levels, "INFO = 40, LOG_INFO") 50 | || zlog_level_list_set(levels, "NOTICE = 60, LOG_NOTICE") 51 | || zlog_level_list_set(levels, "WARN = 80, LOG_WARNING") 52 | || zlog_level_list_set(levels, "ERROR = 100, LOG_ERR") 53 | || zlog_level_list_set(levels, "FATAL = 120, LOG_ALERT") 54 | || zlog_level_list_set(levels, "UNKNOWN = 254, LOG_ERR") 55 | || zlog_level_list_set(levels, "! = 255, LOG_INFO"); 56 | } 57 | 58 | zc_arraylist_t *zlog_level_list_new(void) 59 | { 60 | zc_arraylist_t *levels; 61 | 62 | levels = zc_arraylist_new((zc_arraylist_del_fn)zlog_level_del); 63 | if (!levels) { 64 | zc_error("zc_arraylist_new fail"); 65 | return NULL; 66 | } 67 | 68 | if (zlog_level_list_set_default(levels)) { 69 | zc_error("zlog_level_set_default fail"); 70 | goto err; 71 | } 72 | 73 | //zlog_level_list_profile(levels, ZC_DEBUG); 74 | return levels; 75 | err: 76 | zc_arraylist_del(levels); 77 | return NULL; 78 | } 79 | 80 | /*******************************************************************************/ 81 | int zlog_level_list_set(zc_arraylist_t *levels, char *line) 82 | { 83 | zlog_level_t *a_level; 84 | 85 | a_level = zlog_level_new(line); 86 | if (!a_level) { 87 | zc_error("zlog_level_new fail"); 88 | return -1; 89 | } 90 | 91 | if (zc_arraylist_set(levels, a_level->int_level, a_level)) { 92 | zc_error("zc_arraylist_set fail"); 93 | goto err; 94 | } 95 | 96 | return 0; 97 | err: 98 | zc_error("line[%s]", line); 99 | zlog_level_del(a_level); 100 | return -1; 101 | } 102 | 103 | zlog_level_t *zlog_level_list_get(zc_arraylist_t *levels, int l) 104 | { 105 | zlog_level_t *a_level; 106 | 107 | #if 0 108 | if ((l <= 0) || (l > 254)) { 109 | /* illegal input from zlog() */ 110 | zc_error("l[%d] not in (0,254), set to UNKOWN", l); 111 | l = 254; 112 | } 113 | #endif 114 | 115 | a_level = zc_arraylist_get(levels, l); 116 | if (a_level) { 117 | return a_level; 118 | } else { 119 | /* empty slot */ 120 | zc_error("l[%d] not in (0,254), or has no level defined," 121 | "see configure file define, set to UNKOWN", l); 122 | return zc_arraylist_get(levels, 254); 123 | } 124 | } 125 | 126 | /*******************************************************************************/ 127 | 128 | int zlog_level_list_atoi(zc_arraylist_t *levels, char *str) 129 | { 130 | int i; 131 | zlog_level_t *a_level; 132 | 133 | if (str == NULL || *str == '\0') { 134 | zc_error("str is [%s], can't find level", str); 135 | return -1; 136 | } 137 | 138 | zc_arraylist_foreach(levels, i, a_level) { 139 | if (a_level && STRICMP(str, ==, a_level->str_uppercase)) { 140 | return i; 141 | } 142 | } 143 | 144 | zc_error("str[%s] can't found in level list", str); 145 | return -1; 146 | } 147 | 148 | -------------------------------------------------------------------------------- /src/format.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "zc_defs.h" 17 | #include "thread.h" 18 | #include "spec.h" 19 | #include "format.h" 20 | 21 | void zlog_format_profile(zlog_format_t * a_format, int flag) 22 | { 23 | 24 | zc_assert(a_format,); 25 | zc_profile(flag, "---format[%p][%s = %s(%p)]---", 26 | a_format, 27 | a_format->name, 28 | a_format->pattern, 29 | a_format->pattern_specs); 30 | 31 | #if 0 32 | int i; 33 | zlog_spec_t *a_spec; 34 | zc_arraylist_foreach(a_format->pattern_specs, i, a_spec) { 35 | zlog_spec_profile(a_spec, flag); 36 | } 37 | #endif 38 | 39 | return; 40 | } 41 | 42 | /*******************************************************************************/ 43 | void zlog_format_del(zlog_format_t * a_format) 44 | { 45 | zc_assert(a_format,); 46 | if (a_format->pattern_specs) { 47 | zc_arraylist_del(a_format->pattern_specs); 48 | } 49 | zc_debug("zlog_format_del[%p]", a_format); 50 | free(a_format); 51 | return; 52 | } 53 | 54 | zlog_format_t *zlog_format_new(char *line, int * time_cache_count) 55 | { 56 | int nscan = 0; 57 | zlog_format_t *a_format = NULL; 58 | int nread = 0; 59 | const char *p_start; 60 | const char *p_end; 61 | char *p; 62 | char *q; 63 | zlog_spec_t *a_spec; 64 | 65 | zc_assert(line, NULL); 66 | 67 | a_format = calloc(1, sizeof(zlog_format_t)); 68 | if (!a_format) { 69 | zc_error("calloc fail, errno[%d]", errno); 70 | return NULL; 71 | } 72 | 73 | /* line default = "%d(%F %X.%l) %-6V (%c:%F:%L) - %m%n" 74 | * name default 75 | * pattern %d(%F %X.%l) %-6V (%c:%F:%L) - %m%n 76 | */ 77 | memset(a_format->name, 0x00, sizeof(a_format->name)); 78 | nread = 0; 79 | nscan = sscanf(line, " %[^= \t] = %n", a_format->name, &nread); 80 | if (nscan != 1) { 81 | zc_error("format[%s], syntax wrong", line); 82 | goto err; 83 | } 84 | 85 | if (*(line + nread) != '"') { 86 | zc_error("the 1st char of pattern is not \", line+nread[%s]", line+nread); 87 | goto err; 88 | } 89 | 90 | for (p = a_format->name; *p != '\0'; p++) { 91 | if ((!isalnum(*p)) && (*p != '_')) { 92 | zc_error("a_format->name[%s] character is not in [a-Z][0-9][_]", a_format->name); 93 | goto err; 94 | } 95 | } 96 | 97 | p_start = line + nread + 1; 98 | p_end = strrchr(p_start, '"'); 99 | if (!p_end) { 100 | zc_error("there is no \" at end of pattern, line[%s]", line); 101 | goto err; 102 | } 103 | 104 | if (p_end - p_start > sizeof(a_format->pattern) - 1) { 105 | zc_error("pattern is too long"); 106 | goto err; 107 | } 108 | memset(a_format->pattern, 0x00, sizeof(a_format->pattern)); 109 | memcpy(a_format->pattern, p_start, p_end - p_start); 110 | 111 | if (zc_str_replace_env(a_format->pattern, sizeof(a_format->pattern))) { 112 | zc_error("zc_str_replace_env fail"); 113 | goto err; 114 | } 115 | 116 | a_format->pattern_specs = 117 | zc_arraylist_new((zc_arraylist_del_fn) zlog_spec_del); 118 | if (!(a_format->pattern_specs)) { 119 | zc_error("zc_arraylist_new fail"); 120 | goto err; 121 | } 122 | 123 | for (p = a_format->pattern; *p != '\0'; p = q) { 124 | a_spec = zlog_spec_new(p, &q, time_cache_count); 125 | if (!a_spec) { 126 | zc_error("zlog_spec_new fail"); 127 | goto err; 128 | } 129 | 130 | if (zc_arraylist_add(a_format->pattern_specs, a_spec)) { 131 | zlog_spec_del(a_spec); 132 | zc_error("zc_arraylist_add fail"); 133 | goto err; 134 | } 135 | } 136 | 137 | zlog_format_profile(a_format, ZC_DEBUG); 138 | return a_format; 139 | err: 140 | zlog_format_del(a_format); 141 | return NULL; 142 | } 143 | 144 | /*******************************************************************************/ 145 | /* return 0 success, or buf is full 146 | * return -1 fail 147 | */ 148 | int zlog_format_gen_msg(zlog_format_t * a_format, zlog_thread_t * a_thread) 149 | { 150 | int i; 151 | zlog_spec_t *a_spec; 152 | 153 | zlog_buf_restart(a_thread->msg_buf); 154 | 155 | zc_arraylist_foreach(a_format->pattern_specs, i, a_spec) { 156 | if (zlog_spec_gen_msg(a_spec, a_thread) == 0) { 157 | continue; 158 | } else { 159 | return -1; 160 | } 161 | } 162 | 163 | return 0; 164 | } 165 | -------------------------------------------------------------------------------- /doc/GettingStart-EN.txt: -------------------------------------------------------------------------------- 1 | 0. What is zlog? 2 | 3 | zlog is a reliable, high-performance, thread safe, flexible, clear-model, pure C logging library. 4 | 5 | Actually, in the C world there was NO good logging library for applications like logback in java or log4cxx in c++. Using printf can work, but can not be redirected or reformatted easily. syslog is slow and is designed for system use. 6 | So I wrote zlog. 7 | It is faster, safer and more powerful than log4c. So it can be widely used. 8 | 9 | 1. Install 10 | 11 | Downloads: https://github.com/HardySimpson/zlog/releases 12 | 13 | $ tar -zxvf zlog-latest-stable.tar.gz 14 | $ cd zlog-latest-stable/ 15 | $ make 16 | $ sudo make install 17 | or 18 | $ make PREFIX=/usr/local/ 19 | $ sudo make PREFIX=/usr/local/ install 20 | 21 | PREFIX indicates the installation destination for zlog. After installation, refresh your dynamic linker to make sure your program can find zlog library. 22 | 23 | $ sudo vi /etc/ld.so.conf 24 | /usr/local/lib 25 | $ sudo ldconfig 26 | 27 | Before running a real program, make sure libzlog.so is in the directory where the system's dynamic lib loader can find it. The command metioned above are for linux. Other systems will need a similar set of actions. 28 | 29 | 30 | 2. Introduce configure file 31 | 32 | There are 3 important concepts in zlog: categories, formats and rules. 33 | 34 | Categories specify 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. 35 | 36 | Formats describe log patterns, such as: with or without time stamp, source file, source line. 37 | 38 | Rules consist 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. Still there is complex match range of category. Rule decouples variable conditions. For example, log4j must specify a level for each logger(or inherit from father logger). That's not convenient when each grade of logger has its own level for output(child logger output at the level of debug, when father logger output at the level of error) 39 | 40 | Now create a configuration file. The function zlog_init takes the files path as its only argument. 41 | $ cat /etc/zlog.conf 42 | 43 | [formats] 44 | simple = "%m%n" 45 | [rules] 46 | my_cat.DEBUG >stdout; simple 47 | 48 | In the configuration file log messages in the category "my_cat" and a level of DEBUG or higher are output to standard output, with the format of simple(%m - usermessage %n - newline). If you want to direct out to a file and limit the files maximum size, use this configuration 49 | 50 | my_cat.DEBUG "/var/log/aa.log", 1M; simple 51 | 52 | 3. Using zlog API in C source file 53 | $ vi test_hello.c 54 | 55 | #include 56 | 57 | #include "zlog.h" 58 | 59 | int main(int argc, char** argv) 60 | { 61 | int rc; 62 | zlog_category_t *c; 63 | 64 | rc = zlog_init("/etc/zlog.conf"); 65 | if (rc) { 66 | printf("init failed\n"); 67 | return -1; 68 | } 69 | 70 | c = zlog_get_category("my_cat"); 71 | if (!c) { 72 | printf("get cat fail\n"); 73 | zlog_fini(); 74 | return -2; 75 | } 76 | 77 | zlog_info(c, "hello, zlog"); 78 | 79 | zlog_fini(); 80 | 81 | return 0; 82 | } 83 | 84 | 4. Complie, and run it!s 85 | 86 | $ cc -c -o test_hello.o test_hello.c -I/usr/local/include 87 | $ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread 88 | $ ./test_hello 89 | hello, zlog 90 | 91 | 5. Advanced Usage 92 | * syslog model, better than log4j model 93 | * log format customization 94 | * multiple output destinations including static file path, dynamic file path, stdout, stderr, syslog, user-defined ouput 95 | * runtime manually or automatically refresh configure(safely) 96 | * high-performance, 250'000 logs/second on my laptop, about 1000 times faster than syslog(3) with rsyslogd 97 | * user-defined log level 98 | * thread-safe and process-safe log file rotation 99 | * microsecond accuracy 100 | * dzlog, a default category log API for easy use 101 | * MDC, a log4j style key-value map 102 | * self debuggable, can output zlog's self debug&error log at runtime 103 | * No external dependencies, just based on a POSIX system and a C99 compliant vsnprintf. 104 | 105 | 106 | 6. Links: 107 | 108 | Homepage: http://hardysimpson.github.com/zlog 109 | Downloads: https://github.com/HardySimpson/zlog/releases 110 | Author's Email: HardySimpson1984@gmail.com 111 | 112 | auto tools version: https://github.com/bmanojlovic/zlog 113 | cmake verion: https://github.com/lisongmin/zlog 114 | windows version: https://github.com/lopsd07/WinZlog 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 0. What is zlog? 2 | ------------- 3 | 4 | zlog is a reliable, high-performance, thread safe, flexible, clear-model, pure C logging library. 5 | 6 | Actually, in the C world there was NO good logging library for applications like logback in java or log4cxx in c++. Using printf can work, but can not be redirected or reformatted easily. syslog is slow and is designed for system use. 7 | So I wrote zlog. 8 | It is faster, safer and more powerful than log4c. So it can be widely used. 9 | 10 | 1. Install 11 | ------------- 12 | 13 | Downloads: https://github.com/HardySimpson/zlog/releases 14 | 15 | $ tar -zxvf zlog-latest-stable.tar.gz 16 | $ cd zlog-latest-stable/ 17 | $ make 18 | $ sudo make install 19 | 20 | or 21 | 22 | $ make PREFIX=/usr/local/ 23 | $ sudo make PREFIX=/usr/local/ install 24 | 25 | PREFIX indicates the installation destination for zlog. After installation, refresh your dynamic linker to make sure your program can find zlog library. 26 | 27 | $ sudo vi /etc/ld.so.conf 28 | /usr/local/lib 29 | $ sudo ldconfig 30 | 31 | Before running a real program, make sure libzlog.so is in the directory where the system's dynamic lib loader can find it. The command metioned above are for linux. Other systems will need a similar set of actions. 32 | 33 | 34 | 2. Introduce configure file 35 | ------------- 36 | 37 | There are 3 important concepts in zlog: categories, formats and rules. 38 | 39 | Categories specify 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. 40 | 41 | Formats describe log patterns, such as: with or without time stamp, source file, source line. 42 | 43 | Rules consist 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. Still there is complex match range of category. Rule decouples variable conditions. For example, log4j must specify a level for each logger(or inherit from father logger). That's not convenient when each grade of logger has its own level for output(child logger output at the level of debug, when father logger output at the level of error) 44 | 45 | Now create a configuration file. The function zlog_init takes the files path as its only argument. 46 | $ cat /etc/zlog.conf 47 | 48 | [formats] 49 | simple = "%m%n" 50 | [rules] 51 | my_cat.DEBUG >stdout; simple 52 | 53 | In the configuration file log messages in the category "my_cat" and a level of DEBUG or higher are output to standard output, with the format of simple(%m - usermessage %n - newline). If you want to direct out to a file and limit the files maximum size, use this configuration 54 | 55 | my_cat.DEBUG "/var/log/aa.log", 1M; simple 56 | 57 | 3. Using zlog API in C source file 58 | ------------- 59 | $ vi test_hello.c 60 | 61 | #include 62 | 63 | #include "zlog.h" 64 | 65 | int main(int argc, char** argv) 66 | { 67 | int rc; 68 | zlog_category_t *c; 69 | 70 | rc = zlog_init("/etc/zlog.conf"); 71 | if (rc) { 72 | printf("init failed\n"); 73 | return -1; 74 | } 75 | 76 | c = zlog_get_category("my_cat"); 77 | if (!c) { 78 | printf("get cat fail\n"); 79 | zlog_fini(); 80 | return -2; 81 | } 82 | 83 | zlog_info(c, "hello, zlog"); 84 | 85 | zlog_fini(); 86 | 87 | return 0; 88 | } 89 | 90 | 4. Compile, and run it! 91 | ------------- 92 | $ cc -c -o test_hello.o test_hello.c -I/usr/local/include 93 | $ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread 94 | $ ./test_hello 95 | hello, zlog 96 | 97 | 5. Advanced Usage 98 | ------------- 99 | * syslog model, better than log4j model 100 | * log format customization 101 | * multiple output destinations including static file path, dynamic file path, stdout, stderr, syslog, user-defined output 102 | * runtime manually or automatically refresh configure(safely) 103 | * high-performance, 250'000 logs/second on my laptop, about 1000 times faster than syslog(3) with rsyslogd 104 | * user-defined log level 105 | * thread-safe and process-safe log file rotation 106 | * microsecond accuracy 107 | * dzlog, a default category log API for easy use 108 | * MDC, a log4j style key-value map 109 | * self debuggable, can output zlog's self debug&error log at runtime 110 | * No external dependencies, just based on a POSIX system and a C99 compliant vsnprintf. 111 | 112 | 6. Links: 113 | ------------- 114 | * Homepage: http://hardysimpson.github.io/zlog 115 | * Downloads: https://github.com/HardySimpson/zlog/releases 116 | * Author's Email: HardySimpson1984@gmail.com 117 | * auto tools version: https://github.com/bmanojlovic/zlog 118 | * cmake verion: https://github.com/lisongmin/zlog 119 | * windows version: https://github.com/lopsd07/WinZlog 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/thread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "zc_defs.h" 13 | #include "event.h" 14 | #include "buf.h" 15 | #include "thread.h" 16 | #include "mdc.h" 17 | 18 | void zlog_thread_profile(zlog_thread_t * a_thread, int flag) 19 | { 20 | zc_assert(a_thread,); 21 | zc_profile(flag, "--thread[%p][%p][%p][%p,%p,%p,%p,%p]--", 22 | a_thread, 23 | a_thread->mdc, 24 | a_thread->event, 25 | a_thread->pre_path_buf, 26 | a_thread->path_buf, 27 | a_thread->archive_path_buf, 28 | a_thread->pre_msg_buf, 29 | a_thread->msg_buf); 30 | 31 | zlog_mdc_profile(a_thread->mdc, flag); 32 | zlog_event_profile(a_thread->event, flag); 33 | zlog_buf_profile(a_thread->pre_path_buf, flag); 34 | zlog_buf_profile(a_thread->path_buf, flag); 35 | zlog_buf_profile(a_thread->archive_path_buf, flag); 36 | zlog_buf_profile(a_thread->pre_msg_buf, flag); 37 | zlog_buf_profile(a_thread->msg_buf, flag); 38 | return; 39 | } 40 | /*******************************************************************************/ 41 | void zlog_thread_del(zlog_thread_t * a_thread) 42 | { 43 | zc_assert(a_thread,); 44 | if (a_thread->mdc) 45 | zlog_mdc_del(a_thread->mdc); 46 | if (a_thread->event) 47 | zlog_event_del(a_thread->event); 48 | if (a_thread->pre_path_buf) 49 | zlog_buf_del(a_thread->pre_path_buf); 50 | if (a_thread->path_buf) 51 | zlog_buf_del(a_thread->path_buf); 52 | if (a_thread->archive_path_buf) 53 | zlog_buf_del(a_thread->archive_path_buf); 54 | if (a_thread->pre_msg_buf) 55 | zlog_buf_del(a_thread->pre_msg_buf); 56 | if (a_thread->msg_buf) 57 | zlog_buf_del(a_thread->msg_buf); 58 | 59 | zc_debug("zlog_thread_del[%p]", a_thread); 60 | free(a_thread); 61 | return; 62 | } 63 | 64 | zlog_thread_t *zlog_thread_new(int init_version, size_t buf_size_min, size_t buf_size_max, int time_cache_count) 65 | { 66 | zlog_thread_t *a_thread; 67 | 68 | a_thread = calloc(1, sizeof(zlog_thread_t)); 69 | if (!a_thread) { 70 | zc_error("calloc fail, errno[%d]", errno); 71 | return NULL; 72 | } 73 | 74 | a_thread->init_version = init_version; 75 | 76 | a_thread->mdc = zlog_mdc_new(); 77 | if (!a_thread->mdc) { 78 | zc_error("zlog_mdc_new fail"); 79 | goto err; 80 | } 81 | 82 | a_thread->event = zlog_event_new(time_cache_count); 83 | if (!a_thread->event) { 84 | zc_error("zlog_event_new fail"); 85 | goto err; 86 | } 87 | 88 | a_thread->pre_path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL); 89 | if (!a_thread->pre_path_buf) { 90 | zc_error("zlog_buf_new fail"); 91 | goto err; 92 | } 93 | 94 | a_thread->path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL); 95 | if (!a_thread->path_buf) { 96 | zc_error("zlog_buf_new fail"); 97 | goto err; 98 | } 99 | 100 | a_thread->archive_path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL); 101 | if (!a_thread->archive_path_buf) { 102 | zc_error("zlog_buf_new fail"); 103 | goto err; 104 | } 105 | 106 | a_thread->pre_msg_buf = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE); 107 | if (!a_thread->pre_msg_buf) { 108 | zc_error("zlog_buf_new fail"); 109 | goto err; 110 | } 111 | 112 | a_thread->msg_buf = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE); 113 | if (!a_thread->msg_buf) { 114 | zc_error("zlog_buf_new fail"); 115 | goto err; 116 | } 117 | 118 | 119 | //zlog_thread_profile(a_thread, ZC_DEBUG); 120 | return a_thread; 121 | err: 122 | zlog_thread_del(a_thread); 123 | return NULL; 124 | } 125 | 126 | /*******************************************************************************/ 127 | int zlog_thread_rebuild_msg_buf(zlog_thread_t * a_thread, size_t buf_size_min, size_t buf_size_max) 128 | { 129 | zlog_buf_t *pre_msg_buf_new = NULL; 130 | zlog_buf_t *msg_buf_new = NULL; 131 | zc_assert(a_thread, -1); 132 | 133 | if ( (a_thread->msg_buf->size_min == buf_size_min) 134 | && (a_thread->msg_buf->size_max == buf_size_max)) { 135 | zc_debug("buf size not changed, no need rebuild"); 136 | return 0; 137 | } 138 | 139 | pre_msg_buf_new = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE); 140 | if (!pre_msg_buf_new) { 141 | zc_error("zlog_buf_new fail"); 142 | goto err; 143 | } 144 | 145 | msg_buf_new = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE); 146 | if (!msg_buf_new) { 147 | zc_error("zlog_buf_new fail"); 148 | goto err; 149 | } 150 | 151 | zlog_buf_del(a_thread->pre_msg_buf); 152 | a_thread->pre_msg_buf = pre_msg_buf_new; 153 | 154 | zlog_buf_del(a_thread->msg_buf); 155 | a_thread->msg_buf = msg_buf_new; 156 | 157 | return 0; 158 | err: 159 | if (pre_msg_buf_new) zlog_buf_del(pre_msg_buf_new); 160 | if (msg_buf_new) zlog_buf_del(msg_buf_new); 161 | return -1; 162 | } 163 | 164 | int zlog_thread_rebuild_event(zlog_thread_t * a_thread, int time_cache_count) 165 | { 166 | zlog_event_t *event_new = NULL; 167 | zc_assert(a_thread, -1); 168 | 169 | event_new = zlog_event_new(time_cache_count); 170 | if (!event_new) { 171 | zc_error("zlog_event_new fail"); 172 | goto err; 173 | } 174 | 175 | zlog_event_del(a_thread->event); 176 | a_thread->event = event_new; 177 | return 0; 178 | err: 179 | if (event_new) zlog_event_del(event_new); 180 | return -1; 181 | } 182 | 183 | 184 | /*******************************************************************************/ 185 | -------------------------------------------------------------------------------- /src/event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #define _GNU_SOURCE // For distros like Centos for syscall interface 10 | 11 | #include "fmacros.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include "zc_defs.h" 26 | #include "event.h" 27 | #ifdef _WIN32 28 | #include 29 | #endif 30 | 31 | void zlog_event_profile(zlog_event_t * a_event, int flag) 32 | { 33 | zc_assert(a_event,); 34 | zc_profile(flag, "---event[%p][%s,%s][%s(%ld),%s(%ld),%ld,%d][%p,%s][%ld,%ld][%ld,%ld][%d]---", 35 | a_event, 36 | a_event->category_name, a_event->host_name, 37 | a_event->file, a_event->file_len, 38 | a_event->func, a_event->func_len, 39 | a_event->line, a_event->level, 40 | a_event->hex_buf, a_event->str_format, 41 | a_event->time_stamp.tv_sec, a_event->time_stamp.tv_usec, 42 | (long)a_event->pid, (long)a_event->tid, 43 | a_event->time_cache_count); 44 | return; 45 | } 46 | 47 | /*******************************************************************************/ 48 | 49 | void zlog_event_del(zlog_event_t * a_event) 50 | { 51 | zc_assert(a_event,); 52 | if (a_event->time_caches) free(a_event->time_caches); 53 | zc_debug("zlog_event_del[%p]", a_event); 54 | free(a_event); 55 | return; 56 | } 57 | 58 | zlog_event_t *zlog_event_new(int time_cache_count) 59 | { 60 | zlog_event_t *a_event; 61 | 62 | a_event = calloc(1, sizeof(zlog_event_t)); 63 | if (!a_event) { 64 | zc_error("calloc fail, errno[%d]", errno); 65 | return NULL; 66 | } 67 | 68 | a_event->time_caches = calloc(time_cache_count, sizeof(zlog_time_cache_t)); 69 | if (!a_event->time_caches) { 70 | zc_error("calloc fail, errno[%d]", errno); 71 | free(a_event); 72 | return NULL; 73 | } 74 | a_event->time_cache_count = time_cache_count; 75 | 76 | /* 77 | * at the zlog_init we gethostname, 78 | * u don't always change your hostname, eh? 79 | */ 80 | if (gethostname(a_event->host_name, sizeof(a_event->host_name) - 1)) { 81 | zc_error("gethostname fail, errno[%d]", errno); 82 | goto err; 83 | } 84 | 85 | a_event->host_name_len = strlen(a_event->host_name); 86 | 87 | /* tid is bound to a_event 88 | * as in whole lifecycle event persists 89 | * even fork to oth pid, tid not change 90 | */ 91 | a_event->tid = pthread_self(); 92 | 93 | a_event->tid_str_len = sprintf(a_event->tid_str, "%lu", (unsigned long)a_event->tid); 94 | a_event->tid_hex_str_len = sprintf(a_event->tid_hex_str, "%x", (unsigned int)a_event->tid); 95 | 96 | #ifdef __linux__ 97 | a_event->ktid = syscall(SYS_gettid); 98 | #elif __APPLE__ 99 | uint64_t tid64; 100 | pthread_threadid_np(NULL, &tid64); 101 | a_event->tid = (pthread_t)tid64; 102 | #endif 103 | 104 | #if defined __linux__ || __APPLE__ 105 | a_event->ktid_str_len = sprintf(a_event->ktid_str, "%u", (unsigned int)a_event->ktid); 106 | #endif 107 | 108 | //zlog_event_profile(a_event, ZC_DEBUG); 109 | return a_event; 110 | err: 111 | zlog_event_del(a_event); 112 | return NULL; 113 | } 114 | 115 | /*******************************************************************************/ 116 | void zlog_event_set_fmt(zlog_event_t * a_event, 117 | char *category_name, size_t category_name_len, 118 | const char *file, size_t file_len, const char *func, size_t func_len, long line, int level, 119 | const char *str_format, va_list str_args) 120 | { 121 | /* 122 | * category_name point to zlog_category_output's category.name 123 | */ 124 | a_event->category_name = category_name; 125 | a_event->category_name_len = category_name_len; 126 | 127 | a_event->file = (char *) file; 128 | a_event->file_len = file_len; 129 | a_event->func = (char *) func; 130 | a_event->func_len = func_len; 131 | a_event->line = line; 132 | a_event->level = level; 133 | 134 | a_event->generate_cmd = ZLOG_FMT; 135 | a_event->str_format = str_format; 136 | va_copy(a_event->str_args, str_args); 137 | 138 | /* pid should fetch eveytime, as no one knows, 139 | * when does user fork his process 140 | * so clean here, and fetch at spec.c 141 | */ 142 | a_event->pid = (pid_t) 0; 143 | 144 | /* in a event's life cycle, time will be get when spec need, 145 | * and keep unchange though all event's life cycle 146 | * zlog_spec_write_time gettimeofday 147 | */ 148 | a_event->time_stamp.tv_sec = 0; 149 | return; 150 | } 151 | 152 | void zlog_event_set_hex(zlog_event_t * a_event, 153 | char *category_name, size_t category_name_len, 154 | const char *file, size_t file_len, const char *func, size_t func_len, long line, int level, 155 | const void *hex_buf, size_t hex_buf_len) 156 | { 157 | /* 158 | * category_name point to zlog_category_output's category.name 159 | */ 160 | a_event->category_name = category_name; 161 | a_event->category_name_len = category_name_len; 162 | 163 | a_event->file = (char *) file; 164 | a_event->file_len = file_len; 165 | a_event->func = (char *) func; 166 | a_event->func_len = func_len; 167 | a_event->line = line; 168 | a_event->level = level; 169 | 170 | a_event->generate_cmd = ZLOG_HEX; 171 | a_event->hex_buf = hex_buf; 172 | a_event->hex_buf_len = hex_buf_len; 173 | 174 | /* pid should fetch eveytime, as no one knows, 175 | * when does user fork his process 176 | * so clean here, and fetch at spec.c 177 | */ 178 | a_event->pid = (pid_t) 0; 179 | 180 | /* in a event's life cycle, time will be get when spec need, 181 | * and keep unchange though all event's life cycle 182 | */ 183 | a_event->time_stamp.tv_sec = 0; 184 | return; 185 | } 186 | -------------------------------------------------------------------------------- /test/test_multithread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2017 by Philippe Corbes 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | * 8 | * This test programm start NB_THREADS threads. 9 | * Each thread loop and log an Info message every THREAD_LOOP_DELAY us (=10ms). 10 | * The main loop check configuration file modification every seconds and reload configuration on file update. 11 | * The main loop force reload configuration every RELOAD_DELAY " (=10"). 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "zlog.h" 22 | 23 | #define CONFIG "test_multithread.conf" 24 | #define NB_THREADS 200 25 | #define THREAD_LOOP_DELAY 10000 /* 0.01" */ 26 | #define RELOAD_DELAY 10 27 | 28 | enum { 29 | ZLOG_LEVEL_TRACE = 10, 30 | ZLOG_LEVEL_SECURITY = 150, 31 | /* must equals conf file setting */ 32 | }; 33 | 34 | #define zlog_trace(cat, format, args...) \ 35 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 36 | ZLOG_LEVEL_TRACE, format, ##args) 37 | 38 | #define zlog_security(cat, format, args...) \ 39 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 40 | ZLOG_LEVEL_SECURITY, format, ##args) 41 | 42 | 43 | struct thread_info { /* Used as argument to thread_start() */ 44 | pthread_t thread_id; /* ID returned by pthread_create() */ 45 | int thread_num; /* Application-defined thread # */ 46 | zlog_category_t *zc; /* The logger category struc address; (All threads will use the same category, so he same address) */ 47 | long long int loop; /* Counter incremented to check the thread's health */ 48 | }; 49 | 50 | struct thread_info *tinfo; 51 | 52 | 53 | void intercept(int sig) 54 | { 55 | int i; 56 | 57 | printf("\nIntercept signal %d\n\n", sig); 58 | 59 | signal (sig, SIG_DFL); 60 | raise (sig); 61 | 62 | printf("You can import datas below in a spreadsheat and check if any thread stopped increment the Loop counter during the test.\n\n"); 63 | printf("Thread;Loop\n"); 64 | for (i=0; izc = zlog_get_category("thrd"); 79 | if (!tinfo->zc) { 80 | printf("get thrd %d cat fail\n", tinfo->thread_num); 81 | } 82 | else 83 | { 84 | while(1) 85 | { 86 | usleep(THREAD_LOOP_DELAY); 87 | zlog_info(tinfo->zc, "%d;%lld", tinfo->thread_num, tinfo->loop++); 88 | } 89 | } 90 | 91 | return NULL; 92 | } 93 | 94 | int main(int argc, char** argv) 95 | { 96 | int rc; 97 | zlog_category_t *zc; 98 | zlog_category_t *mc; 99 | zlog_category_t *hl; 100 | int i = 0; 101 | struct stat stat_0, stat_1; 102 | 103 | /* Create the logging directory if not yet ceated */ 104 | mkdir("./test_multithread-logs", 0777); 105 | 106 | if (stat(CONFIG, &stat_0)) 107 | { 108 | printf("Configuration file not found\n"); 109 | return -1; 110 | } 111 | 112 | rc = zlog_init(CONFIG); 113 | if (rc) { 114 | printf("main init failed\n"); 115 | return -2; 116 | } 117 | 118 | zc = zlog_get_category("main"); 119 | if (!zc) { 120 | printf("main get cat fail\n"); 121 | zlog_fini(); 122 | return -3; 123 | } 124 | 125 | mc = zlog_get_category("clsn"); 126 | if (!mc) { 127 | printf("clsn get cat fail\n"); 128 | zlog_fini(); 129 | return -3; 130 | } 131 | 132 | hl = zlog_get_category("high"); 133 | if (!hl) { 134 | printf("high get cat fail\n"); 135 | zlog_fini(); 136 | return -3; 137 | } 138 | 139 | /* Interrupt (ANSI). */ 140 | if (signal(SIGINT, intercept) == SIG_IGN ) 141 | { 142 | zlog_fatal(zc, "Can't caught the signal SIGINT, Interrupt (ANSI)"); 143 | signal(SIGINT, SIG_IGN ); 144 | return -4; 145 | } 146 | 147 | // start threads 148 | tinfo = calloc(NB_THREADS, sizeof(struct thread_info)); 149 | for (i=0; i 0) 197 | reload = (i % RELOAD_DELAY == 0); 198 | 199 | if (reload) 200 | { 201 | zlog_info(zc, "Will reload configuration..."); 202 | rc = zlog_reload(CONFIG); 203 | if (rc) { 204 | printf("main init failed\n"); 205 | return -6; 206 | } 207 | zlog_info(zc, "Configuration reloaded :)"); 208 | stat(CONFIG, &stat_0); 209 | } 210 | } 211 | 212 | exit(EXIT_SUCCESS); 213 | } 214 | -------------------------------------------------------------------------------- /src/category.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | #include "fmacros.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #include "category.h" 14 | #include "rule.h" 15 | #include "zc_defs.h" 16 | 17 | void zlog_category_profile(zlog_category_t *a_category, int flag) 18 | { 19 | int i; 20 | zlog_rule_t *a_rule; 21 | 22 | zc_assert(a_category,); 23 | zc_profile(flag, "--category[%p][%s][%p]--", 24 | a_category, 25 | a_category->name, 26 | a_category->fit_rules); 27 | if (a_category->fit_rules) { 28 | zc_arraylist_foreach(a_category->fit_rules, i, a_rule) { 29 | zlog_rule_profile(a_rule, flag); 30 | } 31 | } 32 | return; 33 | } 34 | 35 | /*******************************************************************************/ 36 | void zlog_category_del(zlog_category_t * a_category) 37 | { 38 | zc_assert(a_category,); 39 | if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules); 40 | zc_debug("zlog_category_del[%p]", a_category); 41 | free(a_category); 42 | return; 43 | } 44 | 45 | /* overlap one rule's level bitmap to cateogry, 46 | * so category can judge whether a log level will be output by itself 47 | * It is safe when configure is reloaded, when rule will be released an recreated 48 | */ 49 | static void zlog_cateogry_overlap_bitmap(zlog_category_t * a_category, zlog_rule_t *a_rule) 50 | { 51 | int i; 52 | for(i = 0; i < sizeof(a_rule->level_bitmap); i++) { 53 | a_category->level_bitmap[i] |= a_rule->level_bitmap[i]; 54 | } 55 | } 56 | 57 | static int zlog_category_obtain_rules(zlog_category_t * a_category, zc_arraylist_t * rules) 58 | { 59 | int i; 60 | int count = 0; 61 | int fit = 0; 62 | zlog_rule_t *a_rule; 63 | zlog_rule_t *wastebin_rule = NULL; 64 | 65 | /* before set, clean last fit rules first */ 66 | if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules); 67 | 68 | memset(a_category->level_bitmap, 0x00, sizeof(a_category->level_bitmap)); 69 | 70 | a_category->fit_rules = zc_arraylist_new(NULL); 71 | if (!(a_category->fit_rules)) { 72 | zc_error("zc_arraylist_new fail"); 73 | return -1; 74 | } 75 | 76 | /* get match rules from all rules */ 77 | zc_arraylist_foreach(rules, i, a_rule) { 78 | fit = zlog_rule_match_category(a_rule, a_category->name); 79 | if (fit) { 80 | if (zc_arraylist_add(a_category->fit_rules, a_rule)) { 81 | zc_error("zc_arrylist_add fail"); 82 | goto err; 83 | } 84 | zlog_cateogry_overlap_bitmap(a_category, a_rule); 85 | count++; 86 | } 87 | 88 | if (zlog_rule_is_wastebin(a_rule)) { 89 | wastebin_rule = a_rule; 90 | } 91 | } 92 | 93 | if (count == 0) { 94 | if (wastebin_rule) { 95 | zc_debug("category[%s], no match rules, use wastebin_rule", a_category->name); 96 | if (zc_arraylist_add(a_category->fit_rules, wastebin_rule)) { 97 | zc_error("zc_arrylist_add fail"); 98 | goto err; 99 | } 100 | zlog_cateogry_overlap_bitmap(a_category, wastebin_rule); 101 | count++; 102 | } else { 103 | zc_debug("category[%s], no match rules & no wastebin_rule", a_category->name); 104 | } 105 | } 106 | 107 | return 0; 108 | err: 109 | zc_arraylist_del(a_category->fit_rules); 110 | a_category->fit_rules = NULL; 111 | return -1; 112 | } 113 | 114 | zlog_category_t *zlog_category_new(const char *name, zc_arraylist_t * rules) 115 | { 116 | size_t len; 117 | zlog_category_t *a_category; 118 | 119 | zc_assert(name, NULL); 120 | zc_assert(rules, NULL); 121 | 122 | len = strlen(name); 123 | if (len > sizeof(a_category->name) - 1) { 124 | zc_error("name[%s] too long", name); 125 | return NULL; 126 | } 127 | a_category = calloc(1, sizeof(zlog_category_t)); 128 | if (!a_category) { 129 | zc_error("calloc fail, errno[%d]", errno); 130 | return NULL; 131 | } 132 | strcpy(a_category->name, name); 133 | a_category->name_len = len; 134 | if (zlog_category_obtain_rules(a_category, rules)) { 135 | zc_error("zlog_category_fit_rules fail"); 136 | goto err; 137 | } 138 | 139 | zlog_category_profile(a_category, ZC_DEBUG); 140 | return a_category; 141 | err: 142 | zlog_category_del(a_category); 143 | return NULL; 144 | } 145 | /*******************************************************************************/ 146 | /* update success: fit_rules 1, fit_rules_backup 1 */ 147 | /* update fail: fit_rules 0, fit_rules_backup 1 */ 148 | int zlog_category_update_rules(zlog_category_t * a_category, zc_arraylist_t * new_rules) 149 | { 150 | zc_assert(a_category, -1); 151 | zc_assert(new_rules, -1); 152 | 153 | /* 1st, mv fit_rules fit_rules_backup */ 154 | if (a_category->fit_rules_backup) zc_arraylist_del(a_category->fit_rules_backup); 155 | a_category->fit_rules_backup = a_category->fit_rules; 156 | a_category->fit_rules = NULL; 157 | 158 | memcpy(a_category->level_bitmap_backup, a_category->level_bitmap, 159 | sizeof(a_category->level_bitmap)); 160 | 161 | /* 2nd, obtain new_rules to fit_rules */ 162 | if (zlog_category_obtain_rules(a_category, new_rules)) { 163 | zc_error("zlog_category_obtain_rules fail"); 164 | a_category->fit_rules = NULL; 165 | return -1; 166 | } 167 | 168 | /* keep the fit_rules_backup not change, return */ 169 | return 0; 170 | } 171 | 172 | /* commit fail: fit_rules_backup != 0 */ 173 | /* commit success: fit_rules 1, fit_rules_backup 0 */ 174 | void zlog_category_commit_rules(zlog_category_t * a_category) 175 | { 176 | zc_assert(a_category,); 177 | if (!a_category->fit_rules_backup) { 178 | zc_warn("a_category->fit_rules_backup is NULL, never update before"); 179 | return; 180 | } 181 | 182 | zc_arraylist_del(a_category->fit_rules_backup); 183 | a_category->fit_rules_backup = NULL; 184 | memset(a_category->level_bitmap_backup, 0x00, 185 | sizeof(a_category->level_bitmap_backup)); 186 | return; 187 | } 188 | 189 | /* rollback fail: fit_rules_backup != 0 */ 190 | /* rollback success: fit_rules 1, fit_rules_backup 0 */ 191 | /* so whether update succes or not, make things back to old */ 192 | void zlog_category_rollback_rules(zlog_category_t * a_category) 193 | { 194 | zc_assert(a_category,); 195 | if (!a_category->fit_rules_backup) { 196 | zc_warn("a_category->fit_rules_backup in NULL, never update before"); 197 | return; 198 | } 199 | 200 | if (a_category->fit_rules) { 201 | /* update success, rm new and backup */ 202 | zc_arraylist_del(a_category->fit_rules); 203 | a_category->fit_rules = a_category->fit_rules_backup; 204 | a_category->fit_rules_backup = NULL; 205 | } else { 206 | /* update fail, just backup */ 207 | a_category->fit_rules = a_category->fit_rules_backup; 208 | a_category->fit_rules_backup = NULL; 209 | } 210 | 211 | memcpy(a_category->level_bitmap, a_category->level_bitmap_backup, 212 | sizeof(a_category->level_bitmap)); 213 | memset(a_category->level_bitmap_backup, 0x00, 214 | sizeof(a_category->level_bitmap_backup)); 215 | 216 | return; /* always success */ 217 | } 218 | 219 | /*******************************************************************************/ 220 | 221 | int zlog_category_output(zlog_category_t * a_category, zlog_thread_t * a_thread) 222 | { 223 | int i; 224 | int rc = 0; 225 | zlog_rule_t *a_rule; 226 | 227 | /* go through all match rules to output */ 228 | zc_arraylist_foreach(a_category->fit_rules, i, a_rule) { 229 | rc = zlog_rule_output(a_rule, a_thread); 230 | } 231 | 232 | return rc; 233 | } 234 | -------------------------------------------------------------------------------- /src/zc_hashtable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "zc_defs.h" 14 | #include "zc_hashtable.h" 15 | 16 | struct zc_hashtable_s { 17 | size_t nelem; 18 | 19 | zc_hashtable_entry_t **tab; 20 | size_t tab_size; 21 | 22 | zc_hashtable_hash_fn hash; 23 | zc_hashtable_equal_fn equal; 24 | zc_hashtable_del_fn key_del; 25 | zc_hashtable_del_fn value_del; 26 | }; 27 | 28 | zc_hashtable_t *zc_hashtable_new(size_t a_size, 29 | zc_hashtable_hash_fn hash, 30 | zc_hashtable_equal_fn equal, 31 | zc_hashtable_del_fn key_del, 32 | zc_hashtable_del_fn value_del) 33 | { 34 | zc_hashtable_t *a_table; 35 | 36 | a_table = calloc(1, sizeof(*a_table)); 37 | if (!a_table) { 38 | zc_error("calloc fail, errno[%d]", errno); 39 | return NULL; 40 | } 41 | 42 | a_table->tab = calloc(a_size, sizeof(*(a_table->tab))); 43 | if (!a_table->tab) { 44 | zc_error("calloc fail, errno[%d]", errno); 45 | free(a_table); 46 | return NULL; 47 | } 48 | a_table->tab_size = a_size; 49 | 50 | a_table->nelem = 0; 51 | a_table->hash = hash; 52 | a_table->equal = equal; 53 | 54 | /* these two could be NULL */ 55 | a_table->key_del = key_del; 56 | a_table->value_del = value_del; 57 | 58 | return a_table; 59 | } 60 | 61 | void zc_hashtable_del(zc_hashtable_t * a_table) 62 | { 63 | size_t i; 64 | zc_hashtable_entry_t *p; 65 | zc_hashtable_entry_t *q; 66 | 67 | if (!a_table) { 68 | zc_error("a_table[%p] is NULL, just do nothing", a_table); 69 | return; 70 | } 71 | 72 | for (i = 0; i < a_table->tab_size; i++) { 73 | for (p = (a_table->tab)[i]; p; p = q) { 74 | q = p->next; 75 | if (a_table->key_del) { 76 | a_table->key_del(p->key); 77 | } 78 | if (a_table->value_del) { 79 | a_table->value_del(p->value); 80 | } 81 | free(p); 82 | } 83 | } 84 | if (a_table->tab) 85 | free(a_table->tab); 86 | free(a_table); 87 | 88 | return; 89 | } 90 | 91 | void zc_hashtable_clean(zc_hashtable_t * a_table) 92 | { 93 | size_t i; 94 | zc_hashtable_entry_t *p; 95 | zc_hashtable_entry_t *q; 96 | 97 | for (i = 0; i < a_table->tab_size; i++) { 98 | for (p = (a_table->tab)[i]; p; p = q) { 99 | q = p->next; 100 | if (a_table->key_del) { 101 | a_table->key_del(p->key); 102 | } 103 | if (a_table->value_del) { 104 | a_table->value_del(p->value); 105 | } 106 | free(p); 107 | } 108 | (a_table->tab)[i] = NULL; 109 | } 110 | a_table->nelem = 0; 111 | return; 112 | } 113 | 114 | static int zc_hashtable_rehash(zc_hashtable_t * a_table) 115 | { 116 | size_t i; 117 | size_t j; 118 | size_t tab_size; 119 | zc_hashtable_entry_t **tab; 120 | zc_hashtable_entry_t *p; 121 | zc_hashtable_entry_t *q; 122 | 123 | tab_size = 2 * a_table->tab_size; 124 | tab = calloc(tab_size, sizeof(*tab)); 125 | if (!tab) { 126 | zc_error("calloc fail, errno[%d]", errno); 127 | return -1; 128 | } 129 | 130 | for (i = 0; i < a_table->tab_size; i++) { 131 | for (p = (a_table->tab)[i]; p; p = q) { 132 | q = p->next; 133 | 134 | p->next = NULL; 135 | p->prev = NULL; 136 | j = p->hash_key % tab_size; 137 | if (tab[j]) { 138 | tab[j]->prev = p; 139 | p->next = tab[j]; 140 | } 141 | tab[j] = p; 142 | } 143 | } 144 | free(a_table->tab); 145 | a_table->tab = tab; 146 | a_table->tab_size = tab_size; 147 | 148 | return 0; 149 | } 150 | 151 | zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t * a_table, const void *a_key) 152 | { 153 | unsigned int i; 154 | zc_hashtable_entry_t *p; 155 | 156 | i = a_table->hash(a_key) % a_table->tab_size; 157 | for (p = (a_table->tab)[i]; p; p = p->next) { 158 | if (a_table->equal(a_key, p->key)) 159 | return p; 160 | } 161 | 162 | return NULL; 163 | } 164 | 165 | void *zc_hashtable_get(zc_hashtable_t * a_table, const void *a_key) 166 | { 167 | unsigned int i; 168 | zc_hashtable_entry_t *p; 169 | 170 | i = a_table->hash(a_key) % a_table->tab_size; 171 | for (p = (a_table->tab)[i]; p; p = p->next) { 172 | if (a_table->equal(a_key, p->key)) 173 | return p->value; 174 | } 175 | 176 | return NULL; 177 | } 178 | 179 | int zc_hashtable_put(zc_hashtable_t * a_table, void *a_key, void *a_value) 180 | { 181 | int rc = 0; 182 | unsigned int i; 183 | zc_hashtable_entry_t *p = NULL; 184 | 185 | i = a_table->hash(a_key) % a_table->tab_size; 186 | for (p = (a_table->tab)[i]; p; p = p->next) { 187 | if (a_table->equal(a_key, p->key)) 188 | break; 189 | } 190 | 191 | if (p) { 192 | if (a_table->key_del) { 193 | a_table->key_del(p->key); 194 | } 195 | if (a_table->value_del) { 196 | a_table->value_del(p->value); 197 | } 198 | p->key = a_key; 199 | p->value = a_value; 200 | return 0; 201 | } else { 202 | if (a_table->nelem > a_table->tab_size * 1.3) { 203 | rc = zc_hashtable_rehash(a_table); 204 | if (rc) { 205 | zc_error("rehash fail"); 206 | return -1; 207 | } 208 | } 209 | 210 | p = calloc(1, sizeof(*p)); 211 | if (!p) { 212 | zc_error("calloc fail, errno[%d]", errno); 213 | return -1; 214 | } 215 | 216 | p->hash_key = a_table->hash(a_key); 217 | p->key = a_key; 218 | p->value = a_value; 219 | p->next = NULL; 220 | p->prev = NULL; 221 | 222 | i = p->hash_key % a_table->tab_size; 223 | if ((a_table->tab)[i]) { 224 | (a_table->tab)[i]->prev = p; 225 | p->next = (a_table->tab)[i]; 226 | } 227 | (a_table->tab)[i] = p; 228 | a_table->nelem++; 229 | } 230 | 231 | return 0; 232 | } 233 | 234 | void zc_hashtable_remove(zc_hashtable_t * a_table, const void *a_key) 235 | { 236 | zc_hashtable_entry_t *p; 237 | unsigned int i; 238 | 239 | if (!a_table || !a_key) { 240 | zc_error("a_table[%p] or a_key[%p] is NULL, just do nothing", a_table, a_key); 241 | return; 242 | } 243 | 244 | i = a_table->hash(a_key) % a_table->tab_size; 245 | for (p = (a_table->tab)[i]; p; p = p->next) { 246 | if (a_table->equal(a_key, p->key)) 247 | break; 248 | } 249 | 250 | if (!p) { 251 | zc_error("p[%p] not found in hashtable", p); 252 | return; 253 | } 254 | 255 | if (a_table->key_del) { 256 | a_table->key_del(p->key); 257 | } 258 | if (a_table->value_del) { 259 | a_table->value_del(p->value); 260 | } 261 | 262 | if (p->next) { 263 | p->next->prev = p->prev; 264 | } 265 | if (p->prev) { 266 | p->prev->next = p->next; 267 | } else { 268 | unsigned int i; 269 | 270 | i = p->hash_key % a_table->tab_size; 271 | a_table->tab[i] = p->next; 272 | } 273 | 274 | free(p); 275 | a_table->nelem--; 276 | 277 | return; 278 | } 279 | 280 | zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t * a_table) 281 | { 282 | size_t i; 283 | zc_hashtable_entry_t *p; 284 | 285 | for (i = 0; i < a_table->tab_size; i++) { 286 | for (p = (a_table->tab)[i]; p; p = p->next) { 287 | if (p) 288 | return p; 289 | } 290 | } 291 | 292 | return NULL; 293 | } 294 | 295 | zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t * a_table, zc_hashtable_entry_t * a_entry) 296 | { 297 | size_t i; 298 | size_t j; 299 | 300 | if (a_entry->next) 301 | return a_entry->next; 302 | 303 | i = a_entry->hash_key % a_table->tab_size; 304 | 305 | for (j = i + 1; j < a_table->tab_size; j++) { 306 | if ((a_table->tab)[j]) { 307 | return (a_table->tab)[j]; 308 | } 309 | } 310 | 311 | return NULL; 312 | } 313 | 314 | /*******************************************************************************/ 315 | 316 | unsigned int zc_hashtable_str_hash(const void *str) 317 | { 318 | unsigned int h = 5381; 319 | const char *p = (const char *)str; 320 | 321 | while (*p != '\0') 322 | h = ((h << 5) + h) + (*p++); /* hash * 33 + c */ 323 | 324 | return h; 325 | } 326 | 327 | int zc_hashtable_str_equal(const void *key1, const void *key2) 328 | { 329 | return (STRCMP((const char *)key1, ==, (const char *)key2)); 330 | } 331 | -------------------------------------------------------------------------------- /src/makefile: -------------------------------------------------------------------------------- 1 | # zlog makefile 2 | # Copyright (C) 2010-2012 Hardy Simpson 3 | # This file is released under the LGPL 2.1 license, see the COPYING file 4 | 5 | OBJ= \ 6 | buf.o \ 7 | category.o \ 8 | category_table.o \ 9 | conf.o \ 10 | event.o \ 11 | format.o \ 12 | level.o \ 13 | level_list.o \ 14 | mdc.o \ 15 | record.o \ 16 | record_table.o \ 17 | rotater.o \ 18 | rule.o \ 19 | spec.o \ 20 | thread.o \ 21 | zc_arraylist.o \ 22 | zc_hashtable.o \ 23 | zc_profile.o \ 24 | zc_util.o \ 25 | lockfile.o \ 26 | zlog.o 27 | BINS=zlog-chk-conf 28 | LIBNAME=libzlog 29 | 30 | ZLOG_MAJOR=1 31 | ZLOG_MINOR=2 32 | 33 | 34 | # for mingw (cut the last part of the uname) 35 | UNAME := $(shell uname | cut -c -5) 36 | 37 | ifeq ($(UNAME), MINGW) 38 | $(print compiling on mingw !!) 39 | OBJ := $(OBJ) zlog_win.o 40 | endif 41 | 42 | # Fallback to gcc when $CC is not in $PATH. 43 | CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc') 44 | OPTIMIZATION?=-O2 45 | 46 | ifeq ($(UNAME), MINGW) 47 | #XXX: ignore warnings on mingw for now 48 | WARNINGS=-Wall -Wstrict-prototypes -fwrapv 49 | else 50 | WARNINGS=-Wall -Werror -Wstrict-prototypes -fwrapv 51 | endif 52 | 53 | DEBUG?= -g -ggdb 54 | REAL_CFLAGS=$(OPTIMIZATION) -fPIC -pthread $(CFLAGS) $(WARNINGS) $(DEBUG) 55 | REAL_LDFLAGS=$(LDFLAGS) -pthread 56 | 57 | DYLIBSUFFIX=so 58 | STLIBSUFFIX=a 59 | DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(ZLOG_MAJOR).$(ZLOG_MINOR) 60 | DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(ZLOG_MAJOR) 61 | DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) 62 | DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) 63 | STLIBNAME=$(LIBNAME).$(STLIBSUFFIX) 64 | STLIB_MAKE_CMD=ar rcs $(STLIBNAME) 65 | 66 | # Installation related variables 67 | PREFIX?=/usr/local 68 | INCLUDE_PATH?=include 69 | LIBRARY_PATH?=lib 70 | BINARY_PATH=bin 71 | INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH) 72 | INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH) 73 | INSTALL_BINARY_PATH= $(PREFIX)/$(BINARY_PATH) 74 | 75 | # Platform-specific overrides 76 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 77 | compiler_platform := $(shell sh -c '$(CC) --version|grep -i apple') 78 | 79 | ifeq ($(uname_S),SunOS) 80 | # REAL_LDFLAGS+= -ldl -lnsl -lsocket 81 | DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS) 82 | INSTALL= cp -r 83 | endif 84 | 85 | # For Darwin builds, check the compiler platform above is not empty. The covers cross compilation on Linux 86 | ifneq ($(compiler_platform),) 87 | DYLIBSUFFIX=dylib 88 | DYLIB_MINOR_NAME=$(LIBNAME).$(ZLOG_MAJOR).$(ZLOG_MINOR).$(DYLIBSUFFIX) 89 | DYLIB_MAJOR_NAME=$(LIBNAME).$(ZLOG_MAJOR).$(DYLIBSUFFIX) 90 | DYLIB_MAKE_CMD=$(CC) -dynamiclib -install_name $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) 91 | REAL_CFLAGS+= -D_DARWIN_C_SOURCE 92 | endif 93 | 94 | ifeq ($(uname_S),AIX) 95 | # this logic of minor major is not relevant on AIX or at least not widely used 96 | # not to mention dynamic linker .a preference... 97 | DYLIB_MAKE_CMD=$(CC) -shared -Wl,-G,-b64 -maix64 -pthread -o $(DYLIBNAME) $(LDFLAGS) 98 | REAL_CFLAGS+= -maix64 99 | STLIB_MAKE_CMD=OBJECT_MODE=64 ar rcs $(STLIBNAME) $(DYLIB_MAJOR_NAME) 100 | endif 101 | 102 | ifeq ($(UNAME), MINGW) 103 | $(print compiling on mingw !!) 104 | DYLIBSUFFIX=dll 105 | STLIBSUFFIX=nogo 106 | 107 | REAL_CFLAGS := $(REAL_CFLAGS) -I$(INSTALL_INCLUDE_PATH) 108 | REAL_LDFLAGS := $(REAL_LDFLAGS) -L$(INSTALL_LIBRARY_PATH) -lws2_32 -lunixem 109 | endif 110 | 111 | all: $(DYLIBNAME) $(BINS) 112 | 113 | # Deps (use make dep to generate this) 114 | buf.o: buf.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 115 | zc_xplatform.h zc_util.h buf.h 116 | category.o: category.c fmacros.h category.h zc_defs.h zc_profile.h \ 117 | zc_arraylist.h zc_hashtable.h zc_xplatform.h zc_util.h thread.h event.h \ 118 | buf.h mdc.h rule.h format.h rotater.h record.h 119 | category_table.o: category_table.c zc_defs.h zc_profile.h zc_arraylist.h \ 120 | zc_hashtable.h zc_xplatform.h zc_util.h category_table.h category.h \ 121 | thread.h event.h buf.h mdc.h 122 | conf.o: conf.c fmacros.h conf.h zc_defs.h zc_profile.h zc_arraylist.h \ 123 | zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \ 124 | mdc.h rotater.h rule.h record.h level_list.h level.h 125 | event.o: event.c fmacros.h zc_defs.h zc_profile.h zc_arraylist.h \ 126 | zc_hashtable.h zc_xplatform.h zc_util.h event.h 127 | format.o: format.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 128 | zc_xplatform.h zc_util.h thread.h event.h buf.h mdc.h spec.h format.h 129 | level.o: level.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 130 | zc_xplatform.h zc_util.h level.h 131 | level_list.o: level_list.c zc_defs.h zc_profile.h zc_arraylist.h \ 132 | zc_hashtable.h zc_xplatform.h zc_util.h level.h level_list.h 133 | mdc.o: mdc.c mdc.h zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 134 | zc_xplatform.h zc_util.h 135 | record.o: record.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 136 | zc_xplatform.h zc_util.h record.h 137 | record_table.o: record_table.c zc_defs.h zc_profile.h zc_arraylist.h \ 138 | zc_hashtable.h zc_xplatform.h zc_util.h record_table.h record.h 139 | rotater.o: rotater.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 140 | zc_xplatform.h zc_util.h rotater.h 141 | rule.o: rule.c fmacros.h rule.h zc_defs.h zc_profile.h zc_arraylist.h \ 142 | zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \ 143 | mdc.h rotater.h record.h level_list.h level.h spec.h 144 | spec.o: spec.c fmacros.h spec.h event.h zc_defs.h zc_profile.h \ 145 | zc_arraylist.h zc_hashtable.h zc_xplatform.h zc_util.h buf.h thread.h \ 146 | mdc.h level_list.h level.h 147 | thread.o: thread.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 148 | zc_xplatform.h zc_util.h event.h buf.h thread.h mdc.h 149 | zc_arraylist.o: zc_arraylist.c zc_defs.h zc_profile.h zc_arraylist.h \ 150 | zc_hashtable.h zc_xplatform.h zc_util.h 151 | zc_hashtable.o: zc_hashtable.c zc_defs.h zc_profile.h zc_arraylist.h \ 152 | zc_hashtable.h zc_xplatform.h zc_util.h 153 | zc_profile.o: zc_profile.c fmacros.h zc_profile.h zc_xplatform.h 154 | zc_util.o: zc_util.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \ 155 | zc_xplatform.h zc_util.h 156 | zlog-chk-conf.o: zlog-chk-conf.c fmacros.h zlog.h 157 | lockfile.o: lockfile.c 158 | zlog.o: zlog.c fmacros.h conf.h zc_defs.h zc_profile.h zc_arraylist.h \ 159 | zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \ 160 | mdc.h rotater.h category_table.h category.h record_table.h \ 161 | record.h rule.h 162 | zlog_win.o: zlog_win.c 163 | 164 | $(DYLIBNAME): $(OBJ) 165 | $(DYLIB_MAKE_CMD) $(OBJ) $(REAL_LDFLAGS) 166 | # for use in test folder - linux and requirement for aix runtime 167 | # resolving 168 | cp -f $(DYLIBNAME) $(DYLIB_MAJOR_NAME) 169 | cp -f $(DYLIBNAME) $(DYLIB_MINOR_NAME) 170 | 171 | $(STLIBNAME): $(OBJ) 172 | $(STLIB_MAKE_CMD) $(OBJ) 173 | 174 | dynamic: $(DYLIBNAME) 175 | static: $(STLIBNAME) 176 | 177 | # Binaries: 178 | zlog-chk-conf: zlog-chk-conf.o $(STLIBNAME) $(DYLIBNAME) 179 | $(CC) -o $@ zlog-chk-conf.o -L. -lzlog $(REAL_LDFLAGS) 180 | 181 | .c.o: 182 | $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $< 183 | 184 | clean: 185 | rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) *.o *.gcda *.gcno *.gcov $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME) 186 | 187 | dep: 188 | $(CC) -MM *.c 189 | 190 | # Installation target 191 | 192 | ifeq ($(uname_S),SunOS) 193 | INSTALL?= cp -r 194 | endif 195 | 196 | ifeq ($(uname_S),AIX) 197 | INSTALL?= cp -r 198 | endif 199 | 200 | 201 | INSTALL?= cp -a 202 | 203 | install: $(DYLIBNAME) $(STLIBNAME) 204 | mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) $(INSTALL_BINARY_PATH) 205 | $(INSTALL) zlog.h $(INSTALL_INCLUDE_PATH) 206 | $(INSTALL) zlog-chk-conf $(INSTALL_BINARY_PATH) 207 | $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) 208 | cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME) 209 | cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME) 210 | $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) 211 | 212 | 32bit: 213 | @echo "" 214 | @echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386" 215 | @echo "" 216 | $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" 217 | 218 | gprof: 219 | $(MAKE) CFLAGS="-pg" LDFLAGS="-pg" 220 | 221 | gcov: 222 | $(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs" 223 | 224 | coverage: gcov 225 | make check 226 | mkdir -p tmp/lcov 227 | lcov -d . -c -o tmp/lcov/hiredis.info 228 | genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info 229 | 230 | noopt: 231 | $(MAKE) OPTIMIZATION="" 232 | 233 | .PHONY: all clean dep install 32bit gprof gcov noopt 234 | -------------------------------------------------------------------------------- /src/zlog.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the zlog Library. 3 | * 4 | * Copyright (C) 2011 by Hardy Simpson 5 | * 6 | * Licensed under the LGPL v2.1, see the file COPYING in base directory. 7 | */ 8 | 9 | #ifndef __zlog_h 10 | #define __zlog_h 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #include /* for va_list */ 17 | #include /* for size_t */ 18 | 19 | # if defined __GNUC__ 20 | # define ZLOG_CHECK_PRINTF(m,n) __attribute__((format(printf,m,n))) 21 | # else 22 | # define ZLOG_CHECK_PRINTF(m,n) 23 | # endif 24 | 25 | typedef struct zlog_category_s zlog_category_t; 26 | 27 | int zlog_init(const char *config); 28 | int zlog_init_from_string(const char *config_string); 29 | int zlog_reload(const char *config); 30 | int zlog_reload_from_string(const char *conf_string); 31 | void zlog_fini(void); 32 | 33 | void zlog_profile(void); 34 | 35 | zlog_category_t *zlog_get_category(const char *cname); 36 | int zlog_level_enabled(zlog_category_t *category, const int level); 37 | 38 | int zlog_put_mdc(const char *key, const char *value); 39 | char *zlog_get_mdc(const char *key); 40 | void zlog_remove_mdc(const char *key); 41 | void zlog_clean_mdc(void); 42 | 43 | int zlog_level_switch(zlog_category_t * category, int level); 44 | int zlog_level_enabled(zlog_category_t * category, int level); 45 | 46 | void zlog(zlog_category_t * category, 47 | const char *file, size_t filelen, 48 | const char *func, size_t funclen, 49 | long line, int level, 50 | const char *format, ...) ZLOG_CHECK_PRINTF(8,9); 51 | void vzlog(zlog_category_t * category, 52 | const char *file, size_t filelen, 53 | const char *func, size_t funclen, 54 | long line, int level, 55 | const char *format, va_list args); 56 | void hzlog(zlog_category_t * category, 57 | const char *file, size_t filelen, 58 | const char *func, size_t funclen, 59 | long line, int level, 60 | const void *buf, size_t buflen); 61 | 62 | int dzlog_init(const char *confpath, const char *cname); 63 | int dzlog_set_category(const char *cname); 64 | 65 | void dzlog(const char *file, size_t filelen, 66 | const char *func, size_t funclen, 67 | long line, int level, 68 | const char *format, ...) ZLOG_CHECK_PRINTF(7,8); 69 | void vdzlog(const char *file, size_t filelen, 70 | const char *func, size_t funclen, 71 | long line, int level, 72 | const char *format, va_list args); 73 | void hdzlog(const char *file, size_t filelen, 74 | const char *func, size_t funclen, 75 | long line, int level, 76 | const void *buf, size_t buflen); 77 | 78 | typedef struct zlog_msg_s { 79 | char *buf; 80 | size_t len; 81 | char *path; 82 | } zlog_msg_t; 83 | 84 | typedef int (*zlog_record_fn)(zlog_msg_t *msg); 85 | int zlog_set_record(const char *rname, zlog_record_fn record); 86 | 87 | const char *zlog_version(void); 88 | 89 | /******* useful macros, can be redefined at user's h file **********/ 90 | 91 | typedef enum { 92 | ZLOG_LEVEL_DEBUG = 20, 93 | ZLOG_LEVEL_INFO = 40, 94 | ZLOG_LEVEL_NOTICE = 60, 95 | ZLOG_LEVEL_WARN = 80, 96 | ZLOG_LEVEL_ERROR = 100, 97 | ZLOG_LEVEL_FATAL = 120 98 | } zlog_level; 99 | 100 | #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L 101 | # if defined __GNUC__ && __GNUC__ >= 2 102 | # define __func__ __FUNCTION__ 103 | # else 104 | # define __func__ "" 105 | # endif 106 | #endif 107 | 108 | #if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L 109 | /* zlog macros */ 110 | #define zlog_fatal(cat, ...) \ 111 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 112 | ZLOG_LEVEL_FATAL, __VA_ARGS__) 113 | #define zlog_error(cat, ...) \ 114 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 115 | ZLOG_LEVEL_ERROR, __VA_ARGS__) 116 | #define zlog_warn(cat, ...) \ 117 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 118 | ZLOG_LEVEL_WARN, __VA_ARGS__) 119 | #define zlog_notice(cat, ...) \ 120 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 121 | ZLOG_LEVEL_NOTICE, __VA_ARGS__) 122 | #define zlog_info(cat, ...) \ 123 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 124 | ZLOG_LEVEL_INFO, __VA_ARGS__) 125 | #define zlog_debug(cat, ...) \ 126 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 127 | ZLOG_LEVEL_DEBUG, __VA_ARGS__) 128 | /* dzlog macros */ 129 | #define dzlog_fatal(...) \ 130 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 131 | ZLOG_LEVEL_FATAL, __VA_ARGS__) 132 | #define dzlog_error(...) \ 133 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 134 | ZLOG_LEVEL_ERROR, __VA_ARGS__) 135 | #define dzlog_warn(...) \ 136 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 137 | ZLOG_LEVEL_WARN, __VA_ARGS__) 138 | #define dzlog_notice(...) \ 139 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 140 | ZLOG_LEVEL_NOTICE, __VA_ARGS__) 141 | #define dzlog_info(...) \ 142 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 143 | ZLOG_LEVEL_INFO, __VA_ARGS__) 144 | #define dzlog_debug(...) \ 145 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 146 | ZLOG_LEVEL_DEBUG, __VA_ARGS__) 147 | #elif defined __GNUC__ 148 | /* zlog macros */ 149 | #define zlog_fatal(cat, format, args...) \ 150 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 151 | ZLOG_LEVEL_FATAL, format, ##args) 152 | #define zlog_error(cat, format, args...) \ 153 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 154 | ZLOG_LEVEL_ERROR, format, ##args) 155 | #define zlog_warn(cat, format, args...) \ 156 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 157 | ZLOG_LEVEL_WARN, format, ##args) 158 | #define zlog_notice(cat, format, args...) \ 159 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 160 | ZLOG_LEVEL_NOTICE, format, ##args) 161 | #define zlog_info(cat, format, args...) \ 162 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 163 | ZLOG_LEVEL_INFO, format, ##args) 164 | #define zlog_debug(cat, format, args...) \ 165 | zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 166 | ZLOG_LEVEL_DEBUG, format, ##args) 167 | /* dzlog macros */ 168 | #define dzlog_fatal(format, args...) \ 169 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 170 | ZLOG_LEVEL_FATAL, format, ##args) 171 | #define dzlog_error(format, args...) \ 172 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 173 | ZLOG_LEVEL_ERROR, format, ##args) 174 | #define dzlog_warn(format, args...) \ 175 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 176 | ZLOG_LEVEL_WARN, format, ##args) 177 | #define dzlog_notice(format, args...) \ 178 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 179 | ZLOG_LEVEL_NOTICE, format, ##args) 180 | #define dzlog_info(format, args...) \ 181 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 182 | ZLOG_LEVEL_INFO, format, ##args) 183 | #define dzlog_debug(format, args...) \ 184 | dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 185 | ZLOG_LEVEL_DEBUG, format, ##args) 186 | #endif 187 | 188 | /* vzlog macros */ 189 | #define vzlog_fatal(cat, format, args) \ 190 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 191 | ZLOG_LEVEL_FATAL, format, args) 192 | #define vzlog_error(cat, format, args) \ 193 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 194 | ZLOG_LEVEL_ERROR, format, args) 195 | #define vzlog_warn(cat, format, args) \ 196 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 197 | ZLOG_LEVEL_WARN, format, args) 198 | #define vzlog_notice(cat, format, args) \ 199 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 200 | ZLOG_LEVEL_NOTICE, format, args) 201 | #define vzlog_info(cat, format, args) \ 202 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 203 | ZLOG_LEVEL_INFO, format, args) 204 | #define vzlog_debug(cat, format, args) \ 205 | vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 206 | ZLOG_LEVEL_DEBUG, format, args) 207 | 208 | /* hzlog macros */ 209 | #define hzlog_fatal(cat, buf, buf_len) \ 210 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 211 | ZLOG_LEVEL_FATAL, buf, buf_len) 212 | #define hzlog_error(cat, buf, buf_len) \ 213 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 214 | ZLOG_LEVEL_ERROR, buf, buf_len) 215 | #define hzlog_warn(cat, buf, buf_len) \ 216 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 217 | ZLOG_LEVEL_WARN, buf, buf_len) 218 | #define hzlog_notice(cat, buf, buf_len) \ 219 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 220 | ZLOG_LEVEL_NOTICE, buf, buf_len) 221 | #define hzlog_info(cat, buf, buf_len) \ 222 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 223 | ZLOG_LEVEL_INFO, buf, buf_len) 224 | #define hzlog_debug(cat, buf, buf_len) \ 225 | hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 226 | ZLOG_LEVEL_DEBUG, buf, buf_len) 227 | 228 | 229 | /* vdzlog macros */ 230 | #define vdzlog_fatal(format, args) \ 231 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 232 | ZLOG_LEVEL_FATAL, format, args) 233 | #define vdzlog_error(format, args) \ 234 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 235 | ZLOG_LEVEL_ERROR, format, args) 236 | #define vdzlog_warn(format, args) \ 237 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 238 | ZLOG_LEVEL_WARN, format, args) 239 | #define vdzlog_notice(format, args) \ 240 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 241 | ZLOG_LEVEL_NOTICE, format, args) 242 | #define vdzlog_info(format, args) \ 243 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 244 | ZLOG_LEVEL_INFO, format, args) 245 | #define vdzlog_debug(format, args) \ 246 | vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 247 | ZLOG_LEVEL_DEBUG, format, args) 248 | 249 | /* hdzlog macros */ 250 | #define hdzlog_fatal(buf, buf_len) \ 251 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 252 | ZLOG_LEVEL_FATAL, buf, buf_len) 253 | #define hdzlog_error(buf, buf_len) \ 254 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 255 | ZLOG_LEVEL_ERROR, buf, buf_len) 256 | #define hdzlog_warn(buf, buf_len) \ 257 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 258 | ZLOG_LEVEL_WARN, buf, buf_len) 259 | #define hdzlog_notice(buf, buf_len) \ 260 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 261 | ZLOG_LEVEL_NOTICE, buf, buf_len) 262 | #define hdzlog_info(buf, buf_len) \ 263 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 264 | ZLOG_LEVEL_INFO, buf, buf_len) 265 | #define hdzlog_debug(buf, buf_len) \ 266 | hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \ 267 | ZLOG_LEVEL_DEBUG, buf, buf_len) 268 | 269 | /* enabled macros */ 270 | #define zlog_fatal_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_FATAL) 271 | #define zlog_error_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_ERROR) 272 | #define zlog_warn_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_WARN) 273 | #define zlog_notice_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_NOTICE) 274 | #define zlog_info_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_INFO) 275 | #define zlog_debug_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_DEBUG) 276 | 277 | #ifdef __cplusplus 278 | } 279 | #endif 280 | 281 | #endif 282 | --------------------------------------------------------------------------------