Skip to content

Commit

Permalink
Initial log format rework
Browse files Browse the repository at this point in the history
 - Removed static qualifier from tracef() to fix potential
   multithreading bug;
 - Added log levels.

Signed-off-by: Anatoliy Bilenko <[email protected]>
  • Loading branch information
just-now committed Nov 29, 2023
1 parent 09108b8 commit 4c7743b
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 16 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,6 @@ Usage Notes
-----------

Detailed tracing will be enabled when the environment variable `LIBDQLITE_TRACE` is set before startup.

The value of it can be in `[0..5]` range and reperesents a tracing level, where
`0` means "no traces" emitted, `5` enables minimum (FATAL records only), and `1`
enables maximum verbosity (all: DEBUG, INFO, WARN, ERROR, FATAL records).
2 changes: 2 additions & 0 deletions src/lib/byte.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ DQLITE_INLINE size_t BytePad64(size_t size)
return size;
}

#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof(a)[0]))

#if defined(__GNUC__) && __GNUC__ < 10
#pragma GCC diagnostic pop
#endif
Expand Down
88 changes: 86 additions & 2 deletions src/tracing.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,98 @@
#include "tracing.h"

#include <stdio.h> /* stderr */
#include <stdlib.h>
#include <string.h> /* strstr, strlen */
#include <sys/syscall.h> /* syscall */
#include <unistd.h> /* syscall, getpid */
#include "assert.h" /* assert */
#include "lib/byte.h" /* ARRAY_SIZE */

#define LIBDQLITE_TRACE "LIBDQLITE_TRACE"

bool _dqliteTracingEnabled = false;
static unsigned tracer__level;
static pid_t tracerPidCached;

void dqliteTracingMaybeEnable(bool enable)
{
if (getenv(LIBDQLITE_TRACE) != NULL) {
const char *trace_level = getenv(LIBDQLITE_TRACE);

if (trace_level != NULL) {
tracerPidCached = getpid();

Check warning on line 21 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L21

Added line #L21 was not covered by tests
_dqliteTracingEnabled = enable;

tracer__level = (unsigned)atoi(trace_level);
tracer__level =

Check warning on line 25 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L24-L25

Added lines #L24 - L25 were not covered by tests
tracer__level < TRACE_NR ? tracer__level : TRACE_NONE;
}
}

static inline const char *tracerShortFileName(const char *fname)

Check warning on line 30 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L30

Added line #L30 was not covered by tests
{
static const char top_src_dir[] = "dqlite/";
const char *p;

p = strstr(fname, top_src_dir);

Check warning on line 35 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L35

Added line #L35 was not covered by tests
return p != NULL ? p + strlen(top_src_dir) : fname;
}

static inline const char *tracerTraceLevelName(unsigned int level)

Check warning on line 39 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L39

Added line #L39 was not covered by tests
{
static const char *levels[] = {
"NONE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL",
};

return level < ARRAY_SIZE(levels) ? levels[level] : levels[0];
}

static pid_t tracerPidCached;

/* NOTE: on i386 and other platforms there're no specifically imported gettid()
functions in unistd.h
*/
static inline pid_t gettidImpl(void)

Check warning on line 53 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L53

Added line #L53 was not covered by tests
{
return (pid_t)syscall(SYS_gettid);

Check warning on line 55 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L55

Added line #L55 was not covered by tests
}

static inline void tracerEmit(const char *file,

Check warning on line 58 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L58

Added line #L58 was not covered by tests
unsigned int line,
const char *func,
unsigned int level,
const char *message)
{
struct timespec ts = {0};
struct tm tm;

Check warning on line 65 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L64-L65

Added lines #L64 - L65 were not covered by tests
pid_t tid = gettidImpl();

clock_gettime(CLOCK_REALTIME, &ts);
gmtime_r(&ts.tv_sec, &tm);

Check warning on line 69 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L68-L69

Added lines #L68 - L69 were not covered by tests

/*
Example:
LIBDQLITE[182942] 2023-11-27T14:46:24.912050507 001132 INFO
uvClientSend src/uv_send.c:218 connection available...
*/
fprintf(stderr,
"LIBDQLITE[%6.6u] %04d-%02d-%02dT%02d:%02d:%02d.%09lu "
"%6.6u %-7s %-20s %s:%-3i %s\n",
tracerPidCached,

tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec, ts.tv_nsec,

(unsigned)tid, tracerTraceLevelName(level), func,
tracerShortFileName(file), line, message);
}

Check warning on line 86 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L86

Added line #L86 was not covered by tests

void stderrTracerEmit(const char *file,

Check warning on line 88 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L88

Added line #L88 was not covered by tests
unsigned int line,
const char *func,
unsigned int level,
const char *message)
{
assert(tracer__level < TRACE_NR);

Check warning on line 94 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L94

Added line #L94 was not covered by tests

if (level >= tracer__level)
tracerEmit(file, line, func, level, message);
}

Check warning on line 98 in src/tracing.c

View check run for this annotation

Codecov / codecov/patch

src/tracing.c#L97-L98

Added lines #L97 - L98 were not covered by tests
48 changes: 35 additions & 13 deletions src/tracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,43 @@
/* This global variable is only written once at startup and is only read
* from there on. Users should not manipulate the value of this variable. */
DQLITE_VISIBLE_TO_TESTS extern bool _dqliteTracingEnabled;

#define tracef(...) \
do { \
if (UNLIKELY(_dqliteTracingEnabled)) { \
static char _msg[1024]; \
snprintf(_msg, sizeof(_msg), __VA_ARGS__); \
struct timespec ts = {0}; \
/* Ignore errors */ \
clock_gettime(CLOCK_REALTIME, &ts); \
int64_t ns = ts.tv_sec * 1000000000 + ts.tv_nsec; \
fprintf(stderr, "LIBDQLITE %" PRId64 " %s:%d %s\n", \
ns, __func__, __LINE__, _msg); \
} \
DQLITE_VISIBLE_TO_TESTS void stderrTracerEmit(const char *file,
unsigned int line,
const char *func,
unsigned int level,
const char *message);

#define tracef0(LEVEL, ...) \
do { \
if (UNLIKELY(_dqliteTracingEnabled)) { \
char _msg[1024]; \
snprintf(_msg, sizeof _msg, __VA_ARGS__); \
stderrTracerEmit(__FILE__, __LINE__, __func__, \
(LEVEL), _msg); \
} \
} while (0)

enum dqlite_trace_level {
/** Represents an invalid trace level */
TRACE_NONE,
/** Lower-level information to debug and analyse incorrect behavior */
TRACE_DEBUG,
/** Information about current system's state */
TRACE_INFO,
/**
* Condition which requires a special handling, something which doesn't
* happen normally
*/
TRACE_WARN,
/** Resource unavailable, no connectivity, invalid value, etc. */
TRACE_ERROR,
/** System is not able to continue performing its basic function */
TRACE_FATAL,
TRACE_NR,
};

#define tracef(...) tracef0(TRACE_DEBUG, __VA_ARGS__)

/* Enable tracing if the appropriate env variable is set, or disable tracing. */
DQLITE_VISIBLE_TO_TESTS void dqliteTracingMaybeEnable(bool enabled);

Expand Down

0 comments on commit 4c7743b

Please sign in to comment.