[syslog-ng] [PATCH 3/3] format-json: Support type hints
Gergely Nagy
algernon at balabit.hu
Thu Nov 15 18:24:18 CET 2012
Unfortunately, format-json does not use the yacc grammar to parse its
options, so we have to implement our own: this is what
value_pairs_parse_type() does, conveniently hidden, so that
value_pairs_new_from_cmdline() will do the right thing, and annotate
the constructed templates with type hints.
The assumption made here is that if a template string has '(' and a
')' after, then it is a type-hinted template. This may be refined
later to be stricter (for example, to require the closing parens to be
at the end).
And since we can construct type-hinted templates from the
command-line, we can teach $(format-json) to handle these types too!
Signed-off-by: Gergely Nagy <algernon at balabit.hu>
---
lib/value-pairs.c | 32 ++++++++++++++++++++++++++++++--
modules/json/format-json.c | 35 ++++++++++++++++++++++++++++++-----
modules/json/tests/test_json.c | 12 ++++++++++++
3 files changed, 72 insertions(+), 7 deletions(-)
diff --git a/lib/value-pairs.c b/lib/value-pairs.c
index da2e391..a8511fd 100644
--- a/lib/value-pairs.c
+++ b/lib/value-pairs.c
@@ -151,6 +151,32 @@ value_pairs_add_glob_pattern(ValuePairs *vp, const gchar *pattern,
vp->patterns[i] = p;
}
+static void
+value_pairs_parse_type(gchar *spec, gchar **value, gchar **type)
+{
+ char *sp, *ep;
+
+ *type = NULL;
+
+ sp = strchr(spec, '(');
+ if (sp == NULL)
+ {
+ *value = spec;
+ return;
+ }
+ ep = strchr(sp, ')');
+ if (ep == NULL)
+ {
+ *value = spec;
+ return;
+ }
+
+ *value = sp + 1;
+ *type = spec;
+ sp[0] = '\0';
+ ep[0] = '\0';
+}
+
gboolean
value_pairs_add_pair_with_type(ValuePairs *vp, GlobalConfig *cfg,
const gchar *key, const gchar *type,
@@ -770,7 +796,7 @@ vp_cmdline_parse_pair (const gchar *option_name, const gchar *value,
gpointer *args = (gpointer *) data;
ValuePairs *vp = (ValuePairs *) args[1];
GlobalConfig *cfg = (GlobalConfig *) args[0];
- gchar **kv;
+ gchar **kv, *v, *t;
vp_cmdline_parse_rekey_finish (data);
if (!g_strstr_len (value, strlen (value), "="))
@@ -781,7 +807,9 @@ vp_cmdline_parse_pair (const gchar *option_name, const gchar *value,
}
kv = g_strsplit(value, "=", 2);
- value_pairs_add_pair (vp, cfg, kv[0], kv[1]);
+ value_pairs_parse_type(kv[1], &v, &t);
+
+ value_pairs_add_pair_with_type(vp, cfg, kv[0], t, v, NULL);
g_free (kv[0]);
g_free (kv[1]);
diff --git a/modules/json/format-json.c b/modules/json/format-json.c
index 4b79701..cbdb513 100644
--- a/modules/json/format-json.c
+++ b/modules/json/format-json.c
@@ -172,11 +172,36 @@ tf_json_value(const gchar *name, const gchar *prefix,
if (state->need_comma)
g_string_append_c(state->buffer, ',');
- g_string_append_c(state->buffer, '"');
- g_string_append_escaped(state->buffer, name);
- g_string_append(state->buffer, "\":\"");
- g_string_append_escaped(state->buffer, value);
- g_string_append_c(state->buffer, '"');
+ switch (type)
+ {
+ case TEMPLATE_TYPE_STRING:
+ case TEMPLATE_TYPE_DATETIME:
+ default:
+ g_string_append_c(state->buffer, '"');
+ g_string_append_escaped(state->buffer, name);
+ g_string_append(state->buffer, "\":\"");
+ g_string_append_escaped(state->buffer, value);
+ g_string_append_c(state->buffer, '"');
+ break;
+ case TEMPLATE_TYPE_INT32:
+ case TEMPLATE_TYPE_INT64:
+ g_string_append_c(state->buffer, '"');
+ g_string_append_escaped(state->buffer, name);
+ g_string_append(state->buffer, "\":");
+ g_string_append(state->buffer, value);
+ break;
+ case TEMPLATE_TYPE_BOOLEAN:
+ {
+ g_string_append_c(state->buffer, '"');
+ g_string_append_escaped(state->buffer, name);
+ g_string_append(state->buffer, "\":");
+ if (value[0] == 't' || value[0] == 'T' || value[0] == '1')
+ g_string_append(state->buffer, "true");
+ else
+ g_string_append(state->buffer, "false");
+ break;
+ }
+ }
state->need_comma = TRUE;
diff --git a/modules/json/tests/test_json.c b/modules/json/tests/test_json.c
index 8087c3e..ada48b6 100644
--- a/modules/json/tests/test_json.c
+++ b/modules/json/tests/test_json.c
@@ -23,6 +23,17 @@ test_format_json_rekey(void)
"{\"_msg\":{\"text\":\"dotted\"}}");
}
+void
+test_format_json_with_type_hints(void)
+{
+ assert_template_format("$(format-json i32=int32(1234))",
+ "{\"i32\":1234}");
+ assert_template_format("$(format-json \"i=ifoo(\")",
+ "{\"i\":\"ifoo(\"}");
+ assert_template_format("$(format-json b=boolean(TRUE))",
+ "{\"b\":true}");
+}
+
int
main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
{
@@ -34,6 +45,7 @@ main(int argc G_GNUC_UNUSED, char *argv[] G_GNUC_UNUSED)
test_format_json();
test_format_json_rekey();
+ test_format_json_with_type_hints();
deinit_template_tests();
app_shutdown();
--
1.7.10.4
More information about the syslog-ng
mailing list