Added logging sub-system
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/build
|
||||
/dist
|
||||
/nbproject/private
|
||||
|
||||
@@ -41,6 +41,7 @@ OBJECTFILES= \
|
||||
${OBJECTDIR}/src/http-reader.o \
|
||||
${OBJECTDIR}/src/http-server.o \
|
||||
${OBJECTDIR}/src/http.o \
|
||||
${OBJECTDIR}/src/log.o \
|
||||
${OBJECTDIR}/src/main.o \
|
||||
${OBJECTDIR}/src/mime.o \
|
||||
${OBJECTDIR}/src/queue.o \
|
||||
@@ -103,6 +104,11 @@ ${OBJECTDIR}/src/http.o: nbproject/Makefile-${CND_CONF}.mk src/http.c
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http.o src/http.c
|
||||
|
||||
${OBJECTDIR}/src/log.o: nbproject/Makefile-${CND_CONF}.mk src/log.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -g -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/log.o src/log.c
|
||||
|
||||
${OBJECTDIR}/src/main.o: nbproject/Makefile-${CND_CONF}.mk src/main.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
|
||||
@@ -41,6 +41,7 @@ OBJECTFILES= \
|
||||
${OBJECTDIR}/src/http-reader.o \
|
||||
${OBJECTDIR}/src/http-server.o \
|
||||
${OBJECTDIR}/src/http.o \
|
||||
${OBJECTDIR}/src/log.o \
|
||||
${OBJECTDIR}/src/main.o \
|
||||
${OBJECTDIR}/src/mime.o \
|
||||
${OBJECTDIR}/src/queue.o \
|
||||
@@ -103,6 +104,11 @@ ${OBJECTDIR}/src/http.o: nbproject/Makefile-${CND_CONF}.mk src/http.c
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http.o src/http.c
|
||||
|
||||
${OBJECTDIR}/src/log.o: nbproject/Makefile-${CND_CONF}.mk src/log.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
$(COMPILE.c) -O2 -Werror -DINI_ALLOW_BOM=0 -DINI_ALLOW_MULTILINE=0 -D_GNU_SOURCE -Ilib -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/log.o src/log.c
|
||||
|
||||
${OBJECTDIR}/src/main.o: nbproject/Makefile-${CND_CONF}.mk src/main.c
|
||||
${MKDIR} -p ${OBJECTDIR}/src
|
||||
${RM} "$@.d"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<itemPath>src/http.h</itemPath>
|
||||
<itemPath>lib/http_parser.h</itemPath>
|
||||
<itemPath>lib/ini.h</itemPath>
|
||||
<itemPath>src/log.h</itemPath>
|
||||
<itemPath>src/main.h</itemPath>
|
||||
<itemPath>src/mime.h</itemPath>
|
||||
<itemPath>src/queue.h</itemPath>
|
||||
@@ -30,6 +31,7 @@
|
||||
<itemPath>src/http.c</itemPath>
|
||||
<itemPath>lib/http_parser.c</itemPath>
|
||||
<itemPath>lib/ini.c</itemPath>
|
||||
<itemPath>src/log.c</itemPath>
|
||||
<itemPath>src/main.c</itemPath>
|
||||
<itemPath>src/mime.c</itemPath>
|
||||
<itemPath>src/queue.c</itemPath>
|
||||
@@ -115,6 +117,10 @@
|
||||
</item>
|
||||
<item path="src/http.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/log.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/log.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.h" ex="false" tool="3" flavor2="0">
|
||||
@@ -201,6 +207,10 @@
|
||||
</item>
|
||||
<item path="src/http.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/log.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/log.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.c" ex="false" tool="0" flavor2="0">
|
||||
</item>
|
||||
<item path="src/main.h" ex="false" tool="3" flavor2="0">
|
||||
|
||||
197
src/log.c
Normal file
197
src/log.c
Normal file
@@ -0,0 +1,197 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <bits/stdio2.h>
|
||||
|
||||
#include "ut/utlist.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#define XX(n, s, f) |L##n
|
||||
const log_level LALL = 0 LOG_LEVEL_TABLE(XX);
|
||||
#undef XX
|
||||
|
||||
#define XX(n, s, f) [L##n]=s,
|
||||
const char *log_level_name[] = {
|
||||
LOG_LEVEL_TABLE(XX)
|
||||
};
|
||||
#undef XX
|
||||
|
||||
log* log_new(const char* name, FILE *output) {
|
||||
log* l = calloc(1, sizeof(log));
|
||||
l->output = output;
|
||||
l->name = calloc(strlen(name)+1, sizeof(char));
|
||||
strcpy(l->name, name);
|
||||
l->running = false;
|
||||
|
||||
return l;
|
||||
}
|
||||
void log_delete(log *l) {
|
||||
free(l->name);
|
||||
free(l);
|
||||
}
|
||||
bool log_start(log *l) {
|
||||
if (l->running == true) {
|
||||
return true;
|
||||
}
|
||||
int pfd[2];
|
||||
if (pipe(pfd) != 0) {
|
||||
LOG(LERROR, "Failed to create log pipe");
|
||||
return false;
|
||||
}
|
||||
l->pRead = pfd[0];
|
||||
l->pWrite = pfd[1];
|
||||
|
||||
|
||||
if (pthread_create(&l->thread, NULL, log_loop, (void*)l) != 0) {
|
||||
LOG(LERROR, "Failed to create log thread");
|
||||
close(l->pRead);
|
||||
close(l->pWrite);
|
||||
return false;
|
||||
}
|
||||
l->running = true;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
void*log_loop(void* arg) {
|
||||
log *l = (log*)arg;
|
||||
void** buf = calloc(1, sizeof(void*));
|
||||
char* timestr = calloc(32, sizeof(char));
|
||||
time_t ctime;
|
||||
struct tm *tinfo = calloc(1,sizeof(struct tm));
|
||||
while(true) {
|
||||
if (read(l->pRead, buf, sizeof(void*)) <= 0) {
|
||||
if (l->running == false) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "log[%s] read failed: %s. logger aborted\n", l->name, strerror(errno));
|
||||
log_stop(l);
|
||||
break;
|
||||
}
|
||||
ctime = time(NULL);
|
||||
localtime_r(&ctime, tinfo);
|
||||
if (strftime(timestr, 32, "%F %R", tinfo) == 0) {
|
||||
strcpy(timestr, "N/A");
|
||||
}
|
||||
log_msg* msg = (log_msg*)(*buf);
|
||||
fprintf(l->output, "[%s][%s] %s\n", timestr, log_level_name[msg->level], msg->msg);
|
||||
fflush(l->output);
|
||||
log_msg_delete(msg);
|
||||
}
|
||||
free(buf);
|
||||
free(timestr);
|
||||
}
|
||||
void log_stop(log *l) {
|
||||
l->running = false;
|
||||
close(l->pWrite);
|
||||
if (pthread_equal(l->thread, pthread_self())!=0) {
|
||||
pthread_detach(l->thread);
|
||||
} else {
|
||||
pthread_join(l->thread, NULL);
|
||||
}
|
||||
close(l->pRead);
|
||||
}
|
||||
void log_write(log *l, log_level level, const char* message) {
|
||||
if (l == NULL) {
|
||||
fprintf(stderr, "%s\n", message);
|
||||
return;
|
||||
}
|
||||
if (l->running == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* msgstr = calloc(strlen(message)+1, sizeof(char));
|
||||
log_msg *msg = log_msg_new(level, msgstr);
|
||||
write(l->pWrite, &msg, sizeof(log_msg*));
|
||||
}
|
||||
|
||||
log_msg* log_msg_new(log_level level, char *msg) {
|
||||
log_msg *m = calloc(1, sizeof(log_msg));
|
||||
m->level = level;
|
||||
m->msg = msg;
|
||||
return m;
|
||||
}
|
||||
void log_msg_delete(log_msg* msg) {
|
||||
free(msg->msg);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static log_register* _register;
|
||||
|
||||
void log_register_add(log *l, bool def, log_level levels) {
|
||||
if (l->running == false) {
|
||||
log_start(l);
|
||||
}
|
||||
log_register *elem;
|
||||
if (def == true) {
|
||||
LL_FOREACH(_register, elem) {
|
||||
elem->def = false;
|
||||
}
|
||||
}
|
||||
log_register *lr = calloc(1, sizeof(log_register));
|
||||
lr->l = l;
|
||||
lr->def = def;
|
||||
lr->levels = levels;
|
||||
LL_APPEND(_register, lr);
|
||||
}
|
||||
void log_register_remove(log *l) {
|
||||
log_register *elem, *tmp;
|
||||
LL_FOREACH_SAFE(_register, elem, tmp) {
|
||||
if (elem->l == l) {
|
||||
LL_DELETE(_register, elem);
|
||||
free(elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
log* log_register_get(const char* name) {
|
||||
log_register *def = NULL, *elem;
|
||||
LL_FOREACH(_register, elem) {
|
||||
if (name != NULL && strcasecmp(name, elem->l->name) == 0) {
|
||||
return elem->l;
|
||||
}
|
||||
if (elem->def == true) {
|
||||
def = elem;
|
||||
if (name == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (def!=NULL) ? def->l : NULL;
|
||||
}
|
||||
void log_register_clear() {
|
||||
log_register *elem, *tmp;
|
||||
LL_FOREACH_SAFE(_register, elem, tmp) {
|
||||
LL_DELETE(_register, elem);
|
||||
log_stop(elem->l);
|
||||
log_delete(elem->l);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
void log_register_write(log_level level, const char* fmt, ...) {
|
||||
char msg[LOG_LENGTH];
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vsnprintf(msg, LOG_LENGTH, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
int count=0;
|
||||
log_register *elem;
|
||||
LL_FOREACH(_register, elem) {
|
||||
if ((elem->levels & level) == level) {
|
||||
log_write(elem->l, level, msg);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
//Write to default log if not matched against any registered
|
||||
if (count == 0) {
|
||||
log_write(log_register_get(NULL), level, msg);
|
||||
}
|
||||
}
|
||||
82
src/log.h
Normal file
82
src/log.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* File: log.h
|
||||
* Author: sam
|
||||
*
|
||||
* Created on 06 August 2014, 12:06
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define LOG_LEVEL_TABLE(XX) \
|
||||
XX(DEBUG, "DEBUG", 1 << 0) \
|
||||
XX(INFO, "INFO", 1 << 1) \
|
||||
XX(WARNING, "WARNING", 1 << 2) \
|
||||
XX(ERROR, "ERROR", 1 << 3) \
|
||||
XX(FATAL, "FATAL", 1 << 4)
|
||||
|
||||
#define XX(n, s, f) L##n=f,
|
||||
typedef enum log_level {
|
||||
LOG_LEVEL_TABLE(XX)
|
||||
} log_level;
|
||||
#undef XX
|
||||
|
||||
#define LOG(level, fmt, ...) log_register_write(level, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define LOG_LENGTH 256
|
||||
|
||||
extern const log_level LALL;
|
||||
|
||||
extern const char *log_level_name[];
|
||||
|
||||
typedef struct log {
|
||||
char* name;
|
||||
int pRead, pWrite;
|
||||
FILE *output;
|
||||
pthread_t thread;
|
||||
bool running;
|
||||
} log;
|
||||
|
||||
typedef struct log_msg {
|
||||
log_level level;
|
||||
char* msg;
|
||||
} log_msg;
|
||||
|
||||
typedef struct log_register {
|
||||
log *l;
|
||||
bool def;
|
||||
log_level levels;
|
||||
struct log_register *next;
|
||||
} log_register;
|
||||
|
||||
log* log_new(const char* name, FILE *output);
|
||||
void log_delete(log *l);
|
||||
bool log_start(log *l);
|
||||
void log_stop(log *l);
|
||||
void*log_loop(void* arg);
|
||||
void log_write(log *l, log_level level, const char* message);
|
||||
|
||||
log_msg* log_msg_new(log_level level, char *msg);
|
||||
void log_msg_delete(log_msg* msg);
|
||||
|
||||
void log_register_add(log *l, bool def, log_level levels);
|
||||
void log_register_remove(log *l);
|
||||
log* log_register_get(const char* name);
|
||||
void log_register_clear();
|
||||
void log_register_write(log_level level, const char* fmt, ...);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOG_H */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "mime.h"
|
||||
#include "queue.h"
|
||||
#include "thread-pool.h"
|
||||
#include "log.h"
|
||||
|
||||
int serverfd = 0;
|
||||
volatile static bool stop = false;
|
||||
@@ -40,6 +41,9 @@ static void signal_int(int signum) {
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
log_register_add(log_new("stderr", stderr), true, LALL & ~(LINFO|LDEBUG));
|
||||
log_register_add(log_new("stdout", stdout), false, LDEBUG | LINFO);
|
||||
|
||||
|
||||
mime_init(NULL);
|
||||
config_server *config = config_server_new();
|
||||
@@ -158,6 +162,7 @@ int main(int argc, char** argv) {
|
||||
mime_destroy();
|
||||
config_server_delete(config);
|
||||
svr_release(serverfd);
|
||||
log_register_clear();
|
||||
serverfd = 0;
|
||||
|
||||
return (EXIT_SUCCESS);
|
||||
|
||||
@@ -172,7 +172,7 @@ void* thread_mgt(void* arg) {
|
||||
//Remove threads
|
||||
LL_FOREACH_SAFE(pool->threads, elem, tmp) {
|
||||
thread_stop(elem);
|
||||
LL_DELETE(pool->threads, elem);
|
||||
thread_pool_remove_thread(pool, elem);
|
||||
thread_delete(elem);
|
||||
}
|
||||
}
|
||||
32
src/util.c
32
src/util.c
@@ -9,39 +9,51 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
void fatal(char* fmt, ...) {
|
||||
char msg[128] = {0};
|
||||
char msg[LOG_LENGTH] = {0};
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vsnprintf(msg, 128, fmt, va);
|
||||
vsnprintf(msg, LOG_LENGTH, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
perror(msg);
|
||||
LOG(LFATAL, msg);
|
||||
log_register_clear();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
void warning(bool use_errno, char* fmt, ...) {
|
||||
char msg[128] = {0};
|
||||
char msg[LOG_LENGTH] = {0};
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vsnprintf(msg, 128, fmt, va);
|
||||
vsnprintf(msg, LOG_LENGTH, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
if (use_errno == true) {
|
||||
perror(msg);
|
||||
char *errnostr = calloc(64, sizeof(char));
|
||||
strerror_r(errno, errnostr, 64);
|
||||
char *errstr = calloc(strlen(msg)+strlen(errnostr)+3, sizeof(char));
|
||||
strcat(errstr, msg);
|
||||
strcat(errstr, ": ");
|
||||
strcat(errstr, errnostr);
|
||||
LOG(LWARNING, errstr);
|
||||
free(errnostr);
|
||||
free(errstr);
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
LOG(LWARNING, msg);
|
||||
}
|
||||
}
|
||||
void info(char* fmt, ...) {
|
||||
char msg[LOG_LENGTH] = {0};
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vfprintf(stdout, fmt, va);
|
||||
fputc('\n', stdout);
|
||||
vsnprintf(msg, LOG_LENGTH, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
LOG(LINFO, msg);
|
||||
}
|
||||
|
||||
char** str_splitlines(char *str, size_t *line_count) {
|
||||
|
||||
Reference in New Issue
Block a user