/* * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * @file * * Logging framework for unix services. * * * Supported outputs: * - syslog * - log file * - stderr * * @section logging_prefix Logging context * * It is possible to pass context info to all logging calls * and later add details to log lines or to filter based on it. * * Each call references 2 macros: * - LOG_CONTEXT_DEF - which can define/call any variables * - LOG_CONTEXT - which should return a pointer variable. * * Later, global callback function \ref logging_prefix_cb * will get this pointer with destination buffer and can either * add more info for log line or tell to skip logging this message. */ #ifndef _USUAL_LOGGING_H_ #define _USUAL_LOGGING_H_ #include /* internal log levels */ enum LogLevel { LG_FATAL = 0, LG_ERROR = 1, LG_WARNING = 2, LG_STATS = 3, LG_INFO = 4, LG_DEBUG = 5, LG_NOISE = 6, }; #ifndef LOG_CONTEXT_DEF /** Example: Prepare dummy context pointer */ #define LOG_CONTEXT_DEF void *_log_ctx = NULL #endif #ifndef LOG_CONTEXT /** Example: Reference dummy context pointer */ #define LOG_CONTEXT _log_ctx #endif /** * Signature for logging_prefix_cb. Return value is either added string length in dst * or negative value to skip logging. */ typedef int (*logging_prefix_fn_t)(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen); /** * Optional global callback for each log line. * * It can either add info to log message or skip logging it. */ extern logging_prefix_fn_t logging_prefix_cb; /** * Global verbosity level. * * 0 - show only info level msgs (default) * 1 - show debug msgs (log_debug) * 2 - show noise msgs (log_noise) */ extern int cf_verbose; /** * Toggle logging to stderr. Default: 1. * daemon.c turns this off if goes to background */ extern int cf_quiet; /** * Logfile location, default NULL */ extern const char *cf_logfile; /** Syslog on/off */ extern int cf_syslog; /** ident for syslog, if NULL syslog is disabled (default) */ extern const char *cf_syslog_ident; /** Facility name */ extern const char *cf_syslog_facility; /** Max log level for syslog writer */ extern enum LogLevel cf_syslog_level; /** Max log level for logfile writer */ extern enum LogLevel cf_logfile_level; /** Max log level for stderr writer */ extern enum LogLevel cf_stderr_level; /* * Internal API. */ /* non-fatal logging */ void log_generic(enum LogLevel level, void *ctx, const char *s, ...) _PRINTF(3, 4); /* this is also defined in base.h for Assert() */ void log_fatal(const char *file, int line, const char *func, bool show_perror, void *ctx, const char *s, ...) _PRINTF(6, 7); /* * Public API */ /** Log error message */ #define log_error(...) do { LOG_CONTEXT_DEF; \ log_generic(LG_ERROR, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log warning message */ #define log_warning(...) do { LOG_CONTEXT_DEF; \ log_generic(LG_WARNING, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log stats (liveness) message */ #define log_stats(...) do { LOG_CONTEXT_DEF; \ log_generic(LG_STATS, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log info message */ #define log_info(...) do { LOG_CONTEXT_DEF; \ log_generic(LG_INFO, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log debug message */ #define log_debug(...) do { LOG_CONTEXT_DEF; \ if (unlikely(cf_verbose > 0)) \ log_generic(LG_DEBUG, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log debug noise */ #define log_noise(...) do { LOG_CONTEXT_DEF; \ if (unlikely(cf_verbose > 1)) \ log_generic(LG_NOISE, LOG_CONTEXT, __VA_ARGS__); \ } while (0) /** Log and die. It also logs source location */ #define fatal(...) do { LOG_CONTEXT_DEF; \ log_fatal(__FILE__, __LINE__, __func__, false, LOG_CONTEXT, __VA_ARGS__); \ exit(1); } while (0) /** Log strerror and die. Error message also includes strerror(errno) */ #define fatal_perror(...) do { LOG_CONTEXT_DEF; \ log_fatal(__FILE__, __LINE__, __func__, true, LOG_CONTEXT, __VA_ARGS__); \ exit(1); } while (0) /** Less verbose fatal() */ #define die(...) do { LOG_CONTEXT_DEF; \ log_generic(LG_FATAL, LOG_CONTEXT, __VA_ARGS__); \ exit(1); } while (0) /** * Close open logfiles and syslog. * * Useful when rotating log files. */ void reset_logging(void); #endif