Hi, I've integrated this patch into 3.3 as agreed, it needed some slight modifications, but I've done that while integrating. Thanks. On Sun, 2011-04-24 at 11:30 +0200, Gergely Nagy wrote:
The template function implementation below is a port of Balint Kovacs' format_json work, from syslog-ng 3.2 to 3.3, and to json-c and value-pairs().
The usage is as simple as:
destination d_json { file("/tmp/messages.json" template("$(format_json --scope selected_macros --scope nv_pairs)")); };
Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- configure.in | 26 ++++++++++ modules/Makefile.am | 2 +- modules/tfjson/Makefile.am | 11 ++++ modules/tfjson/tfjson.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletions(-) create mode 100644 modules/tfjson/Makefile.am create mode 100644 modules/tfjson/tfjson.c
diff --git a/configure.in b/configure.in index 16f70c1..284b33d 100644 --- a/configure.in +++ b/configure.in @@ -26,6 +26,7 @@ OPENSSL_MIN_VERSION="0.9.8" LIBDBI_MIN_VERSION="0.8.0" IVYKIS_MIN_VERSION="0.18" PCRE_MIN_VERSION="6.1" +JSON_C_MIN_VERSION="0.9"
dnl *************************************************************************** dnl Initial setup @@ -162,6 +163,10 @@ AC_ARG_WITH(ivykis, Link against the system supplied or the builting ivykis library.] ,,with_ivykis="internal")
+AC_ARG_ENABLE(json, + [ --enable-json Enable support for JSON template formatting (default: auto)] + ,,enable_json="auto") + dnl *************************************************************************** dnl Checks for programs. AC_PROG_CC @@ -537,6 +542,23 @@ if test "x$linking_mode" != "xdynamic" -a "x$blb_cv_static_glib" = "xno"; then fi
dnl *************************************************************************** +dnl json-glib headers/libraries +dnl *************************************************************************** +if test "x$enable_json" = "xyes" -o "x$enable_json" = "xauto"; then + PKG_CHECK_MODULES(JSON, json >= $JSON_C_MIN_VERSION,,JSON_LIBS="") + if test -z "$JSON_LIBS"; then + if test "x$enable_json" = "xyes"; then + AC_MSG_ERROR(Cannot find json >= $JSON_C_MIN_VERSION.) + else + AC_MSG_WARN(Cannot find json >= $JSON_C_MIN_VERSION.) + fi + enable_json="no" + else + enable_json="yes" + fi +fi + +dnl *************************************************************************** dnl pcre headers/libraries dnl ***************************************************************************
@@ -893,6 +915,7 @@ AM_CONDITIONAL(ENABLE_SQL, [test "$enable_sql" = "yes"]) AM_CONDITIONAL(ENABLE_SUN_STREAMS, [test "$enable_sun_streams" = "yes"]) AM_CONDITIONAL(ENABLE_PACCT, [test "$enable_pacct" = "yes"]) AM_CONDITIONAL(ENABLE_MONGODB, [test "$enable_mongodb" = "yes"]) +AM_CONDITIONAL(ENABLE_JSON, [test "$enable_json" = "yes"])
# substitution into manual pages expanded_sysconfdir=[`patheval $sysconfdir | sed -e 's/-/\\\\-/g'`] @@ -953,6 +976,7 @@ AC_OUTPUT(dist.conf modules/pacctformat/Makefile modules/basicfuncs/Makefile modules/convertfuncs/Makefile + modules/tfjson/Makefile scripts/Makefile scripts/update-patterndb doc/Makefile @@ -1000,4 +1024,6 @@ echo " SSL support (module) : ${enable_ssl:=no}" echo " SQL support (module) : ${enable_sql:=no}" echo " PACCT module (EXPERIMENTAL) : ${enable_pacct:=no}" echo " MongoDB destination (module): ${enable_mongodb:=no}" +echo " JSON support (module) : ${enable_json:=no}" +
diff --git a/modules/Makefile.am b/modules/Makefile.am index 38cde6b..46de2b8 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = afsocket afsql afstreams affile afprog afuser afmongodb csvparser confgen syslogformat pacctformat basicfuncs convertfuncs dbparser dummy +SUBDIRS = afsocket afsql afstreams affile afprog afuser afmongodb csvparser confgen syslogformat pacctformat basicfuncs convertfuncs dbparser tfjson dummy diff --git a/modules/tfjson/Makefile.am b/modules/tfjson/Makefile.am new file mode 100644 index 0000000..8b30f83 --- /dev/null +++ b/modules/tfjson/Makefile.am @@ -0,0 +1,11 @@ +moduledir = @moduledir@ +export top_srcdir + +if ENABLE_JSON +AM_CPPFLAGS = -I$(top_srcdir)/lib -I../../lib @JSON_CFLAGS@ +module_LTLIBRARIES = libtfjson.la + +libtfjson_la_SOURCES = tfjson.c +libtfjson_la_LIBADD = ../../lib/libsyslog-ng.la @JSON_LIBS@ +libtfjson_la_LDFLAGS = -avoid-version +endif diff --git a/modules/tfjson/tfjson.c b/modules/tfjson/tfjson.c new file mode 100644 index 0000000..f23b2ac --- /dev/null +++ b/modules/tfjson/tfjson.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2002-2011 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011 Balint Kovacs <blint@balabit.hu> + * Copyright (c) 2011 Gergely Nagy <algernon@balabit.hu> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "plugin.h" +#include "templates.h" +#include "filter.h" +#include "filter-expr-parser.h" +#include "cfg.h" + +#include <json.h> + +static gboolean +tf_json_prepare(LogTemplateFunction *self, LogTemplate *parent, + gint argc, gchar *argv[], + gpointer *state, GDestroyNotify *state_destroy, + GError **error) +{ + ValuePairs *vp; + + vp = value_pairs_new_from_cmdline (parent->cfg, argc, argv, error); + if (!vp) + return FALSE; + + *state = vp; + *state_destroy = (GDestroyNotify) value_pairs_free; + + return TRUE; +} + +static gboolean +tf_json_foreach (const gchar *name, const gchar *value, gpointer user_data) +{ + json_object *root = (json_object *)user_data; + json_object *this; + + this = json_object_new_string (value); + json_object_object_add (root, name, this); + + return FALSE; +} + +static json_object * +tf_json_format_message(ValuePairs *vp, LogMessage *msg) +{ + json_object *root; + + root = json_object_new_object(); + value_pairs_foreach (vp, tf_json_foreach, msg, 0, root); + + return root; +} + +static void +tf_json_call(LogTemplateFunction *self, gpointer state, GPtrArray *arg_bufs, + LogMessage **messages, gint num_messages, LogTemplateOptions *opts, + gint tz, gint seq_num, const gchar *context_id, GString *result) +{ + gint i; + ValuePairs *vp = (ValuePairs *)state; + + for (i = 0; i < num_messages; i++) + { + LogMessage *msg = messages[i]; + json_object *json; + + json = tf_json_format_message(vp, msg); + g_string_append(result, json_object_to_json_string (json)); + json_object_put(json); + } +} + +static void +tf_json_eval (LogTemplateFunction *self, gpointer state, GPtrArray *arg_bufs, + LogMessage **messages, gint num_messages, LogTemplateOptions *opts, + gint tz, gint seq_num) +{ + return; +} + +TEMPLATE_FUNCTION(tf_json, tf_json_prepare, tf_json_eval, tf_json_call, NULL); + +static Plugin builtin_tmpl_func_plugins[] = + { + TEMPLATE_FUNCTION_PLUGIN(tf_json, "format_json"), + }; + +gboolean +tfjson_module_init(GlobalConfig *cfg, CfgArgs *args) +{ + plugin_register(cfg, builtin_tmpl_func_plugins, G_N_ELEMENTS(builtin_tmpl_func_plugins)); + return TRUE; +}
-- Bazsi