/*
* UCW Library -- Logging
*
- * (c) 1997--2009 Martin Mares <mj@ucw.cz>
+ * (c) 1997--2015 Martin Mares <mj@ucw.cz>
* (c) 2008 Tomas Gavenciak <gavento@ucw.cz>
*
* This software may be freely distributed and used according to the terms
#define log_close_all ucw_log_close_all
#define log_close_stream ucw_log_close_stream
#define log_configured ucw_log_configured
+#define log_drop_stderr ucw_log_drop_stderr
#define log_find_type ucw_log_find_type
#define log_new_configured ucw_log_new_configured
#define log_new_fd ucw_log_new_fd
#define log_new_file ucw_log_new_file
#define log_new_stream ucw_log_new_stream
#define log_new_syslog ucw_log_new_syslog
+#define log_pass_filtered ucw_log_pass_filtered
#define log_register_type ucw_log_register_type
#define log_rm_substream ucw_log_rm_substream
#define log_set_default_stream ucw_log_set_default_stream
int m_len; // Length without the \0
struct tm *tm; // Current time
struct timeval *tv;
- uns flags; // Category and other flags as passed to msg()
+ uint flags; // Category and other flags as passed to msg()
char *raw_msg; // Unformatted parts
char *stime;
char *sutime;
+ uint depth; // Recursion depth
+ bool error; // An error has occurred (e.g., an infinite loop in sub-streams)
};
/**
struct log_stream {
char *name; // Optional name, allocated by the user (or constructor)
int regnum; // Stream number, already encoded by LS_SET_STRNUM(); -1 if closed
- uns levels; // Bitmask of accepted severity levels (default: all)
- uns types; // Bitmask of accepted message types (default: all)
- uns msgfmt; // Formatting flags (LSFMT_xxx)
- uns use_count; // Number of references to the stream
- uns stream_flags; // Various other flags (LSFLAG_xxx)
+ uint levels; // Bitmask of accepted severity levels (default: all)
+ uint types; // Bitmask of accepted message types (default: all)
+ uint msgfmt; // Formatting flags (LSFMT_xxx)
+ uint use_count; // Number of references to the stream
+ uint stream_flags; // Various other flags (LSFLAG_xxx)
int (*filter)(struct log_stream* ls, struct log_msg *m); // Filter function, return non-zero to discard the message
clist substreams; // Pass the message to these streams (simple_list of pointers)
int (*handler)(struct log_stream *ls, struct log_msg *m); // Called to commit the message, return 0 for success, errno on error
/***
* === Message flags
*
- * The @flags parameter of msg() is divided to several groups of bits (from the LSB):
+ * The @flags parameter of <<basics:msg()>> is divided to several groups of bits (from the LSB):
* message severity level (`L_xxx`), destination stream, message type
* and control bits (e.g., `L_SIGHANDLER`).
***/
int log_find_type(const char *name);
/** Given a flag set, extract the message type ID and return its name. **/
-char *log_type_name(uns flags);
+char *log_type_name(uint flags);
/*** === Operations on streams ***/
* Set formatting flags of a given stream and all its substreams. The flags are
* AND'ed with @mask and OR'ed with @data.
**/
-void log_set_format(struct log_stream *ls, uns mask, uns data);
+void log_set_format(struct log_stream *ls, uint mask, uint data);
/**
* Find a stream by its registration number (in the format of logging flags).
* Returns NULL if there is no such stream.
**/
-struct log_stream *log_stream_by_flags(uns flags);
+struct log_stream *log_stream_by_flags(uint flags);
/** Return a pointer to the default stream (stream #0). **/
static inline struct log_stream *log_default_stream(void)
* In fact, it takes the fixed default stream and attaches @ls as its only
* substream. If there were any other substreams, they are removed.
*
- * Log streams created by log_file() or log_configured() are made default
+ * Log streams created by <<basics:log_file()>> or @log_configured() are made default
* by calling this function.
**/
void log_set_default_stream(struct log_stream *ls);
**/
void log_close_all(void);
+/**
+ * The filter function of a stream might want to modify the message
+ * before passing it to the handler and/or substreams. In this case,
+ * the filter should make a local copy of `struct log_msg`, call
+ * @log_pass_filtered() on it and return true, so that the original
+ * message will not be processed any further.
+ **/
+void log_pass_filtered(struct log_stream *ls, struct log_msg *m);
+
/***
* === Logging to files
*
* even in multi-threaded programs.
***/
-struct log_stream *log_new_file(const char *path, uns flags); /** Create a stream bound to a log file. See `FF_xxx` for @flags. **/
-struct log_stream *log_new_fd(int fd, uns flags); /** Create a stream bound to a file descriptor. See `FF_xxx` for @flags. **/
+struct log_stream *log_new_file(const char *path, uint flags); /** Create a stream bound to a log file. See `FF_xxx` for @flags. **/
+struct log_stream *log_new_fd(int fd, uint flags); /** Create a stream bound to a file descriptor. See `FF_xxx` for @flags. **/
enum log_file_flag { /** Flags used for file-based logging **/
FF_FORMAT_NAME = 1, // Internal: Name contains strftime escapes
void log_switch_enable(void); /** Negate the effect of log_switch_disable(). **/
int log_switch(void); /** Switch log files manually. **/
+/**
+ * Drop stderr if it is not already redirected to a log file.
+ * This is usually needed in daemons to make sure that the original
+ * stderr does not stay open (stdin and stdout are dropped by our
+ * <<daemon:,daemon setup functions>> automatically). More specifically,
+ * it makes stderr a clone of stdout.
+ **/
+void log_drop_stderr(void);
+
/***
* === Logging to syslog
*