- Add new logging system, supports logging to stdout/stderr and optionally logfile and system log (syslog on unix, windows event log on win32)
This commit is contained in:
parent
3b0cc0e0dc
commit
d22da7e24e
|
@ -0,0 +1,73 @@
|
||||||
|
/* GKrellM
|
||||||
|
| Copyright (C) 1999-2008 Bill Wilson
|
||||||
|
|
|
||||||
|
| Author: Bill Wilson billw@gkrellm.net
|
||||||
|
| Latest versions might be found at: http://gkrellm.net
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| GKrellM is free software: you can redistribute it and/or modify it
|
||||||
|
| under the terms of the GNU General Public License as published by
|
||||||
|
| the Free Software Foundation, either version 3 of the License, or
|
||||||
|
| (at your option) any later version.
|
||||||
|
|
|
||||||
|
| GKrellM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
| License for more details.
|
||||||
|
|
|
||||||
|
| You should have received a copy of the GNU General Public License
|
||||||
|
| along with this program. If not, see http://www.gnu.org/licenses/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GK_LOG_P_H
|
||||||
|
#define GK_LOG_P_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef void (*GkrellmLogFunc) (GLogLevelFlags log_level, const gchar *message);
|
||||||
|
typedef gboolean (*GkrellmLogInitFunc) (void);
|
||||||
|
typedef gboolean (*GkrellmLogCleanupFunc) (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs a log handler and adds default logging behaviour.
|
||||||
|
*
|
||||||
|
* All GLib log functions and macros (i..e g_log(), g_debug(), g_warning() etc)
|
||||||
|
* are handled by our log handler from now on
|
||||||
|
**/
|
||||||
|
void gkrellm_log_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes our log handler reverting to default GLib log behaviour.
|
||||||
|
**/
|
||||||
|
void gkrellm_log_cleanup(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers another log function.
|
||||||
|
*
|
||||||
|
* Calls function @p init if it's not NULL and registers function @p log if
|
||||||
|
* the (optional) call to @p init was successful.
|
||||||
|
*
|
||||||
|
* @note This is mainly used by gkrellmd to register an additional
|
||||||
|
* syslog handler.
|
||||||
|
**/
|
||||||
|
gboolean gkrellm_log_register(
|
||||||
|
GkrellmLogFunc log,
|
||||||
|
GkrellmLogInitFunc init,
|
||||||
|
GkrellmLogCleanupFunc cleanup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a log function
|
||||||
|
*
|
||||||
|
* Also calls the GkrellmLogCleanupFunc passed together with @p log
|
||||||
|
* in gkrellm_log_register().
|
||||||
|
**/
|
||||||
|
gboolean gkrellm_log_unregister(GkrellmLogFunc log);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables logging into a file
|
||||||
|
*
|
||||||
|
* @param filename path to logfile or NULL to disable logging into a file
|
||||||
|
**/
|
||||||
|
void gkrellm_log_set_filename(const gchar* filename);
|
||||||
|
|
||||||
|
#endif //GK_LOG_P_H
|
|
@ -0,0 +1,291 @@
|
||||||
|
/* GKrellM
|
||||||
|
| Copyright (C) 1999-2008 Bill Wilson
|
||||||
|
|
|
||||||
|
| Author: Stefan Gehn stefan.gkrellm@srcbox.net
|
||||||
|
| Latest versions might be found at: http://gkrellm.net
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| GKrellM is free software: you can redistribute it and/or modify it
|
||||||
|
| under the terms of the GNU General Public License as published by
|
||||||
|
| the Free Software Foundation, either version 3 of the License, or
|
||||||
|
| (at your option) any later version.
|
||||||
|
|
|
||||||
|
| GKrellM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
| License for more details.
|
||||||
|
|
|
||||||
|
| You should have received a copy of the GNU General Public License
|
||||||
|
| along with this program. If not, see http://www.gnu.org/licenses/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Wanted logic:
|
||||||
|
|
||||||
|
- g_print for user-visible messages, --version and --help fall into this category.
|
||||||
|
g_print usage should be kept at a minimum because
|
||||||
|
gkrellm is a gui-app, while gkrellmd is a daemon. Neither of them is suited
|
||||||
|
for terminal-interaction.
|
||||||
|
|
||||||
|
- gkrellm_debug(DEBUG_FOO, "msg"); for all debug messages.
|
||||||
|
|
||||||
|
- g_warning("msg") for all failed function calls etc.
|
||||||
|
|
||||||
|
Output should go to:
|
||||||
|
- g_print : gui-window or stdout where applicable
|
||||||
|
- gkrellm_debug : gui-window or logfile if set
|
||||||
|
- gkrellm_warning: gui-window or logfile if set
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "log-private.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#if !defined(WIN32)
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif // !WIN32
|
||||||
|
|
||||||
|
// Include gkrellm headers to access _GK struct inside gkrellm_debug()
|
||||||
|
#if defined(GKRELLM_SERVER)
|
||||||
|
#include "../server/gkrellmd.h"
|
||||||
|
#include "../server/gkrellmd-private.h"
|
||||||
|
#else
|
||||||
|
#include "../src/gkrellm.h"
|
||||||
|
#include "../src/gkrellm-private.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _GkrellmLogFacility
|
||||||
|
{
|
||||||
|
GkrellmLogFunc log;
|
||||||
|
GkrellmLogCleanupFunc cleanup;
|
||||||
|
} GkrellmLogFacility;
|
||||||
|
|
||||||
|
static GPtrArray *s_log_facility_ptr_array = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Logging into a logfile
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle to a logfile.
|
||||||
|
* Set by gkrellm_log_set_filename() and used by gkrellm_log_to_file()
|
||||||
|
**/
|
||||||
|
static FILE *s_gkrellm_logfile = NULL;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gkrellm_log_file_cleanup()
|
||||||
|
{
|
||||||
|
if (s_gkrellm_logfile)
|
||||||
|
fclose(s_gkrellm_logfile);
|
||||||
|
s_gkrellm_logfile = NULL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gkrellm_log_file_log(GLogLevelFlags log_level, const gchar *message)
|
||||||
|
{
|
||||||
|
time_t raw_time;
|
||||||
|
char *local_time_str;
|
||||||
|
|
||||||
|
if (!s_gkrellm_logfile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Prepend log message with current date/time
|
||||||
|
time(&raw_time);
|
||||||
|
local_time_str = ctime(&raw_time);
|
||||||
|
local_time_str[24] = ' '; // overwrite newline with space
|
||||||
|
fputs(local_time_str, s_gkrellm_logfile);
|
||||||
|
|
||||||
|
fputs(message, s_gkrellm_logfile);
|
||||||
|
fflush(s_gkrellm_logfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gkrellm_log_set_filename(const gchar* filename)
|
||||||
|
{
|
||||||
|
// Remove from logging chain if we already had been registered before
|
||||||
|
// This also cleans up an open logfile.
|
||||||
|
gkrellm_log_unregister(gkrellm_log_file_log);
|
||||||
|
|
||||||
|
if (filename && filename[0] != '\0')
|
||||||
|
{
|
||||||
|
// Open the file to log into
|
||||||
|
s_gkrellm_logfile = fopen(filename, "at");
|
||||||
|
// Add our callbacks to logging chain
|
||||||
|
if (s_gkrellm_logfile)
|
||||||
|
{
|
||||||
|
gkrellm_log_register(gkrellm_log_file_log, NULL,
|
||||||
|
gkrellm_log_file_cleanup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//! Logs onto stdout/stderr
|
||||||
|
static void
|
||||||
|
gkrellm_log_to_terminal(GLogLevelFlags log_level, const gchar *message)
|
||||||
|
{
|
||||||
|
// warning, error or critical go to stderr
|
||||||
|
if (log_level & G_LOG_LEVEL_WARNING
|
||||||
|
|| log_level & G_LOG_LEVEL_CRITICAL
|
||||||
|
|| log_level & G_LOG_LEVEL_ERROR)
|
||||||
|
{
|
||||||
|
fputs(message, stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(WIN32)
|
||||||
|
// debug on windows gets special treatment
|
||||||
|
if (log_level & G_LOG_LEVEL_DEBUG)
|
||||||
|
OutputDebugStringA(message);
|
||||||
|
#endif
|
||||||
|
// Everything also ends up on stdout
|
||||||
|
// (may be invisible on most desktop-systems, especially on windows!)
|
||||||
|
fputs(message, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//! Handler that receives all the log-messages first
|
||||||
|
static void
|
||||||
|
gkrellm_log_handler(const gchar *log_domain, GLogLevelFlags log_level,
|
||||||
|
const gchar *message, gpointer user_data)
|
||||||
|
{
|
||||||
|
gchar *localized_message;
|
||||||
|
gint i;
|
||||||
|
GkrellmLogFacility *f;
|
||||||
|
|
||||||
|
localized_message = g_locale_from_utf8(message, -1, NULL, NULL, NULL);
|
||||||
|
if (localized_message == NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < s_log_facility_ptr_array->len; i++)
|
||||||
|
{
|
||||||
|
f = (g_ptr_array_index(s_log_facility_ptr_array, i));
|
||||||
|
f->log(log_level, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < s_log_facility_ptr_array->len; i++)
|
||||||
|
{
|
||||||
|
f = (g_ptr_array_index(s_log_facility_ptr_array, i));
|
||||||
|
f->log(log_level, localized_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(localized_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Non-Static functions that can be used in gkrellm
|
||||||
|
|
||||||
|
void
|
||||||
|
gkrellm_log_init()
|
||||||
|
{
|
||||||
|
if (s_log_facility_ptr_array)
|
||||||
|
return; // already initialized
|
||||||
|
s_log_facility_ptr_array = g_ptr_array_new();
|
||||||
|
g_log_set_handler (NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
|
||||||
|
| G_LOG_FLAG_RECURSION, gkrellm_log_handler, NULL);
|
||||||
|
gkrellm_log_register(gkrellm_log_to_terminal, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gkrellm_log_cleanup()
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
GkrellmLogFacility *f;
|
||||||
|
|
||||||
|
if (!s_log_facility_ptr_array)
|
||||||
|
return; // gkrellm_log_init() not called yet
|
||||||
|
|
||||||
|
// Call cleanup on all log-facilities and free our internal struct
|
||||||
|
for (i = 0; i < s_log_facility_ptr_array->len; i++)
|
||||||
|
{
|
||||||
|
f = (g_ptr_array_index(s_log_facility_ptr_array, i));
|
||||||
|
if (f->cleanup != NULL)
|
||||||
|
f->cleanup();
|
||||||
|
g_free(f);
|
||||||
|
}
|
||||||
|
g_ptr_array_free(s_log_facility_ptr_array, TRUE);
|
||||||
|
s_log_facility_ptr_array = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gkrellm_log_register(
|
||||||
|
GkrellmLogFunc log,
|
||||||
|
GkrellmLogInitFunc init,
|
||||||
|
GkrellmLogCleanupFunc cleanup)
|
||||||
|
{
|
||||||
|
GkrellmLogFacility *f;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (!s_log_facility_ptr_array)
|
||||||
|
return FALSE; // gkrellm_log_init() not called yet
|
||||||
|
|
||||||
|
// Check if log callback is already regisrered
|
||||||
|
for (i = 0; i < s_log_facility_ptr_array->len; i++)
|
||||||
|
{
|
||||||
|
f = (g_ptr_array_index(s_log_facility_ptr_array, i));
|
||||||
|
if (f->log == log)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init != NULL && init() == FALSE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// remember logging function and cleanup function in a struct
|
||||||
|
f = g_new0(GkrellmLogFacility, 1);
|
||||||
|
f->log = log;
|
||||||
|
f->cleanup = cleanup;
|
||||||
|
|
||||||
|
// add struct to list of log facilities
|
||||||
|
g_ptr_array_add(s_log_facility_ptr_array, (gpointer)f);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gkrellm_log_unregister(GkrellmLogFunc log)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
GkrellmLogFacility *f;
|
||||||
|
|
||||||
|
if (!s_log_facility_ptr_array)
|
||||||
|
return FALSE; // gkrellm_log_init() not called yet
|
||||||
|
|
||||||
|
for (i = 0; i < s_log_facility_ptr_array->len; i++)
|
||||||
|
{
|
||||||
|
f = (g_ptr_array_index(s_log_facility_ptr_array, i));
|
||||||
|
if (f->log == log)
|
||||||
|
{
|
||||||
|
if (f->cleanup != NULL)
|
||||||
|
f->cleanup();
|
||||||
|
g_ptr_array_remove_index(s_log_facility_ptr_array, i);
|
||||||
|
g_free(f);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Public functions that can be used in gkrellm and plugins
|
||||||
|
|
||||||
|
void
|
||||||
|
gkrellm_debug(guint debug_level, const gchar *format, ...)
|
||||||
|
{
|
||||||
|
if (_GK.debug_level & debug_level)
|
||||||
|
{
|
||||||
|
va_list varargs;
|
||||||
|
va_start(varargs, format);
|
||||||
|
|
||||||
|
g_logv(NULL, G_LOG_LEVEL_DEBUG, format, varargs);
|
||||||
|
|
||||||
|
va_end(varargs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* GKrellM
|
||||||
|
* Copyright (C) 1999-2008 Bill Wilson
|
||||||
|
*
|
||||||
|
* @author Bill Wilson <billw@gkrellm.net>
|
||||||
|
*
|
||||||
|
| Latest versions might be found at: http://gkrellm.net
|
||||||
|
|
|
||||||
|
|
|
||||||
|
| GKrellM is free software: you can redistribute it and/or modify it
|
||||||
|
| under the terms of the GNU General Public License as published by
|
||||||
|
| the Free Software Foundation, either version 3 of the License, or
|
||||||
|
| (at your option) any later version.
|
||||||
|
|
|
||||||
|
| GKrellM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
| or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
| License for more details.
|
||||||
|
|
|
||||||
|
| You should have received a copy of the GNU General Public License
|
||||||
|
| along with this program. If not, see http://www.gnu.org/licenses/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GK_LOG_H
|
||||||
|
#define GK_LOG_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints our and/or logs a debug message.
|
||||||
|
*
|
||||||
|
* If a logfile was set @see gkrellm_log_set_filename() the message will
|
||||||
|
* be logged into the logfile as well.
|
||||||
|
**/
|
||||||
|
void gkrellm_debug(guint debug_level, const gchar *format, ...);
|
||||||
|
|
||||||
|
#endif //GK_LOG_H
|
Loading…
Reference in New Issue