Skip to content

Commit

Permalink
Merge pull request #143 from alltilla/filterx-vars-function
Browse files Browse the repository at this point in the history
filterx: add vars() function
  • Loading branch information
bazsi authored Jun 6, 2024
2 parents 4b5f9b6 + 2be477b commit 216714f
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/filterx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set(FILTERX_HEADERS
filterx/filterx-private.h
filterx/func-istype.h
filterx/func-len.h
filterx/func-vars.h
filterx/expr-plus.h
PARENT_SCOPE
)
Expand Down Expand Up @@ -82,6 +83,7 @@ set(FILTERX_SOURCES
filterx/expr-regexp.c
filterx/func-istype.c
filterx/func-len.c
filterx/func-vars.c
filterx/expr-plus.c
filterx/filterx-private.c
PARENT_SCOPE
Expand Down
2 changes: 2 additions & 0 deletions lib/filterx/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ filterxinclude_HEADERS = \
lib/filterx/expr-regexp.h \
lib/filterx/func-istype.h \
lib/filterx/func-len.h \
lib/filterx/func-vars.h \
lib/filterx/filterx-private.h


Expand Down Expand Up @@ -84,6 +85,7 @@ filterx_sources = \
lib/filterx/expr-regexp.c \
lib/filterx/func-istype.c \
lib/filterx/func-len.c \
lib/filterx/func-vars.c \
lib/filterx/filterx-private.c \
lib/filterx/filterx-grammar.y

Expand Down
2 changes: 2 additions & 0 deletions lib/filterx/filterx-globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "filterx/object-dict-interface.h"
#include "filterx/func-istype.h"
#include "filterx/func-len.h"
#include "filterx/func-vars.h"

static GHashTable *filterx_builtin_simple_functions = NULL;
static GHashTable *filterx_builtin_function_ctors = NULL;
Expand Down Expand Up @@ -81,6 +82,7 @@ _simple_init(void)
g_assert(filterx_builtin_simple_function_register("int", filterx_typecast_integer));
g_assert(filterx_builtin_simple_function_register("double", filterx_typecast_double));
g_assert(filterx_builtin_simple_function_register("len", filterx_simple_function_len));
g_assert(filterx_builtin_simple_function_register("vars", filterx_simple_function_vars));

}

Expand Down
24 changes: 24 additions & 0 deletions lib/filterx/filterx-scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ filterx_variable_get_nv_handle(FilterXVariable *v)
return v->handle & ~FILTERX_HANDLE_FLOATING_BIT;
}

const gchar *
filterx_variable_get_name(FilterXVariable *v, gssize *len)
{
return log_msg_get_handle_name(filterx_variable_get_nv_handle(v), len);
}

FilterXObject *
filterx_variable_get_value(FilterXVariable *v)
{
Expand Down Expand Up @@ -233,6 +239,24 @@ filterx_scope_register_declared_variable(FilterXScope *self,
return v;
}

gboolean
filterx_scope_foreach_variable(FilterXScope *self, FilterXScopeForeachFunc func, gpointer user_data)
{
for (gsize i = 0; i < self->variables->len; i++)
{
FilterXVariable *variable = &g_array_index(self->variables, FilterXVariable, i);

if (filterx_variable_handle_is_floating(variable->handle) &&
!variable->declared && variable->generation != self->generation)
continue;

if (!func(variable, user_data))
return FALSE;
}

return TRUE;
}

/*
* 1) sync objects to message
* 2) drop undeclared objects
Expand Down
4 changes: 4 additions & 0 deletions lib/filterx/filterx-scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ typedef enum

gboolean filterx_variable_is_floating(FilterXVariable *v);
gboolean filterx_variable_handle_is_floating(FilterXVariableHandle handle);
const gchar *filterx_variable_get_name(FilterXVariable *v, gssize *len);
FilterXObject *filterx_variable_get_value(FilterXVariable *v);
void filterx_variable_set_value(FilterXVariable *v, FilterXObject *new_value);
void filterx_variable_unset_value(FilterXVariable *v);
Expand All @@ -55,6 +56,8 @@ gboolean filterx_variable_is_set(FilterXVariable *v);
*/
typedef struct _FilterXScope FilterXScope;

typedef gboolean (*FilterXScopeForeachFunc)(FilterXVariable *variable, gpointer user_data);

void filterx_scope_set_dirty(FilterXScope *self);
gboolean filterx_scope_is_dirty(FilterXScope *self);
void filterx_scope_sync(FilterXScope *self, LogMessage *msg);
Expand All @@ -67,6 +70,7 @@ FilterXVariable *filterx_scope_register_variable(FilterXScope *self,
FilterXVariable *filterx_scope_register_declared_variable(FilterXScope *self,
FilterXVariableHandle handle,
FilterXObject *initial_value);
gboolean filterx_scope_foreach_variable(FilterXScope *self, FilterXScopeForeachFunc func, gpointer user_data);

/* copy on write */
void filterx_scope_write_protect(FilterXScope *self);
Expand Down
66 changes: 66 additions & 0 deletions lib/filterx/func-vars.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2024 Attila Szakacs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, 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
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/

#include "func-vars.h"
#include "filterx-eval.h"
#include "object-json.h"
#include "object-string.h"

static gboolean
_add_to_dict(FilterXVariable *variable, gpointer user_data)
{
FilterXObject *vars = (FilterXObject *) user_data;

gssize name_len;
const gchar *name_str = filterx_variable_get_name(variable, &name_len);
FilterXObject *name = filterx_string_new(name_str, name_len);

FilterXObject *value = filterx_variable_get_value(variable);
FilterXObject *cloned_value = filterx_object_clone(value);
filterx_object_unref(value);

gboolean success = filterx_object_set_subscript(vars, name, &cloned_value);

filterx_object_unref(cloned_value);
filterx_object_unref(name);
return success;
}

FilterXObject *
filterx_simple_function_vars(GPtrArray *args)
{
if (args && args->len != 0)
{
msg_error("filterx: vars() function does not take any arguments");
return NULL;
}

FilterXEvalContext *context = filterx_eval_get_context();
FilterXObject *vars = filterx_json_object_new_empty();

if (filterx_scope_foreach_variable(context->scope, _add_to_dict, vars))
return vars;

filterx_object_unref(vars);
return NULL;
}
31 changes: 31 additions & 0 deletions lib/filterx/func-vars.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024 Attila Szakacs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, 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
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/

#ifndef FILTERX_FUNC_VARS_H_INCLUDED
#define FILTERX_FUNC_VARS_H_INCLUDED

#include "filterx/expr-function.h"

FilterXObject *filterx_simple_function_vars(GPtrArray *args);

#endif
26 changes: 24 additions & 2 deletions tests/light/functional_tests/filterx/test_filterx.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from src.syslog_ng_config.renderer import render_statement


def create_config(config, filterx_expr, msg="foobar"):
def create_config(config, filterx_expr_1, filterx_expr_2=None, msg="foobar"):
file_true = config.create_file_destination(file_name="dest-true.log", template="'$MSG\n'")
file_false = config.create_file_destination(file_name="dest-false.log", template="'$MSG\n'")

Expand Down Expand Up @@ -68,7 +68,8 @@ def create_config(config, filterx_expr, msg="foobar"):
log {{
source(genmsg);
if {{
filterx {{ {filterx_expr} \n}};
filterx {{ {filterx_expr_1} \n}};
{"filterx { " + filterx_expr_2 + " };" if filterx_expr_2 is not None else ""}
destination(dest_true);
}} else {{
destination(dest_false);
Expand Down Expand Up @@ -1487,3 +1488,24 @@ def test_parse_csv_dialect(config, syslog_ng):
assert file_true.get_stats()["processed"] == 1
assert "processed" not in file_false.get_stats()
assert file_true.read_log() == '["PTHREAD \\"support initialized"]\n'


def test_vars(config, syslog_ng):
(file_true, file_false) = create_config(
config,
filterx_expr_1=r"""
$logmsg_variable = "foo";
scope_local_variable = "bar";
declare pipeline_level_variable = "baz";
""",
filterx_expr_2=r"""
log = otel_logrecord({"body": "foobar", "attributes": {"attribute": 42}});
js_array = json_array([1, 2, 3, [4, 5, 6]]);
$MSG = vars();
""",
)
syslog_ng.start(config)

assert file_true.get_stats()["processed"] == 1
assert "processed" not in file_false.get_stats()
assert file_true.read_log() == '{"logmsg_variable":"foo","pipeline_level_variable":"baz","log":{"body":"foobar","attributes":{"attribute":42}},"js_array":[1,2,3,[4,5,6]]}\n'

0 comments on commit 216714f

Please sign in to comment.