Þ   briarpig  » thorn  » demos  » log


demos are explained here; a menu at top column right indexes actual topic demos. Here we demo logging.

problem

     Wil wants to lace his code with logging calls that only emit data at runtime when enabled by a suitable log level. In practice, Wil uses logging mainly for error cases that should almost always log a message. But the api should be such that logging can be disabled, or routed in a new way, perhaps to a new place like syslog.

     This could easily be the shortest demo because Wil doesn't think logging is interesting. Therefore almost no detail will be shown here. But this in itself is part of the message: logging is trivial.

     All the complexity occurs when folks on a development team start discussing exactly what should be logged, and what format it should use, and how to tune a potential deluge of data to suite available resources.

     All of this Wil considers officially "not interesting" — he'll do it any way you want but won't spend any time on discussion. Wil says, whatever you want, knock yourself out. Just specify the syntax.

     So Wil has no comment, unless you suggest logging be turned off so it can't be generated, because seeing it would confuse a user, or alarm a customer, or violate a user interface principle. Wil says logging must always be on — at least for critical messages, so it's possible to see clues why your system failed. Crucial evidence must not be hidden.

void yellerrno(int line, const char* file) { int e = errno; ylog(1, "(%s:%d) errno=%d\n", file, line, e); }

     This is minimal errno reporting. Typically Wil also prints the string returned from strerror(). Maybe your taste runs to perror() as well. But what Wil really wants here is usually a backtrace showing the call stack, which clarifies the context surrounding error events. Wil actually forgets this yellerrno() method exists half the time. (Oh, well.) It should also backtrace when supported.

void ylog(int level, const char* fmt, ...) { « char temp[ 2048 + 2 ]; va_list args; va_start(args,fmt); vsnprintf(temp, 2048, fmt, args); // reserves last nul byte va_end(args); temp[2048] = 0; // whether or not vsnprintf() also wrote a nul fprintf(stderr, "ylog(%d) %s\n", level, temp); }

     Wil uses this ylog() entry point often, just to print messages when odd things happen. In real development environments, a lot of effort goes into handling exactly where this content is channeled. For Wil's purposes, stderr is just fine until his needs change. You can spin the format and temp buffer size several ways; and you can use the integer length return vsnprintf() as well to avoid using %s format on principle.

     All Wil really cares about is a standard api entry point, and a first version getting the job done without fuss. You can add fuss later.

     The integer level argument indicates severity, with zero as the highest (typically meaning the process is doomed). One usually means "please always print" and all higher values are just increasing degrees of optional verbosity for tracing that can be tuned out.

A submenu for demos appears below, letting you go to the page on a topic written as a demo (as the demos page defines it).

menu

     thorn: todo, names, fd, iovec, assert, log « Þ, run, hex, crc, buf, in, out, quote, escape, compare, file, deck, cow, arc, blob, tree, slice, rand, time, stat, hash, heap, node, primes, page, book, pile, stack, atomic, lock, mutex, thread, map, meter, list, iter, ctype

     (mu: toy, peg, imm, tag, box, symbol, token, number, bigint, class, method, reader, writer, eval, env, vm, gc, world, pcode, compiler, asm, lathe, lisp, smalltalk, design, weight, jar, card, harp, debug, profile)

     Some demos are stubs: todo is a demo guide. See toy for mu updates on language pages; names introduces naming schemes.

api

     Wil's idea of api for logging is minimal. Basically, as long as you can specify level of importance, and handle printf() style formatting, that's enough for Wil.

     The current minimalist api only has three methods, so in addition to a generic "print this" style method, Wil can also invoke calls specific to errno reporting, to strongly hint a backtrace would be good in addition to a mere log message.

extern void ylog(int level, const char* fmt, ...); extern void yellf(int line, const char* file, const char* fmt, ...); extern void yellerrno(int line, const char* file);

     The name yellf basically means formatted yell. There's not much to say except yelling means to get someone's attention. Suitable for shouting "fire!" when the process is in trouble. But ylog(0, ...) means that too.

void yellf(int line, const char* file, const char* fmt, ...) { « char temp[ 2048 + 2 ]; va_list args; va_start(args,fmt); vsnprintf(temp, 2048, fmt, args); // reserves last nul byte va_end(args); temp[2048] = 0; // whether or not vsnprintf() also wrote a nul ylog(1, "(%s:%d) %s\n", file, line, temp); }

     This needs a backtrace, but Wil hasn't added those to þ yet since he only has an api that works on Linux, and most of Wil's testing lately is on a Mac at home.

dialog

     Wil's brief conversation with Stu about logging ends in a blink.

     "So you have logging," Stu noted without interest.

     "Yeah," Wil chimed. "Pretty exciting, huh?"

     "Whatever," Stu waved.

     Suddenly Dex burst into the room. "Is this the meeting about syslog management?" Dex asked. "I've years of experience to share."

     "Down the hall," Wil pointed.

     Stu nodded vigorously, pointing the same way. "Knock em out, Dex."

     As Dex ran off, Wil jumped up and urged Stu to leave too. "Let's scram before he gets back," Wil hissed. "No time to lose."