// server-side logging of events
#include "cube.h"
#if !defined(WIN32) && !defined(__APPLE__)
#include <syslog.h>
#include <signal.h>
#define AC_USE_SYSLOG
static const int facilities[] = { LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7 };
static const int levels[] = { LOG_DEBUG, LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR };
#else
static const int levels[] = { 7, 7, 6, 4, 3 };
ENetSocket logsock = ENET_SOCKET_NULL;
ENetAddress logdest = { ENET_HOST_ANY, 514 };
#endif
#define ACLOG_LIMIT (2 * 1024 * 1024) // 2 MiB
static const char *levelprefix[] = { "", "", "", "WARNING: ", "ERROR: " };
static const char *levelname[] = { "DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR", "DISABLED" };
static FILE *fp = NULL;
static string filepath, ident, ident_full;
static int facility = -1,
#ifdef AC_USE_SYSLOG_DISABLE
filethreshold = ACLOG_NUM,
syslogthreshold = ACLOG_INFO,
#else
filethreshold = ACLOG_INFO,
syslogthreshold = ACLOG_NUM,
#endif
consolethreshold = ACLOG_INFO;
static bool timestamp = false, enabled = false;
bool initlogging(const char *identity, int facility_, int consolethres, int filethres, int syslogthres, bool logtimestamp)
{
facility = facility_ & 7;
timestamp = logtimestamp;
if(consolethres >= 0) consolethreshold = min(consolethres, (int)ACLOG_NUM);
if(filethres >= 0) filethreshold = min(filethres, (int)ACLOG_NUM);
if(syslogthres >= 0) syslogthreshold = min(syslogthres, (int)ACLOG_NUM);
if(ident != identity)
copystring(ident, identity);
formatstring(ident_full)("ACR[%s]", identity);
if(syslogthreshold < ACLOG_NUM)
{
#ifdef AC_USE_SYSLOG
openlog(ident_full, LOG_NDELAY, facilities[facility]);
#else
if((logsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM)) == ENET_SOCKET_NULL || enet_address_set_host(&logdest, "localhost") < 0) syslogthreshold = ACLOG_NUM;
#endif
}
static int lognum = 0;
formatstring(filepath)("serverlog_%s_%s.part%d.txt", timestring(true), identity, ++lognum);
if(fp) { fclose(fp); fp = NULL; }
if(filethreshold < ACLOG_NUM)
{
fp = fopen(filepath, "w");
if(!fp) printf("failed to open \"%s\" for writing\n", filepath);
}
defformatstring(msg)("logging started: console(%s), file(%s", levelname[consolethreshold], levelname[fp ? filethreshold : ACLOG_NUM]);
if(fp) concatformatstring(msg, ", \"%s\"", filepath);
concatformatstring(msg, "), syslog(%s", levelname[syslogthreshold]);
if(syslogthreshold < ACLOG_NUM) concatformatstring(msg, ", \"%s\", local%d", ident_full, facility);
concatformatstring(msg, "), timestamp(%s)", timestamp ? "ENABLED" : "DISABLED");
enabled = consolethreshold < ACLOG_NUM || fp || syslogthreshold < ACLOG_NUM;
if(enabled) printf("%s\n", msg);
return enabled;
}
void exitlogging()
{
if(fp) { fclose(fp); fp = NULL; }
#ifdef AC_USE_SYSLOG
if(syslogthreshold < ACLOG_NUM) closelog();
#endif
syslogthreshold = ACLOG_NUM;
enabled = false;
}
bool logline(int level, const char *msg, ...)
{
if(!enabled) return false;
if(level < 0 || level >= ACLOG_NUM) return false;
static int flogsz = 0;
defvformatstring(sf, msg, msg);
filtertext(sf, sf, 2);
const char *ts = timestamp ? timestring(true, "%b %d %Y %H:%M:%S ") : "", *ld = levelprefix[level];
char *p, *l = sf;
do
{ // break into single lines first
if((p = strchr(l, '\n'))) *p = '\0';
if(consolethreshold <= level) printf("%s%s%s\n", ts, ld, l);
if(fp && filethreshold <= level) flogsz += max(0, fprintf(fp, "%s%s%s\n", ts, ld, l));
if(syslogthreshold <= level)
#ifdef AC_USE_SYSLOG
syslog(levels[level], "%s", l);
#else
{
defformatstring(text)("<%d>%s: %s", (16 + facility) * 8 + levels[level], ident_full, l); // no TIMESTAMP, no hostname: syslog will add this
ENetBuffer buf;
buf.data = text;
buf.dataLength = strlen(text);
enet_socket_send(logsock, &logdest, &buf, 1);
}
#endif
l = p + 1;
}
while(p);
if(consolethreshold <= level) fflush(stdout);
if(fp && filethreshold <= level)
{
fflush(fp);
// reset log if it's too big
if(flogsz >= ACLOG_LIMIT)
{
initlogging(ident, facility, consolethreshold, filethreshold, syslogthreshold, timestamp);
flogsz = 0;
}
}
return consolethreshold <= level;
}
Advertisement
153
pages
Log.cpp
Advertisement