diff options
Diffstat (limited to 'src/log.c')
-rw-r--r-- | src/log.c | 481 |
1 files changed, 292 insertions, 189 deletions
@@ -1,241 +1,344 @@ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <time.h> -#include <syslog.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> - -#include "log.h" #include "common.h" - -// ---------------------------------------------------------------------------- -// LOG - const char *program_name = ""; unsigned long long debug_flags = DEBUG; -int silent = 0; +int access_log_syslog = 1; +int error_log_syslog = 1; +int output_log_syslog = 1; // debug log -int access_fd = -1; +int stdaccess_fd = -1; FILE *stdaccess = NULL; -int access_log_syslog = 1; -int error_log_syslog = 1; -int output_log_syslog = 1; // debug log +const char *stdaccess_filename = NULL; +const char *stderr_filename = NULL; +const char *stdout_filename = NULL; + +void syslog_init(void) { + static int i = 0; + + if(!i) { + openlog(program_name, LOG_PID, LOG_DAEMON); + i = 1; + } +} + +int open_log_file(int fd, FILE **fp, const char *filename, int *enabled_syslog) { + int f, t; + + if(!filename || !*filename || !strcmp(filename, "none")) + filename = "/dev/null"; + + if(!strcmp(filename, "syslog")) { + filename = "/dev/null"; + syslog_init(); + if(enabled_syslog) *enabled_syslog = 1; + } + else if(enabled_syslog) *enabled_syslog = 0; + + // don't do anything if the user is willing + // to have the standard one + if(!strcmp(filename, "system")) { + if(fd != -1) return fd; + filename = "stdout"; + } + + if(!strcmp(filename, "stdout")) + f = STDOUT_FILENO; + + else if(!strcmp(filename, "stderr")) + f = STDERR_FILENO; + + else { + f = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0664); + if(f == -1) { + error("Cannot open file '%s'. Leaving %d to its default.", filename, fd); + return fd; + } + } + + // if there is a level-2 file pointer + // flush it before switching the level-1 fds + if(fp && *fp) + fflush(*fp); + + if(fd != f && fd != -1) { + // it automatically closes + t = dup2(f, fd); + if (t == -1) { + error("Cannot dup2() new fd %d to old fd %d for '%s'", f, fd, filename); + close(f); + return fd; + } + // info("dup2() new fd %d to old fd %d for '%s'", f, fd, filename); + close(f); + } + else fd = f; + + if(fp && !*fp) { + *fp = fdopen(fd, "a"); + if (!*fp) + error("Cannot fdopen() fd %d ('%s')", fd, filename); + else { + if (setvbuf(*fp, NULL, _IOLBF, 0) != 0) + error("Cannot set line buffering on fd %d ('%s')", fd, filename); + } + } + + return fd; +} + +void reopen_all_log_files() { + if(stdout_filename) + open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog); + + if(stderr_filename) + open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog); + + if(stdaccess_filename) + stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog); +} + +void open_all_log_files() { + // disable stdin + open_log_file(STDIN_FILENO, &stdin, "/dev/null", NULL); + + open_log_file(STDOUT_FILENO, &stdout, stdout_filename, &output_log_syslog); + open_log_file(STDERR_FILENO, &stderr, stderr_filename, &error_log_syslog); + stdaccess_fd = open_log_file(stdaccess_fd, &stdaccess, stdaccess_filename, &access_log_syslog); +} + +// ---------------------------------------------------------------------------- +// error log throttling time_t error_log_throttle_period = 1200; unsigned long error_log_errors_per_period = 200; int error_log_limit(int reset) { - static time_t start = 0; - static unsigned long counter = 0, prevented = 0; - - // do not throttle if the period is 0 - if(error_log_throttle_period == 0) - return 0; - - // prevent all logs if the errors per period is 0 - if(error_log_errors_per_period == 0) - return 1; - - time_t now = time(NULL); - if(!start) start = now; - - if(reset) { - if(prevented) { - log_date(stderr); - fprintf(stderr, "%s: Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n" - , program_name - , program_name - , prevented - , now - start - ); - } - - start = now; - counter = 0; - prevented = 0; - } - - // detect if we log too much - counter++; - - if(now - start > error_log_throttle_period) { - if(prevented) { - log_date(stderr); - fprintf(stderr, "%s: Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n" - , program_name - , program_name - , prevented - , error_log_throttle_period - ); - } - - // restart the period accounting - start = now; - counter = 1; - prevented = 0; - - // log this error - return 0; - } - - if(counter > error_log_errors_per_period) { - if(!prevented) { - log_date(stderr); - 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" - , program_name - , counter - , now - start - , error_log_errors_per_period - , error_log_throttle_period - , program_name - , start + error_log_throttle_period - now); - } - - prevented++; - - // prevent logging this error - return 1; - } - - return 0; + static time_t start = 0; + static unsigned long counter = 0, prevented = 0; + + // do not throttle if the period is 0 + if(error_log_throttle_period == 0) + return 0; + + // prevent all logs if the errors per period is 0 + if(error_log_errors_per_period == 0) + return 1; + + time_t now = time(NULL); + if(!start) start = now; + + if(reset) { + if(prevented) { + log_date(stderr); + fprintf(stderr, "%s: Resetting logging for process '%s' (prevented %lu logs in the last %ld seconds).\n" + , program_name + , program_name + , prevented + , now - start + ); + } + + start = now; + counter = 0; + prevented = 0; + } + + // detect if we log too much + counter++; + + if(now - start > error_log_throttle_period) { + if(prevented) { + log_date(stderr); + fprintf(stderr, "%s: Resuming logging from process '%s' (prevented %lu logs in the last %ld seconds).\n" + , program_name + , program_name + , prevented + , error_log_throttle_period + ); + } + + // restart the period accounting + start = now; + counter = 1; + prevented = 0; + + // log this error + return 0; + } + + if(counter > error_log_errors_per_period) { + if(!prevented) { + log_date(stderr); + 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" + , program_name + , counter + , now - start + , error_log_errors_per_period + , error_log_throttle_period + , program_name + , start + error_log_throttle_period - now); + } + + prevented++; + + // prevent logging this error + return 1; + } + + return 0; } +// ---------------------------------------------------------------------------- +// print the date + +// FIXME +// this should print the date in a buffer the way it +// is now, logs from multiple threads may be multiplexed + void log_date(FILE *out) { - char outstr[200]; - time_t t; - struct tm *tmp, tmbuf; + char outstr[24]; + time_t t; + struct tm *tmp, tmbuf; - t = time(NULL); - tmp = localtime_r(&t, &tmbuf); + t = time(NULL); + tmp = localtime_r(&t, &tmbuf); - if (tmp == NULL) return; - if (strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0) return; + if (tmp == NULL) return; + if (unlikely(strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0)) return; - fprintf(out, "%s: ", outstr); + fprintf(out, "%s: ", outstr); } +// ---------------------------------------------------------------------------- +// debug log + void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) { - va_list args; - - log_date(stdout); - va_start( args, fmt ); - fprintf(stdout, "DEBUG (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); - vfprintf( stdout, fmt, args ); - va_end( args ); - fprintf(stdout, "\n"); - // fflush( stdout ); - - if(output_log_syslog) { - va_start( args, fmt ); - vsyslog(LOG_ERR, fmt, args ); - va_end( args ); - } + va_list args; + + log_date(stdout); + va_start( args, fmt ); + printf("DEBUG (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); + vprintf(fmt, args); + va_end( args ); + putchar('\n'); + + if(output_log_syslog) { + va_start( args, fmt ); + vsyslog(LOG_ERR, fmt, args ); + va_end( args ); + } + + fflush(stdout); } +// ---------------------------------------------------------------------------- +// info log + void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) { - va_list args; + va_list args; - // prevent logging too much - if(error_log_limit(0)) return; + // prevent logging too much + if(error_log_limit(0)) return; - log_date(stderr); + log_date(stderr); - va_start( args, fmt ); - if(debug_flags) fprintf(stderr, "INFO (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); - else fprintf(stderr, "INFO: %s: ", program_name); - vfprintf( stderr, fmt, args ); - va_end( args ); + va_start( args, fmt ); + if(debug_flags) fprintf(stderr, "INFO (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); + else fprintf(stderr, "INFO: %s: ", program_name); + vfprintf( stderr, fmt, args ); + va_end( args ); - fprintf(stderr, "\n"); + fputc('\n', stderr); - if(error_log_syslog) { - va_start( args, fmt ); - vsyslog(LOG_INFO, fmt, args ); - va_end( args ); - } + if(error_log_syslog) { + va_start( args, fmt ); + vsyslog(LOG_INFO, fmt, args ); + va_end( args ); + } } +// ---------------------------------------------------------------------------- +// error log + void error_int( const char *prefix, const char *file, const char *function, const unsigned long line, const char *fmt, ... ) { - va_list args; - - // prevent logging too much - if(error_log_limit(0)) return; - - log_date(stderr); - - va_start( args, fmt ); - if(debug_flags) fprintf(stderr, "%s (%04lu@%-10.10s:%-15.15s): %s: ", prefix, line, file, function, program_name); - else fprintf(stderr, "%s: %s: ", prefix, program_name); - vfprintf( stderr, fmt, args ); - va_end( args ); - - if(errno) { - char buf[200]; - char *s = strerror_r(errno, buf, 200); - fprintf(stderr, " (errno %d, %s)\n", errno, s); - errno = 0; - } - else fprintf(stderr, "\n"); - - if(error_log_syslog) { - va_start( args, fmt ); - vsyslog(LOG_ERR, fmt, args ); - va_end( args ); - } + va_list args; + + // prevent logging too much + if(error_log_limit(0)) return; + + log_date(stderr); + + va_start( args, fmt ); + if(debug_flags) fprintf(stderr, "%s (%04lu@%-10.10s:%-15.15s): %s: ", prefix, line, file, function, program_name); + else fprintf(stderr, "%s: %s: ", prefix, program_name); + vfprintf( stderr, fmt, args ); + va_end( args ); + + if(errno) { + char buf[1024]; + fprintf(stderr, " (errno %d, %s)\n", errno, strerror_r(errno, buf, 1023)); + errno = 0; + } + else + fputc('\n', stderr); + + if(error_log_syslog) { + va_start( args, fmt ); + vsyslog(LOG_ERR, fmt, args ); + va_end( args ); + } } void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... ) { - va_list args; + va_list args; - log_date(stderr); + log_date(stderr); - va_start( args, fmt ); - if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); - else fprintf(stderr, "FATAL: %s: ", program_name); - vfprintf( stderr, fmt, args ); - va_end( args ); + va_start( args, fmt ); + if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-10.10s:%-15.15s): %s: ", line, file, function, program_name); + else fprintf(stderr, "FATAL: %s: ", program_name); + vfprintf( stderr, fmt, args ); + va_end( args ); - perror(" # "); - fprintf(stderr, "\n"); + perror(" # "); + fputc('\n', stderr); - if(error_log_syslog) { - va_start( args, fmt ); - vsyslog(LOG_CRIT, fmt, args ); - va_end( args ); - } + if(error_log_syslog) { + va_start( args, fmt ); + vsyslog(LOG_CRIT, fmt, args ); + va_end( args ); + } - exit(1); + netdata_cleanup_and_exit(1); } +// ---------------------------------------------------------------------------- +// access log + void log_access( const char *fmt, ... ) { - va_list args; - - if(stdaccess) { - log_date(stdaccess); - - va_start( args, fmt ); - vfprintf( stdaccess, fmt, args ); - va_end( args ); - fprintf( stdaccess, "\n"); - // fflush( stdaccess ); - } - - if(access_log_syslog) { - va_start( args, fmt ); - vsyslog(LOG_INFO, fmt, args ); - va_end( args ); - } + va_list args; + + if(stdaccess) { + log_date(stdaccess); + + va_start( args, fmt ); + vfprintf( stdaccess, fmt, args ); + va_end( args ); + fputc('\n', stdaccess); + } + + if(access_log_syslog) { + va_start( args, fmt ); + vsyslog(LOG_INFO, fmt, args ); + va_end( args ); + } } |