3 const char *program_name = "";
4 unsigned long long debug_flags = DEBUG;
6 int access_log_syslog = 1;
7 int error_log_syslog = 1;
8 int output_log_syslog = 1; // debug log
10 int stdaccess_fd = -1;
11 FILE *stdaccess = NULL;
13 const char *stdaccess_filename = NULL;
14 const char *stderr_filename = NULL;
15 const char *stdout_filename = NULL;
17 void syslog_init(void) {
21 openlog(program_name, LOG_PID, LOG_DAEMON);
26 int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) {
29 if(!filename || !*filename || !strsame(filename, "none"))
30 filename = "/dev/null";
32 if(!strsame(filename, "syslog")) {
33 filename = "/dev/null";
35 if(enabled_syslog) *enabled_syslog = 1;
37 else if(enabled_syslog) *enabled_syslog = 0;
39 // don't do anything if the user is willing
40 // to have the standard one
41 if(!strsame(filename, "system")) {
42 if(fd != -1) return fd;
46 if(!strsame(filename, "stdout"))
49 else if(!strsame(filename, "stderr"))
53 f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664);
55 error("Cannot open file '%s'. Leaving %d to its default.", filename, fd);
60 // if there is a level-2 file pointer
61 // flush it before switching the level-1 fds
65 if(fd != f && fd != -1) {
66 // it automatically closes
69 error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
73 // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename);
79 *fp = fdopen(fd, "a");
81 error("Cannot fdopen() fd %d ('%s')", fd, filename);
83 if (setvbuf(*fp, NULL, _IOLBF, 0) != 0)
84 error("Cannot set line buffering on fd %d ('%s')", fd, filename);
91 void reopen_all_log_files() {
93 open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog);
96 open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog);
98 if(stdaccess_filename)
99 stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog);
102 void open_all_log_files() {
104 open_log_file(STDIN_FILENO, (FILE **)&stdin, "/dev/null", NULL);
106 open_log_file(STDOUT_FILENO, (FILE **)&stdout, stdout_filename, &output_log_syslog);
107 open_log_file(STDERR_FILENO, (FILE **)&stderr, stderr_filename, &error_log_syslog);
108 stdaccess_fd = open_log_file(stdaccess_fd, (FILE **)&stdaccess, stdaccess_filename, &access_log_syslog);
111 // ----------------------------------------------------------------------------
112 // error log throttling
114 time_t error_log_throttle_period_backup = 0;
115 time_t error_log_throttle_period = 1200;
116 unsigned long error_log_errors_per_period = 200;
118 int error_log_limit(int reset) {
119 static time_t start = 0;
120 static unsigned long counter = 0, prevented = 0;
122 // do not throttle if the period is 0
123 if(error_log_throttle_period == 0)
126 // prevent all logs if the errors per period is 0
127 if(error_log_errors_per_period == 0)
128 #ifdef NETDATA_INTERNAL_CHECKS
134 time_t now = now_monotonic_sec();
135 if(!start) start = now;
140 fprintf(stderr, "%s: Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n"
153 // detect if we log too much
156 if(now - start > error_log_throttle_period) {
159 fprintf(stderr, "%s: Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n"
163 , error_log_throttle_period
167 // restart the period accounting
176 if(counter > error_log_errors_per_period) {
179 fprintf(stderr, "%s: Too many logs (%lu logs in %ld seconds, threshold is set to %lu logs in %ld seconds). Preventing more logs from process '%s' for %ld seconds.\n"
183 , error_log_errors_per_period
184 , error_log_throttle_period
186 , start + error_log_throttle_period - now);
191 // prevent logging this error
192 #ifdef NETDATA_INTERNAL_CHECKS
202 // ----------------------------------------------------------------------------
206 // this should print the date in a buffer the way it
207 // is now, logs from multiple threads may be multiplexed
209 void log_date(FILE *out)
213 struct tm *tmp, tmbuf;
215 t = now_realtime_sec();
216 tmp = localtime_r(&t, &tmbuf);
218 if (tmp == NULL) return;
219 if (unlikely(strftime(outstr, sizeof(outstr), "%Y-%m-%d %H:%M:%S", tmp) == 0)) return;
221 fprintf(out, "%s: ", outstr);
224 // ----------------------------------------------------------------------------
227 void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
232 va_start( args, fmt );
233 printf("%s: DEBUG (%04lu@%-10.10s:%-15.15s): ", program_name, line, file, function);
238 if(output_log_syslog) {
239 va_start( args, fmt );
240 vsyslog(LOG_ERR, fmt, args );
247 // ----------------------------------------------------------------------------
250 void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
254 // prevent logging too much
255 if(error_log_limit(0)) return;
259 va_start( args, fmt );
260 if(debug_flags) fprintf(stderr, "%s: INFO: (%04lu@%-10.10s:%-15.15s):", program_name, line, file, function);
261 else fprintf(stderr, "%s: INFO: ", program_name);
262 vfprintf( stderr, fmt, args );
267 if(error_log_syslog) {
268 va_start( args, fmt );
269 vsyslog(LOG_INFO, fmt, args );
274 // ----------------------------------------------------------------------------
277 #if defined(STRERROR_R_CHAR_P)
278 // GLIBC version of strerror_r
279 static const char *strerror_result(const char *a, const char *b) { (void)b; return a; }
280 #elif defined(HAVE_STRERROR_R)
281 // POSIX version of strerror_r
282 static const char *strerror_result(int a, const char *b) { (void)a; return b; }
283 #elif defined(HAVE_C__GENERIC)
286 // http://stackoverflow.com/questions/479207/function-overloading-in-c
287 static const char *strerror_result_int(int a, const char *b) { (void)a; return b; }
288 static const char *strerror_result_string(const char *a, const char *b) { (void)b; return a; }
290 #define strerror_result(a, b) _Generic((a), \
291 int: strerror_result_int, \
292 char *: strerror_result_string \
296 #error "cannot detect the format of function strerror_r()"
299 void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... )
303 // prevent logging too much
304 if(error_log_limit(0)) return;
308 va_start( args, fmt );
309 if(debug_flags) fprintf(stderr, "%s: %s: (%04lu@%-10.10s:%-15.15s): ", program_name, prefix, line, file, function);
310 else fprintf(stderr, "%s: %s: ", program_name, prefix);
311 vfprintf( stderr, fmt, args );
316 fprintf(stderr, " (errno %d, %s)\n", errno, strerror_result(strerror_r(errno, buf, 1023), buf));
322 if(error_log_syslog) {
323 va_start( args, fmt );
324 vsyslog(LOG_ERR, fmt, args );
329 void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
335 va_start( args, fmt );
336 if(debug_flags) fprintf(stderr, "%s: FATAL: (%04lu@%-10.10s:%-15.15s): ", program_name, line, file, function);
337 else fprintf(stderr, "%s: FATAL: ", program_name);
338 vfprintf( stderr, fmt, args );
344 if(error_log_syslog) {
345 va_start( args, fmt );
346 vsyslog(LOG_CRIT, fmt, args );
350 netdata_cleanup_and_exit(1);
353 // ----------------------------------------------------------------------------
356 void log_access( const char *fmt, ... )
363 va_start( args, fmt );
364 vfprintf( stdaccess, fmt, args );
366 fputc('\n', stdaccess);
369 if(access_log_syslog) {
370 va_start( args, fmt );
371 vsyslog(LOG_INFO, fmt, args );