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 a '--with-package-string' argument
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-package-string arg
---
configure.ac | 10 ++++++
libvirt.spec.in | 7 ++++
src/util/logging.c | 86 +++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 88 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index f310a5e..92d77e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,16 @@ AC_SUBST([LIBVIRT_VERSION])
AC_SUBST([LIBVIRT_VERSION_INFO])
AC_SUBST([LIBVIRT_VERSION_NUMBER])
+AC_ARG_WITH([package-string],
+ [AS_HELP_STRING([--with-package-string],
+ [Extra package name/version string])],
+ [],[])
+if test "x$with_package_string" != "xno"
+then
+ AC_DEFINE_UNQUOTED([PACKAGE_STRING], ["$with_package_string"],
+ [Extra package name/version string])
+fi
+
dnl Required minimum versions of all libs we depend on
LIBXML_REQUIRED="2.6.0"
GNUTLS_REQUIRED="1.0.25"
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 0a2d10e..43c9067 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -592,6 +592,12 @@ of recent versions of Linux (and other OSes).
%define _without_dtrace --without-dtrace
%endif
+%define when %(date +"%%m-%%d-%%Y-%%H:%%M:%%S")
+%define where %(hostname)
+%define who %{?packager}%{!?packager:Unknown}
+%define with_package_string --with-package-string="%{release} (%{who}, %{when},
%{where})"
+
+
%configure %{?_without_xen} \
%{?_without_qemu} \
%{?_without_openvz} \
@@ -626,6 +632,7 @@ of recent versions of Linux (and other OSes).
%{?_without_macvtap} \
%{?_without_audit} \
%{?_without_dtrace} \
+ %{with_package_string} \
--with-qemu-user=%{qemu_user} \
--with-qemu-group=%{qemu_group} \
--with-init-script=redhat \
diff --git a/src/util/logging.c b/src/util/logging.c
index a80c3e3..5102e06 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -108,6 +108,7 @@ static int virLogNbFilters = 0;
* after filtering, multiple output can be used simultaneously
*/
struct _virLogOutput {
+ bool logVersion;
void *data;
virLogOutputFunc f;
virLogCloseFunc c;
@@ -490,6 +491,7 @@ int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void
*data,
goto cleanup;
}
ret = virLogNbOutputs++;
+ virLogOutputs[ret].logVersion = true;
virLogOutputs[ret].f = f;
virLogOutputs[ret].c = c;
virLogOutputs[ret].data = data;
@@ -501,6 +503,50 @@ cleanup:
return ret;
}
+static int
+virLogFormatString(char **msg,
+ const char *funcname,
+ long long linenr,
+ struct tm *time_info,
+ struct timeval *cur_time,
+ int priority,
+ const char *str)
+{
+ int ret;
+ if ((funcname != NULL)) {
+ ret = virAsprintf(msg, "%02d:%02d:%02d.%03d: %d: %s : %s:%lld : %s\n",
+ time_info->tm_hour, time_info->tm_min,
+ time_info->tm_sec, (int) cur_time->tv_usec / 1000,
+ virThreadSelfID(),
+ virLogPriorityString(priority), funcname, linenr, str);
+ } else {
+ ret = virAsprintf(msg, "%02d:%02d:%02d.%03d: %d: %s : %s\n",
+ time_info->tm_hour, time_info->tm_min,
+ time_info->tm_sec, (int) cur_time->tv_usec / 1000,
+ virThreadSelfID(),
+ virLogPriorityString(priority), str);
+ }
+ return ret;
+}
+
+static int
+virLogVersionString(char **msg,
+ struct tm *time_info,
+ struct timeval *cur_time)
+{
+#ifdef PACKAGE_STRING
+# define LOG_VERSION_STRING \
+ "libvirt version: " VERSION ", package: " PACKAGE_STRING
+#else
+# define LOG_VERSION_STRING \
+ "libvirt version: " VERSION
+#endif
+
+ return virLogFormatString(msg, NULL, 0,
+ time_info, cur_time,
+ VIR_LOG_INFO, LOG_VERSION_STRING);
+}
+
/**
* virLogMessage:
* @category: where is that message coming from
@@ -516,6 +562,7 @@ cleanup:
*/
void virLogMessage(const char *category, int priority, const char *funcname,
long long linenr, int flags, const char *fmt, ...) {
+ static bool logVersionStderr = true;
char *str = NULL;
char *msg;
struct timeval cur_time;
@@ -547,19 +594,9 @@ void virLogMessage(const char *category, int priority, const char
*funcname,
gettimeofday(&cur_time, NULL);
localtime_r(&cur_time.tv_sec, &time_info);
- if ((funcname != NULL)) {
- ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %d: %s : %s:%lld :
%s\n",
- time_info.tm_hour, time_info.tm_min,
- time_info.tm_sec, (int) cur_time.tv_usec / 1000,
- virThreadSelfID(),
- virLogPriorityString(priority), funcname, linenr, str);
- } else {
- ret = virAsprintf(&msg, "%02d:%02d:%02d.%03d: %d: %s : %s\n",
- time_info.tm_hour, time_info.tm_min,
- time_info.tm_sec, (int) cur_time.tv_usec / 1000,
- virThreadSelfID(),
- virLogPriorityString(priority), str);
- }
+ ret = virLogFormatString(&msg, funcname, linenr,
+ &time_info, &cur_time,
+ priority, str);
VIR_FREE(str);
if (ret < 0) {
/* apparently we're running out of memory */
@@ -578,12 +615,31 @@ void virLogMessage(const char *category, int priority, const char
*funcname,
virLogStr(msg, len);
virLogLock();
for (i = 0; i < virLogNbOutputs;i++) {
- if (priority >= virLogOutputs[i].priority)
+ if (priority >= virLogOutputs[i].priority) {
+ if (virLogOutputs[i].logVersion) {
+ char *ver = NULL;
+ if (virLogVersionString(&ver, &time_info, &cur_time) >=
0)
+ virLogOutputs[i].f(category, priority, __func__, __LINE__,
+ ver, strlen(ver),
+ virLogOutputs[i].data);
+ VIR_FREE(ver);
+ virLogOutputs[i].logVersion = false;
+ }
virLogOutputs[i].f(category, priority, funcname, linenr,
msg, len, virLogOutputs[i].data);
+ }
}
- if ((virLogNbOutputs == 0) && (flags != 1))
+ if ((virLogNbOutputs == 0) && (flags != 1)) {
+ if (logVersionStderr) {
+ char *ver = NULL;
+ if (virLogVersionString(&ver, &time_info, &cur_time) >= 0)
+ ignore_value (safewrite(STDERR_FILENO,
+ ver, strlen(ver)));
+ VIR_FREE(ver);
+ logVersionStderr = false;
+ }
ignore_value (safewrite(STDERR_FILENO, msg, len));
+ }
virLogUnlock();
VIR_FREE(msg);
--
1.7.3.4