2008-11-06 16:36:07 +00:00
|
|
|
/*
|
|
|
|
* logging.c: internal logging and debugging
|
|
|
|
*
|
2012-01-25 20:13:25 +00:00
|
|
|
* Copyright (C) 2008, 2010-2012 Red Hat, Inc.
|
2008-11-06 16:36:07 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-11-06 16:36:07 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2009-01-06 18:32:03 +00:00
|
|
|
#include <unistd.h>
|
2011-03-07 13:23:53 +00:00
|
|
|
#include <signal.h>
|
2012-09-05 22:27:42 +00:00
|
|
|
#include <execinfo.h>
|
2008-12-22 10:36:54 +00:00
|
|
|
#if HAVE_SYSLOG_H
|
2010-03-09 18:22:22 +00:00
|
|
|
# include <syslog.h>
|
2008-12-22 10:36:54 +00:00
|
|
|
#endif
|
2012-09-25 17:31:01 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#if HAVE_SYS_UN_H
|
|
|
|
# include <sys/un.h>
|
|
|
|
#endif
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-06 16:36:07 +00:00
|
|
|
#include "logging.h"
|
2008-12-22 10:36:54 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "util.h"
|
2009-10-08 15:05:01 +00:00
|
|
|
#include "buf.h"
|
2009-01-15 19:56:05 +00:00
|
|
|
#include "threads.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2011-11-29 12:32:31 +00:00
|
|
|
#include "virtime.h"
|
2012-09-25 17:31:01 +00:00
|
|
|
#include "intprops.h"
|
2008-11-06 16:36:07 +00:00
|
|
|
|
2012-10-01 22:38:56 +00:00
|
|
|
/* Journald output is only supported on Linux new enough to expose
|
|
|
|
* htole64. */
|
|
|
|
#if HAVE_SYSLOG_H && defined(__linux__) && HAVE_DECL_HTOLE64
|
|
|
|
# define USE_JOURNALD 1
|
|
|
|
#endif
|
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
|
2012-09-27 13:44:22 +00:00
|
|
|
VIR_ENUM_DECL(virLogSource)
|
|
|
|
VIR_ENUM_IMPL(virLogSource, VIR_LOG_FROM_LAST,
|
|
|
|
"file",
|
|
|
|
"error",
|
|
|
|
"audit",
|
|
|
|
"trace",
|
|
|
|
"library");
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/*
|
|
|
|
* A logging buffer to keep some history over logs
|
|
|
|
*/
|
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
static int virLogSize = 64 * 1024;
|
|
|
|
static char *virLogBuffer = NULL;
|
2008-12-22 10:36:54 +00:00
|
|
|
static int virLogLen = 0;
|
|
|
|
static int virLogStart = 0;
|
|
|
|
static int virLogEnd = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Filters are used to refine the rules on what to keep or drop
|
|
|
|
* based on a matching pattern (currently a substring)
|
|
|
|
*/
|
|
|
|
struct _virLogFilter {
|
|
|
|
const char *match;
|
2012-09-27 12:58:58 +00:00
|
|
|
virLogPriority priority;
|
2012-05-09 14:18:56 +00:00
|
|
|
unsigned int flags;
|
2008-12-22 10:36:54 +00:00
|
|
|
};
|
|
|
|
typedef struct _virLogFilter virLogFilter;
|
|
|
|
typedef virLogFilter *virLogFilterPtr;
|
|
|
|
|
|
|
|
static virLogFilterPtr virLogFilters = NULL;
|
|
|
|
static int virLogNbFilters = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Outputs are used to emit the messages retained
|
|
|
|
* after filtering, multiple output can be used simultaneously
|
|
|
|
*/
|
|
|
|
struct _virLogOutput {
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
bool logVersion;
|
2008-12-22 10:36:54 +00:00
|
|
|
void *data;
|
|
|
|
virLogOutputFunc f;
|
|
|
|
virLogCloseFunc c;
|
2012-09-27 12:58:58 +00:00
|
|
|
virLogPriority priority;
|
2009-10-08 15:05:01 +00:00
|
|
|
virLogDestination dest;
|
|
|
|
const char *name;
|
2008-12-22 10:36:54 +00:00
|
|
|
};
|
|
|
|
typedef struct _virLogOutput virLogOutput;
|
|
|
|
typedef virLogOutput *virLogOutputPtr;
|
|
|
|
|
|
|
|
static virLogOutputPtr virLogOutputs = NULL;
|
|
|
|
static int virLogNbOutputs = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Default priorities
|
|
|
|
*/
|
2009-07-01 11:21:15 +00:00
|
|
|
static virLogPriority virLogDefaultPriority = VIR_LOG_DEFAULT;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
static int virLogResetFilters(void);
|
|
|
|
static int virLogResetOutputs(void);
|
2012-09-27 13:44:22 +00:00
|
|
|
static void virLogOutputToFd(virLogSource src,
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *filename,
|
2012-09-27 13:14:01 +00:00
|
|
|
int linenr,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname,
|
2012-09-20 18:24:00 +00:00
|
|
|
const char *timestamp,
|
|
|
|
unsigned int flags,
|
2012-09-27 13:14:01 +00:00
|
|
|
const char *rawstr,
|
|
|
|
const char *str,
|
2012-09-20 18:24:00 +00:00
|
|
|
void *data);
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Logs accesses must be serialized though a mutex
|
|
|
|
*/
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutex virLogMutex;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
void
|
|
|
|
virLogLock(void)
|
2008-12-22 10:36:54 +00:00
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&virLogMutex);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
virLogUnlock(void)
|
2008-12-22 10:36:54 +00:00
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&virLogMutex);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static const char *
|
|
|
|
virLogOutputString(virLogDestination ldest)
|
|
|
|
{
|
2009-10-08 15:05:01 +00:00
|
|
|
switch (ldest) {
|
2011-01-21 16:30:17 +00:00
|
|
|
case VIR_LOG_TO_STDERR:
|
|
|
|
return "stderr";
|
|
|
|
case VIR_LOG_TO_SYSLOG:
|
|
|
|
return "syslog";
|
|
|
|
case VIR_LOG_TO_FILE:
|
|
|
|
return "file";
|
2012-09-25 17:31:01 +00:00
|
|
|
case VIR_LOG_TO_JOURNALD:
|
|
|
|
return "journald";
|
2009-10-08 15:05:01 +00:00
|
|
|
}
|
2011-01-21 16:30:17 +00:00
|
|
|
return "unknown";
|
2009-10-08 15:05:01 +00:00
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static const char *
|
|
|
|
virLogPriorityString(virLogPriority lvl)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
switch (lvl) {
|
2011-01-21 16:30:17 +00:00
|
|
|
case VIR_LOG_DEBUG:
|
|
|
|
return "debug";
|
|
|
|
case VIR_LOG_INFO:
|
|
|
|
return "info";
|
|
|
|
case VIR_LOG_WARN:
|
|
|
|
return "warning";
|
|
|
|
case VIR_LOG_ERROR:
|
|
|
|
return "error";
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2011-01-21 16:30:17 +00:00
|
|
|
return "unknown";
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
static int
|
|
|
|
virLogOnceInit(void)
|
2012-07-11 13:35:42 +00:00
|
|
|
{
|
2011-03-08 10:31:20 +00:00
|
|
|
const char *pbm = NULL;
|
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(&virLogMutex) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogLock();
|
2011-03-23 19:23:59 +00:00
|
|
|
if (VIR_ALLOC_N(virLogBuffer, virLogSize + 1) < 0) {
|
2011-03-08 10:31:20 +00:00
|
|
|
/*
|
|
|
|
* The debug buffer is not a critical component, allow startup
|
|
|
|
* even in case of failure to allocate it in case of a
|
|
|
|
* configuration mistake.
|
|
|
|
*/
|
|
|
|
virLogSize = 64 * 1024;
|
2011-03-23 19:23:59 +00:00
|
|
|
if (VIR_ALLOC_N(virLogBuffer, virLogSize + 1) < 0) {
|
2011-03-08 10:31:20 +00:00
|
|
|
pbm = "Failed to allocate debug buffer: deactivating debug log\n";
|
|
|
|
virLogSize = 0;
|
|
|
|
} else {
|
|
|
|
pbm = "Failed to allocate debug buffer: reduced to 64 kB\n";
|
|
|
|
}
|
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogLen = 0;
|
|
|
|
virLogStart = 0;
|
|
|
|
virLogEnd = 0;
|
2009-07-01 11:21:15 +00:00
|
|
|
virLogDefaultPriority = VIR_LOG_DEFAULT;
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogUnlock();
|
2011-03-08 10:31:20 +00:00
|
|
|
if (pbm)
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("%s", pbm);
|
2011-01-21 16:30:17 +00:00
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-07-11 13:35:42 +00:00
|
|
|
VIR_ONCE_GLOBAL_INIT(virLog)
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
/**
|
|
|
|
* virLogSetBufferSize:
|
|
|
|
* @size: size of the buffer in kilobytes or <= 0 to deactivate
|
|
|
|
*
|
|
|
|
* Dynamically set the size or deactivate the logging buffer used to keep
|
|
|
|
* a trace of all recent debug output. Note that the content of the buffer
|
|
|
|
* is lost if it gets reallocated.
|
|
|
|
*
|
|
|
|
* Return -1 in case of failure or 0 in case of success
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogSetBufferSize(int size)
|
|
|
|
{
|
2011-03-08 10:31:20 +00:00
|
|
|
int ret = 0;
|
|
|
|
int oldsize;
|
|
|
|
char *oldLogBuffer;
|
|
|
|
const char *pbm = NULL;
|
|
|
|
|
|
|
|
if (size < 0)
|
|
|
|
size = 0;
|
|
|
|
|
2012-07-11 13:35:42 +00:00
|
|
|
if (virLogInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (size * 1024 == virLogSize)
|
2011-03-08 10:31:20 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
|
|
|
|
oldsize = virLogSize;
|
|
|
|
oldLogBuffer = virLogBuffer;
|
|
|
|
|
2011-03-23 19:23:59 +00:00
|
|
|
if (INT_MAX / 1024 <= size) {
|
2011-03-08 10:31:20 +00:00
|
|
|
pbm = "Requested log size of %d kB too large\n";
|
|
|
|
ret = -1;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
virLogSize = size * 1024;
|
2011-03-23 19:23:59 +00:00
|
|
|
if (VIR_ALLOC_N(virLogBuffer, virLogSize + 1) < 0) {
|
2011-03-08 10:31:20 +00:00
|
|
|
pbm = "Failed to allocate debug buffer of %d kB\n";
|
|
|
|
virLogBuffer = oldLogBuffer;
|
|
|
|
virLogSize = oldsize;
|
|
|
|
ret = -1;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(oldLogBuffer);
|
|
|
|
virLogLen = 0;
|
|
|
|
virLogStart = 0;
|
|
|
|
virLogEnd = 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virLogUnlock();
|
|
|
|
if (pbm)
|
|
|
|
VIR_ERROR(pbm, size);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogReset:
|
|
|
|
*
|
|
|
|
* Reset the logging module to its default initial state
|
|
|
|
*
|
|
|
|
* Returns 0 if successful, and -1 in case or error
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogReset(void)
|
|
|
|
{
|
2012-07-11 13:35:42 +00:00
|
|
|
if (virLogInitialize() < 0)
|
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
virLogResetFilters();
|
|
|
|
virLogResetOutputs();
|
|
|
|
virLogLen = 0;
|
|
|
|
virLogStart = 0;
|
|
|
|
virLogEnd = 0;
|
2009-07-01 11:21:15 +00:00
|
|
|
virLogDefaultPriority = VIR_LOG_DEFAULT;
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogUnlock();
|
2011-01-21 16:30:17 +00:00
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/*
|
|
|
|
* Store a string in the ring buffer
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
static void
|
|
|
|
virLogStr(const char *str)
|
2011-09-28 13:20:07 +00:00
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int tmp;
|
2011-09-28 13:20:07 +00:00
|
|
|
int len;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
if ((str == NULL) || (virLogBuffer == NULL) || (virLogSize <= 0))
|
2008-12-22 10:36:54 +00:00
|
|
|
return;
|
2011-09-28 13:20:07 +00:00
|
|
|
len = strlen(str);
|
2011-03-19 02:19:31 +00:00
|
|
|
if (len >= virLogSize)
|
2008-12-22 10:36:54 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copy the data and reset the end, we cycle over the end of the buffer
|
|
|
|
*/
|
2011-03-08 10:31:20 +00:00
|
|
|
if (virLogEnd + len >= virLogSize) {
|
|
|
|
tmp = virLogSize - virLogEnd;
|
2008-12-22 10:36:54 +00:00
|
|
|
memcpy(&virLogBuffer[virLogEnd], str, tmp);
|
2009-09-03 16:36:59 +00:00
|
|
|
memcpy(&virLogBuffer[0], &str[tmp], len - tmp);
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogEnd = len - tmp;
|
|
|
|
} else {
|
|
|
|
memcpy(&virLogBuffer[virLogEnd], str, len);
|
|
|
|
virLogEnd += len;
|
|
|
|
}
|
2011-03-19 02:19:31 +00:00
|
|
|
virLogBuffer[virLogEnd] = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
/*
|
|
|
|
* Update the log length, and if full move the start index
|
|
|
|
*/
|
|
|
|
virLogLen += len;
|
2011-03-08 10:31:20 +00:00
|
|
|
if (virLogLen > virLogSize) {
|
|
|
|
tmp = virLogLen - virLogSize;
|
|
|
|
virLogLen = virLogSize;
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogStart += tmp;
|
2011-03-08 10:31:20 +00:00
|
|
|
if (virLogStart >= virLogSize)
|
|
|
|
virLogStart -= virLogSize;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virLogDumpAllFD(const char *msg, int len)
|
|
|
|
{
|
2011-03-03 08:32:18 +00:00
|
|
|
int i, found = 0;
|
|
|
|
|
2011-03-07 13:23:53 +00:00
|
|
|
if (len <= 0)
|
|
|
|
len = strlen(msg);
|
|
|
|
|
2011-03-03 08:32:18 +00:00
|
|
|
for (i = 0; i < virLogNbOutputs;i++) {
|
|
|
|
if (virLogOutputs[i].f == virLogOutputToFd) {
|
2012-01-25 20:13:25 +00:00
|
|
|
int fd = (intptr_t) virLogOutputs[i].data;
|
2011-03-03 08:32:18 +00:00
|
|
|
|
|
|
|
if (fd >= 0) {
|
|
|
|
ignore_value (safewrite(fd, msg, len));
|
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
ignore_value (safewrite(STDERR_FILENO, msg, len));
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2011-03-03 08:32:18 +00:00
|
|
|
/**
|
|
|
|
* virLogEmergencyDumpAll:
|
|
|
|
* @signum: the signal number
|
|
|
|
*
|
|
|
|
* Emergency function called, possibly from a signal handler.
|
|
|
|
* It need to output the debug ring buffer through the log
|
|
|
|
* output which are safe to use from a signal handler.
|
|
|
|
* In case none is found it is emitted to standard error.
|
2008-12-22 10:36:54 +00:00
|
|
|
*/
|
2011-03-03 08:32:18 +00:00
|
|
|
void
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogEmergencyDumpAll(int signum)
|
|
|
|
{
|
2011-03-07 13:23:53 +00:00
|
|
|
int len;
|
2011-04-14 09:22:35 +00:00
|
|
|
int oldLogStart, oldLogLen;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-03-07 13:23:53 +00:00
|
|
|
switch (signum) {
|
2011-03-08 08:01:25 +00:00
|
|
|
#ifdef SIGFPE
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGFPE:
|
|
|
|
virLogDumpAllFD( "Caught signal Floating-point exception", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSEGV
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGSEGV:
|
|
|
|
virLogDumpAllFD( "Caught Segmentation violation", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGILL
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGILL:
|
|
|
|
virLogDumpAllFD( "Caught illegal instruction", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGABRT
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGABRT:
|
|
|
|
virLogDumpAllFD( "Caught abort signal", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGBUS
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGBUS:
|
|
|
|
virLogDumpAllFD( "Caught bus error", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR2
|
2011-03-07 13:23:53 +00:00
|
|
|
case SIGUSR2:
|
|
|
|
virLogDumpAllFD( "Caught User-defined signal 2", -1);
|
|
|
|
break;
|
2011-03-08 08:01:25 +00:00
|
|
|
#endif
|
2011-03-07 13:23:53 +00:00
|
|
|
default:
|
|
|
|
virLogDumpAllFD( "Caught unexpected signal", -1);
|
|
|
|
break;
|
|
|
|
}
|
2011-03-08 10:31:20 +00:00
|
|
|
if ((virLogBuffer == NULL) || (virLogSize <= 0)) {
|
|
|
|
virLogDumpAllFD(" internal log buffer deactivated\n", -1);
|
2011-03-15 08:10:03 +00:00
|
|
|
return;
|
2011-03-08 10:31:20 +00:00
|
|
|
}
|
2011-03-15 08:10:03 +00:00
|
|
|
|
2011-03-07 13:23:53 +00:00
|
|
|
virLogDumpAllFD(" dumping internal log buffer:\n", -1);
|
|
|
|
virLogDumpAllFD("\n\n ====== start of log =====\n\n", -1);
|
2011-03-15 08:10:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since we can't lock the buffer safely from a signal handler
|
|
|
|
* we mark it as empty in case of concurrent access, and proceed
|
|
|
|
* with the data, at worse we will output something a bit weird
|
|
|
|
* if another thread start logging messages at the same time.
|
|
|
|
* Note that virLogStr() uses virLogEnd for the computations and
|
|
|
|
* writes to the buffer and only then updates virLogLen and virLogStart
|
|
|
|
* so it's best to reset it first.
|
|
|
|
*/
|
|
|
|
oldLogStart = virLogStart;
|
|
|
|
oldLogLen = virLogLen;
|
|
|
|
virLogEnd = 0;
|
|
|
|
virLogLen = 0;
|
|
|
|
virLogStart = 0;
|
|
|
|
|
|
|
|
while (oldLogLen > 0) {
|
|
|
|
if (oldLogStart + oldLogLen < virLogSize) {
|
|
|
|
virLogBuffer[oldLogStart + oldLogLen] = 0;
|
|
|
|
virLogDumpAllFD(&virLogBuffer[oldLogStart], oldLogLen);
|
|
|
|
oldLogStart += oldLogLen;
|
|
|
|
oldLogLen = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
} else {
|
2011-03-15 08:10:03 +00:00
|
|
|
len = virLogSize - oldLogStart;
|
2011-03-08 10:31:20 +00:00
|
|
|
virLogBuffer[virLogSize] = 0;
|
2011-03-15 08:10:03 +00:00
|
|
|
virLogDumpAllFD(&virLogBuffer[oldLogStart], len);
|
|
|
|
oldLogLen -= len;
|
|
|
|
oldLogStart = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-07 13:23:53 +00:00
|
|
|
virLogDumpAllFD("\n\n ====== end of log =====\n\n", -1);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2008-11-06 16:36:07 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogSetDefaultPriority:
|
|
|
|
* @priority: the default priority level
|
|
|
|
*
|
|
|
|
* Set the default priority level, i.e. any logged data of a priority
|
|
|
|
* equal or superior to this level will be logged, unless a specific rule
|
|
|
|
* was defined for the log category of the message.
|
|
|
|
*
|
|
|
|
* Returns 0 if successful, -1 in case of error.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogSetDefaultPriority(virLogPriority priority)
|
|
|
|
{
|
2009-08-06 13:38:11 +00:00
|
|
|
if ((priority < VIR_LOG_DEBUG) || (priority > VIR_LOG_ERROR)) {
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("Ignoring invalid log level setting.");
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2009-08-06 13:38:11 +00:00
|
|
|
}
|
2012-07-11 13:35:42 +00:00
|
|
|
if (virLogInitialize() < 0)
|
|
|
|
return -1;
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogDefaultPriority = priority;
|
2011-01-21 16:30:17 +00:00
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogResetFilters:
|
|
|
|
*
|
|
|
|
* Removes the set of logging filters defined.
|
|
|
|
*
|
|
|
|
* Returns the number of filters removed
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
static int
|
|
|
|
virLogResetFilters(void)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < virLogNbFilters;i++)
|
|
|
|
VIR_FREE(virLogFilters[i].match);
|
|
|
|
VIR_FREE(virLogFilters);
|
|
|
|
virLogNbFilters = 0;
|
2011-01-21 16:30:17 +00:00
|
|
|
return i;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogDefineFilter:
|
|
|
|
* @match: the pattern to match
|
|
|
|
* @priority: the priority to give to messages matching the pattern
|
2012-05-09 14:18:56 +00:00
|
|
|
* @flags: extra flags, see virLogFilterFlags enum
|
2008-12-22 10:36:54 +00:00
|
|
|
*
|
|
|
|
* Defines a pattern used for log filtering, it allow to select or
|
|
|
|
* reject messages independently of the default priority.
|
|
|
|
* The filter defines a rules that will apply only to messages matching
|
|
|
|
* the pattern (currently if @match is a substring of the message category)
|
|
|
|
*
|
|
|
|
* Returns -1 in case of failure or the filter number if successful
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogDefineFilter(const char *match,
|
|
|
|
virLogPriority priority,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:29:02 +00:00
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int i;
|
|
|
|
char *mdup = NULL;
|
|
|
|
|
2012-05-09 14:18:56 +00:00
|
|
|
virCheckFlags(VIR_LOG_STACK_TRACE, -1);
|
2011-07-06 22:29:02 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
if ((match == NULL) || (priority < VIR_LOG_DEBUG) ||
|
|
|
|
(priority > VIR_LOG_ERROR))
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
for (i = 0;i < virLogNbFilters;i++) {
|
|
|
|
if (STREQ(virLogFilters[i].match, match)) {
|
|
|
|
virLogFilters[i].priority = priority;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mdup = strdup(match);
|
2009-11-10 11:56:11 +00:00
|
|
|
if (mdup == NULL) {
|
2008-12-22 10:36:54 +00:00
|
|
|
i = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
i = virLogNbFilters;
|
|
|
|
if (VIR_REALLOC_N(virLogFilters, virLogNbFilters + 1)) {
|
|
|
|
i = -1;
|
|
|
|
VIR_FREE(mdup);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virLogFilters[i].match = mdup;
|
|
|
|
virLogFilters[i].priority = priority;
|
2012-05-09 14:18:56 +00:00
|
|
|
virLogFilters[i].flags = flags;
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogNbFilters++;
|
|
|
|
cleanup:
|
|
|
|
virLogUnlock();
|
2011-01-21 16:30:17 +00:00
|
|
|
return i;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogFiltersCheck:
|
|
|
|
* @input: the input string
|
|
|
|
*
|
|
|
|
* Check the input of the message against the existing filters. Currently
|
|
|
|
* the match is just a substring check of the category used as the input
|
|
|
|
* string, a more subtle approach could be used instead
|
|
|
|
*
|
|
|
|
* Returns 0 if not matched or the new priority if found.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
static int
|
|
|
|
virLogFiltersCheck(const char *input,
|
|
|
|
unsigned int *flags)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int ret = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
for (i = 0;i < virLogNbFilters;i++) {
|
|
|
|
if (strstr(input, virLogFilters[i].match)) {
|
|
|
|
ret = virLogFilters[i].priority;
|
2012-05-09 14:18:56 +00:00
|
|
|
*flags = virLogFilters[i].flags;
|
2008-12-22 10:36:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virLogUnlock();
|
2011-01-21 16:30:17 +00:00
|
|
|
return ret;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogResetOutputs:
|
|
|
|
*
|
|
|
|
* Removes the set of logging output defined.
|
|
|
|
*
|
|
|
|
* Returns the number of output removed
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
static int
|
|
|
|
virLogResetOutputs(void)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0;i < virLogNbOutputs;i++) {
|
|
|
|
if (virLogOutputs[i].c != NULL)
|
|
|
|
virLogOutputs[i].c(virLogOutputs[i].data);
|
2009-10-08 15:05:01 +00:00
|
|
|
VIR_FREE(virLogOutputs[i].name);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(virLogOutputs);
|
|
|
|
i = virLogNbOutputs;
|
|
|
|
virLogNbOutputs = 0;
|
2011-01-21 16:30:17 +00:00
|
|
|
return i;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogDefineOutput:
|
|
|
|
* @f: the function to call to output a message
|
2009-10-08 15:05:01 +00:00
|
|
|
* @c: the function to call to close the output (or NULL)
|
2008-12-22 10:36:54 +00:00
|
|
|
* @data: extra data passed as first arg to the function
|
|
|
|
* @priority: minimal priority for this filter, use 0 for none
|
2009-10-08 15:05:01 +00:00
|
|
|
* @dest: where to send output of this priority
|
|
|
|
* @name: optional name data associated with an output
|
2008-12-22 10:36:54 +00:00
|
|
|
* @flags: extra flag, currently unused
|
|
|
|
*
|
|
|
|
* Defines an output function for log messages. Each message once
|
|
|
|
* gone though filtering is emitted through each registered output.
|
|
|
|
*
|
|
|
|
* Returns -1 in case of failure or the output number if successful
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogDefineOutput(virLogOutputFunc f,
|
|
|
|
virLogCloseFunc c,
|
|
|
|
void *data,
|
|
|
|
virLogPriority priority,
|
|
|
|
virLogDestination dest,
|
|
|
|
const char *name,
|
|
|
|
unsigned int flags)
|
2011-07-06 22:29:02 +00:00
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int ret = -1;
|
2009-10-08 15:05:01 +00:00
|
|
|
char *ndup = NULL;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-07-06 22:29:02 +00:00
|
|
|
virCheckFlags(0, -1);
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
if (f == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2009-10-08 15:05:01 +00:00
|
|
|
if (dest == VIR_LOG_TO_SYSLOG || dest == VIR_LOG_TO_FILE) {
|
|
|
|
if (name == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2009-10-08 15:05:01 +00:00
|
|
|
ndup = strdup(name);
|
|
|
|
if (ndup == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2009-10-08 15:05:01 +00:00
|
|
|
}
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogLock();
|
|
|
|
if (VIR_REALLOC_N(virLogOutputs, virLogNbOutputs + 1)) {
|
2009-11-10 11:56:11 +00:00
|
|
|
VIR_FREE(ndup);
|
2008-12-22 10:36:54 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
ret = virLogNbOutputs++;
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
virLogOutputs[ret].logVersion = true;
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogOutputs[ret].f = f;
|
|
|
|
virLogOutputs[ret].c = c;
|
|
|
|
virLogOutputs[ret].data = data;
|
|
|
|
virLogOutputs[ret].priority = priority;
|
2009-10-08 15:05:01 +00:00
|
|
|
virLogOutputs[ret].dest = dest;
|
|
|
|
virLogOutputs[ret].name = ndup;
|
2008-12-22 10:36:54 +00:00
|
|
|
cleanup:
|
|
|
|
virLogUnlock();
|
2011-01-21 16:30:17 +00:00
|
|
|
return ret;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 13:20:07 +00:00
|
|
|
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
static int
|
|
|
|
virLogFormatString(char **msg,
|
2012-09-27 13:00:21 +00:00
|
|
|
int linenr,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname,
|
2012-09-27 12:58:58 +00:00
|
|
|
virLogPriority priority,
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
const char *str)
|
|
|
|
{
|
|
|
|
int ret;
|
2011-03-30 11:57:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Be careful when changing the following log message formatting, we rely
|
|
|
|
* on it when stripping libvirt debug messages from qemu log files. So when
|
|
|
|
* changing this, you might also need to change the code there.
|
|
|
|
* virLogFormatString() function name is mentioned there so it's sufficient
|
|
|
|
* to just grep for it to find the right place.
|
|
|
|
*/
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
if ((funcname != NULL)) {
|
2012-09-27 13:00:21 +00:00
|
|
|
ret = virAsprintf(msg, "%d: %s : %s:%d : %s\n",
|
2011-09-28 13:20:07 +00:00
|
|
|
virThreadSelfID(), virLogPriorityString(priority),
|
|
|
|
funcname, linenr, str);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
} else {
|
2011-09-28 13:20:07 +00:00
|
|
|
ret = virAsprintf(msg, "%d: %s : %s\n",
|
|
|
|
virThreadSelfID(), virLogPriorityString(priority),
|
|
|
|
str);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
static int
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogVersionString(const char **rawmsg,
|
|
|
|
char **msg)
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
{
|
|
|
|
#ifdef PACKAGER_VERSION
|
|
|
|
# ifdef PACKAGER
|
|
|
|
# define LOG_VERSION_STRING \
|
|
|
|
"libvirt version: " VERSION ", package: " PACKAGER_VERSION " (" PACKAGER ")"
|
|
|
|
# else
|
|
|
|
# define LOG_VERSION_STRING \
|
|
|
|
"libvirt version: " VERSION ", package: " PACKAGER_VERSION
|
|
|
|
# endif
|
|
|
|
#else
|
|
|
|
# define LOG_VERSION_STRING \
|
|
|
|
"libvirt version: " VERSION
|
|
|
|
#endif
|
|
|
|
|
2012-09-27 11:45:33 +00:00
|
|
|
*rawmsg = LOG_VERSION_STRING;
|
2012-09-27 13:28:44 +00:00
|
|
|
return virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, LOG_VERSION_STRING);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogMessage:
|
2012-09-27 13:44:22 +00:00
|
|
|
* @source: where is that message coming from
|
2008-12-22 10:36:54 +00:00
|
|
|
* @priority: the priority level
|
2012-09-27 13:44:22 +00:00
|
|
|
* @filename: file where the message was emitted
|
2008-12-22 10:44:10 +00:00
|
|
|
* @linenr: line where the message was emitted
|
2012-09-27 13:44:22 +00:00
|
|
|
* @funcname: the function emitting the (debug) message
|
2008-12-22 10:36:54 +00:00
|
|
|
* @fmt: the string format
|
|
|
|
* @...: the arguments
|
|
|
|
*
|
2011-12-01 23:08:34 +00:00
|
|
|
* Call the libvirt logger with some information. Based on the configuration
|
2008-12-22 10:36:54 +00:00
|
|
|
* the message may be stored, sent to output or just discarded
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
void
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogMessage(virLogSource source,
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *filename,
|
2012-09-27 13:14:01 +00:00
|
|
|
int linenr,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname,
|
2012-09-27 13:14:01 +00:00
|
|
|
const char *fmt, ...)
|
2012-01-23 14:57:16 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogVMessage(source, priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
filename, linenr, funcname,
|
2012-09-27 13:44:22 +00:00
|
|
|
fmt, ap);
|
2012-01-23 14:57:16 +00:00
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2012-01-23 14:57:16 +00:00
|
|
|
/**
|
|
|
|
* virLogVMessage:
|
2012-09-27 13:44:22 +00:00
|
|
|
* @source: where is that message coming from
|
2012-01-23 14:57:16 +00:00
|
|
|
* @priority: the priority level
|
2012-09-27 13:44:22 +00:00
|
|
|
* @filename: file where the message was emitted
|
2012-01-23 14:57:16 +00:00
|
|
|
* @linenr: line where the message was emitted
|
2012-09-27 13:44:22 +00:00
|
|
|
* @funcname: the function emitting the (debug) message
|
2012-01-23 14:57:16 +00:00
|
|
|
* @fmt: the string format
|
|
|
|
* @vargs: format args
|
|
|
|
*
|
|
|
|
* Call the libvirt logger with some information. Based on the configuration
|
|
|
|
* the message may be stored, sent to output or just discarded
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
void
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogVMessage(virLogSource source,
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *filename,
|
2012-09-27 13:14:01 +00:00
|
|
|
int linenr,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname,
|
2012-09-27 13:14:01 +00:00
|
|
|
const char *fmt,
|
|
|
|
va_list vargs)
|
2011-07-06 22:29:02 +00:00
|
|
|
{
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
static bool logVersionStderr = true;
|
2008-12-22 10:36:54 +00:00
|
|
|
char *str = NULL;
|
2011-03-02 12:26:02 +00:00
|
|
|
char *msg = NULL;
|
2011-11-29 12:32:31 +00:00
|
|
|
char timestamp[VIR_TIME_STRING_BUFLEN];
|
2011-09-28 13:20:07 +00:00
|
|
|
int fprio, i, ret;
|
2011-02-16 23:49:15 +00:00
|
|
|
int saved_errno = errno;
|
2011-03-02 12:26:02 +00:00
|
|
|
int emit = 1;
|
2012-05-09 14:18:56 +00:00
|
|
|
unsigned int filterflags = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-07-11 13:35:42 +00:00
|
|
|
if (virLogInitialize() < 0)
|
|
|
|
return;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
if (fmt == NULL)
|
2011-02-16 23:49:15 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* check against list of specific logging patterns
|
|
|
|
*/
|
2012-09-27 13:44:22 +00:00
|
|
|
fprio = virLogFiltersCheck(filename, &filterflags);
|
2008-12-22 10:36:54 +00:00
|
|
|
if (fprio == 0) {
|
|
|
|
if (priority < virLogDefaultPriority)
|
2011-03-02 12:26:02 +00:00
|
|
|
emit = 0;
|
2011-02-16 23:49:15 +00:00
|
|
|
} else if (priority < fprio) {
|
2011-03-02 12:26:02 +00:00
|
|
|
emit = 0;
|
2011-02-16 23:49:15 +00:00
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-03-08 10:31:20 +00:00
|
|
|
if ((emit == 0) && ((virLogBuffer == NULL) || (virLogSize <= 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/*
|
|
|
|
* serialize the error message, add level and timestamp
|
|
|
|
*/
|
2012-01-23 14:57:16 +00:00
|
|
|
if (virVasprintf(&str, fmt, vargs) < 0) {
|
2011-02-16 23:49:15 +00:00
|
|
|
goto cleanup;
|
2011-05-24 17:20:19 +00:00
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-09-27 13:28:44 +00:00
|
|
|
ret = virLogFormatString(&msg, linenr, funcname, priority, str);
|
2011-02-16 23:49:15 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2011-11-29 12:32:31 +00:00
|
|
|
if (virTimeStringNowRaw(timestamp) < 0)
|
|
|
|
timestamp[0] = '\0';
|
2011-09-28 13:20:07 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/*
|
2011-03-02 12:26:02 +00:00
|
|
|
* Log based on defaults, first store in the history buffer,
|
|
|
|
* then if emit push the message on the outputs defined, if none
|
2008-12-22 10:36:54 +00:00
|
|
|
* use stderr.
|
|
|
|
* NOTE: the locking is a single point of contention for multiple
|
|
|
|
* threads, but avoid intermixing. Maybe set up locks per output
|
|
|
|
* to improve paralellism.
|
|
|
|
*/
|
2011-09-28 13:20:07 +00:00
|
|
|
virLogLock();
|
|
|
|
virLogStr(timestamp);
|
|
|
|
virLogStr(msg);
|
|
|
|
virLogUnlock();
|
2011-03-02 12:26:02 +00:00
|
|
|
if (emit == 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogLock();
|
2011-09-28 13:20:07 +00:00
|
|
|
for (i = 0; i < virLogNbOutputs; i++) {
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
if (priority >= virLogOutputs[i].priority) {
|
|
|
|
if (virLogOutputs[i].logVersion) {
|
2012-09-27 11:45:33 +00:00
|
|
|
const char *rawver;
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
char *ver = NULL;
|
2012-09-27 11:45:33 +00:00
|
|
|
if (virLogVersionString(&rawver, &ver) >= 0)
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputs[i].f(VIR_LOG_FROM_FILE, VIR_LOG_INFO,
|
2012-09-27 13:28:44 +00:00
|
|
|
__FILE__, __LINE__, __func__,
|
2012-09-27 11:45:33 +00:00
|
|
|
timestamp, 0, rawver, ver,
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
virLogOutputs[i].data);
|
|
|
|
VIR_FREE(ver);
|
|
|
|
virLogOutputs[i].logVersion = false;
|
|
|
|
}
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputs[i].f(source, priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
filename, linenr, funcname,
|
2012-05-09 14:18:56 +00:00
|
|
|
timestamp, filterflags,
|
2012-09-27 11:45:33 +00:00
|
|
|
str, msg, virLogOutputs[i].data);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2012-09-27 13:44:22 +00:00
|
|
|
if ((virLogNbOutputs == 0) && (source != VIR_LOG_FROM_ERROR)) {
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
if (logVersionStderr) {
|
2012-09-27 11:45:33 +00:00
|
|
|
const char *rawver;
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
char *ver = NULL;
|
2012-09-27 11:45:33 +00:00
|
|
|
if (virLogVersionString(&rawver, &ver) >= 0)
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputToFd(VIR_LOG_FROM_FILE, VIR_LOG_INFO,
|
2012-09-27 13:28:44 +00:00
|
|
|
__FILE__, __LINE__, __func__,
|
2012-09-27 11:45:33 +00:00
|
|
|
timestamp, 0, rawver, ver,
|
2011-09-28 13:20:07 +00:00
|
|
|
(void *) STDERR_FILENO);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
VIR_FREE(ver);
|
|
|
|
logVersionStderr = false;
|
|
|
|
}
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputToFd(source, priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
filename, linenr, funcname,
|
2012-05-09 14:18:56 +00:00
|
|
|
timestamp, filterflags,
|
2012-09-27 11:45:33 +00:00
|
|
|
str, msg, (void *) STDERR_FILENO);
|
Imprint all logs with version + package build information
The logging functions are enhanced so that immediately prior to
the first log message being printed to any output channel, the
libvirt package version will be printed.
eg
$ LIBVIRT_DEBUG=1 virsh
18:13:28.013: 17536: info : libvirt version: 0.8.7
18:13:28.013: 17536: debug : virInitialize:361 : register drivers
...
The 'configure' script gains two new arguments which can be
used as
--with-packager="Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10"
--with-packager-version="1.fc14"
to allow distros to append a custom string with package specific
data.
The RPM specfile is modified so that it appends the RPM version,
the build host, the build date and the packager name.
eg
$ LIBVIRT_DEBUG=1 virsh
18:14:52.086: 17551: info : libvirt version: 0.8.7, package: 1.fc13 (Fedora Project, x86-01.phx2.fedoraproject.org, 01-27-2011-18:00:10)
18:14:52.086: 17551: debug : virInitialize:361 : register drivers
Thus when distro packagers receive bug reports they can clearly
see what version was in use, even if the bug reporter mistakenly
or intentionally lies about version/builds
* src/util/logging.c: Output version data prior to first log message
* libvirt.spec.in: Include RPM release, date, hostname & packager
* configure.ac: Add --with-packager & --with-packager-version args
2011-01-27 18:11:16 +00:00
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
virLogUnlock();
|
|
|
|
|
2011-02-16 23:49:15 +00:00
|
|
|
cleanup:
|
2012-09-27 11:45:33 +00:00
|
|
|
VIR_FREE(str);
|
2011-03-02 12:26:02 +00:00
|
|
|
VIR_FREE(msg);
|
2011-02-16 23:49:15 +00:00
|
|
|
errno = saved_errno;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-05-09 14:18:56 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
static void
|
|
|
|
virLogStackTraceToFd(int fd)
|
2012-05-09 14:18:56 +00:00
|
|
|
{
|
|
|
|
void *array[100];
|
|
|
|
int size;
|
|
|
|
static bool doneWarning = false;
|
|
|
|
const char *msg = "Stack trace not available on this platform\n";
|
2012-09-05 22:27:42 +00:00
|
|
|
|
|
|
|
#define STRIP_DEPTH 3
|
|
|
|
size = backtrace(array, ARRAY_CARDINALITY(array));
|
|
|
|
if (size) {
|
|
|
|
backtrace_symbols_fd(array + STRIP_DEPTH, size - STRIP_DEPTH, fd);
|
|
|
|
ignore_value(safewrite(fd, "\n", 1));
|
|
|
|
} else if (!doneWarning) {
|
2012-05-09 14:18:56 +00:00
|
|
|
ignore_value(safewrite(fd, msg, strlen(msg)));
|
|
|
|
doneWarning = true;
|
|
|
|
}
|
2012-09-05 22:27:42 +00:00
|
|
|
#undef STRIP_DEPTH
|
2012-05-09 14:18:56 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
static void
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputToFd(virLogSource source ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority priority ATTRIBUTE_UNUSED,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *filename ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
int linenr ATTRIBUTE_UNUSED,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
const char *timestamp,
|
|
|
|
unsigned int flags,
|
|
|
|
const char *rawstr ATTRIBUTE_UNUSED,
|
|
|
|
const char *str,
|
|
|
|
void *data)
|
2011-09-28 13:20:07 +00:00
|
|
|
{
|
2012-01-25 20:13:25 +00:00
|
|
|
int fd = (intptr_t) data;
|
2011-09-28 13:20:07 +00:00
|
|
|
char *msg;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
if (fd < 0)
|
2012-09-20 18:24:00 +00:00
|
|
|
return;
|
2011-09-28 13:20:07 +00:00
|
|
|
|
|
|
|
if (virAsprintf(&msg, "%s: %s", timestamp, str) < 0)
|
2012-09-20 18:24:00 +00:00
|
|
|
return;
|
2011-09-28 13:20:07 +00:00
|
|
|
|
2012-09-20 18:24:00 +00:00
|
|
|
ignore_value(safewrite(fd, msg, strlen(msg)));
|
2011-09-28 13:20:07 +00:00
|
|
|
VIR_FREE(msg);
|
|
|
|
|
2012-05-09 14:18:56 +00:00
|
|
|
if (flags & VIR_LOG_STACK_TRACE)
|
|
|
|
virLogStackTraceToFd(fd);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virLogCloseFd(void *data)
|
2012-06-07 13:16:50 +00:00
|
|
|
{
|
2012-01-25 20:13:25 +00:00
|
|
|
int fd = (intptr_t) data;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-06-07 13:16:50 +00:00
|
|
|
VIR_LOG_CLOSE(fd);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virLogAddOutputToStderr(virLogPriority priority)
|
|
|
|
{
|
2009-10-08 15:05:01 +00:00
|
|
|
if (virLogDefineOutput(virLogOutputToFd, NULL, (void *)2L, priority,
|
|
|
|
VIR_LOG_TO_STDERR, NULL, 0) < 0)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virLogAddOutputToFile(virLogPriority priority,
|
|
|
|
const char *file)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
int fd;
|
|
|
|
|
2009-10-08 15:05:01 +00:00
|
|
|
fd = open(file, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
|
2008-12-22 10:36:54 +00:00
|
|
|
if (fd < 0)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2012-01-25 20:13:25 +00:00
|
|
|
if (virLogDefineOutput(virLogOutputToFd, virLogCloseFd,
|
|
|
|
(void *)(intptr_t)fd,
|
2009-10-08 15:05:01 +00:00
|
|
|
priority, VIR_LOG_TO_FILE, file, 0) < 0) {
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(fd);
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2011-01-21 16:30:17 +00:00
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
#if HAVE_SYSLOG_H
|
2012-09-27 13:14:01 +00:00
|
|
|
static int
|
|
|
|
virLogPrioritySyslog(virLogPriority priority)
|
2012-09-27 11:34:04 +00:00
|
|
|
{
|
|
|
|
switch (priority) {
|
|
|
|
case VIR_LOG_DEBUG:
|
|
|
|
return LOG_DEBUG;
|
|
|
|
case VIR_LOG_INFO:
|
|
|
|
return LOG_INFO;
|
|
|
|
case VIR_LOG_WARN:
|
|
|
|
return LOG_WARNING;
|
|
|
|
case VIR_LOG_ERROR:
|
|
|
|
return LOG_ERR;
|
|
|
|
default:
|
|
|
|
return LOG_ERR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static void
|
2012-09-27 13:44:22 +00:00
|
|
|
virLogOutputToSyslog(virLogSource source ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority priority,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *filename ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
int linenr ATTRIBUTE_UNUSED,
|
2012-09-27 13:28:44 +00:00
|
|
|
const char *funcname ATTRIBUTE_UNUSED,
|
2012-09-27 13:14:01 +00:00
|
|
|
const char *timestamp ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags,
|
|
|
|
const char *rawstr ATTRIBUTE_UNUSED,
|
|
|
|
const char *str,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
2011-09-28 13:20:07 +00:00
|
|
|
{
|
2012-09-20 18:24:00 +00:00
|
|
|
virCheckFlags(VIR_LOG_STACK_TRACE,);
|
2012-05-09 14:18:56 +00:00
|
|
|
|
2012-09-27 11:34:04 +00:00
|
|
|
syslog(virLogPrioritySyslog(priority), "%s", str);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2009-01-20 21:34:44 +00:00
|
|
|
static char *current_ident = NULL;
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virLogCloseSyslog(void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
closelog();
|
2009-01-20 21:34:44 +00:00
|
|
|
VIR_FREE(current_ident);
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virLogAddOutputToSyslog(virLogPriority priority,
|
|
|
|
const char *ident)
|
|
|
|
{
|
2009-01-20 21:34:44 +00:00
|
|
|
/*
|
|
|
|
* ident needs to be kept around on Solaris
|
|
|
|
*/
|
|
|
|
VIR_FREE(current_ident);
|
|
|
|
current_ident = strdup(ident);
|
|
|
|
if (current_ident == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2009-01-20 21:34:44 +00:00
|
|
|
|
|
|
|
openlog(current_ident, 0, 0);
|
2008-12-22 10:36:54 +00:00
|
|
|
if (virLogDefineOutput(virLogOutputToSyslog, virLogCloseSyslog, NULL,
|
2009-10-08 15:05:01 +00:00
|
|
|
priority, VIR_LOG_TO_SYSLOG, ident, 0) < 0) {
|
2008-12-22 10:36:54 +00:00
|
|
|
closelog();
|
2009-01-20 21:34:44 +00:00
|
|
|
VIR_FREE(current_ident);
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2011-01-21 16:30:17 +00:00
|
|
|
return 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2012-09-25 17:31:01 +00:00
|
|
|
|
|
|
|
|
2012-10-01 22:38:56 +00:00
|
|
|
# if USE_JOURNALD
|
2012-09-25 17:31:01 +00:00
|
|
|
# define IOVEC_SET_STRING(iov, str) \
|
|
|
|
do { \
|
|
|
|
struct iovec *_i = &(iov); \
|
|
|
|
_i->iov_base = (char*)str; \
|
|
|
|
_i->iov_len = strlen(str); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
# define IOVEC_SET_INT(iov, buf, val) \
|
|
|
|
do { \
|
|
|
|
struct iovec *_i = &(iov); \
|
|
|
|
_i->iov_base = virFormatIntDecimal(buf, sizeof(buf), val); \
|
|
|
|
_i->iov_len = strlen(buf); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static int journalfd = -1;
|
|
|
|
|
|
|
|
static void
|
|
|
|
virLogOutputToJournald(virLogSource source,
|
|
|
|
virLogPriority priority,
|
|
|
|
const char *filename,
|
|
|
|
int linenr,
|
|
|
|
const char *funcname,
|
|
|
|
const char *timestamp ATTRIBUTE_UNUSED,
|
|
|
|
unsigned int flags,
|
|
|
|
const char *rawstr,
|
|
|
|
const char *str ATTRIBUTE_UNUSED,
|
|
|
|
void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virCheckFlags(VIR_LOG_STACK_TRACE,);
|
|
|
|
int buffd = -1;
|
|
|
|
size_t niov = 0;
|
|
|
|
struct msghdr mh;
|
|
|
|
struct sockaddr_un sa;
|
|
|
|
union {
|
|
|
|
struct cmsghdr cmsghdr;
|
|
|
|
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
|
|
|
} control;
|
|
|
|
struct cmsghdr *cmsg;
|
|
|
|
/* We use /dev/shm instead of /tmp here, since we want this to
|
|
|
|
* be a tmpfs, and one that is available from early boot on
|
|
|
|
* and where unprivileged users can create files. */
|
|
|
|
char path[] = "/dev/shm/journal.XXXXXX";
|
|
|
|
char priostr[INT_BUFSIZE_BOUND(priority)];
|
|
|
|
char linestr[INT_BUFSIZE_BOUND(linenr)];
|
|
|
|
|
2012-10-11 16:31:20 +00:00
|
|
|
/* First message takes up to 4 iovecs, and each
|
2012-09-25 17:31:01 +00:00
|
|
|
* other field needs 3, assuming they don't have
|
|
|
|
* newlines in them
|
|
|
|
*/
|
|
|
|
# define IOV_SIZE (4 + (5 * 3))
|
|
|
|
struct iovec iov[IOV_SIZE];
|
|
|
|
|
|
|
|
if (strchr(rawstr, '\n')) {
|
|
|
|
uint64_t nstr;
|
2012-10-11 16:31:20 +00:00
|
|
|
/* If 'str' contains a newline, then we must
|
2012-09-25 17:31:01 +00:00
|
|
|
* encode the string length, since we can't
|
|
|
|
* rely on the newline for the field separator
|
|
|
|
*/
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "MESSAGE\n");
|
|
|
|
nstr = htole64(strlen(rawstr));
|
|
|
|
iov[niov].iov_base = (char*)&nstr;
|
|
|
|
iov[niov].iov_len = sizeof(nstr);
|
|
|
|
niov++;
|
|
|
|
} else {
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "MESSAGE=");
|
|
|
|
}
|
|
|
|
IOVEC_SET_STRING(iov[niov++], rawstr);
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "PRIORITY=");
|
|
|
|
IOVEC_SET_INT(iov[niov++], priostr, priority);
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "LIBVIRT_SOURCE=");
|
|
|
|
IOVEC_SET_STRING(iov[niov++], virLogSourceTypeToString(source));
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "CODE_FILE=");
|
|
|
|
IOVEC_SET_STRING(iov[niov++], filename);
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "CODE_LINE=");
|
|
|
|
IOVEC_SET_INT(iov[niov++], linestr, linenr);
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "CODE_FUNC=");
|
|
|
|
IOVEC_SET_STRING(iov[niov++], funcname);
|
|
|
|
IOVEC_SET_STRING(iov[niov++], "\n");
|
|
|
|
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
sa.sun_family = AF_UNIX;
|
|
|
|
if (!virStrcpy(sa.sun_path, "/run/systemd/journal/socket", sizeof(sa.sun_path)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
memset(&mh, 0, sizeof(mh));
|
|
|
|
mh.msg_name = &sa;
|
|
|
|
mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(sa.sun_path);
|
|
|
|
mh.msg_iov = iov;
|
|
|
|
mh.msg_iovlen = niov;
|
|
|
|
|
|
|
|
if (sendmsg(journalfd, &mh, MSG_NOSIGNAL) >= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (errno != EMSGSIZE && errno != ENOBUFS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Message was too large, so dump to temporary file
|
|
|
|
* and pass an FD to the journal
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* NB: mkostemp is not declared async signal safe by
|
|
|
|
* POSIX, but this is Linux only code and the GLibc
|
|
|
|
* impl is safe enough, only using open() and inline
|
|
|
|
* asm to read a timestamp (falling back to gettimeofday
|
|
|
|
* on some arches
|
|
|
|
*/
|
|
|
|
if ((buffd = mkostemp(path, O_CLOEXEC|O_RDWR)) < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (unlink(path) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (writev(buffd, iov, niov) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
mh.msg_iov = NULL;
|
|
|
|
mh.msg_iovlen = 0;
|
|
|
|
|
|
|
|
memset(&control, 0, sizeof(control));
|
|
|
|
mh.msg_control = &control;
|
|
|
|
mh.msg_controllen = sizeof(control);
|
|
|
|
|
|
|
|
cmsg = CMSG_FIRSTHDR(&mh);
|
|
|
|
cmsg->cmsg_level = SOL_SOCKET;
|
|
|
|
cmsg->cmsg_type = SCM_RIGHTS;
|
|
|
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
|
|
|
memcpy(CMSG_DATA(cmsg), &buffd, sizeof(int));
|
|
|
|
|
|
|
|
mh.msg_controllen = cmsg->cmsg_len;
|
|
|
|
|
|
|
|
sendmsg(journalfd, &mh, MSG_NOSIGNAL);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_LOG_CLOSE(buffd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void virLogCloseJournald(void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
VIR_LOG_CLOSE(journalfd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virLogAddOutputToJournald(int priority)
|
|
|
|
{
|
|
|
|
if ((journalfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
|
|
|
|
return -1;
|
|
|
|
if (virSetInherit(journalfd, false) < 0) {
|
|
|
|
VIR_LOG_CLOSE(journalfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (virLogDefineOutput(virLogOutputToJournald, virLogCloseJournald, NULL,
|
|
|
|
priority, VIR_LOG_TO_JOURNALD, NULL, 0) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2012-10-01 22:38:56 +00:00
|
|
|
# endif /* USE_JOURNALD */
|
2008-12-22 10:36:54 +00:00
|
|
|
#endif /* HAVE_SYSLOG_H */
|
|
|
|
|
|
|
|
#define IS_SPACE(cur) \
|
|
|
|
((*cur == ' ') || (*cur == '\t') || (*cur == '\n') || \
|
|
|
|
(*cur == '\r') || (*cur == '\\'))
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogParseOutputs:
|
|
|
|
* @outputs: string defining a (set of) output(s)
|
|
|
|
*
|
|
|
|
* The format for an output can be:
|
|
|
|
* x:stderr
|
|
|
|
* output goes to stderr
|
|
|
|
* x:syslog:name
|
|
|
|
* use syslog for the output and use the given name as the ident
|
|
|
|
* x:file:file_path
|
|
|
|
* output to a file, with the given filepath
|
|
|
|
* In all case the x prefix is the minimal level, acting as a filter
|
|
|
|
* 0: everything
|
|
|
|
* 1: DEBUG
|
|
|
|
* 2: INFO
|
|
|
|
* 3: WARNING
|
|
|
|
* 4: ERROR
|
|
|
|
*
|
|
|
|
* Multiple output can be defined in a single @output, they just need to be
|
|
|
|
* separated by spaces.
|
|
|
|
*
|
|
|
|
* Returns the number of output parsed and installed or -1 in case of error
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogParseOutputs(const char *outputs)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
const char *cur = outputs, *str;
|
|
|
|
char *name;
|
2009-10-08 15:05:01 +00:00
|
|
|
char *abspath;
|
2012-09-27 12:58:58 +00:00
|
|
|
virLogPriority prio;
|
2009-08-06 13:38:11 +00:00
|
|
|
int ret = -1;
|
|
|
|
int count = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
if (cur == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
2012-10-24 20:51:44 +00:00
|
|
|
VIR_DEBUG("outputs=%s", outputs);
|
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
virSkipSpaces(&cur);
|
|
|
|
while (*cur != 0) {
|
|
|
|
prio= virParseNumber(&cur);
|
2009-07-01 11:21:15 +00:00
|
|
|
if ((prio < VIR_LOG_DEBUG) || (prio > VIR_LOG_ERROR))
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
if (*cur != ':')
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
cur++;
|
|
|
|
if (STREQLEN(cur, "stderr", 6)) {
|
|
|
|
cur += 6;
|
|
|
|
if (virLogAddOutputToStderr(prio) == 0)
|
2009-08-06 13:38:11 +00:00
|
|
|
count++;
|
2008-12-22 10:36:54 +00:00
|
|
|
} else if (STREQLEN(cur, "syslog", 6)) {
|
|
|
|
cur += 6;
|
|
|
|
if (*cur != ':')
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
cur++;
|
|
|
|
str = cur;
|
|
|
|
while ((*cur != 0) && (!IS_SPACE(cur)))
|
|
|
|
cur++;
|
|
|
|
if (str == cur)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
#if HAVE_SYSLOG_H
|
|
|
|
name = strndup(str, cur - str);
|
|
|
|
if (name == NULL)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
if (virLogAddOutputToSyslog(prio, name) == 0)
|
2009-08-06 13:38:11 +00:00
|
|
|
count++;
|
2008-12-22 10:36:54 +00:00
|
|
|
VIR_FREE(name);
|
|
|
|
#endif /* HAVE_SYSLOG_H */
|
|
|
|
} else if (STREQLEN(cur, "file", 4)) {
|
|
|
|
cur += 4;
|
|
|
|
if (*cur != ':')
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
cur++;
|
|
|
|
str = cur;
|
|
|
|
while ((*cur != 0) && (!IS_SPACE(cur)))
|
|
|
|
cur++;
|
|
|
|
if (str == cur)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
name = strndup(str, cur - str);
|
|
|
|
if (name == NULL)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2009-10-08 15:05:01 +00:00
|
|
|
if (virFileAbsPath(name, &abspath) < 0) {
|
|
|
|
VIR_FREE(name);
|
|
|
|
return -1; /* skip warning here because setting was fine */
|
|
|
|
}
|
|
|
|
if (virLogAddOutputToFile(prio, abspath) == 0)
|
2009-08-06 13:38:11 +00:00
|
|
|
count++;
|
2008-12-22 10:36:54 +00:00
|
|
|
VIR_FREE(name);
|
2009-10-08 15:05:01 +00:00
|
|
|
VIR_FREE(abspath);
|
2012-09-25 17:31:01 +00:00
|
|
|
} else if (STREQLEN(cur, "journald", 8)) {
|
|
|
|
cur += 8;
|
2012-10-01 22:38:56 +00:00
|
|
|
#if USE_JOURNALD
|
2012-09-25 17:31:01 +00:00
|
|
|
if (virLogAddOutputToJournald(prio) == 0)
|
|
|
|
count++;
|
2012-10-01 22:38:56 +00:00
|
|
|
#endif /* USE_JOURNALD */
|
2008-12-22 10:36:54 +00:00
|
|
|
} else {
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
virSkipSpaces(&cur);
|
|
|
|
}
|
2009-08-06 13:38:11 +00:00
|
|
|
ret = count;
|
|
|
|
cleanup:
|
|
|
|
if (ret == -1)
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("Ignoring invalid log output setting.");
|
2011-01-21 16:30:17 +00:00
|
|
|
return ret;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2008-12-22 10:36:54 +00:00
|
|
|
/**
|
|
|
|
* virLogParseFilters:
|
|
|
|
* @filters: string defining a (set of) filter(s)
|
|
|
|
*
|
|
|
|
* The format for a filter is:
|
|
|
|
* x:name
|
|
|
|
* where name is a match string
|
|
|
|
* the x prefix is the minimal level where the messages should be logged
|
|
|
|
* 1: DEBUG
|
|
|
|
* 2: INFO
|
|
|
|
* 3: WARNING
|
|
|
|
* 4: ERROR
|
|
|
|
*
|
|
|
|
* Multiple filter can be defined in a single @filters, they just need to be
|
|
|
|
* separated by spaces.
|
|
|
|
*
|
|
|
|
* Returns the number of filter parsed and installed or -1 in case of error
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogParseFilters(const char *filters)
|
|
|
|
{
|
2008-12-22 10:36:54 +00:00
|
|
|
const char *cur = filters, *str;
|
|
|
|
char *name;
|
2012-09-27 12:58:58 +00:00
|
|
|
virLogPriority prio;
|
2009-08-06 13:38:11 +00:00
|
|
|
int ret = -1;
|
|
|
|
int count = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
if (cur == NULL)
|
2011-01-21 16:30:17 +00:00
|
|
|
return -1;
|
2008-12-22 10:36:54 +00:00
|
|
|
|
|
|
|
virSkipSpaces(&cur);
|
|
|
|
while (*cur != 0) {
|
2012-05-09 14:18:56 +00:00
|
|
|
unsigned int flags = 0;
|
2008-12-22 10:36:54 +00:00
|
|
|
prio= virParseNumber(&cur);
|
2009-07-01 11:21:15 +00:00
|
|
|
if ((prio < VIR_LOG_DEBUG) || (prio > VIR_LOG_ERROR))
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
if (*cur != ':')
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
cur++;
|
2012-05-09 14:18:56 +00:00
|
|
|
if (*cur == '+') {
|
|
|
|
flags |= VIR_LOG_STACK_TRACE;
|
|
|
|
cur++;
|
|
|
|
}
|
2008-12-22 10:36:54 +00:00
|
|
|
str = cur;
|
|
|
|
while ((*cur != 0) && (!IS_SPACE(cur)))
|
|
|
|
cur++;
|
|
|
|
if (str == cur)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2008-12-22 10:36:54 +00:00
|
|
|
name = strndup(str, cur - str);
|
|
|
|
if (name == NULL)
|
2009-08-06 13:38:11 +00:00
|
|
|
goto cleanup;
|
2012-05-09 14:18:56 +00:00
|
|
|
if (virLogDefineFilter(name, prio, flags) >= 0)
|
2009-08-06 13:38:11 +00:00
|
|
|
count++;
|
2008-12-22 10:36:54 +00:00
|
|
|
VIR_FREE(name);
|
|
|
|
virSkipSpaces(&cur);
|
|
|
|
}
|
2009-08-06 13:38:11 +00:00
|
|
|
ret = count;
|
|
|
|
cleanup:
|
|
|
|
if (ret == -1)
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("Ignoring invalid log filter setting.");
|
2011-01-21 16:30:17 +00:00
|
|
|
return ret;
|
2008-12-22 10:36:54 +00:00
|
|
|
}
|
2009-08-06 13:45:50 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-08-06 13:45:50 +00:00
|
|
|
/**
|
|
|
|
* virLogGetDefaultPriority:
|
|
|
|
*
|
|
|
|
* Returns the current logging priority level.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
virLogPriority
|
|
|
|
virLogGetDefaultPriority(void)
|
|
|
|
{
|
2011-01-21 16:30:17 +00:00
|
|
|
return virLogDefaultPriority;
|
2009-08-06 13:45:50 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-10-08 15:05:01 +00:00
|
|
|
/**
|
|
|
|
* virLogGetFilters:
|
|
|
|
*
|
|
|
|
* Returns a string listing the current filters, in the format originally
|
|
|
|
* specified in the config file or environment. Caller must free the
|
|
|
|
* result.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
char *
|
|
|
|
virLogGetFilters(void)
|
|
|
|
{
|
2009-10-08 15:05:01 +00:00
|
|
|
int i;
|
|
|
|
virBuffer filterbuf = VIR_BUFFER_INITIALIZER;
|
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
for (i = 0; i < virLogNbFilters; i++) {
|
2012-05-09 14:18:56 +00:00
|
|
|
const char *sep = ":";
|
|
|
|
if (virLogFilters[i].flags & VIR_LOG_STACK_TRACE)
|
|
|
|
sep = ":+";
|
|
|
|
virBufferAsprintf(&filterbuf, "%d%s%s ",
|
|
|
|
virLogFilters[i].priority,
|
|
|
|
sep,
|
2009-10-08 15:05:01 +00:00
|
|
|
virLogFilters[i].match);
|
|
|
|
}
|
|
|
|
virLogUnlock();
|
|
|
|
|
2009-12-09 23:00:50 +00:00
|
|
|
if (virBufferError(&filterbuf)) {
|
|
|
|
virBufferFreeAndReset(&filterbuf);
|
2009-10-08 15:05:01 +00:00
|
|
|
return NULL;
|
2009-12-09 23:00:50 +00:00
|
|
|
}
|
2009-10-08 15:05:01 +00:00
|
|
|
|
|
|
|
return virBufferContentAndReset(&filterbuf);
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-10-08 15:05:01 +00:00
|
|
|
/**
|
|
|
|
* virLogGetOutputs:
|
|
|
|
*
|
|
|
|
* Returns a string listing the current outputs, in the format originally
|
|
|
|
* specified in the config file or environment. Caller must free the
|
|
|
|
* result.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
char *
|
|
|
|
virLogGetOutputs(void)
|
|
|
|
{
|
2009-10-08 15:05:01 +00:00
|
|
|
int i;
|
|
|
|
virBuffer outputbuf = VIR_BUFFER_INITIALIZER;
|
|
|
|
|
|
|
|
virLogLock();
|
|
|
|
for (i = 0; i < virLogNbOutputs; i++) {
|
2012-09-27 13:04:21 +00:00
|
|
|
virLogDestination dest = virLogOutputs[i].dest;
|
2009-10-08 15:05:01 +00:00
|
|
|
if (i)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&outputbuf, " ");
|
2009-10-08 15:05:01 +00:00
|
|
|
switch (dest) {
|
|
|
|
case VIR_LOG_TO_SYSLOG:
|
|
|
|
case VIR_LOG_TO_FILE:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&outputbuf, "%d:%s:%s",
|
2009-10-08 15:05:01 +00:00
|
|
|
virLogOutputs[i].priority,
|
|
|
|
virLogOutputString(dest),
|
|
|
|
virLogOutputs[i].name);
|
|
|
|
break;
|
|
|
|
default:
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&outputbuf, "%d:%s",
|
2009-10-08 15:05:01 +00:00
|
|
|
virLogOutputs[i].priority,
|
|
|
|
virLogOutputString(dest));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
virLogUnlock();
|
|
|
|
|
2009-12-09 23:00:50 +00:00
|
|
|
if (virBufferError(&outputbuf)) {
|
|
|
|
virBufferFreeAndReset(&outputbuf);
|
2009-10-08 15:05:01 +00:00
|
|
|
return NULL;
|
2009-12-09 23:00:50 +00:00
|
|
|
}
|
2009-10-08 15:05:01 +00:00
|
|
|
|
|
|
|
return virBufferContentAndReset(&outputbuf);
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-08-06 13:45:50 +00:00
|
|
|
/**
|
|
|
|
* virLogGetNbFilters:
|
|
|
|
*
|
|
|
|
* Returns the current number of defined log filters.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogGetNbFilters(void)
|
|
|
|
{
|
2011-01-21 16:30:17 +00:00
|
|
|
return virLogNbFilters;
|
2009-08-06 13:45:50 +00:00
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-08-06 13:45:50 +00:00
|
|
|
/**
|
|
|
|
* virLogGetNbOutputs:
|
|
|
|
*
|
|
|
|
* Returns the current number of defined log outputs.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogGetNbOutputs(void)
|
|
|
|
{
|
2011-01-21 16:30:17 +00:00
|
|
|
return virLogNbOutputs;
|
2009-08-06 13:45:50 +00:00
|
|
|
}
|
2009-08-06 13:55:07 +00:00
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-08-06 13:55:07 +00:00
|
|
|
/**
|
|
|
|
* virLogParseDefaultPriority:
|
|
|
|
* @priority: string defining the desired logging level
|
|
|
|
*
|
|
|
|
* Parses and sets the default log priority level. It can take a string or
|
|
|
|
* number corresponding to the following levels:
|
|
|
|
* 1: DEBUG
|
|
|
|
* 2: INFO
|
|
|
|
* 3: WARNING
|
|
|
|
* 4: ERROR
|
|
|
|
*
|
|
|
|
* Returns the parsed log level or -1 on error.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
int
|
|
|
|
virLogParseDefaultPriority(const char *priority)
|
|
|
|
{
|
2009-08-06 13:55:07 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (STREQ(priority, "1") || STREQ(priority, "debug"))
|
|
|
|
ret = virLogSetDefaultPriority(VIR_LOG_DEBUG);
|
|
|
|
else if (STREQ(priority, "2") || STREQ(priority, "info"))
|
|
|
|
ret = virLogSetDefaultPriority(VIR_LOG_INFO);
|
|
|
|
else if (STREQ(priority, "3") || STREQ(priority, "warning"))
|
|
|
|
ret = virLogSetDefaultPriority(VIR_LOG_WARN);
|
|
|
|
else if (STREQ(priority, "4") || STREQ(priority, "error"))
|
|
|
|
ret = virLogSetDefaultPriority(VIR_LOG_ERROR);
|
|
|
|
else
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("Ignoring invalid log level setting");
|
2009-08-06 13:55:07 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-27 13:14:01 +00:00
|
|
|
|
2009-08-06 13:55:07 +00:00
|
|
|
/**
|
|
|
|
* virLogSetFromEnv:
|
|
|
|
*
|
|
|
|
* Sets virLogDefaultPriority, virLogFilters and virLogOutputs based on
|
|
|
|
* environment variables.
|
|
|
|
*/
|
2012-09-27 13:14:01 +00:00
|
|
|
void
|
|
|
|
virLogSetFromEnv(void)
|
|
|
|
{
|
2009-08-06 13:55:07 +00:00
|
|
|
char *debugEnv;
|
|
|
|
|
|
|
|
debugEnv = getenv("LIBVIRT_DEBUG");
|
|
|
|
if (debugEnv && *debugEnv)
|
|
|
|
virLogParseDefaultPriority(debugEnv);
|
|
|
|
debugEnv = getenv("LIBVIRT_LOG_FILTERS");
|
|
|
|
if (debugEnv && *debugEnv)
|
2010-12-01 16:42:17 +00:00
|
|
|
virLogParseFilters(debugEnv);
|
2009-08-06 13:55:07 +00:00
|
|
|
debugEnv = getenv("LIBVIRT_LOG_OUTPUTS");
|
|
|
|
if (debugEnv && *debugEnv)
|
2010-12-01 16:42:17 +00:00
|
|
|
virLogParseOutputs(debugEnv);
|
2009-08-06 13:55:07 +00:00
|
|
|
}
|