added my fancy C logging library v0.000001
This commit is contained in:
parent
16e775d324
commit
f5e4ac0244
4 changed files with 236 additions and 0 deletions
33
c/color.h
Normal file
33
c/color.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/** Various helper functions.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @file
|
||||
*/
|
||||
|
||||
#ifndef _COLOR_H_
|
||||
#define _COLOR_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Some color escape codes for pretty log messages */
|
||||
#define GRY(str) "\e[30m" str "\e[0m" /**< Print str in gray */
|
||||
#define RED(str) "\e[31m" str "\e[0m" /**< Print str in red */
|
||||
#define GRN(str) "\e[32m" str "\e[0m" /**< Print str in green */
|
||||
#define YEL(str) "\e[33m" str "\e[0m" /**< Print str in yellow */
|
||||
#define BLU(str) "\e[34m" str "\e[0m" /**< Print str in blue */
|
||||
#define MAG(str) "\e[35m" str "\e[0m" /**< Print str in magenta */
|
||||
#define CYN(str) "\e[36m" str "\e[0m" /**< Print str in cyan */
|
||||
#define WHT(str) "\e[37m" str "\e[0m" /**< Print str in white */
|
||||
#define BLD(str) "\e[1m" str "\e[0m" /**< Print str in bold */
|
||||
|
||||
#define GFX(chr) "\e(0" chr "\e(B"
|
||||
#define UP(n) "\e[" ## n ## "A"
|
||||
#define DOWN(n) "\e[" ## n ## "B"
|
||||
#define RIGHT(n) "\e[" ## n ## "C"
|
||||
#define LEFT(n) "\e[" ## n ## "D"
|
||||
|
||||
#endif /* _COLOR_H_ */
|
70
c/logger.c
Normal file
70
c/logger.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "color.h"
|
||||
#include "logger.h"
|
||||
|
||||
/* This global variable contains the debug level for debug() and assert() macros */
|
||||
int _debug = V;
|
||||
int _indent = 0;
|
||||
|
||||
static struct timeval epoch;
|
||||
|
||||
void _outdent(int *old)
|
||||
{
|
||||
_indent = *old;
|
||||
}
|
||||
|
||||
void log_reset()
|
||||
{
|
||||
gettimeofday(&epoch, NULL);
|
||||
}
|
||||
|
||||
void log_level(int lvl)
|
||||
{
|
||||
_debug = lvl;
|
||||
}
|
||||
|
||||
void print(enum log_level lvl, const char *fmt, ...)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
/* Timestamp */
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
fprintf(stderr, "%8.3f ", timespec_delta(&epoch, &tv));
|
||||
|
||||
switch (lvl) {
|
||||
case DEBUG: fprintf(stderr, BLD("%-5s "), GRY("Debug")); break;
|
||||
case INFO: fprintf(stderr, BLD("%-5s "), WHT(" Info")); break;
|
||||
case WARN: fprintf(stderr, BLD("%-5s "), YEL(" Warn")); break;
|
||||
case ERROR: fprintf(stderr, BLD("%-5s "), RED("Error")); break;
|
||||
}
|
||||
|
||||
if (_indent) {
|
||||
for (int i = 0; i < _indent-1; i++)
|
||||
fprintf(stderr, GFX("\x78") " ");
|
||||
|
||||
fprintf(stderr, GFX("\x74") " ");
|
||||
}
|
||||
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
double timespec_delta(struct timeval *start, struct timeval *end)
|
||||
{
|
||||
double sec = end->tv_sec - start->tv_sec;
|
||||
double usec = end->tv_usec - start->tv_usec;
|
||||
|
||||
if (usec < 0) {
|
||||
sec -= 1;
|
||||
usec += 1e6;
|
||||
}
|
||||
|
||||
return sec + usec * 1e-6;
|
||||
}
|
85
c/logger.h
Normal file
85
c/logger.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef V
|
||||
#define V 5
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define EXPECT(x, v) __builtin_expect(x, v)
|
||||
#define INDENT int __attribute__ ((__cleanup__(_outdent), unused)) _old_indent = _indent++;
|
||||
#else
|
||||
#define EXPECT(x, v) (x)
|
||||
#define INDENT ;
|
||||
#endif
|
||||
|
||||
/* These global variables allow changing the output style and verbosity */
|
||||
extern int _debug;
|
||||
extern int _indent;
|
||||
|
||||
void outdent(int *old);
|
||||
|
||||
/** The log level which is passed as first argument to print() */
|
||||
enum log_level { DEBUG, INFO, WARN, ERROR };
|
||||
|
||||
/** Reset the timer for log outputs to zero. */
|
||||
void log_reset();
|
||||
|
||||
/** Set the current logging level */
|
||||
void log_level(int lvl);
|
||||
|
||||
/** Get delta between two timespec structs */
|
||||
double timespec_delta(struct timeval *start, struct timeval *end);
|
||||
|
||||
/** Logs variadic messages to stdout.
|
||||
*
|
||||
* @param lvl The log level
|
||||
* @param fmt The format string (printf alike)
|
||||
*/
|
||||
void print(enum log_level lvl, const char *fmt, ...);
|
||||
|
||||
/** Check assertion and exit if failed. */
|
||||
#define assert(exp) do { \
|
||||
if (EXPECT(!exp, 0)) { \
|
||||
print(ERROR, "Assertion failed: '%s' in %s, %s:%d", \
|
||||
#exp, __FUNCTION__, __BASE_FILE__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} } while (0)
|
||||
|
||||
/** Printf alike debug message with level. */
|
||||
#define debug(lvl, msg, ...) do { \
|
||||
if (lvl <= _debug) \
|
||||
print(DEBUG, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Printf alike info message. */
|
||||
#define info(msg, ...) do { \
|
||||
print(INFO, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Printf alike warning message. */
|
||||
#define warn(msg, ...) do { \
|
||||
print(WARN, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Print error and exit. */
|
||||
#define error(msg, ...) do { \
|
||||
print(ERROR, msg, ##__VA_ARGS__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
/** Print error and strerror(errno). */
|
||||
#define serror(msg, ...) do { \
|
||||
print(ERROR, msg ": %s", ##__VA_ARGS__, \
|
||||
strerror(errno)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
/** Print configuration error and exit. */
|
||||
#define cerror(c, msg, ...) do { \
|
||||
print(ERROR, msg " in %s:%u", ##__VA_ARGS__, \
|
||||
(config_setting_source_file(c)) ? \
|
||||
config_setting_source_file(c) : "(stdio)", \
|
||||
config_setting_source_line(c)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
48
c/logger_test.c
Normal file
48
c/logger_test.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
void recursive(int i)
|
||||
{ INDENT
|
||||
info("We are inside the recursive function. Current level = %d", i);
|
||||
|
||||
if (i) {
|
||||
usleep(rand() * 3e6 / RAND_MAX);
|
||||
recursive(i-1);
|
||||
}
|
||||
}
|
||||
|
||||
void goodbye()
|
||||
{
|
||||
warn("There was an error message. Program terminating...");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Reset log timer to zero */
|
||||
epoch_reset();
|
||||
|
||||
/* Register exit() handler */
|
||||
atexit(goodbye);
|
||||
|
||||
info("Welcome, this is a little program to demo the logger");
|
||||
|
||||
recursive(5);
|
||||
|
||||
/* Some other types of messages */
|
||||
info("This is a info message");
|
||||
warn("This is a warning message");
|
||||
|
||||
/* Debug messages are only printed if the level (1st arg) is higher than the current level */
|
||||
debug(3, "This is a debug message");
|
||||
|
||||
/* INDENT's are valid per code block */
|
||||
{ INDENT
|
||||
info("This is an indented message");
|
||||
}
|
||||
|
||||
/* Error messages will cause program termination */
|
||||
error("This is an error message");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue