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(a)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