1
0
mirror of https://gitlab.xiph.org/xiph/icecast-common.git synced 2024-12-04 14:46:31 -05:00
icecast-common/src/logmsg.c

205 lines
5.8 KiB
C
Raw Normal View History

/* Icecast
*
* This program is distributed under the GNU General Public License, version 2.
* A copy of this license is included with this source.
*
* Copyright 2019, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <igloo/logmsg.h>
#include <igloo/interface.h>
#include <igloo/objecthandler.h>
#include <igloo/io.h>
#include "private.h"
#define LOG_MAXLINELEN 1024
struct igloo_logmsg_tag {
igloo_ro_base_t __base;
char *msgid;
char *cat;
char *func;
char *codefile;
ssize_t codeline;
struct timespec ts;
igloo_loglevel_t level;
igloo_logmsg_opt_t options;
igloo_list_t *referenced;
char *string;
};
static void __free(igloo_ro_t self)
{
igloo_logmsg_t *logmsg = igloo_RO_TO_TYPE(self, igloo_logmsg_t);
free(logmsg->msgid);
free(logmsg->cat);
free(logmsg->func);
free(logmsg->codefile);
free(logmsg->string);
igloo_ro_unref(logmsg->referenced);
}
igloo_RO_PUBLIC_TYPE(igloo_logmsg_t,
igloo_RO_TYPEDECL_FREE(__free)
);
igloo_logmsg_t * igloo_logmsg_new(const char *name, igloo_ro_t associated,
const char *msgid,
const char *cat,
const char *func, const char *codefile, const ssize_t codeline,
const struct timespec * ts,
igloo_loglevel_t level, igloo_logmsg_opt_t options,
igloo_list_t *referenced,
const char *format, ...)
{
igloo_logmsg_t *logmsg = igloo_ro_new_raw(igloo_logmsg_t, name, associated);
va_list ap;
char string[LOG_MAXLINELEN];
if (!logmsg)
return NULL;
logmsg->codeline = codeline;
logmsg->level = level;
logmsg->options = options;
va_start(ap, format);
igloo_private__vsnprintf(string, sizeof(string), format, ap);
va_end(ap);
do {
#define __set_str(x) \
if (x) { \
logmsg->x = strdup((x)); \
if (!logmsg->x) \
break; \
}
__set_str(msgid);
__set_str(cat);
__set_str(func);
__set_str(codefile);
logmsg->string = strdup(string);
if (!logmsg->string)
break;
if (ts) {
logmsg->ts = *ts;
} else {
if (clock_gettime(CLOCK_REALTIME, &(logmsg->ts)) != 0)
break;
}
if (referenced) {
if (igloo_ro_ref(referenced) != 0)
break;
logmsg->referenced = referenced;
}
return logmsg;
} while (0);
igloo_ro_unref(logmsg);
return NULL;
}
int igloo_logmsg_get_context(igloo_logmsg_t *msg, const char **msgid, const char **cat, const char **func, const char **codefile, const ssize_t *codeline, struct timespec **ts);
int igloo_logmsg_get_message(igloo_logmsg_t *msg, igloo_loglevel_t *level, const char **string);
int igloo_logmsg_get_extra(igloo_logmsg_t *msg, igloo_logmsg_opt_t *options, igloo_list_t **list);
static const char * __level2str(igloo_loglevel_t level)
{
switch (level) {
case IGLOO_LOGLEVEL__ERROR: return "<<<ERROR>>>"; break;
case IGLOO_LOGLEVEL__NONE: return "NONE"; break;
case IGLOO_LOGLEVEL_ERROR: return "EROR"; break;
case IGLOO_LOGLEVEL_WARN: return "WARN"; break;
case IGLOO_LOGLEVEL_INFO: return "INFO"; break;
case IGLOO_LOGLEVEL_DEBUG: return "DBUG"; break;
}
return "<<<unknowm log level>>>";
}
static igloo_filter_result_t __handle(igloo_INTERFACE_BASIC_ARGS, igloo_ro_t object)
{
igloo_logmsg_t *msg = igloo_RO_TO_TYPE(object, igloo_logmsg_t);
const char *level = NULL;
time_t now;
char pre[256+LOG_MAXLINELEN];
int datelen;
2019-07-06 14:28:39 -04:00
char flags[3] = " ";
if (!msg)
return igloo_FILTER_RESULT_DROP;
2019-07-06 14:28:39 -04:00
if (msg->options & igloo_LOGMSG_OPT_DEVEL)
flags[0] = 'D';
if (msg->options & igloo_LOGMSG_OPT_ASKACK)
flags[1] = 'A';
level = __level2str(msg->level);
now = msg->ts.tv_sec;
datelen = strftime(pre, sizeof(pre), "[%Y-%m-%d %H:%M:%S]", localtime(&now));
2019-07-06 14:28:39 -04:00
snprintf(pre+datelen, sizeof(pre)-datelen, " %s [%s] %s/%s(%s:%zi) %s\n", level, flags, msg->cat, msg->func, msg->codefile, msg->codeline, msg->string);
igloo_io_write(igloo_RO_TO_TYPE(*backend_object, igloo_io_t), pre, strlen(pre));
return igloo_FILTER_RESULT_PASS;
}
static const igloo_objecthandler_ifdesc_t igloo_logmsg_formarter_ifdesc = {
igloo_INTERFACE_DESCRIPTION_BASE(igloo_objecthandler_ifdesc_t),
.is_thread_safe = 1,
.handle = __handle
};
typedef enum {
igloo_FST_NORMAL
} igloo_logmsg_formarter_subtype_t;
igloo_objecthandler_t * igloo_logmsg_formarter(igloo_ro_t backend, const char *subformat, const char *name, igloo_ro_t associated)
{
igloo_logmsg_formarter_subtype_t *sf = NULL;
igloo_objecthandler_t *objecthandler;
if (!igloo_RO_IS_VALID(backend, igloo_io_t))
return NULL;
if (!subformat || strcmp(subformat, "default") == 0)
subformat = "normal";
if (strcmp(subformat, "normal") == 0) {
sf = malloc(sizeof(*sf));
if (!sf)
return NULL;
*sf = igloo_FST_NORMAL;
} else {
return NULL;
}
objecthandler = igloo_objecthandler_new(&igloo_logmsg_formarter_ifdesc, backend, sf, name, associated);
if (!objecthandler) {
free(sf);
}
return objecthandler;
}
igloo_filter_t * igloo_logmsg_filter(igloo_loglevel_t level_min, igloo_loglevel_t level_max, igloo_logmsg_opt_t options_required, igloo_logmsg_opt_t options_absent, const struct timespec * ts_min, const struct timespec * ts_max, const char *cat, const char *name, igloo_ro_t associated);