i3
|
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 }