mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 20:28:56 +00:00
logging finished
This commit is contained in:
parent
7dfa80572d
commit
4b6cbba04f
4 changed files with 327 additions and 3 deletions
7
Makefile
7
Makefile
|
@ -7,15 +7,16 @@ BIN_NAME = cfloor
|
|||
|
||||
all: $(BIN_NAME)
|
||||
|
||||
test: obj/test.o obj/networking.o obj/linked.o
|
||||
test: obj/test.o obj/networking.o obj/linked.o obj/logging.o
|
||||
$(LD) $(LDFLAGS) -o $@ $^
|
||||
valgrind: CFLAGS += -static -g
|
||||
valgrind: clean test
|
||||
valgrind --leak-check=yes ./test
|
||||
|
||||
obj/test.o: src/networking.h
|
||||
obj/networking.o: src/networking.h src/headers.h
|
||||
obj/test.o: src/networking.h src/linked.h src/logging.h
|
||||
obj/networking.o: src/networking.h src/headers.h src/linked.h
|
||||
obj/linked.o: src/linked.h
|
||||
obj/loggin.o: src/logging.h
|
||||
|
||||
obj/%.o: src/%.c obj
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
|
269
src/logging.c
Normal file
269
src/logging.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
#ifdef BACKTRACE
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
struct {
|
||||
FILE* file;
|
||||
enum loglevel loglevel;
|
||||
bool color;
|
||||
} logger[MAX_LOGGER];
|
||||
int loggerCount = 0;
|
||||
|
||||
void (*_criticalHandler)() = NULL;
|
||||
|
||||
void setLogging(FILE* file, enum loglevel loglevel, bool color) {
|
||||
if (loggerCount == MAX_LOGGER - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < loggerCount; i++) {
|
||||
if ((logger[i].file == file)) {
|
||||
found = true;
|
||||
logger[i].loglevel = loglevel;
|
||||
logger[i].color = color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
logger[loggerCount].file = file;
|
||||
logger[loggerCount].loglevel = loglevel;
|
||||
logger[loggerCount].color = color;
|
||||
loggerCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void setCriticalHandler(void (*handler)()) {
|
||||
_criticalHandler = handler;
|
||||
}
|
||||
|
||||
void callCritical() {
|
||||
if (_criticalHandler != NULL)
|
||||
_criticalHandler();
|
||||
}
|
||||
|
||||
#define BACKTRACE_BUFFER_SIZE 16
|
||||
void printBacktrace() {
|
||||
#ifdef BACKTRACE
|
||||
|
||||
void* buffer[BACKTRACE_BUFFER_SIZE];
|
||||
char** strings;
|
||||
int entries = backtrace(buffer, BACKTRACE_BUFFER_SIZE);
|
||||
strings = backtrace_symbols(buffer, entries);
|
||||
|
||||
if (strings == NULL) {
|
||||
fprintf(stderr, "Error while backtracing: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
int tmp = (entries < BACKTRACE_BUFFER_SIZE) ? entries : entries - 1;
|
||||
|
||||
// from 1 to ignore printBacktrace
|
||||
for (int i = 1; i < tmp; i++) {
|
||||
fprintf(stderr, " at %s\n", strings[i]);
|
||||
}
|
||||
if (tmp < entries) {
|
||||
fprintf(stderr, " ...\n");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
fprintf(stderr, "Error: Not compiled with backtrace support.\n");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
char* getTimestamp() {
|
||||
#define MSEC_LENGTH (3)
|
||||
#define TIME_LENGTH (4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + MSEC_LENGTH)
|
||||
char* result = malloc(TIME_LENGTH + 1);
|
||||
if (result == NULL) {
|
||||
fprintf(stderr, "\nDEVASTATING: Couldn't malloc for log time.\n");
|
||||
callCritical();
|
||||
exit(EXIT_DEVASTATING);
|
||||
}
|
||||
|
||||
|
||||
int millisec;
|
||||
struct tm* tm_info;
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
millisec = (int) (tv.tv_usec / 1000.0);
|
||||
if (millisec >= 1000) {
|
||||
millisec -=1000;
|
||||
tv.tv_sec++;
|
||||
}
|
||||
|
||||
tm_info = localtime(&tv.tv_sec);
|
||||
|
||||
strftime(result, 26, "%Y-%m-%dT%H:%M:%S", tm_info);
|
||||
|
||||
char* msecBuffer = malloc(1 + MSEC_LENGTH + 1);
|
||||
|
||||
if (msecBuffer == NULL) {
|
||||
fprintf(stderr, "\nDEVASTATING: Couldn't malloc for log time.\n");
|
||||
callCritical();
|
||||
exit(EXIT_DEVASTATING);
|
||||
}
|
||||
|
||||
snprintf(msecBuffer, 1 + MSEC_LENGTH + 1, ".%03d", millisec);
|
||||
|
||||
strncat(result, msecBuffer, TIME_LENGTH + 1);
|
||||
|
||||
free(msecBuffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char* getLoglevelString(enum loglevel loglevel, bool color) {
|
||||
#define DEBUG_STRING "[DEBUG]"
|
||||
#define VERBOSE_STRING "[VERBOSE]"
|
||||
#define INFO_STRING "[INFO]"
|
||||
#define WARN_STRING "[WARNING]"
|
||||
#define ERROR_STRING "[ERROR]"
|
||||
#define CRITICAL_STRING "[CRITICAL]"
|
||||
#define UNKNOWN_STRING "[UNKNOWN]"
|
||||
|
||||
#define DEBUG_COLOR "\033[37m"
|
||||
#define VERBOSE_COLOR "\033[35m"
|
||||
#define INFO_COLOR "\033[36m"
|
||||
#define WARN_COLOR "\033[33m"
|
||||
#define ERROR_COLOR "\033[31m"
|
||||
#define CRITICAL_COLOR "\033[41m\033[30m"
|
||||
#define UNKNOWN_COLOR "\033[41m\033[30m"
|
||||
|
||||
#define COLOR_END "\033[0m"
|
||||
|
||||
switch(loglevel) {
|
||||
case DEBUG:
|
||||
if (color)
|
||||
return DEBUG_COLOR DEBUG_STRING COLOR_END;
|
||||
else
|
||||
return DEBUG_STRING;
|
||||
break;
|
||||
case VERBOSE:
|
||||
if (color)
|
||||
return VERBOSE_COLOR VERBOSE_STRING COLOR_END;
|
||||
else
|
||||
return VERBOSE_STRING;
|
||||
break;
|
||||
case INFO:
|
||||
if (color)
|
||||
return INFO_COLOR INFO_STRING COLOR_END;
|
||||
else
|
||||
return INFO_STRING;
|
||||
break;
|
||||
case WARN:
|
||||
if (color)
|
||||
return WARN_COLOR WARN_STRING COLOR_END;
|
||||
else
|
||||
return WARN_STRING;
|
||||
break;
|
||||
case ERROR:
|
||||
if (color)
|
||||
return ERROR_COLOR ERROR_STRING COLOR_END;
|
||||
else
|
||||
return ERROR_STRING;
|
||||
break;
|
||||
case CRITICAL:
|
||||
if (color)
|
||||
return CRITICAL_COLOR CRITICAL_STRING COLOR_END;
|
||||
else
|
||||
return CRITICAL_STRING;
|
||||
break;
|
||||
default:
|
||||
if (color)
|
||||
return UNKNOWN_COLOR UNKNOWN_STRING COLOR_END;
|
||||
else
|
||||
return UNKNOWN_STRING;
|
||||
break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vlogging(enum loglevel loglevel, const char* format, va_list argptr) {
|
||||
char* timestamp = getTimestamp();
|
||||
|
||||
for(int i = 0; i < loggerCount; i++) {
|
||||
if (loglevel < logger[i].loglevel)
|
||||
continue;
|
||||
|
||||
char* loglevelString = getLoglevelString(loglevel, logger[i].color);
|
||||
fprintf(logger[i].file, "%s %s ", timestamp, loglevelString);
|
||||
|
||||
vfprintf(logger[i].file, format, argptr);
|
||||
|
||||
fprintf(logger[i].file, "\n");
|
||||
}
|
||||
|
||||
free(timestamp);
|
||||
|
||||
if (loglevel == CRITICAL)
|
||||
callCritical();
|
||||
}
|
||||
|
||||
void logging(enum loglevel loglevel, const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(loglevel, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void debug(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(DEBUG, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void verbose(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(VERBOSE, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void info(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(INFO, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void warn(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(WARN, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void error(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(ERROR, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void critical(const char* format, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
vlogging(CRITICAL, format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
29
src/logging.h
Normal file
29
src/logging.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
enum loglevel {
|
||||
DEBUG, VERBOSE, INFO, WARN, ERROR, CRITICAL
|
||||
};
|
||||
|
||||
#define EXIT_DEVASTATING (255)
|
||||
|
||||
#define DEFAULT_LOGLEVEL (WARN)
|
||||
|
||||
#define MAX_LOGGER (10)
|
||||
|
||||
void setLogging(FILE* file, enum loglevel loglevel, bool color);
|
||||
void setCriticalHandler(void (*handler)());
|
||||
|
||||
void printBacktrace();
|
||||
|
||||
void logging(enum loglevel loglevel, const char* format, ...);
|
||||
void debug(const char* format, ...);
|
||||
void verbose(const char* format, ...);
|
||||
void info(const char* format, ...);
|
||||
void warn(const char* format, ...);
|
||||
void error(const char* format, ...);
|
||||
void critical(const char* format, ...);
|
||||
|
||||
#endif
|
25
src/test.c
25
src/test.c
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "networking.h"
|
||||
#include "linked.h"
|
||||
#include "logging.h"
|
||||
|
||||
bool global = true;
|
||||
|
||||
|
@ -84,6 +85,22 @@ void testLinkedList() {
|
|||
linked_destroy(&list);
|
||||
}
|
||||
|
||||
void criticalHandler() {
|
||||
printf("This is the critical handler.\n");
|
||||
printBacktrace();
|
||||
}
|
||||
void testLogging() {
|
||||
setLogging(stderr, DEFAULT_LOGLEVEL, true);
|
||||
|
||||
info("This info should not be displayed.");
|
||||
warn("This warning should be displayed.");
|
||||
error("This error should be displayed.");
|
||||
|
||||
setCriticalHandler(&criticalHandler);
|
||||
|
||||
critical("This critical should be displayed.");
|
||||
}
|
||||
|
||||
handler_t handlerGetter(struct metaData metaData, const char* host) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -109,6 +126,14 @@ int main(int argc, char** argv) {
|
|||
printf("linked lists: %s\n\n", global ? "OK" : "FAILED");
|
||||
global = true;
|
||||
|
||||
printf("logging\n");
|
||||
printf("============\n\n");
|
||||
testLogging();
|
||||
if (!global)
|
||||
overall = false;
|
||||
printf("logging: %s\n\n", global ? "OK" : "FAILED");
|
||||
global = true;
|
||||
|
||||
|
||||
printf("\nOverall: %s\n", overall ? "OK" : "FAILED");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue