I'm pleased to announce the first release of selog, which you can download from <http://dotat.at/prog/selog/>.
Selog is a library of routines that unifies error reporting, activity logging, and debug tracing. It allows programmers to give their users flexible control over which messages are written and where they are written to.
Selog is designed to be as simple as possible while still being extremely efficient, powerful, and flexible. The essence of selog is:
- Obtain a configuration string from the user, which looks like:
- When the program starts, initialize selog with the user's configuration.
- Define a selector for each different kind of message.
static selog_selector sel = SELINIT("example", SELOG_INFO);
- Use the selog() function to emit messages instead of printf() or syslog().
selog(sel, "message number %d", n);
Selectors determine which messages are written and where they are written to, under the control of the user's configuration. You can direct messages to any combination of stderr, syslog, files, pipes, etc. You can omit or include optional parts of messages under the control of selectors. You don't have to signal the program when you rotate its log files.
The C interface consists of just 13 functions, 5 macros, 2 types, and an enum. There are a few variations of the basic selog() one-shot logging function, or you can quickly and easily compose messages in stages. The check to skip disabled messages is extremely small and fast.
Selog comes with shell command and Lua interfaces, plus interposition libraries which you can use to fool old code that calls err() or syslog() into using selog instead.
I started work on selog when I found myself writing yet another half-arsed logging/debugging module that could only be used by the program it was written for. The problem needed to be solved properly, but I couldn't find a decent existing solution.
Exim's logging and debugging facilities provided the basis for selog's configuration syntax and the idea for the fast check to disable debugging code. Like many other programs, Exim's logging and debugging code is non-orthogonal and non-reusable; selog exists to avoid problems like Exim's fixed set of log files and the lack of debugging redirection.
The architecture of log4j and its many imitators provided many nice ideas to copy, in particular selog's selectors and channels are similar to log4j's loggers and appenders. However log4j is unnecessarily complicated, so selog discards plenty of its ideas, such as hierarchial category names and arbitrarily configurable message layouts. Bloaty log4c provided a salutory anti-pattern.
I've tried to make this first release fairly polished - e.g. it has comprehensive documentation - however it has not had its portability catches polished off, and in particular I'm going to be interested to see how much trouble my use of C99 features causes. The next step is to go back to the program that I wrote selog for, and put the code to use...