aboutsummaryrefslogtreecommitdiffstats
path: root/src/Log.cxx
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-09-27 22:31:24 +0200
committerMax Kellermann <max@duempel.org>2013-10-02 08:57:55 +0200
commit060814daa83f6a94f5934464ae42a406c5c7e947 (patch)
treef636ec6cdbb8e52fda6db987d2a28fc73c7b94b4 /src/Log.cxx
parentc53492a76a8a05825e1c7f699c05645eee891199 (diff)
downloadmpd-060814daa83f6a94f5934464ae42a406c5c7e947.tar.gz
mpd-060814daa83f6a94f5934464ae42a406c5c7e947.tar.xz
mpd-060814daa83f6a94f5934464ae42a406c5c7e947.zip
Log: new logging library API
Prepare to migrate away from GLib. Currently, we're still using GLib as a backend.
Diffstat (limited to '')
-rw-r--r--src/Log.cxx345
1 files changed, 90 insertions, 255 deletions
diff --git a/src/Log.cxx b/src/Log.cxx
index 869327d25..f36e68133 100644
--- a/src/Log.cxx
+++ b/src/Log.cxx
@@ -18,7 +18,7 @@
*/
#include "config.h"
-#include "Log.hxx"
+#include "LogV.hxx"
#include "ConfigData.hxx"
#include "ConfigGlobal.hxx"
#include "ConfigOption.hxx"
@@ -30,322 +30,157 @@
#include "util/Domain.hxx"
#include "system/FatalError.hxx"
+#include <glib.h>
+
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
-#include <stdarg.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
-#include <glib.h>
-
-#ifdef HAVE_SYSLOG
-#include <syslog.h>
-#endif
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "log"
-#define LOG_LEVEL_SECURE G_LOG_LEVEL_INFO
-
-#define LOG_DATE_BUF_SIZE 16
-#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
-
-static constexpr Domain log_domain("log");
-
-static GLogLevelFlags log_threshold = G_LOG_LEVEL_MESSAGE;
+static GLogLevelFlags
+ToGLib(LogLevel level)
+{
+ switch (level) {
+ case LogLevel::DEBUG:
+ return G_LOG_LEVEL_DEBUG;
-static const char *log_charset;
+ case LogLevel::INFO:
+ return G_LOG_LEVEL_MESSAGE;
-static bool stdout_mode = true;
-static int out_fd;
-static Path out_path = Path::Null();
+ case LogLevel::WARNING:
+ case LogLevel::ERROR:
+ return G_LOG_LEVEL_WARNING;
+ }
-static void redirect_logs(int fd)
-{
- assert(fd >= 0);
- if (dup2(fd, STDOUT_FILENO) < 0)
- FatalSystemError("Failed to dup2 stdout");
- if (dup2(fd, STDERR_FILENO) < 0)
- FatalSystemError("Failed to dup2 stderr");
+ assert(false);
+ gcc_unreachable();
}
-static const char *log_date(void)
+void
+Log(const Domain &domain, LogLevel level, const char *msg)
{
- static char buf[LOG_DATE_BUF_SIZE];
- time_t t = time(NULL);
- strftime(buf, LOG_DATE_BUF_SIZE, "%b %d %H:%M : ", localtime(&t));
- return buf;
+ g_log(domain.GetName(), ToGLib(level), "%s", msg);
}
-/**
- * Determines the length of the string excluding trailing whitespace
- * characters.
- */
-static int
-chomp_length(const char *p)
+void
+LogFormatV(const Domain &domain, LogLevel level, const char *fmt, va_list ap)
{
- size_t length = strlen(p);
-
- while (length > 0 && g_ascii_isspace(p[length - 1]))
- --length;
-
- return (int)length;
+ g_logv(domain.GetName(), ToGLib(level), fmt, ap);
}
-static void
-file_log_func(const gchar *domain,
- GLogLevelFlags log_level,
- const gchar *message, gcc_unused gpointer user_data)
+void
+LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...)
{
- char *converted;
-
- if (log_level > log_threshold)
- return;
-
- if (log_charset != NULL) {
- converted = g_convert_with_fallback(message, -1,
- log_charset, "utf-8",
- NULL, NULL, NULL, NULL);
- if (converted != NULL)
- message = converted;
- } else
- converted = NULL;
-
- if (domain == nullptr)
- domain = "";
-
- fprintf(stderr, "%s%s%s%.*s\n",
- stdout_mode ? "" : log_date(),
- domain, *domain == 0 ? "" : ": ",
- chomp_length(message), message);
-
- g_free(converted);
+ va_list ap;
+ va_start(ap, fmt);
+ LogFormatV(domain, level, fmt, ap);
+ va_end(ap);
}
-static void
-log_init_stdout(void)
+void
+FormatDebug(const Domain &domain, const char *fmt, ...)
{
- g_log_set_default_handler(file_log_func, NULL);
+ va_list ap;
+ va_start(ap, fmt);
+ LogFormatV(domain, LogLevel::DEBUG, fmt, ap);
+ va_end(ap);
}
-static int
-open_log_file(void)
+void
+FormatInfo(const Domain &domain, const char *fmt, ...)
{
- assert(!out_path.IsNull());
-
- return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
+ va_list ap;
+ va_start(ap, fmt);
+ LogFormatV(domain, LogLevel::INFO, fmt, ap);
+ va_end(ap);
}
-static bool
-log_init_file(unsigned line, Error &error)
+void
+FormatWarning(const Domain &domain, const char *fmt, ...)
{
- assert(!out_path.IsNull());
-
- out_fd = open_log_file();
- if (out_fd < 0) {
- const std::string out_path_utf8 = out_path.ToUTF8();
- error.FormatErrno("failed to open log file \"%s\" (config line %u)",
- out_path_utf8.c_str(), line);
- return false;
- }
-
- g_log_set_default_handler(file_log_func, NULL);
- return true;
+ va_list ap;
+ va_start(ap, fmt);
+ LogFormatV(domain, LogLevel::WARNING, fmt, ap);
+ va_end(ap);
}
-#ifdef HAVE_SYSLOG
-
-static int
-glib_to_syslog_level(GLogLevelFlags log_level)
+void
+FormatError(const Domain &domain, const char *fmt, ...)
{
- switch (log_level & G_LOG_LEVEL_MASK) {
- case G_LOG_LEVEL_ERROR:
- case G_LOG_LEVEL_CRITICAL:
- return LOG_ERR;
-
- case G_LOG_LEVEL_WARNING:
- return LOG_WARNING;
-
- case G_LOG_LEVEL_MESSAGE:
- return LOG_NOTICE;
-
- case G_LOG_LEVEL_INFO:
- return LOG_INFO;
-
- case G_LOG_LEVEL_DEBUG:
- return LOG_DEBUG;
-
- default:
- return LOG_NOTICE;
- }
+ va_list ap;
+ va_start(ap, fmt);
+ LogFormatV(domain, LogLevel::ERROR, fmt, ap);
+ va_end(ap);
}
-static void
-syslog_log_func(const gchar *domain,
- GLogLevelFlags log_level, const gchar *message,
- gcc_unused gpointer user_data)
+void
+LogError(const Error &error)
{
- if (stdout_mode) {
- /* fall back to the file log function during
- startup */
- file_log_func(domain, log_level,
- message, user_data);
- return;
- }
-
- if (log_level > log_threshold)
- return;
-
- if (domain == nullptr)
- domain = "";
-
- syslog(glib_to_syslog_level(log_level), "%s%s%.*s",
- domain, *domain == 0 ? "" : ": ",
- chomp_length(message), message);
+ Log(error.GetDomain(), LogLevel::ERROR, error.GetMessage());
}
-static void
-log_init_syslog(void)
+void
+LogError(const Error &error, const char *msg)
{
- assert(out_path.IsNull());
-
- openlog(PACKAGE, 0, LOG_DAEMON);
- g_log_set_default_handler(syslog_log_func, NULL);
+ LogFormat(error.GetDomain(), LogLevel::ERROR, "%s: %s",
+ msg, error.GetMessage());
}
-#endif
-
-static inline GLogLevelFlags
-parse_log_level(const char *value, unsigned line)
+void
+FormatError(const Error &error, const char *fmt, ...)
{
- if (0 == strcmp(value, "default"))
- return G_LOG_LEVEL_MESSAGE;
- if (0 == strcmp(value, "secure"))
- return LOG_LEVEL_SECURE;
- else if (0 == strcmp(value, "verbose"))
- return G_LOG_LEVEL_DEBUG;
- else {
- FormatFatalError("unknown log level \"%s\" at line %u",
- value, line);
- return G_LOG_LEVEL_MESSAGE;
- }
+ char msg[1024];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+
+ LogError(error, msg);
}
void
-log_early_init(bool verbose)
+LogErrno(const Domain &domain, int e, const char *msg)
{
- if (verbose)
- log_threshold = G_LOG_LEVEL_DEBUG;
-
- log_init_stdout();
+ LogFormat(domain, LogLevel::ERROR, "%s: %s", msg, g_strerror(e));
}
-bool
-log_init(bool verbose, bool use_stdout, Error &error)
+void
+LogErrno(const Domain &domain, const char *msg)
{
- const struct config_param *param;
-
- g_get_charset(&log_charset);
-
- if (verbose)
- log_threshold = G_LOG_LEVEL_DEBUG;
- else if ((param = config_get_param(CONF_LOG_LEVEL)) != NULL)
- log_threshold = parse_log_level(param->value, param->line);
-
- if (use_stdout) {
- log_init_stdout();
- return true;
- } else {
- param = config_get_param(CONF_LOG_FILE);
- if (param == NULL) {
-#ifdef HAVE_SYSLOG
- /* no configuration: default to syslog (if
- available) */
- log_init_syslog();
- return true;
-#else
- error.Set(log_domain,
- "config parameter 'log_file' not found");
- return false;
-#endif
-#ifdef HAVE_SYSLOG
- } else if (strcmp(param->value, "syslog") == 0) {
- log_init_syslog();
- return true;
-#endif
- } else {
- out_path = config_get_path(CONF_LOG_FILE, error);
- return !out_path.IsNull() &&
- log_init_file(param->line, error);
- }
- }
+ LogErrno(domain, errno, msg);
}
static void
-close_log_files(void)
+FormatErrnoV(const Domain &domain, int e, const char *fmt, va_list ap)
{
- if (stdout_mode)
- return;
+ char msg[1024];
+ vsnprintf(msg, sizeof(msg), fmt, ap);
-#ifdef HAVE_SYSLOG
- if (out_path.IsNull())
- closelog();
-#endif
+ LogErrno(domain, e, msg);
}
void
-log_deinit(void)
+FormatErrno(const Domain &domain, int e, const char *fmt, ...)
{
- close_log_files();
- out_path = Path::Null();
+ va_list ap;
+ va_start(ap, fmt);
+ FormatErrnoV(domain, e, fmt, ap);
+ va_end(ap);
}
-
-void setup_log_output(bool use_stdout)
-{
- fflush(NULL);
- if (!use_stdout) {
-#ifndef WIN32
- if (out_path.IsNull())
- out_fd = open("/dev/null", O_WRONLY);
-#endif
-
- if (out_fd >= 0) {
- redirect_logs(out_fd);
- close(out_fd);
- }
-
- stdout_mode = false;
- log_charset = NULL;
- }
-}
-
-int cycle_log_files(void)
+void
+FormatErrno(const Domain &domain, const char *fmt, ...)
{
- int fd;
-
- if (stdout_mode || out_path.IsNull())
- return 0;
-
- assert(!out_path.IsNull());
-
- g_debug("Cycling log files...\n");
- close_log_files();
-
- fd = open_log_file();
- if (fd < 0) {
- const std::string out_path_utf8 = out_path.ToUTF8();
- g_warning("error re-opening log file: %s",
- out_path_utf8.c_str());
- return -1;
- }
+ const int e = errno;
- redirect_logs(fd);
- g_debug("Done cycling log files\n");
- return 0;
+ va_list ap;
+ va_start(ap, fmt);
+ FormatErrnoV(domain, e, fmt, ap);
+ va_end(ap);
}