OSSP liblog =========== Braindump: - debugging is special case of logging - tracing is special case of debugging License: - ISC/MIT/BSD Sprache: - C++ - C Aufbau: 1. Layer C++ API log.hpp, log.cpp 2. Layer C API log.h log.c 3. Layer C Backend backend.h backend.c - "make striptease" - optimierung: log(..) { } : log(....); : API Levels: - PANIC (-> LOG_EMERG) - CRITICAL (-> LOG_CRIT) - ERROR (-> LOG_ERR) - WARNING - NOTICE - INFO - TRACE (-> LOG_DEBUG) - DEBUG (-> LOG_DEBUG) Level Entscheidungen: >= (default) <= = ; * Backend Channels: 1 Level -> N Channels - file (append) - program (stdin) - syslog - stderr/stdout - null (discard, nicht nur /dev/null) - filedescriptor (escape/ext) - callback function Log Messages: - raw - optional prefixes (inclusive order): string facility level timestamp pid (tid) - errno (like syslog %m) - eigene %{foo}x mit callback function mit context - automatisch: number -> string mapping (fuer error strings) - __FILE__, __LINE__, (__FUNCTION__) Configuration: - ueber C/C++ API - zusaetzlich Config-File 1. /etc/liblog.conf 2. (in ., .., ../..) 3. $HOME/.liblog.conf - !debug -> !code API C (ala MM): - reentrant: log_xxx - non-reentrant: Log_xxx Message Filtering/Masking: - facility und/oder levels und/oder wildcard pattern API Using: - C++: LogManager logm; logm.debug1("test"); logm.configure(" - C: log lh; lh = log_init(LOG_CFGFILE|LOG_CFGPARENT|LOG_XXX|..., "foo" (=facility)); log_configure(lh, "foo", LOG_WARN|LOG_LESSER, null); log_cb(lh, "x", func, ctx); int func(void *ctx, char *str, ...); log_msg(lh, LOG_WARN, "..%{foo}x %s...%E..", cp); log_dbg(lh, "..%{foo}x %s...%E..", cp); log_kill(lh); - Buffered I/O: fuer manche channels non-buffered (debug, errors) fuer manche andere aber buffered (access log, performance) loesung: I/O ueber callbacks (3x: open, write, close) z.B. RRDTool - Varargs: log ist nur wrapper fuer vlog - Source Tree: README .......... information about package INSTALL ......... instructions for installation LICENSE ......... license information TODO ............ to-do list ChangeLog ....... history of all changes Makefile.in ..... build specification configure.in .... GNU Autoconf script source aclocal.m4 ...... GNU Autoconf internal macros libtool ......... GNU Libtool utility shtool .......... GNU Shtool utility l2.m4 ........... GNU Autoconf public macro AC_L2() l2-config.in .... configuration utility script l2.h ............ C API definition l2.c ............ C API+internals implementation l2.hh ........... C++ API definition l2.cc ........... C++ API implementation l2.pod .......... Unix manual page source (POD format) l2_test.c ....... Test application - Error Handling: o log kein Return Code o aber error callback function (dadrin in C++: throw, in C: exit) - Newline Handling: option fuer channel: \r, \r\n, \n oder gleich string und moeglichkeit gar nix (string="") - Perhaps: optionally reopen logfile on each write - An optional syslog(3) compatible API for converting syslog-only based applications (like sendmail) to (restricted) liblog-based applications. - Ein Wort noch zu variablen Argumentlisten in cpp-Makros: gcc unterstützt dies in in der GNU- und der C99-Ausführung. Das heißt, der "..." Parameter kann im Makro respektive über "args" und über "__VA_ARGS__" angesprochen werden. Wichtig ist dabei, daß "..." nicht leer sein -- also kein Argument enthalten -- darf, da sonst der Präprocessor an einem eventuell vorhandenen Komma scheitert. Dies kann beim gcc durch Voranstellen von "##" vor dem "__VA_ARGS__" umgangen werden. Ouch. Beide Erweiterungen sind derzeit nicht aktiv, wenn mit -ansi compiliert wird. Explizit anschalten läßt sich die standard-konforme Erweiterung über "-std=c9x", bzw. "-std=c99" bei neueren gccs.