1 /*
2  * Copyright (c) 2007-2009 Marko Kreen, Skype Technologies OÜ
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * @file
19  *
20  * Logging framework for unix services.
21  *
22  *
23  * Supported outputs:
24  * - syslog
25  * - log file
26  * - stderr
27  *
28  * @section logging_prefix Logging context
29  *
30  * It is possible to pass context info to all logging calls
31  * and later add details to log lines or to filter based on it.
32  *
33  * Each call references 2 macros:
34  * - LOG_CONTEXT_DEF - which can define/call any variables
35  * - LOG_CONTEXT - which should return a pointer variable.
36  *
37  * Later, global callback function \ref logging_prefix_cb
38  * will get this pointer with destination buffer and can either
39  * add more info for log line or tell to skip logging this message.
40  */
41 #ifndef _USUAL_LOGGING_H_
42 #define _USUAL_LOGGING_H_
43 
44 #include <usual/base.h>
45 
46 /* internal log levels */
47 enum LogLevel {
48 	LG_FATAL = 0,
49 	LG_ERROR = 1,
50 	LG_WARNING = 2,
51 	LG_STATS = 3,
52 	LG_INFO = 4,
53 	LG_DEBUG = 5,
54 	LG_NOISE = 6,
55 };
56 #ifndef LOG_CONTEXT_DEF
57 /** Example: Prepare dummy context pointer */
58 #define LOG_CONTEXT_DEF	void *_log_ctx = NULL
59 #endif
60 #ifndef LOG_CONTEXT
61 /** Example: Reference dummy context pointer */
62 #define LOG_CONTEXT	_log_ctx
63 #endif
64 
65 /**
66  * Signature for logging_prefix_cb.  Return value is either added string length in dst
67  * or negative value to skip logging.
68  */
69 typedef int (*logging_prefix_fn_t)(enum LogLevel lev, void *ctx, char *dst, unsigned int dstlen);
70 
71 /**
72  * Optional global callback for each log line.
73  *
74  * It can either add info to log message or skip logging it.
75  */
76 extern logging_prefix_fn_t logging_prefix_cb;
77 
78 /**
79  * Global verbosity level.
80  *
81  * 0 - show only info level msgs (default)
82  * 1 - show debug msgs (log_debug)
83  * 2 - show noise msgs (log_noise)
84  */
85 extern int cf_verbose;
86 
87 /**
88  * Toggle logging to stderr.  Default: 1.
89  * daemon.c turns this off if goes to background
90  */
91 extern int cf_quiet;
92 
93 /**
94  * Logfile location, default NULL
95  */
96 extern const char *cf_logfile;
97 
98 /** Syslog on/off */
99 extern int cf_syslog;
100 /** ident for syslog, if NULL syslog is disabled (default) */
101 extern const char *cf_syslog_ident;
102 /** Facility name */
103 extern const char *cf_syslog_facility;
104 
105 /** Max log level for syslog writer */
106 extern enum LogLevel cf_syslog_level;
107 /** Max log level for logfile writer */
108 extern enum LogLevel cf_logfile_level;
109 /** Max log level for stderr writer */
110 extern enum LogLevel cf_stderr_level;
111 
112 /*
113  * Internal API.
114  */
115 
116 /* non-fatal logging */
117 void log_generic(enum LogLevel level, void *ctx, const char *s, ...) _PRINTF(3, 4);
118 
119 /* this is also defined in base.h for Assert() */
120 void log_fatal(const char *file, int line, const char *func, bool show_perror,
121 	       void *ctx, const char *s, ...) _PRINTF(6, 7);
122 
123 /*
124  * Public API
125  */
126 
127 /** Log error message */
128 #define log_error(...) do { LOG_CONTEXT_DEF; \
129 		log_generic(LG_ERROR, LOG_CONTEXT, __VA_ARGS__); \
130 	} while (0)
131 
132 /** Log warning message */
133 #define log_warning(...) do { LOG_CONTEXT_DEF; \
134 		log_generic(LG_WARNING, LOG_CONTEXT, __VA_ARGS__); \
135 	} while (0)
136 
137 /** Log stats (liveness) message */
138 #define log_stats(...) do { LOG_CONTEXT_DEF; \
139 		log_generic(LG_STATS, LOG_CONTEXT, __VA_ARGS__); \
140 	} while (0)
141 
142 /** Log info message */
143 #define log_info(...) do { LOG_CONTEXT_DEF; \
144 		log_generic(LG_INFO, LOG_CONTEXT, __VA_ARGS__); \
145 	} while (0)
146 
147 /** Log debug message */
148 #define log_debug(...) do { LOG_CONTEXT_DEF; \
149 		if (unlikely(cf_verbose > 0)) \
150 			log_generic(LG_DEBUG, LOG_CONTEXT, __VA_ARGS__); \
151 	} while (0)
152 
153 /** Log debug noise */
154 #define log_noise(...) do { LOG_CONTEXT_DEF; \
155 		if (unlikely(cf_verbose > 1)) \
156 			log_generic(LG_NOISE, LOG_CONTEXT, __VA_ARGS__); \
157 	} while (0)
158 
159 /** Log and die.  It also logs source location */
160 #define fatal(...) do { LOG_CONTEXT_DEF; \
161 	log_fatal(__FILE__, __LINE__, __func__, false, LOG_CONTEXT, __VA_ARGS__); \
162 	exit(1); } while (0)
163 
164 /** Log strerror and die.  Error message also includes strerror(errno) */
165 #define fatal_perror(...) do { LOG_CONTEXT_DEF; \
166 	log_fatal(__FILE__, __LINE__, __func__, true, LOG_CONTEXT, __VA_ARGS__); \
167 	exit(1); } while (0)
168 
169 /** Less verbose fatal() */
170 #define die(...) do { LOG_CONTEXT_DEF; \
171 	log_generic(LG_FATAL, LOG_CONTEXT, __VA_ARGS__); \
172 	exit(1); } while (0)
173 
174 /**
175  * Close open logfiles and syslog.
176  *
177  * Useful when rotating log files.
178  */
179 void reset_logging(void);
180 
181 #endif
182