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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list