view logging.c @ 262:ebbe0f198322

Fix DDS client connection retry
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Tue, 16 Jun 2015 17:16:11 +0200
parents 3622e24a443f
children
line wrap: on
line source

#include <ansi_c.h>
#include <inifile.h>
#include <lowlvlio.h>
#include <ansi_c.h>

#include "config.h"
#include "logging.h"

/* this refers to the event time defined as a global variable in the main program */
extern double utc;
/* main panel id */
extern unsigned int MainPanel;


struct logger {
	unsigned int panel;
	char *dirpath;
	char *filepath;
	int fd;
	int level;
	int yday;
	void(*onerror)(int, const char *);
};


static const char *levels[] = {
	[ERROR] = "ERROR",
	[WARNING] = "WARNING",
	[INFO] = "INFO",
	[DEBUG] = "DEBUG",
};


static inline int strtolevel(const char *str)
{
	for (int i = 0; i < 4; i++) {
		if (streq(levels[i], str))
			return i;
	}
	return DEBUG;
}


static int rotate(struct logger *l, time_t now)
{
	int len, rv;
	char id[7];
	struct tm *t;
	
	if (! l->dirpath)
		return 0;

	/* utc day */
	t = gmtime(&now);	
	if (l->yday == t->tm_yday)
		return 0;

	/* close old file descriptor */
	close(l->fd);
	l->fd = -1;
	
	/* construct new file name */
	strftime(id, sizeof(id), "%y%m%d", t);
	len = strlen(l->dirpath) + 1 + sizeof(id) + strlen("-Log.txt") + 1;
	l->filepath = malloc(len);
	snprintf(l->filepath, len, "%s\\%s-Log.txt", l->dirpath, id);

	/* open new log file */
	rv = open(l->filepath, O_CREAT|O_WRONLY|O_APPEND, 00744);
	if (rv < 0)
		return rv;

	/* update status */
	l->fd = rv;
	l->yday = t->tm_yday;
	__logmessage(l, DEBUG, "logging to '%s'", l->filepath);
	
	return 1;
}


struct logger * __logger_init(void(*onerror)(int, const char *))
{
	int rv, panel;
	char path[MAX_PATHNAME_LEN], *str;

	struct logger *l = malloc(sizeof(struct logger));
	memset(l, 0, sizeof(*l));
	
	l->onerror = onerror;
	l->fd = -1;
	l->level = DEBUG;
	
	panel = LoadPanel(0, "FXAnalyse.uir", LOGGING);
	if (panel < 0)
		return NULL;
	l->panel = panel;
	
	/* configuration file path */
	GetIniFilePath(path); 

	/* load configuration file */ 
	IniText configuration = Ini_New(TRUE);
	Ini_ReadFromFile(configuration, path);

	/* logging folder path */
	rv = Ini_GetStringCopy(configuration, "logging", "folder", &l->dirpath);
	
	/* logging level */
	rv = Ini_GetStringCopy(configuration, "logging", "level", &str);
	if (rv > 0) {
		l->level = strtolevel(str);
		free(str);
	}
	
	Ini_Dispose(configuration);
	
	return l;
}


void __logmessage(struct logger *l, enum loglevel level, const char *frmt, ...)
{
	char msg[1024];
	int len = 0;
	
	/* timestamp */
	len += sprintf(msg, "%014.3f ", utc);
	time_t now = (time_t)utc;
	if (now == 0)
		now = time(NULL);
	struct tm *t = localtime(&now);
	len += strftime(msg + len, sizeof(msg) - len, "%d-%m-%Y %H:%M:%S ", t);
	
	/* level */
	len += snprintf(msg + len, sizeof(msg) - len, "%s: ", levels[level]);
	
	/* message */
	va_list args;
	va_start(args, frmt);
	len += vsnprintf(msg + len, sizeof(msg) - len, frmt, args);
	va_end(args);
	
	/* newline */
	len = MIN(len, sizeof(msg) - 3);
	msg[len++] = '\r';
	msg[len++] = '\n';
	
	/* string terminator */
	msg[len] = '\0';

	/* rotate log file based on current date */
	rotate(l, now);
	
	/* write to log file */
	if ((level <= l->level) && (l->fd >= 0))
		write(l->fd, msg, len);
	
	/* display message */
	SetCtrlVal(l->panel, LOGGING_LOGGING, msg);
	
	/* report error */
	if (level == ERROR)
		l->onerror(level, msg);
}


void __logger_panel_visible(struct logger *l, int visible)
{
	SetPanelAttribute(l->panel, ATTR_VISIBLE, visible);
}