mirror of https://github.com/djcb/mu.git
rework logging system
reimplement the old mu-log.[ch] into mu-logging.{cc,hh} If available (and using an appropriately equipped glib), log to the systemd journal Only g_criticals have stderr output, all the other g_* go to the log file / journal.
This commit is contained in:
parent
73be015cd0
commit
3e233cba9a
49
HACKING
49
HACKING
|
@ -19,7 +19,7 @@
|
|||
on the same line as the statement, except for functions. Tabs for
|
||||
indentation, space for alignment; use 8-char tabs.
|
||||
|
||||
2. Lines should not exceed 80 characters (C) or 100 characters (C++)
|
||||
2. Lines should not exceed 100 characters
|
||||
|
||||
3. Functions should not exceed 35 lines (with few exceptions). You can easily
|
||||
check if any functions violate this rule with 'make line35', which lists
|
||||
|
@ -27,45 +27,34 @@
|
|||
|
||||
4. Source files should not exceed 1000 lines
|
||||
|
||||
5. A function's cyclomatic complexity should not exceed 10 (there could be
|
||||
rare exceptions, see the toplevel ~Makefile.am~). You can test the
|
||||
cyclomatic complexity with the ~pmccabe~ tool; if you installed that, you
|
||||
can use 'make cc10' to list all functions that violate this rule; there
|
||||
should be none.
|
||||
5. Non-static C-functions have the prefix based on their module, e.g.,
|
||||
~mu-foo.h~ declares a function of 'mu_foo_bar (int a);', mu-foo.c implements
|
||||
this. C++ functions using the Mu namespace
|
||||
|
||||
6. Filenames have their components separated with dashes (e.g, ~mu-log.h~), and
|
||||
start with ~mu-~ where appropriate.
|
||||
|
||||
7. Global functions have the prefix based on their module, e.g., ~mu-foo.h~
|
||||
declares a function of 'mu_foo_bar (int a);', mu-foo.c implements this.
|
||||
|
||||
8. Non-global functions *don't* have the module prefix, and are declared
|
||||
6. Non-global functions *don't* have the module prefix, and are declared
|
||||
static.
|
||||
|
||||
9. Functions have their return type on a separate line before the function
|
||||
7. Functions have their return type on a separate line before the function
|
||||
name, so:
|
||||
|
||||
#+BEGIN_EXAMPLE
|
||||
int
|
||||
static int
|
||||
foo (const char *bar)
|
||||
{
|
||||
....
|
||||
}
|
||||
#+END_EXAMPLE
|
||||
|
||||
There is no non-aesthetic reason for this.
|
||||
8. In C code, variable-declarations are at the beginning of a block.
|
||||
|
||||
10. In C code, variable-declarations are at the beginning of a block; in
|
||||
principle, C++ follows that same guideline, unless for heavy yet
|
||||
uncertain initializations following RAII.
|
||||
In C code, the declaration does *not* initialize the variable. This will
|
||||
give the compiler a chance to warn us if the variable is not initialized
|
||||
in a certain code path.
|
||||
|
||||
In C code, the declaration does *not* initialize the variable. This will
|
||||
give the compiler a chance to warn us if the variable is not initialized
|
||||
in a certain code path.
|
||||
|
||||
11. Returned strings of type char* must be freed by the caller; if they are
|
||||
9. Returned strings of type char* must be freed by the caller; if they are
|
||||
not to be freed, 'const char*' should be used instead
|
||||
|
||||
12. Functions calls have a space between function name and arguments, unless
|
||||
10. Functions calls have a space between function name and arguments, unless
|
||||
there are none, so:
|
||||
|
||||
~foo (12, 3)~;
|
||||
|
@ -76,11 +65,11 @@
|
|||
|
||||
after a comma, a space should follow.
|
||||
|
||||
13. Functions that do not take arguments are explicitly declared as
|
||||
11. C-functions that do not take arguments are explicitly declared as
|
||||
f(void) and not f(). Reason: f() means that the arguments are
|
||||
/unspecified/ (in C)
|
||||
|
||||
14. C-code should not use ~//~ comments.
|
||||
12. C-code should not use ~//~ comments.
|
||||
|
||||
|
||||
** Logging
|
||||
|
@ -89,8 +78,7 @@
|
|||
except when logging may not have been initialized.
|
||||
|
||||
The logging system redirects most logging to the log file (typically,
|
||||
~/.cache/mu/mu.log). g_warning, g_message and g_critical are shown to the user,
|
||||
except when running with --quiet, in which case g_message is *not* shown.
|
||||
=~/.cache/mu/mu.log=). ~g_critical~ messages are written to stderr.
|
||||
|
||||
- ~g_message~ is for non-error messages the user will see (unless running with
|
||||
~--quiet~)
|
||||
|
@ -100,9 +88,6 @@
|
|||
friends use this). (and they are written on ~stderr~)
|
||||
- don't use ~g_error~
|
||||
|
||||
If you just want to log something in the log file without writing to screen,
|
||||
use ~MU_LOG_WRITE~, as defined in ~mu-util.h~.
|
||||
|
||||
** Compiling from git
|
||||
|
||||
For hacking, you're strongly advised to use the latest git version.
|
||||
|
|
3
NEWS.org
3
NEWS.org
|
@ -5,6 +5,9 @@
|
|||
|
||||
*** mu
|
||||
|
||||
- Where available (and with suitable glib), log to the systemd journal
|
||||
instead of a =~/.cache/mu.log=
|
||||
|
||||
- Follow symlinks in maildirs, and support moving messsages between across
|
||||
multiple filesystems (but note that that is quite a bit slower than the
|
||||
single-filesystem case)
|
||||
|
|
|
@ -86,7 +86,7 @@ mu_guile_init_instance (const char *muhome)
|
|||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
if (!mu_runtime_init (muhome, "guile"))
|
||||
if (!mu_runtime_init (muhome, "guile", FALSE))
|
||||
return FALSE;
|
||||
|
||||
err = NULL;
|
||||
|
|
|
@ -257,7 +257,8 @@ on_run_maildir_dir (const char* fullpath, gboolean enter,
|
|||
data->_user_data);
|
||||
|
||||
if (err) {
|
||||
MU_WRITE_LOG ("%s: %s", __func__, err->message);
|
||||
g_warning("%s: error handling %s: %s", __func__,
|
||||
fullpath, err->message);
|
||||
g_clear_error(&err);
|
||||
}
|
||||
|
||||
|
|
|
@ -119,10 +119,7 @@ mu_maildir_mkdir (const char* path, mode_t mode, gboolean noindex, GError **err)
|
|||
{
|
||||
g_return_val_if_fail (path, FALSE);
|
||||
|
||||
MU_WRITE_LOG ("%s (%s, %o, %s)", __func__,
|
||||
path, mode, noindex ? "TRUE" : "FALSE");
|
||||
|
||||
if (!create_maildir (path, mode, err))
|
||||
if (!create_maildir (path, mode, err))
|
||||
return FALSE;
|
||||
|
||||
if (noindex && !create_noindex (path, err))
|
||||
|
|
|
@ -241,7 +241,7 @@ try_requery (MuQuery *self, const char* searchexpr, MuMsgFieldId sortfieldid,
|
|||
/* let's assume that infinite regression is
|
||||
* impossible */
|
||||
self->db().reopen();
|
||||
MU_WRITE_LOG ("reopening db after modification");
|
||||
g_message ("reopening db after modification");
|
||||
return mu_query_run (self, searchexpr, sortfieldid,
|
||||
maxnum, flags, err);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "mu-runtime.h"
|
||||
#include "utils/mu-util.h"
|
||||
#include "utils/mu-logger.hh"
|
||||
|
||||
#include <locale.h> /* for setlocale() */
|
||||
|
||||
|
@ -29,24 +30,25 @@ static std::unordered_map<MuRuntimePath, std::string> RuntimePaths;
|
|||
constexpr auto PartsDir = "parts";
|
||||
constexpr auto LogDir = "log";
|
||||
constexpr auto XapianDir = "xapian";
|
||||
constexpr auto Mu = "mu";
|
||||
constexpr auto MuName = "mu";
|
||||
constexpr auto Bookmarks = "bookmarks";
|
||||
|
||||
static const std::string Sepa{G_DIR_SEPARATOR_S};
|
||||
|
||||
|
||||
static void
|
||||
init_paths_xdg ()
|
||||
{
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() +
|
||||
Sepa + Mu + Sepa + XapianDir);
|
||||
Sepa + MuName + Sepa + XapianDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, g_get_user_cache_dir() +
|
||||
Sepa + Mu);
|
||||
Sepa + MuName);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() +
|
||||
Sepa + Mu + Sepa + PartsDir);
|
||||
Sepa + MuName + Sepa + PartsDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() +
|
||||
Sepa + Mu);
|
||||
Sepa + MuName);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, g_get_user_config_dir() +
|
||||
Sepa + Mu);
|
||||
Sepa + MuName);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -60,7 +62,7 @@ init_paths_muhome (const char *muhome)
|
|||
}
|
||||
|
||||
gboolean
|
||||
mu_runtime_init (const char* muhome, const char *name)
|
||||
mu_runtime_init (const char* muhome, const char *name, gboolean debug)
|
||||
{
|
||||
g_return_val_if_fail (RuntimePaths.empty(), FALSE);
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
|
@ -92,10 +94,12 @@ mu_runtime_init (const char* muhome, const char *name)
|
|||
const auto log_path = RuntimePaths[MU_RUNTIME_PATH_LOGDIR] +
|
||||
Sepa + name + ".log";
|
||||
|
||||
if (!mu_log_init (log_path.c_str(), MU_LOG_OPTIONS_BACKUP)) {
|
||||
mu_runtime_uninit();
|
||||
return FALSE;
|
||||
}
|
||||
using namespace Mu;
|
||||
LogOptions opts{LogOptions::None};
|
||||
if (debug)
|
||||
opts |= (LogOptions::Debug | LogOptions::None);
|
||||
|
||||
Mu::log_init(log_path, opts);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -104,7 +108,7 @@ void
|
|||
mu_runtime_uninit (void)
|
||||
{
|
||||
RuntimePaths.clear();
|
||||
mu_log_uninit();
|
||||
Mu::log_uninit();
|
||||
}
|
||||
|
||||
const char*
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#define __MU_RUNTIME_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <utils/mu-log.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -32,10 +31,12 @@ G_BEGIN_DECLS
|
|||
* @param muhome path where to find the mu home directory (typically, ~/.cache/mu)
|
||||
* @param name of the main program, ie. 'mu', 'mug' or
|
||||
* 'procmule'. this influences the name of the e.g. the logfile
|
||||
* @param debug debug-mode
|
||||
*
|
||||
* @return TRUE if succeeded, FALSE in case of error
|
||||
*/
|
||||
gboolean mu_runtime_init (const char *muhome, const char *name);
|
||||
gboolean mu_runtime_init (const char *muhome, const char *name,
|
||||
gboolean debug);
|
||||
|
||||
/**
|
||||
* free all resources
|
||||
|
@ -47,7 +48,7 @@ void mu_runtime_uninit (void);
|
|||
typedef enum {
|
||||
MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */
|
||||
MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */
|
||||
MU_RUNTIME_PATH_CACHE, /* mu cache path for attachments etc. */
|
||||
MU_RUNTIME_PATH_CACHE, /* mu cache path */
|
||||
MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */
|
||||
MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ libmu_utils_la_SOURCES= \
|
|||
mu-date.c \
|
||||
mu-date.h \
|
||||
mu-error.hh \
|
||||
mu-log.c \
|
||||
mu-log.h \
|
||||
mu-logger.cc \
|
||||
mu-logger.hh \
|
||||
mu-command-parser.cc \
|
||||
mu-command-parser.hh \
|
||||
mu-readline.cc \
|
||||
|
|
|
@ -1,319 +0,0 @@
|
|||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||
|
||||
/*
|
||||
** Copyright (C) 2008-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program 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.
|
||||
**
|
||||
** This program 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, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
|
||||
#include "mu-log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mu-util.h"
|
||||
|
||||
#define MU_MAX_LOG_FILE_SIZE 1000 * 1000 /* 1 MB (SI units) */
|
||||
#define MU_LOG_FILE "mu.log"
|
||||
|
||||
struct _MuLog {
|
||||
int _fd; /* log file descriptor */
|
||||
|
||||
MuLogOptions _opts;
|
||||
|
||||
gboolean _color_stdout; /* whether to use color */
|
||||
gboolean _color_stderr;
|
||||
|
||||
GLogFunc _old_log_func;
|
||||
};
|
||||
typedef struct _MuLog MuLog;
|
||||
|
||||
/* we use globals, because logging is a global operation as it
|
||||
* globally modifies the behaviour of g_warning and friends
|
||||
*/
|
||||
static MuLog* MU_LOG = NULL;
|
||||
static void log_write (const char* domain, GLogLevelFlags level,
|
||||
const gchar *msg);
|
||||
|
||||
static void
|
||||
try_close (int fd)
|
||||
{
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (close (fd) < 0)
|
||||
g_printerr ("%s: close() of fd %d failed: %s\n",
|
||||
__func__, fd, strerror(errno));
|
||||
}
|
||||
|
||||
static void
|
||||
silence (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
gboolean
|
||||
mu_log_init_silence (void)
|
||||
{
|
||||
g_return_val_if_fail (!MU_LOG, FALSE);
|
||||
|
||||
MU_LOG = g_new0 (MuLog, 1);
|
||||
MU_LOG->_fd = -1;
|
||||
|
||||
mu_log_options_set (MU_LOG_OPTIONS_NONE);
|
||||
|
||||
MU_LOG->_old_log_func =
|
||||
g_log_set_default_handler ((GLogFunc)silence, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
log_handler (const gchar* log_domain, GLogLevelFlags log_level,
|
||||
const gchar* msg)
|
||||
{
|
||||
if ((log_level & G_LOG_LEVEL_DEBUG) &&
|
||||
!(MU_LOG->_opts & MU_LOG_OPTIONS_DEBUG))
|
||||
return;
|
||||
|
||||
log_write (log_domain ? log_domain : "mu", log_level, msg);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mu_log_options_set (MuLogOptions opts)
|
||||
{
|
||||
g_return_if_fail (MU_LOG);
|
||||
|
||||
MU_LOG->_opts = opts;
|
||||
|
||||
/* when color is, only enable it when output is to a tty */
|
||||
if (MU_LOG->_opts & MU_LOG_OPTIONS_COLOR) {
|
||||
MU_LOG->_color_stdout = isatty(fileno(stdout));
|
||||
MU_LOG->_color_stderr = isatty(fileno(stderr));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MuLogOptions
|
||||
mu_log_options_get (void)
|
||||
{
|
||||
g_return_val_if_fail (MU_LOG, MU_LOG_OPTIONS_NONE);
|
||||
|
||||
return MU_LOG->_opts;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
move_log_file (const char *logfile)
|
||||
{
|
||||
gchar *logfile_old;
|
||||
int rv;
|
||||
|
||||
logfile_old = g_strdup_printf ("%s.old", logfile);
|
||||
rv = rename (logfile, logfile_old);
|
||||
g_free (logfile_old);
|
||||
|
||||
if (rv != 0) {
|
||||
g_warning ("failed to move %s to %s.old: %s",
|
||||
logfile, logfile, strerror(rv));
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
log_file_backup_maybe (const char *logfile)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (logfile, &statbuf) != 0) {
|
||||
if (errno == ENOENT)
|
||||
return TRUE; /* it did not exist yet, no problem */
|
||||
else {
|
||||
g_warning ("failed to stat(2) %s: %s",
|
||||
logfile, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* log file is still below the max size? */
|
||||
if (statbuf.st_size <= MU_MAX_LOG_FILE_SIZE)
|
||||
return TRUE;
|
||||
|
||||
/* log file is too big!; we move it to <logfile>.old, overwriting */
|
||||
return move_log_file (logfile);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
mu_log_init (const char* logfile, MuLogOptions opts)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/* only init once... */
|
||||
g_return_val_if_fail (!MU_LOG, FALSE);
|
||||
g_return_val_if_fail (logfile, FALSE);
|
||||
|
||||
if (opts & MU_LOG_OPTIONS_BACKUP)
|
||||
if (!log_file_backup_maybe(logfile)) {
|
||||
g_warning ("failed to backup log file");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fd = open (logfile, O_WRONLY|O_CREAT|O_APPEND, 00600);
|
||||
if (fd < 0) {
|
||||
g_warning ("%s: open() of '%s' failed: %s", __func__,
|
||||
logfile, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MU_LOG = g_new0 (MuLog, 1);
|
||||
MU_LOG->_fd = fd;
|
||||
|
||||
mu_log_options_set (opts);
|
||||
|
||||
MU_LOG->_old_log_func =
|
||||
g_log_set_default_handler ((GLogFunc)log_handler, NULL);
|
||||
|
||||
MU_WRITE_LOG ("logging started");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
mu_log_uninit (void)
|
||||
{
|
||||
if (!MU_LOG)
|
||||
return;
|
||||
|
||||
MU_WRITE_LOG ("logging stopped");
|
||||
|
||||
try_close (MU_LOG->_fd);
|
||||
g_free (MU_LOG);
|
||||
|
||||
MU_LOG = NULL;
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
levelstr (GLogLevelFlags level)
|
||||
{
|
||||
switch (level) {
|
||||
case G_LOG_LEVEL_WARNING: return " [WARN] ";
|
||||
case G_LOG_LEVEL_ERROR : return " [ERR ] ";
|
||||
case G_LOG_LEVEL_DEBUG: return " [DBG ] ";
|
||||
case G_LOG_LEVEL_CRITICAL: return " [CRIT] ";
|
||||
case G_LOG_LEVEL_MESSAGE: return " [MSG ] ";
|
||||
case G_LOG_LEVEL_INFO : return " [INFO] ";
|
||||
default: return " [LOG ] ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define color_stdout_maybe(C) \
|
||||
do{if (MU_LOG->_color_stdout) fputs ((C),stdout);} while (0)
|
||||
#define color_stderr_maybe(C) \
|
||||
do{if (MU_LOG->_color_stderr) fputs ((C),stderr);} while (0)
|
||||
|
||||
|
||||
|
||||
static void
|
||||
log_write_fd (GLogLevelFlags level, const gchar *msg)
|
||||
{
|
||||
time_t now;
|
||||
char timebuf [22];
|
||||
const char *mylevel;
|
||||
|
||||
/* get the time/date string */
|
||||
now = time(NULL);
|
||||
strftime (timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S",
|
||||
localtime(&now));
|
||||
|
||||
if (write (MU_LOG->_fd, timebuf, strlen (timebuf)) < 0)
|
||||
goto err;
|
||||
|
||||
mylevel = levelstr (level);
|
||||
if (write (MU_LOG->_fd, mylevel, strlen (mylevel)) < 0)
|
||||
goto err;
|
||||
|
||||
if (write (MU_LOG->_fd, msg, strlen (msg)) < 0)
|
||||
goto err;
|
||||
|
||||
if (write (MU_LOG->_fd, "\n", strlen ("\n")) < 0)
|
||||
goto err;
|
||||
|
||||
return; /* all went well */
|
||||
|
||||
err:
|
||||
fprintf (stderr, "%s: failed to write to log: %s\n",
|
||||
__func__, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
log_write_stdout_stderr (GLogLevelFlags level, const gchar *msg)
|
||||
{
|
||||
const char *mu;
|
||||
|
||||
mu = MU_LOG->_opts & MU_LOG_OPTIONS_NEWLINE ?
|
||||
"\nmu: " : "mu: ";
|
||||
|
||||
if (!(MU_LOG->_opts & MU_LOG_OPTIONS_QUIET) &&
|
||||
(level & G_LOG_LEVEL_MESSAGE)) {
|
||||
color_stdout_maybe (MU_COLOR_GREEN);
|
||||
fputs (mu, stdout);
|
||||
fputs (msg, stdout);
|
||||
fputs ("\n", stdout);
|
||||
color_stdout_maybe (MU_COLOR_DEFAULT);
|
||||
}
|
||||
|
||||
/* for errors, log them to stderr as well */
|
||||
if (level & G_LOG_LEVEL_ERROR ||
|
||||
level & G_LOG_LEVEL_CRITICAL ||
|
||||
level & G_LOG_LEVEL_WARNING) {
|
||||
color_stderr_maybe (MU_COLOR_RED);
|
||||
fputs (mu, stderr);
|
||||
fputs (msg, stderr);
|
||||
fputs ("\n", stderr);
|
||||
color_stderr_maybe (MU_COLOR_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
log_write (const char* domain, GLogLevelFlags level, const gchar *msg)
|
||||
{
|
||||
g_return_if_fail (MU_LOG);
|
||||
|
||||
log_write_fd (level, msg);
|
||||
log_write_stdout_stderr (level, msg);
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset:
|
||||
8 -*-*/
|
||||
/*
|
||||
** Copyright (C) 2008-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program 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.
|
||||
**
|
||||
** This program 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, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __MU_LOG_H__
|
||||
#define __MU_LOG_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* mu log is the global logging system */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
enum _MuLogOptions {
|
||||
MU_LOG_OPTIONS_NONE = 0,
|
||||
|
||||
/* when size of log file > MU_MAX_LOG_FILE_SIZE, move the log
|
||||
* file to <log file>.old and start a new one. The .old file will
|
||||
* overwrite existing files of that name */
|
||||
MU_LOG_OPTIONS_BACKUP = 1 << 1,
|
||||
|
||||
/* quiet: don't log non-errors to stdout/stderr */
|
||||
MU_LOG_OPTIONS_QUIET = 1 << 2,
|
||||
|
||||
/* should lines be preceded by \n? useful when errors come
|
||||
* during indexing */
|
||||
MU_LOG_OPTIONS_NEWLINE = 1 << 3,
|
||||
|
||||
/* color in output (iff output is to a tty) */
|
||||
MU_LOG_OPTIONS_COLOR = 1 << 4,
|
||||
|
||||
/* log everything to stderr */
|
||||
MU_LOG_OPTIONS_STDERR = 1 << 5,
|
||||
|
||||
/* debug: debug include debug-level information */
|
||||
MU_LOG_OPTIONS_DEBUG = 1 << 6
|
||||
};
|
||||
typedef enum _MuLogOptions MuLogOptions;
|
||||
|
||||
|
||||
/**
|
||||
* write logging information to a log file
|
||||
*
|
||||
* @param full path to the log file (does not have to exist yet, but
|
||||
* it's directory must)
|
||||
* @param opts logging options
|
||||
*
|
||||
* @return TRUE if initialization succeeds, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_log_init (const char *logfile, MuLogOptions opts)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* be silent except for runtime errors, which will be written to
|
||||
* stderr.
|
||||
*
|
||||
* @return TRUE if initialization succeeds, FALSE otherwise
|
||||
*/
|
||||
gboolean mu_log_init_silence (void) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* uninitialize the logging system, and free all resources
|
||||
*/
|
||||
void mu_log_uninit (void);
|
||||
|
||||
/**
|
||||
* set logging options, a logical-OR'd value of MuLogOptions
|
||||
*
|
||||
* @param opts the options (logically OR'd)
|
||||
*/
|
||||
void mu_log_options_set (MuLogOptions opts);
|
||||
|
||||
/**
|
||||
* get logging options, a logical-OR'd value of MuLogOptions
|
||||
*
|
||||
* @param opts the options (logically OR'd)
|
||||
*/
|
||||
MuLogOptions mu_log_options_get (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /*__MU_LOG_H__*/
|
|
@ -309,20 +309,6 @@ typedef gpointer XapianEnquire;
|
|||
} while (0)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* log something in the log file; note, we use G_LOG_LEVEL_INFO
|
||||
* for such messages
|
||||
*/
|
||||
#define MU_WRITE_LOG(...) \
|
||||
G_STMT_START { \
|
||||
g_log (G_LOG_DOMAIN, \
|
||||
G_LOG_LEVEL_INFO, \
|
||||
__VA_ARGS__); \
|
||||
} G_STMT_END
|
||||
|
||||
|
||||
|
||||
#define MU_G_ERROR_CODE(GE) ((GE)&&(*(GE))?(*(GE))->code:MU_ERROR)
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||
|
||||
/*
|
||||
** Copyright (C) 2008-2016 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2008-2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
|
@ -37,7 +35,6 @@
|
|||
#include "mu-runtime.h"
|
||||
|
||||
#include "utils/mu-util.h"
|
||||
#include "utils/mu-log.h"
|
||||
|
||||
static gboolean MU_CAUGHT_SIGNAL;
|
||||
|
||||
|
@ -180,22 +177,14 @@ show_time (unsigned t, unsigned processed, gboolean color)
|
|||
g_print ("\n");
|
||||
}
|
||||
|
||||
/* when logging to console, print a newline before doing so; this
|
||||
* makes it more clear when something happens during the
|
||||
* indexing/cleanup progress output */
|
||||
#define newline_before_on() \
|
||||
mu_log_options_set(mu_log_options_get() | MU_LOG_OPTIONS_NEWLINE)
|
||||
#define newline_before_off() \
|
||||
mu_log_options_set(mu_log_options_get() & ~MU_LOG_OPTIONS_NEWLINE)
|
||||
|
||||
static MuError
|
||||
cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
||||
GError **err)
|
||||
{
|
||||
MuError rv;
|
||||
time_t t;
|
||||
IndexData idata;
|
||||
gboolean show_progress;
|
||||
MuError rv;
|
||||
time_t t;
|
||||
IndexData idata;
|
||||
gboolean show_progress;
|
||||
|
||||
if (!opts->quiet)
|
||||
g_print ("cleaning up messages [%s]\n",
|
||||
|
@ -206,14 +195,12 @@ cleanup_missing (MuIndex *midx, MuConfig *opts, MuIndexStats *stats,
|
|||
|
||||
t = time (NULL);
|
||||
idata.color = !opts->nocolor;
|
||||
newline_before_on();
|
||||
rv = mu_index_cleanup
|
||||
(midx, stats,
|
||||
show_progress ?
|
||||
(MuIndexCleanupDeleteCallback)index_msg_cb :
|
||||
(MuIndexCleanupDeleteCallback)index_msg_silent_cb,
|
||||
&idata, err);
|
||||
newline_before_off();
|
||||
|
||||
if (!opts->quiet) {
|
||||
print_stats (stats, TRUE, !opts->nocolor);
|
||||
|
@ -235,8 +222,6 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err)
|
|||
show_progress = !opts->quiet && isatty(fileno(stdout));
|
||||
idata.color = !opts->nocolor;
|
||||
|
||||
newline_before_on();
|
||||
|
||||
rv = mu_index_run (midx,
|
||||
opts->rebuild,
|
||||
opts->lazycheck, stats,
|
||||
|
@ -244,11 +229,9 @@ cmd_index (MuIndex *midx, MuConfig *opts, MuIndexStats *stats, GError **err)
|
|||
(MuIndexMsgCallback)index_msg_cb :
|
||||
(MuIndexMsgCallback)index_msg_silent_cb,
|
||||
NULL, &idata);
|
||||
newline_before_off();
|
||||
|
||||
if (rv == MU_OK || rv == MU_STOP) {
|
||||
MU_WRITE_LOG ("index: processed: %u; updated/new: %u",
|
||||
stats->_processed, stats->_updated);
|
||||
g_message ("index: processed: %u; updated/new: %u",
|
||||
stats->_processed, stats->_updated);
|
||||
} else
|
||||
mu_util_g_set_error (err, rv, "error while indexing");
|
||||
|
||||
|
|
34
mu/mu-cmd.c
34
mu/mu-cmd.c
|
@ -33,7 +33,6 @@
|
|||
#include "mu-runtime.h"
|
||||
#include "mu-flags.h"
|
||||
|
||||
#include "utils/mu-log.h"
|
||||
#include "utils/mu-util.h"
|
||||
#include "utils/mu-str.h"
|
||||
#include "utils/mu-date.h"
|
||||
|
@ -342,15 +341,15 @@ foreach_msg_file (MuStore *store, MuConfig *opts,
|
|||
|
||||
if (!check_file_okay (path, TRUE)) {
|
||||
all_ok = FALSE;
|
||||
MU_WRITE_LOG ("not a valid message file: %s", path);
|
||||
g_warning ("not a valid message file: %s", path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!foreach_func (store, path, err)) {
|
||||
all_ok = FALSE;
|
||||
MU_WRITE_LOG ("error with %s: %s", path,
|
||||
(err&&*err) ? (*err)->message :
|
||||
"something went wrong");
|
||||
g_warning ("error with %s: %s", path,
|
||||
(err&&*err) ? (*err)->message :
|
||||
"something went wrong");
|
||||
g_clear_error (err);
|
||||
continue;
|
||||
}
|
||||
|
@ -656,23 +655,6 @@ check_params (MuConfig *opts, GError **err)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_log_options (MuConfig *opts)
|
||||
{
|
||||
MuLogOptions logopts;
|
||||
|
||||
logopts = MU_LOG_OPTIONS_NONE;
|
||||
|
||||
if (opts->quiet)
|
||||
logopts |= MU_LOG_OPTIONS_QUIET;
|
||||
if (!opts->nocolor)
|
||||
logopts |= MU_LOG_OPTIONS_COLOR;
|
||||
if (opts->log_stderr)
|
||||
logopts |= MU_LOG_OPTIONS_STDERR;
|
||||
if (opts->debug)
|
||||
logopts |= MU_LOG_OPTIONS_DEBUG;
|
||||
}
|
||||
|
||||
MuError
|
||||
mu_cmd_execute (MuConfig *opts, GError **err)
|
||||
{
|
||||
|
@ -683,8 +665,6 @@ mu_cmd_execute (MuConfig *opts, GError **err)
|
|||
if (!check_params(opts, err))
|
||||
return MU_G_ERROR_CODE(err);
|
||||
|
||||
set_log_options (opts);
|
||||
|
||||
switch (opts->cmd) {
|
||||
|
||||
/* already handled in mu-config.c */
|
||||
|
@ -692,10 +672,10 @@ mu_cmd_execute (MuConfig *opts, GError **err)
|
|||
|
||||
/* no store needed */
|
||||
|
||||
case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break;
|
||||
case MU_CONFIG_CMD_MKDIR: merr = cmd_mkdir (opts, err); break;
|
||||
case MU_CONFIG_CMD_SCRIPT: merr = mu_cmd_script (opts, err); break;
|
||||
case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break;
|
||||
case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break;
|
||||
case MU_CONFIG_CMD_VIEW: merr = cmd_view (opts, err); break;
|
||||
case MU_CONFIG_CMD_VERIFY: merr = cmd_verify (opts, err); break;
|
||||
case MU_CONFIG_CMD_EXTRACT: merr = mu_cmd_extract (opts, err); break;
|
||||
|
||||
/* read-only store */
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h> /* memset */
|
||||
|
|
|
@ -97,8 +97,8 @@ struct _MuConfig {
|
|||
char *cmdstr; /* cmd string, for user
|
||||
* info */
|
||||
/* general options */
|
||||
gboolean quiet; /* don't give any output */
|
||||
gboolean debug; /* spew out debug info */
|
||||
gboolean quiet; /* don't give any output */
|
||||
gboolean debug; /* log debug-level info */
|
||||
gchar *muhome; /* the House of Mu */
|
||||
gboolean version; /* request mu version */
|
||||
gboolean log_stderr; /* log to stderr (not logfile) */
|
||||
|
|
8
mu/mu.cc
8
mu/mu.cc
|
@ -91,9 +91,9 @@ handle_error (MuConfig *conf, MuError merr, GError **err)
|
|||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GError *err;
|
||||
MuError rv;
|
||||
MuConfig *conf;
|
||||
GError *err;
|
||||
MuError rv;
|
||||
MuConfig *conf;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
|
@ -113,7 +113,7 @@ main (int argc, char *argv[])
|
|||
if (conf->cmd == MU_CONFIG_CMD_NONE)
|
||||
return 0;
|
||||
|
||||
if (!mu_runtime_init (conf->muhome, PACKAGE_NAME)) {
|
||||
if (!mu_runtime_init (conf->muhome, PACKAGE_NAME, conf->debug)) {
|
||||
mu_config_uninit (conf);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -402,7 +402,7 @@ main (int argc, char *argv[])
|
|||
}
|
||||
|
||||
g_option_context_free (octx);
|
||||
mu_runtime_init (mugdata.muhome, "mug");
|
||||
mu_runtime_init (mugdata.muhome, "mug", FALSE);
|
||||
|
||||
mugshell = mug_shell (&mugdata);
|
||||
g_signal_connect (G_OBJECT (mugshell), "destroy",
|
||||
|
|
Loading…
Reference in New Issue