[libvirt] [PATCH 11/12] Add detailed error information to JSON syslog

Miloslav Trmač mitr at redhat.com
Thu Sep 20 18:24:10 UTC 2012


When logging an error, don't throw away the detailed information.
Example record when using the syslog/json output (line-wrapped for
readability):

Sep 18 17:03:24 kulicka libvirt: @cee: {"msg":"Domain not found",
	"category":"../../src/test/test_driver.c","priority":"err",
	"funcname":"testLookupDomainByName","line":1405,
	"timestamp":"2012-09-18 15:03:24.314+0000","domain":12,"code":42,
	"str1":"Domain not found","str2":""}

The format used in other output destinations (e.g. "syslog", "file") is
still unchanged.

The "domain" and "code" numbers are part of the libvirt ABI in
<libvirt/virterror.h>; therefore log processing tools can rely on them,
unlike the text log string (which is translated depending on locale,
and may be modified for other reasons as well).

Alternatively, the "domain" and "code" fields could contain strings
instead of numbers, but it's not clear that it's worth it:
Advantages of numbers:
* the numbers are shorter
* the ABI guarantees that the numbers won't change
Disadvantages of strings:
* adding a ABI-stable string mapping for virErrorNumber would result
  in additional work each time a new error number is added
  (note that virErrorMsg cannot be used for this because it is
  translated)
* a change in the string mapping would be less likely to be noticed
The advantage of using strings is more readability, but note that the
"msg" field above already contains a readable description of the
error.

The JSON object is again allocated on the stack to avoid the risk of
allocations falling, and for similarity with
virLogOutputToSyslogJSON().

Signed-off-by: Miloslav Trmač <mitr at redhat.com>
---
 src/util/logging.c   |  3 +++
 src/util/virterror.c | 32 +++++++++++++++++++++++++++++---
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/src/util/logging.c b/src/util/logging.c
index 987dffc..642d410 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -972,6 +972,9 @@ static void virLogOutputToSyslogJSON(const char *category, int priority,
         goto error;
     if (virJSONStringGeneratorAddProperties(g, &json) != 0)
         goto error;
+    if (properties != NULL
+        && virJSONStringGeneratorAddProperties(g, properties) != 0)
+        goto error;
     json_string = virJSONStringGeneratorFinishObject(g);
     if (json_string == NULL)
         goto error;
diff --git a/src/util/virterror.c b/src/util/virterror.c
index f93b9f6..9fb60e3 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -32,8 +32,11 @@
 #include "logging.h"
 #include "memory.h"
 #include "threads.h"
+#include "json.h"
 #include "util.h"
 
+#include "intprops.h"
+
 virThreadLocal virLastErr;
 
 virErrorFunc virErrorHandler = NULL;     /* global error handler */
@@ -579,8 +582,6 @@ virDispatchError(virConnectPtr conn)
     }
 }
 
-
-
 /**
  * virRaiseErrorFull:
  * @filename: filename where error was raised
@@ -614,6 +615,14 @@ virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED,
                   int int2,
                   const char *fmt, ...)
 {
+    virJSONObject json;
+    virJSONObjectPair json_pairs[7];
+    virJSONValue json_domain, json_code, json_str1, json_str2, json_str3;
+    virJSONValue json_int1, json_int2;
+    char domain_buf[INT_BUFSIZE_BOUND(domain)];
+    char code_buf[INT_BUFSIZE_BOUND(code)];
+    char int1_buf[INT_BUFSIZE_BOUND(int1)];
+    char int2_buf[INT_BUFSIZE_BOUND(int2)];
     int save_errno = errno;
     virErrorPtr to;
     char *str;
@@ -676,8 +685,25 @@ virRaiseErrorFull(const char *filename ATTRIBUTE_UNUSED,
     priority = virErrorLevelPriority(level);
     if (virErrorLogPriorityFilter)
         priority = virErrorLogPriorityFilter(to, priority);
+    virJSONStaticObjectInitialize (&json, json_pairs);
+    virJSONStaticObjectAppendNumberInt(&json, "domain", &json_domain,
+                                       domain_buf, sizeof(domain_buf), domain);
+    virJSONStaticObjectAppendNumberInt(&json, "code", &json_code,
+                                       code_buf, sizeof(code_buf), code);
+    if (str1 != NULL)
+        virJSONStaticObjectAppendString(&json, "str1", &json_str1, str1);
+    if (str1 != NULL)
+        virJSONStaticObjectAppendString(&json, "str2", &json_str2, str2);
+    if (str3 != NULL)
+        virJSONStaticObjectAppendString(&json, "str3", &json_str3, str3);
+    if (int1 != -1)
+        virJSONStaticObjectAppendNumberInt(&json, "int1", &json_int1,
+                                           int1_buf, sizeof(int1_buf), int1);
+    if (int2 != -1)
+        virJSONStaticObjectAppendNumberInt(&json, "int2", &json_int2,
+                                           int2_buf, sizeof(int2_buf), int2);
     virLogMessage(filename, priority,
-                  funcname, linenr, NULL,
+                  funcname, linenr, &json,
                   virErrorLogPriorityFilter ? 0 : 1,
                   "%s", str);
 
-- 
1.7.11.4




More information about the libvir-list mailing list