WIP: Rework logging #48

Draft
Levitating wants to merge 2 commits from Levitating/Cytoplasm:log into master
2 changed files with 62 additions and 63 deletions
Showing only changes of commit 36575b947f - Show all commits

View file

@ -46,6 +46,7 @@
#define LOG_FLAG_COLOR (1 << 0) #define LOG_FLAG_COLOR (1 << 0)
#define LOG_FLAG_SYSLOG (1 << 1) #define LOG_FLAG_SYSLOG (1 << 1)
#define LOG_FLAG_STDOUT (1 << 2)
/** /**
* A log is defined as a configuration that describes the properties * A log is defined as a configuration that describes the properties
@ -110,15 +111,9 @@ extern void LogConfigUnindent(LogConfig *);
extern void LogConfigIndentSet(LogConfig *, size_t); extern void LogConfigIndentSet(LogConfig *, size_t);
/** /**
* Set the file stream that logging output should be written to. This * Set the file stream that logging output should be written to.
* defaults to standard output, but it can be set to standard error,
* or any other arbitrary stream. Passing a NULL value for the stream
* pointer sets the log output to the standard output. Note that the
* output stream is only used if
* .Va LOG_FLAG_SYSLOG
* is not set.
*/ */
extern void LogConfigOutputSet(LogConfig *, Stream *); extern void LogConfigFileSet(LogConfig *, Stream *);
/** /**
* Set a number of boolean options on a log configuration. This * Set a number of boolean options on a log configuration. This
@ -135,12 +130,7 @@ extern void LogConfigOutputSet(LogConfig *, Stream *);
* is checked before writing any terminal sequences. * is checked before writing any terminal sequences.
* .It LOG_FLAG_SYSLOG * .It LOG_FLAG_SYSLOG
* When set, log output to the syslog using * When set, log output to the syslog using
* .Xr syslog 3 , * .Xr syslog 3
* instead of logging to the file set by
* .Fn LogConfigOutputSet .
* This flag always overrides the stream set by that function,
* regardless of when it was set, even if it was set after this flag
* was set.
* .El * .El
*/ */
extern void LogConfigFlagSet(LogConfig *, int); extern void LogConfigFlagSet(LogConfig *, int);

107
src/Log.c
View file

@ -26,6 +26,7 @@
#include <Memory.h> #include <Memory.h>
#include <Util.h> #include <Util.h>
#include <cstdarg>
Levitating marked this conversation as resolved Outdated
Outdated
Review

I think you meant stdarg.h, as those kind of includes are C++isms.

I think you meant stdarg.h, as those kind of includes are C++isms.

It was most likely automatically added by my IDE by accident.

It was most likely automatically added by my IDE by accident.
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
@ -39,7 +40,7 @@ struct LogConfig
{ {
int level; int level;
size_t indent; size_t indent;
Stream *out; Stream *file;
int flags; int flags;
char *tsFmt; char *tsFmt;
@ -65,8 +66,8 @@ LogConfigCreate(void)
LogConfigLevelSet(config, LOG_INFO); LogConfigLevelSet(config, LOG_INFO);
LogConfigIndentSet(config, 0); LogConfigIndentSet(config, 0);
LogConfigOutputSet(config, NULL); /* Will set to stdout */ LogConfigFileSet(config, NULL);
LogConfigFlagSet(config, LOG_FLAG_COLOR); LogConfigFlagSet(config, LOG_FLAG_COLOR | LOG_FLAG_STDOUT);
LogConfigTimeStampFormatSet(config, "%y-%m-%d %H:%M:%S"); LogConfigTimeStampFormatSet(config, "%y-%m-%d %H:%M:%S");
return config; return config;
@ -185,20 +186,20 @@ LogConfigLevelSet(LogConfig * config, int level)
} }
void void
LogConfigOutputSet(LogConfig * config, Stream * out) LogConfigFileSet(LogConfig * config, Stream * file)
{ {
if (!config) if (!config)
{ {
return; return;
} }
if (out) if (file)
{ {
config->out = out; config->file = file;
} }
else else
{ {
config->out = StreamStdout(); config->file = StreamStdout();
} }
} }
@ -222,42 +223,14 @@ LogConfigUnindent(LogConfig * config)
} }
void void
Levitating marked this conversation as resolved Outdated
Outdated
Review

I'd probably consider making LogPrint static here, as it's not even part of the public includes.

I'd probably consider making LogPrint static here, as it's not even part of the public includes.

Yes it should be static!

Yes it should be static!
Logv(LogConfig * config, int level, const char *msg, va_list argp) LogPrint(Stream * stream, LogConfig * config, int level, const char *msg, va_list argp)
{ {
size_t i; size_t i;
int doColor; int doColor;
char indicator; char indicator;
/*
* Only proceed if we have a config and its log level is set to a
* value that permits us to log. This is as close as we can get
* to a no-op function if we aren't logging anything, without doing
* some crazy macro magic.
*/
if (!config || level > config->level)
{
return;
}
/* Misconfiguration */
if (!config->out)
{
return;
}
pthread_mutex_lock(&config->lock);
if (LogConfigFlagGet(config, LOG_FLAG_SYSLOG))
{
/* No further print logic is needed; syslog will handle it all
* for us. */
vsyslog(level, msg, argp);
pthread_mutex_unlock(&config->lock);
return;
}
doColor = LogConfigFlagGet(config, LOG_FLAG_COLOR) doColor = LogConfigFlagGet(config, LOG_FLAG_COLOR)
&& isatty(StreamFileno(config->out)); && isatty(StreamFileno(stream));
if (doColor) if (doColor)
{ {
@ -293,10 +266,10 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp)
break; break;
} }
StreamPuts(config->out, ansi); StreamPuts(stream, ansi);
} }
StreamPutc(config->out, '['); StreamPutc(stream, '[');
if (config->tsFmt) if (config->tsFmt)
{ {
@ -309,15 +282,15 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp)
if (tsLength) if (tsLength)
{ {
StreamPuts(config->out, tsBuffer); StreamPuts(stream, tsBuffer);
if (!isspace((unsigned char) tsBuffer[tsLength - 1])) if (!isspace((unsigned char) tsBuffer[tsLength - 1]))
{ {
StreamPutc(config->out, ' '); StreamPutc(stream, ' ');
} }
} }
} }
StreamPrintf(config->out, "(%lu) ", UtilThreadNo()); StreamPrintf(stream, "(%lu) ", UtilThreadNo());
switch (level) switch (level)
{ {
@ -350,24 +323,60 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp)
break; break;
} }
StreamPrintf(config->out, "%c]", indicator); StreamPrintf(stream, "%c]", indicator);
if (doColor) if (doColor)
{ {
/* ANSI Reset */ /* ANSI Reset */
StreamPuts(config->out, "\033[0m"); StreamPuts(stream, "\033[0m");
} }
StreamPutc(config->out, ' '); StreamPutc(stream, ' ');
for (i = 0; i < config->indent; i++) for (i = 0; i < config->indent; i++)
{ {
StreamPutc(config->out, ' '); StreamPutc(config->file, ' ');
} }
StreamVprintf(config->out, msg, argp); StreamVprintf(stream, msg, argp);
StreamPutc(config->out, '\n'); StreamPutc(stream, '\n');
StreamFlush(config->out); StreamFlush(stream);
}
void
Logv(LogConfig * config, int level, const char *msg, va_list argp)
{
/*
* Only proceed if we have a config and its log level is set to a
* value that permits us to log. This is as close as we can get
* to a no-op function if we aren't logging anything, without doing
* some crazy macro magic.
*/
if (!config || level > config->level)
{
return;
}
/* Misconfiguration */
if (!config->file)
{
return;
}
pthread_mutex_lock(&config->lock);
if (LogConfigFlagGet(config, LOG_FLAG_SYSLOG))
{
vsyslog(level, msg, argp);
}
if (LogConfigFlagGet(config, LOG_FLAG_STDOUT)) {
LogPrint(StreamStdout(), config, level, msg, argp);
}
if (config->file) {
LogPrint(config->file, config, level, msg, argp);
}
pthread_mutex_unlock(&config->lock); pthread_mutex_unlock(&config->lock);
} }