Log file:line instead of function; add cs_log_set_file_level()

cs_log_set_filter() is removed in favor of cs_log_set_file_level() which
allows setting log verbosity of individual files and/or lines.

E.g.: `mg_=1,mjs=1,=4` - level for for everything except mjs and mongoose.

We use the fact that we are usually pretty careful with our file names and use prefixes consistently.

In mos, `debug.file_level` sets the option on boot and `Sys.SetDebug` is updated to parse `file_level` option to change it at runtime.

CL: Log file:line instead of function; add cs_log_set_file_level()

PUBLISHED_FROM=49f18d4d0d3dd224865129a4f8fe6cccd1d9bc12
This commit is contained in:
Deomid Ryabkov authored and Cesanta Bot committed 2019-01-30 12:57:19 +00:00
1 parent 86ffa3a3ea
commit 95a36b1759
7 files changed
+240 -147

No files matched your search

+53 -26
View File
@@ -24,7 +24,7 @@
#include "common/cs_time.h"
#include "common/str_util.h"
enum cs_log_level cs_log_threshold WEAK =
enum cs_log_level cs_log_level WEAK =
#if CS_ENABLE_DEBUG
LL_VERBOSE_DEBUG;
#else
@@ -32,10 +32,9 @@ enum cs_log_level cs_log_threshold WEAK =
#endif
#if CS_ENABLE_STDIO
static char *s_filter_pattern = NULL;
static size_t s_filter_pattern_len;
static char *s_file_level = NULL;
void cs_log_set_filter(const char *pattern) WEAK;
void cs_log_set_file_level(const char *file_level) WEAK;
FILE *cs_log_file WEAK = NULL;
@@ -45,34 +44,62 @@ double cs_log_ts WEAK;
enum cs_log_level cs_log_cur_msg_level WEAK = LL_NONE;
void cs_log_set_filter(const char *pattern) {
free(s_filter_pattern);
if (pattern != NULL) {
s_filter_pattern = strdup(pattern);
s_filter_pattern_len = strlen(pattern);
void cs_log_set_file_level(const char *file_level) {
char *fl = s_file_level;
if (file_level != NULL) {
s_file_level = strdup(file_level);
} else {
s_filter_pattern = NULL;
s_filter_pattern_len = 0;
s_file_level = NULL;
}
free(fl);
}
int cs_log_print_prefix(enum cs_log_level, const char *, const char *) WEAK;
int cs_log_print_prefix(enum cs_log_level level, const char *func,
const char *filename) {
char prefix[21];
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) WEAK;
int cs_log_print_prefix(enum cs_log_level level, const char *file, int ln) {
char prefix[CS_LOG_PREFIX_LEN], *q;
const char *p;
size_t fl = 0, ll = 0, pl = 0;
if (level > cs_log_threshold) return 0;
if (s_filter_pattern != NULL &&
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, func) == 0 &&
mg_match_prefix(s_filter_pattern, s_filter_pattern_len, filename) == 0) {
return 0;
if (level > cs_log_level && s_file_level == NULL) return 0;
p = file + strlen(file);
while (p != file) {
const char c = *(p - 1);
if (c == '/' || c == '\\') break;
p--;
fl++;
}
ll = (ln < 10000 ? (ln < 1000 ? (ln < 100 ? (ln < 10 ? 1 : 2) : 3) : 4) : 5);
if (fl > (sizeof(prefix) - ll - 2)) fl = (sizeof(prefix) - ll - 2);
pl = fl + 1 + ll;
memcpy(prefix, p, fl);
q = prefix + pl;
memset(q, ' ', sizeof(prefix) - pl);
do {
*(--q) = '0' + (ln % 10);
ln /= 10;
} while (ln > 0);
*(--q) = ':';
if (s_file_level != NULL) {
enum cs_log_level pll = cs_log_level;
struct mg_str fl = mg_mk_str(s_file_level), ps = MG_MK_STR_N(prefix, pl);
struct mg_str k, v;
while ((fl = mg_next_comma_list_entry_n(fl, &k, &v)).p != NULL) {
bool yes = !(!mg_str_starts_with(ps, k) || v.len == 0);
if (!yes) continue;
pll = (enum cs_log_level)(*v.p - '0');
break;
}
if (level > pll) return 0;
}
strncpy(prefix, func, 20);
prefix[20] = '\0';
if (cs_log_file == NULL) cs_log_file = stderr;
cs_log_cur_msg_level = level;
fprintf(cs_log_file, "%-20s ", prefix);
fwrite(prefix, 1, sizeof(prefix), cs_log_file);
#if CS_LOG_ENABLE_TS_DIFF
{
double now = cs_time();
@@ -101,15 +128,15 @@ void cs_log_set_file(FILE *file) {
#else
void cs_log_set_filter(const char *pattern) {
(void) pattern;
void cs_log_set_file_level(const char *file_level) {
(void) file_level;
}
#endif /* CS_ENABLE_STDIO */
void cs_log_set_level(enum cs_log_level level) WEAK;
void cs_log_set_level(enum cs_log_level level) {
cs_log_threshold = level;
cs_log_level = level;
#if CS_LOG_ENABLE_TS_DIFF && CS_ENABLE_STDIO
cs_log_ts = cs_time();
#endif
+22 -39
View File
@@ -28,6 +28,10 @@
#define CS_ENABLE_DEBUG 0
#endif
#ifndef CS_LOG_PREFIX_LEN
#define CS_LOG_PREFIX_LEN 24
#endif
#ifndef CS_LOG_ENABLE_TS_DIFF
#define CS_LOG_ENABLE_TS_DIFF 0
#endif
@@ -58,51 +62,28 @@ enum cs_log_level {
void cs_log_set_level(enum cs_log_level level);
/*
* Set log filter. NULL (a default) logs everything.
* Otherwise, function name and file name will be tested against the given
* pattern, and only matching messages will be printed.
* A comma-separated set of prefix=level.
* prefix is matched against the log prefix exactly as printed, including line
* number, but partial match is ok. Check stops on first matching entry.
* If nothing matches, default level is used.
*
* For the pattern syntax, refer to `mg_match_prefix()` in `str_util.h`.
* Examples:
* main.c:=4 - everything from main C at verbose debug level.
* mongoose.c=1,mjs.c=1,=4 - everything at verbose debug except mg_* and mjs_*
*
* Example:
* ```c
* void foo(void) {
* LOG(LL_INFO, ("hello from foo"));
* }
*
* void bar(void) {
* LOG(LL_INFO, ("hello from bar"));
* }
*
* void test(void) {
* cs_log_set_filter(NULL);
* foo();
* bar();
*
* cs_log_set_filter("f*");
* foo();
* bar(); // Will NOT print anything
*
* cs_log_set_filter("bar");
* foo(); // Will NOT print anything
* bar();
* }
* ```
*/
void cs_log_set_filter(const char *pattern);
void cs_log_set_file_level(const char *file_level);
/*
* Helper function which prints message prefix with the given `level`, function
* name `func` and `filename`. If message should be printed (accordingly to the
* current log level and filter), prints the prefix and returns 1, otherwise
* returns 0.
* Helper function which prints message prefix with the given `level`.
* If message should be printed (according to the current log level
* and filter), prints the prefix and returns 1, otherwise returns 0.
*
* Clients should typically just use `LOG()` macro.
*/
int cs_log_print_prefix(enum cs_log_level level, const char *func,
const char *filename);
int cs_log_print_prefix(enum cs_log_level level, const char *fname, int line);
extern enum cs_log_level cs_log_threshold;
extern enum cs_log_level cs_log_level;
#if CS_ENABLE_STDIO
@@ -127,9 +108,11 @@ void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
* LOG(LL_DEBUG, ("my debug message: %d", 123));
* ```
*/
#define LOG(l, x) \
do { \
if (cs_log_print_prefix(l, __func__, __FILE__)) cs_log_printf x; \
#define LOG(l, x) \
do { \
if (cs_log_print_prefix(l, __FILE__, __LINE__)) { \
cs_log_printf x; \
} \
} while (0)
#else