i3: Replace loglevels by a global debug logging

File-limited were not used nor really useful
Besides, they are painful to maintain in Makefile rules compared to the
benefit
next
Quentin Glidic 2012-07-22 00:16:52 +02:00 committed by Michael Stapelberg
parent 1f682eb9c8
commit bdc078914b
11 changed files with 36 additions and 78 deletions

2
.gitignore vendored
View File

@ -1,8 +1,6 @@
*.o *.o
tags tags
include/loglevels.h
include/GENERATED_*.h include/GENERATED_*.h
loglevels.tmp
*.swp *.swp
*.gcda *.gcda
*.gcno *.gcno

View File

@ -6,25 +6,15 @@ include $(TOPDIR)/common.mk
AUTOGENERATED:=src/cfgparse.tab.c src/cfgparse.yy.c AUTOGENERATED:=src/cfgparse.tab.c src/cfgparse.yy.c
FILES:=$(filter-out $(AUTOGENERATED),$(wildcard src/*.c)) FILES:=$(filter-out $(AUTOGENERATED),$(wildcard src/*.c))
FILES:=$(FILES:.c=.o) FILES:=$(FILES:.c=.o)
HEADERS:=$(filter-out include/loglevels.h,$(wildcard include/*.h)) HEADERS:=$(wildcard include/*.h)
CMDPARSE_HEADERS:=include/GENERATED_call.h include/GENERATED_enums.h include/GENERATED_tokens.h CMDPARSE_HEADERS:=include/GENERATED_call.h include/GENERATED_enums.h include/GENERATED_tokens.h
# Recursively generate loglevels.h by explicitly calling make
# We need this step because we need to ensure that loglevels.h will be
# updated if necessary, but we also want to save rebuilds of the object
# files, so we cannot let the object files depend on loglevels.h.
ifeq ($(MAKECMDGOALS),loglevels.h)
#UNUSED:=$(warning Generating loglevels.h)
else
UNUSED:=$(shell $(MAKE) loglevels.h)
endif
SUBDIRS:=i3-msg i3-input i3-nagbar i3-config-wizard i3bar i3-dump-log SUBDIRS:=i3-msg i3-input i3-nagbar i3-config-wizard i3bar i3-dump-log
# Depend on the specific file (.c for each .o) and on all headers # Depend on the specific file (.c for each .o) and on all headers
src/%.o: src/%.c ${HEADERS} src/%.o: src/%.c ${HEADERS}
echo "[i3] CC $<" echo "[i3] CC $<"
$(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="((uint64_t)1 << $(shell awk '/$(shell basename $< .c)/ { print NR; exit 0; }' loglevels.tmp))" -c -o $@ $< $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
all: i3 subdirs all: i3 subdirs
@ -42,18 +32,6 @@ subdirs:
$(MAKE) -C $$dir; \ $(MAKE) -C $$dir; \
done done
loglevels.h:
echo "[i3] LOGLEVELS"
for file in $$(ls src/*.c src/*.y src/*.l | grep -v 'cfgparse.\(tab\|yy\).c'); \
do \
echo $$(basename $$file .c); \
done > loglevels.tmp
(echo "char *loglevels[] = {"; for file in $$(cat loglevels.tmp); \
do \
echo "\"$$file\", "; \
done; \
echo "};") > include/loglevels.h;
# The GENERATED_* files are actually all created from a single pass, so all # The GENERATED_* files are actually all created from a single pass, so all
# files just depend on the first one. # files just depend on the first one.
include/GENERATED_call.h: generate-command-parser.pl parser-specs/commands.spec include/GENERATED_call.h: generate-command-parser.pl parser-specs/commands.spec
@ -67,19 +45,19 @@ include/GENERATED_tokens.h: include/GENERATED_call.h
# and once as an object file for i3. # and once as an object file for i3.
src/commands_parser.o: src/commands_parser.c ${HEADERS} ${CMDPARSE_HEADERS} src/commands_parser.o: src/commands_parser.c ${HEADERS} ${CMDPARSE_HEADERS}
echo "[i3] CC $<" echo "[i3] CC $<"
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DTEST_PARSER -DLOGLEVEL="((uint64_t)1 << $(shell awk '/$(shell basename $< .c)/ { print NR; exit 0; }' loglevels.tmp))" -o test.commands_parser $< $(LIBS) $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DTEST_PARSER -o test.commands_parser $< $(LIBS)
$(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="((uint64_t)1 << $(shell awk '/$(shell basename $< .c)/ { print NR; exit 0; }' loglevels.tmp))" -c -o $@ $< $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
src/cfgparse.yy.o: src/cfgparse.l src/cfgparse.y.o ${HEADERS} src/cfgparse.yy.o: src/cfgparse.l src/cfgparse.y.o ${HEADERS}
echo "[i3] LEX $<" echo "[i3] LEX $<"
$(FLEX) -i -o$(@:.o=.c) $< $(FLEX) -i -o$(@:.o=.c) $<
$(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cfgparse.l/ { print NR }' loglevels.tmp))" -c -o $@ $(@:.o=.c) $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(@:.o=.c)
src/cfgparse.y.o: src/cfgparse.y ${HEADERS} src/cfgparse.y.o: src/cfgparse.y ${HEADERS}
echo "[i3] YACC $<" echo "[i3] YACC $<"
$(BISON) --debug --verbose -b $(basename $< .y) -d $< $(BISON) --debug --verbose -b $(basename $< .y) -d $<
$(CC) $(CPPFLAGS) $(CFLAGS) -DLOGLEVEL="(1 << $(shell awk '/cfgparse.y/ { print NR }' loglevels.tmp))" -c -o $@ $(<:.y=.tab.c) $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $(<:.y=.tab.c)
install: all install: all
@ -129,7 +107,7 @@ dist: distclean
rm -rf i3-${VERSION} rm -rf i3-${VERSION}
clean: clean:
rm -f src/*.o src/*.gcno src/cmdparse.* src/cfgparse.tab.{c,h} src/cfgparse.yy.c src/cfgparse.{output,dot} loglevels.tmp include/loglevels.h include/GENERATED_* rm -f src/*.o src/*.gcno src/cmdparse.* src/cfgparse.tab.{c,h} src/cfgparse.yy.c src/cfgparse.{output,dot} include/GENERATED_*
(which lcov >/dev/null 2>&1 && lcov -d . --zerocounters) || true (which lcov >/dev/null 2>&1 && lcov -d . --zerocounters) || true
$(MAKE) -C libi3 clean $(MAKE) -C libi3 clean
$(MAKE) -C docs clean $(MAKE) -C docs clean

View File

@ -141,7 +141,7 @@ src/load_layout.c::
Contains code for loading layouts from JSON files. Contains code for loading layouts from JSON files.
src/log.c:: src/log.c::
Handles the setting of loglevels, contains the logging functions. Contains the logging functions.
src/main.c:: src/main.c::
Initializes the window manager. Initializes the window manager.

View File

@ -4,7 +4,7 @@
* i3 - an improved dynamic tiling window manager * i3 - an improved dynamic tiling window manager
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
* *
* log.c: Setting of loglevels, logging functions. * log.c: Logging functions.
* *
*/ */
#ifndef _LOG_H #ifndef _LOG_H
@ -17,9 +17,8 @@
is, delete the preceding comma */ is, delete the preceding comma */
#define LOG(fmt, ...) verboselog(fmt, ##__VA_ARGS__) #define LOG(fmt, ...) verboselog(fmt, ##__VA_ARGS__)
#define ELOG(fmt, ...) errorlog("ERROR: " fmt, ##__VA_ARGS__) #define ELOG(fmt, ...) errorlog("ERROR: " fmt, ##__VA_ARGS__)
#define DLOG(fmt, ...) debuglog(LOGLEVEL, "%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) #define DLOG(fmt, ...) debuglog("%s:%s:%d - " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
extern char *loglevels[];
extern char *errorfilename; extern char *errorfilename;
extern char *shmlogname; extern char *shmlogname;
extern int shmlog_size; extern int shmlog_size;
@ -32,10 +31,10 @@ extern int shmlog_size;
void init_logging(void); void init_logging(void);
/** /**
* Enables the given loglevel. * Set debug logging.
* *
*/ */
void add_loglevel(const char *level); void set_debug_logging(const bool _debug_logging);
/** /**
* Set verbosity of i3. If verbose is set to true, informative messages will * Set verbosity of i3. If verbose is set to true, informative messages will
@ -47,10 +46,10 @@ void set_verbosity(bool _verbose);
/** /**
* Logs the given message to stdout while prefixing the current time to it, * Logs the given message to stdout while prefixing the current time to it,
* but only if the corresponding debug loglevel was activated. * but only if debug logging was activated.
* *
*/ */
void debuglog(uint64_t lev, char *fmt, ...); void debuglog(char *fmt, ...);
/** /**
* Logs the given message to stdout while prefixing the current time to it. * Logs the given message to stdout while prefixing the current time to it.

View File

@ -31,7 +31,7 @@ void regex_free(struct regex *regex);
/** /**
* Checks if the given regular expression matches the given input and returns * Checks if the given regular expression matches the given input and returns
* true if it does. In either case, it logs the outcome using LOG(), so it will * true if it does. In either case, it logs the outcome using LOG(), so it will
* be visible without any debug loglevel. * be visible without debug logging.
* *
*/ */
bool regex_matches(struct regex *regex, const char *input); bool regex_matches(struct regex *regex, const char *input);

View File

@ -14,7 +14,7 @@ i3-dump-log [-s <socketpath>]
== DESCRIPTION == DESCRIPTION
Debug versions of i3 automatically use 1% of your RAM (but 25 MiB max) to store Debug versions of i3 automatically use 1% of your RAM (but 25 MiB max) to store
full debug loglevel log output. This is extremely helpful for bugreports and full debug log output. This is extremely helpful for bugreports and
figuring out what is going on, without permanently logging to a file. figuring out what is going on, without permanently logging to a file.
With i3-dump-log, you can dump the SHM log to stdout. With i3-dump-log, you can dump the SHM log to stdout.

View File

@ -9,7 +9,7 @@ i3 - an improved dynamic, tiling window manager
== SYNOPSIS == SYNOPSIS
i3 [-a] [-c configfile] [-C] [-d <loglevel>] [-v] [-V] i3 [-a] [-c configfile] [-C] [-d all] [-v] [-V]
== OPTIONS == OPTIONS
@ -22,8 +22,9 @@ Specifies an alternate configuration file path.
-C:: -C::
Check the configuration file for validity and exit. Check the configuration file for validity and exit.
-d:: -d all::
Specifies the debug loglevel. To see the most output, use -d all. Enables debug logging.
The 'all' parameter is present for historical reasons.
-v:: -v::
Display version number (and date of the last commit). Display version number (and date of the last commit).

View File

@ -427,11 +427,11 @@ struct CommandResult *parse_command(const char *input) {
/* /*
* Logs the given message to stdout while prefixing the current time to it, * Logs the given message to stdout while prefixing the current time to it,
* but only if the corresponding debug loglevel was activated. * but only if debug logging was activated.
* This is to be called by DLOG() which includes filename/linenumber * This is to be called by DLOG() which includes filename/linenumber
* *
*/ */
void debuglog(uint64_t lev, char *fmt, ...) { void debuglog(char *fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);

View File

@ -4,7 +4,7 @@
* i3 - an improved dynamic tiling window manager * i3 - an improved dynamic tiling window manager
* © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
* *
* log.c: Setting of loglevels, logging functions. * log.c: Logging functions.
* *
*/ */
#include <stdarg.h> #include <stdarg.h>
@ -29,10 +29,7 @@
#include "libi3.h" #include "libi3.h"
#include "shmlog.h" #include "shmlog.h"
/* loglevels.h is autogenerated at make time */ static bool debug_logging = false;
#include "loglevels.h"
static uint64_t loglevel = 0;
static bool verbose = false; static bool verbose = false;
static FILE *errorfile; static FILE *errorfile;
char *errorfilename; char *errorfilename;
@ -146,26 +143,11 @@ void set_verbosity(bool _verbose) {
} }
/* /*
* Enables the given loglevel. * Set debug logging.
* *
*/ */
void add_loglevel(const char *level) { void set_debug_logging(const bool _debug_logging) {
/* Handle the special loglevel "all" */ debug_logging = _debug_logging;
if (strcasecmp(level, "all") == 0) {
loglevel = UINT64_MAX;
return;
}
for (int i = 0; i < sizeof(loglevels) / sizeof(char*); i++) {
if (strcasecmp(loglevels[i], level) != 0)
continue;
/* The position in the array (plus one) is the amount of times
* which we need to shift 1 to the left to get our bitmask for
* the specific loglevel. */
loglevel |= (1 << (i+1));
break;
}
} }
/* /*
@ -271,17 +253,17 @@ void errorlog(char *fmt, ...) {
/* /*
* Logs the given message to stdout while prefixing the current time to it, * Logs the given message to stdout while prefixing the current time to it,
* but only if the corresponding debug loglevel was activated. * but only if debug logging was activated.
* This is to be called by DLOG() which includes filename/linenumber * This is to be called by DLOG() which includes filename/linenumber
* *
*/ */
void debuglog(uint64_t lev, char *fmt, ...) { void debuglog(char *fmt, ...) {
va_list args; va_list args;
if (!logbuffer && !(loglevel & lev)) if (!logbuffer && !(debug_logging))
return; return;
va_start(args, fmt); va_start(args, fmt);
vlog((loglevel & lev), fmt, args); vlog(debug_logging, fmt, args);
va_end(args); va_end(args);
} }

View File

@ -318,8 +318,8 @@ int main(int argc, char *argv[]) {
set_verbosity(true); set_verbosity(true);
break; break;
case 'd': case 'd':
LOG("Enabling debug loglevel %s\n", optarg); LOG("Enabling debug logging\n");
add_loglevel(optarg); set_debug_logging(true);
break; break;
case 'l': case 'l':
/* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */ /* DEPRECATED, ignored for the next 3 versions (3.e, 3.f, 3.g) */
@ -367,12 +367,12 @@ int main(int argc, char *argv[]) {
} }
/* fall-through */ /* fall-through */
default: default:
fprintf(stderr, "Usage: %s [-c configfile] [-d loglevel] [-a] [-v] [-V] [-C]\n", argv[0]); fprintf(stderr, "Usage: %s [-c configfile] [-d all] [-a] [-v] [-V] [-C]\n", argv[0]);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "\t-a disable autostart ('exec' lines in config)\n"); fprintf(stderr, "\t-a disable autostart ('exec' lines in config)\n");
fprintf(stderr, "\t-c <file> use the provided configfile instead\n"); fprintf(stderr, "\t-c <file> use the provided configfile instead\n");
fprintf(stderr, "\t-C validate configuration file and exit\n"); fprintf(stderr, "\t-C validate configuration file and exit\n");
fprintf(stderr, "\t-d <level> enable debug output with the specified loglevel\n"); fprintf(stderr, "\t-d all enable debug output\n");
fprintf(stderr, "\t-L <file> path to the serialized layout during restarts\n"); fprintf(stderr, "\t-L <file> path to the serialized layout during restarts\n");
fprintf(stderr, "\t-v display version and exit\n"); fprintf(stderr, "\t-v display version and exit\n");
fprintf(stderr, "\t-V enable verbose mode\n"); fprintf(stderr, "\t-V enable verbose mode\n");

View File

@ -67,7 +67,7 @@ void regex_free(struct regex *regex) {
/* /*
* Checks if the given regular expression matches the given input and returns * Checks if the given regular expression matches the given input and returns
* true if it does. In either case, it logs the outcome using LOG(), so it will * true if it does. In either case, it logs the outcome using LOG(), so it will
* be visible without any debug loglevel. * be visible without debug logging.
* *
*/ */
bool regex_matches(struct regex *regex, const char *input) { bool regex_matches(struct regex *regex, const char *input) {