i3
src/log.c
Go to the documentation of this file.
00001 /*
00002  * vim:ts=4:sw=4:expandtab
00003  *
00004  * i3 - an improved dynamic tiling window manager
00005  *
00006  * © 2009-2010 Michael Stapelberg and contributors
00007  *
00008  * See file LICENSE for license information.
00009  *
00010  * src/log.c: handles the setting of loglevels, contains the logging functions.
00011  *
00012  */
00013 #include <stdarg.h>
00014 #include <stdio.h>
00015 #include <string.h>
00016 #include <stdbool.h>
00017 #include <stdlib.h>
00018 #include <sys/time.h>
00019 
00020 #include "util.h"
00021 #include "log.h"
00022 
00023 /* loglevels.h is autogenerated at make time */
00024 #include "loglevels.h"
00025 
00026 static uint64_t loglevel = 0;
00027 static bool verbose = true;
00028 static FILE *errorfile;
00029 char *errorfilename;
00030 
00031 /*
00032  * Initializes logging by creating an error logfile in /tmp (or
00033  * XDG_RUNTIME_DIR, see get_process_filename()).
00034  *
00035  */
00036 void init_logging() {
00037     errorfilename = get_process_filename("errorlog");
00038     if (errorfilename == NULL) {
00039         ELOG("Could not initialize errorlog\n");
00040         return;
00041     }
00042 
00043     errorfile = fopen(errorfilename, "w");
00044 }
00045 
00046 /*
00047  * Set verbosity of i3. If verbose is set to true, informative messages will
00048  * be printed to stdout. If verbose is set to false, only errors will be
00049  * printed.
00050  *
00051  */
00052 void set_verbosity(bool _verbose) {
00053     verbose = _verbose;
00054 }
00055 
00056 /*
00057  * Enables the given loglevel.
00058  *
00059  */
00060 void add_loglevel(const char *level) {
00061     /* Handle the special loglevel "all" */
00062     if (strcasecmp(level, "all") == 0) {
00063         loglevel = UINT64_MAX;
00064         return;
00065     }
00066 
00067     for (int i = 0; i < sizeof(loglevels) / sizeof(char*); i++) {
00068         if (strcasecmp(loglevels[i], level) != 0)
00069             continue;
00070 
00071         /* The position in the array (plus one) is the amount of times
00072          * which we need to shift 1 to the left to get our bitmask for
00073          * the specific loglevel. */
00074         loglevel |= (1 << (i+1));
00075         break;
00076     }
00077 }
00078 
00079 /*
00080  * Logs the given message to stdout while prefixing the current time to it.
00081  * This is to be called by *LOG() which includes filename/linenumber/function.
00082  *
00083  */
00084 void vlog(char *fmt, va_list args) {
00085     char timebuf[64];
00086 
00087     /* Get current time */
00088     time_t t = time(NULL);
00089     /* Convert time to local time (determined by the locale) */
00090     struct tm *tmp = localtime(&t);
00091     /* Generate time prefix */
00092     strftime(timebuf, sizeof(timebuf), "%x %X - ", tmp);
00093 #ifdef DEBUG_TIMING
00094     struct timeval tv;
00095     gettimeofday(&tv, NULL);
00096     printf("%s%d.%d - ", timebuf, tv.tv_sec, tv.tv_usec);
00097 #else
00098     printf("%s", timebuf);
00099 #endif
00100     vprintf(fmt, args);
00101 }
00102 
00103 /*
00104  * Logs the given message to stdout while prefixing the current time to it,
00105  * but only if verbose mode is activated.
00106  *
00107  */
00108 void verboselog(char *fmt, ...) {
00109     va_list args;
00110 
00111     if (!verbose)
00112         return;
00113 
00114     va_start(args, fmt);
00115     vlog(fmt, args);
00116     va_end(args);
00117 }
00118 
00119 /*
00120  * Logs the given message to stdout while prefixing the current time to it.
00121  *
00122  */
00123 void errorlog(char *fmt, ...) {
00124     va_list args;
00125 
00126     va_start(args, fmt);
00127     vlog(fmt, args);
00128     va_end(args);
00129 
00130     /* also log to the error logfile, if opened */
00131     va_start(args, fmt);
00132     vfprintf(errorfile, fmt, args);
00133     fflush(errorfile);
00134     va_end(args);
00135 }
00136 
00137 /*
00138  * Logs the given message to stdout while prefixing the current time to it,
00139  * but only if the corresponding debug loglevel was activated.
00140  * This is to be called by DLOG() which includes filename/linenumber
00141  *
00142  */
00143 void debuglog(uint64_t lev, char *fmt, ...) {
00144     va_list args;
00145 
00146     if ((loglevel & lev) == 0)
00147         return;
00148 
00149     va_start(args, fmt);
00150     vlog(fmt, args);
00151     va_end(args);
00152 }