added my fancy C logging library v0.000001

This commit is contained in:
Steffen Vogel 2016-02-16 00:21:48 +01:00
parent 16e775d324
commit f5e4ac0244
4 changed files with 236 additions and 0 deletions

33
c/color.h Normal file
View 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
View 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
View 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
View 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;
}