10#include "wvstringlist.h"
17#define snprintf _snprintf
20WvLogRcvBaseList *WvLog::receivers;
21int WvLog::num_receivers = 0, WvLog::num_logs = 0;
24const char *WvLogRcv::loglevels[WvLog::NUM_LOGLEVELS] = {
43WvLog::WvLog(
WvStringParm _app, LogLevel _loglevel, WvLogFilter* _filter)
44 : app(_app), loglevel(_loglevel), filter(_filter)
52WvLog::WvLog(
const WvLog &l)
53 : app(l.app), loglevel(l.loglevel), filter(l.filter)
64 if (!num_logs && default_receiver)
67 delete default_receiver;
68 default_receiver = NULL;
84 if (si.wants.writable)
94 if (si.wants.writable)
105 static const int recursion_max = 8;
106 static int recursion_count = 0;
107 static WvString recursion_msg(
"Too many extra log messages written while "
108 "writing to the log. Suppressing additional messages.\n");
114 if (!default_receiver)
122 if (recursion_count < recursion_max)
123 default_receiver->log(app, loglevel, (
const char *)_buf, len);
124 else if (recursion_count == recursion_max)
125 default_receiver->log(app, WvLog::Warning, recursion_msg.
cstr(),
126 recursion_msg.len());
131 else if (default_receiver)
135 delete default_receiver;
136 default_receiver = NULL;
140 WvLogRcvBaseList::Iter i(*receivers);
141 for (i.rewind(); i.next(); )
145 if (recursion_count < recursion_max)
146 rc.log(app, loglevel, (
const char *)_buf, len);
147 else if (recursion_count == recursion_max)
148 rc.log(app, WvLog::Warning, recursion_msg.
cstr(),
149 recursion_msg.len());
162WvLogRcvBase::WvLogRcvBase()
165 WvLogRcvBase::force_new_line =
false;
166 if (!WvLog::receivers)
167 WvLog::receivers =
new WvLogRcvBaseList;
168 WvLog::receivers->append(
this,
false);
169 WvLog::num_receivers++;
173WvLogRcvBase::~WvLogRcvBase()
175 assert(WvLog::receivers);
176 WvLog::receivers->unlink(
this);
177 if (WvLog::receivers->isempty())
179 delete WvLog::receivers;
180 WvLog::receivers = NULL;
182 WvLog::num_receivers--;
186const char *WvLogRcvBase::appname(
WvStringParm log)
const
195void WvLogRcvBase::static_init()
197 static bool init =
false;
208void WvLogRcvBase::cleanup_on_fork(pid_t p)
212 if (WvLog::receivers)
213 WvLog::receivers->zap();
214 delete WvLog::default_receiver;
215 WvLog::default_receiver = NULL;
216 WvLog::num_receivers = 0;
225WvLogRcv::WvLogRcv(WvLog::LogLevel _max_level) : custom_levels(5)
228 last_level = WvLog::NUM_LOGLEVELS;
230 max_level = _max_level;
243 last_source, loglevels[last_level]);
244 prelen = prefix.len();
250 mid_line(prefix, prelen);
262static bool my_isprint(
char _c)
264 unsigned char c = _c;
265 if (isprint(c) || c >= 128)
273 const char *_buf,
size_t len)
275 WvLog::LogLevel loglevel = (WvLog::LogLevel)_loglevel;
277 WvLog::LogLevel threshold = max_level;
281 Src_LvlDict::Iter i(custom_levels);
287 if (strstr(srcname, i->src))
294 if (loglevel > threshold)
300 time_t now = wvtime().tv_sec;
301 if (source != last_source
302 || loglevel != last_level
303 || WvLogRcvBase::force_new_line)
306 last_source = source;
307 last_level = loglevel;
311 else if (last_time == 0 || now != last_time)
322 const char *buf = (
const char *)_buf, *bufend = buf + len, *cptr;
328 if (buf[0] ==
'\n' || buf[0] ==
'\r')
343 else if (!my_isprint(buf[0]))
345 snprintf(hex, 5,
"[%02x]", buf[0]);
352 for (cptr = buf; cptr < bufend; cptr++)
354 if (*cptr ==
'\n' || !my_isprint(*cptr))
360 mid_line(buf, bufend - buf);
363 else if (*cptr ==
'\n')
365 mid_line((
const char *)buf, cptr - buf);
370 mid_line(buf, cptr - buf);
379bool WvLogRcv::set_custom_levels(
WvString descr)
385 WvStringList::Iter i(lst);
386 lst.
split(descr,
",= ");
391 for (i.rewind(); i.next(); )
395 if (atoi(*i) > 0 && atoi(*i) <= WvLog::NUM_LOGLEVELS)
397 custom_levels.add(
new Src_Lvl(src, atoi(*i)),
true);
420WvLogConsole::WvLogConsole(
int _fd, WvLog::LogLevel _max_level) :
426WvLogConsole::~WvLogConsole()
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
const char * cstr() const
return a (const char *) for this string.
Base class for streams built on Unix file descriptors.
virtual size_t uwrite(const void *buf, size_t count)
unbuffered I/O functions; these ignore the buffer, which is handled by write().
Captures formatted log messages and outputs them to the specified file descriptor.
virtual void _mid_line(const char *str, size_t len)
add text to the current log line.
WvLogRcv adds some intelligence to WvLogRcvBase, to keep track of line-prefix-printing and other form...
virtual void _end_line()
End this (Guaranteed NonEmpty) log line.
virtual void _make_prefix(time_t now)
Set the Prefix and Prefix Length (size_t prelen)
virtual void _begin_line()
Start a new log line (print prefix)
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
virtual bool isok() const
fd==-1, but this stream is always ok
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
virtual size_t uwrite(const void *buf, size_t len)
we override the unbuffered write function, so lines also include the application and log level.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
virtual bool post_select(SelectInfo &si)
post_select() is called after ::select(), and returns true if this object is now ready.
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling ::select().
This is a WvList of WvStrings, and is a really handy way to parse strings.
void split(WvStringParm s, const char *splitchars=" \t\r\n", int limit=0)
split s and form a list ignoring splitchars (except at beginning and end) ie.
WvString is an implementation of a simple and efficient printable-string class.
the data structure used by pre_select()/post_select() and internally by select().
Provides support for forking processes.
void add_wvfork_callback(WvForkCallback cb)
Register a callback to be called during wvfork.
char * trim_string(char *string)
Trims whitespace from the beginning and end of the character string, including carriage return / line...
char * strlwr(char *string)
In-place modify a character string so that all contained letters are in lower case.