Skip to content

Commit 216714f

Browse files
authored
Merge pull request #143 from alltilla/filterx-vars-function
filterx: add vars() function
2 parents 4b5f9b6 + 2be477b commit 216714f

File tree

8 files changed

+155
-2
lines changed

8 files changed

+155
-2
lines changed

lib/filterx/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ set(FILTERX_HEADERS
3838
filterx/filterx-private.h
3939
filterx/func-istype.h
4040
filterx/func-len.h
41+
filterx/func-vars.h
4142
filterx/expr-plus.h
4243
PARENT_SCOPE
4344
)
@@ -82,6 +83,7 @@ set(FILTERX_SOURCES
8283
filterx/expr-regexp.c
8384
filterx/func-istype.c
8485
filterx/func-len.c
86+
filterx/func-vars.c
8587
filterx/expr-plus.c
8688
filterx/filterx-private.c
8789
PARENT_SCOPE

lib/filterx/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ filterxinclude_HEADERS = \
4040
lib/filterx/expr-regexp.h \
4141
lib/filterx/func-istype.h \
4242
lib/filterx/func-len.h \
43+
lib/filterx/func-vars.h \
4344
lib/filterx/filterx-private.h
4445

4546

@@ -84,6 +85,7 @@ filterx_sources = \
8485
lib/filterx/expr-regexp.c \
8586
lib/filterx/func-istype.c \
8687
lib/filterx/func-len.c \
88+
lib/filterx/func-vars.c \
8789
lib/filterx/filterx-private.c \
8890
lib/filterx/filterx-grammar.y
8991

lib/filterx/filterx-globals.c

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "filterx/object-dict-interface.h"
3333
#include "filterx/func-istype.h"
3434
#include "filterx/func-len.h"
35+
#include "filterx/func-vars.h"
3536

3637
static GHashTable *filterx_builtin_simple_functions = NULL;
3738
static GHashTable *filterx_builtin_function_ctors = NULL;
@@ -81,6 +82,7 @@ _simple_init(void)
8182
g_assert(filterx_builtin_simple_function_register("int", filterx_typecast_integer));
8283
g_assert(filterx_builtin_simple_function_register("double", filterx_typecast_double));
8384
g_assert(filterx_builtin_simple_function_register("len", filterx_simple_function_len));
85+
g_assert(filterx_builtin_simple_function_register("vars", filterx_simple_function_vars));
8486

8587
}
8688

lib/filterx/filterx-scope.c

+24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ filterx_variable_get_nv_handle(FilterXVariable *v)
5959
return v->handle & ~FILTERX_HANDLE_FLOATING_BIT;
6060
}
6161

62+
const gchar *
63+
filterx_variable_get_name(FilterXVariable *v, gssize *len)
64+
{
65+
return log_msg_get_handle_name(filterx_variable_get_nv_handle(v), len);
66+
}
67+
6268
FilterXObject *
6369
filterx_variable_get_value(FilterXVariable *v)
6470
{
@@ -233,6 +239,24 @@ filterx_scope_register_declared_variable(FilterXScope *self,
233239
return v;
234240
}
235241

242+
gboolean
243+
filterx_scope_foreach_variable(FilterXScope *self, FilterXScopeForeachFunc func, gpointer user_data)
244+
{
245+
for (gsize i = 0; i < self->variables->len; i++)
246+
{
247+
FilterXVariable *variable = &g_array_index(self->variables, FilterXVariable, i);
248+
249+
if (filterx_variable_handle_is_floating(variable->handle) &&
250+
!variable->declared && variable->generation != self->generation)
251+
continue;
252+
253+
if (!func(variable, user_data))
254+
return FALSE;
255+
}
256+
257+
return TRUE;
258+
}
259+
236260
/*
237261
* 1) sync objects to message
238262
* 2) drop undeclared objects

lib/filterx/filterx-scope.h

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef enum
3737

3838
gboolean filterx_variable_is_floating(FilterXVariable *v);
3939
gboolean filterx_variable_handle_is_floating(FilterXVariableHandle handle);
40+
const gchar *filterx_variable_get_name(FilterXVariable *v, gssize *len);
4041
FilterXObject *filterx_variable_get_value(FilterXVariable *v);
4142
void filterx_variable_set_value(FilterXVariable *v, FilterXObject *new_value);
4243
void filterx_variable_unset_value(FilterXVariable *v);
@@ -55,6 +56,8 @@ gboolean filterx_variable_is_set(FilterXVariable *v);
5556
*/
5657
typedef struct _FilterXScope FilterXScope;
5758

59+
typedef gboolean (*FilterXScopeForeachFunc)(FilterXVariable *variable, gpointer user_data);
60+
5861
void filterx_scope_set_dirty(FilterXScope *self);
5962
gboolean filterx_scope_is_dirty(FilterXScope *self);
6063
void filterx_scope_sync(FilterXScope *self, LogMessage *msg);
@@ -67,6 +70,7 @@ FilterXVariable *filterx_scope_register_variable(FilterXScope *self,
6770
FilterXVariable *filterx_scope_register_declared_variable(FilterXScope *self,
6871
FilterXVariableHandle handle,
6972
FilterXObject *initial_value);
73+
gboolean filterx_scope_foreach_variable(FilterXScope *self, FilterXScopeForeachFunc func, gpointer user_data);
7074

7175
/* copy on write */
7276
void filterx_scope_write_protect(FilterXScope *self);

lib/filterx/func-vars.c

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2024 Attila Szakacs
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As an additional exemption you are allowed to compile & link against the
19+
* OpenSSL libraries as published by the OpenSSL project. See the file
20+
* COPYING for details.
21+
*
22+
*/
23+
24+
#include "func-vars.h"
25+
#include "filterx-eval.h"
26+
#include "object-json.h"
27+
#include "object-string.h"
28+
29+
static gboolean
30+
_add_to_dict(FilterXVariable *variable, gpointer user_data)
31+
{
32+
FilterXObject *vars = (FilterXObject *) user_data;
33+
34+
gssize name_len;
35+
const gchar *name_str = filterx_variable_get_name(variable, &name_len);
36+
FilterXObject *name = filterx_string_new(name_str, name_len);
37+
38+
FilterXObject *value = filterx_variable_get_value(variable);
39+
FilterXObject *cloned_value = filterx_object_clone(value);
40+
filterx_object_unref(value);
41+
42+
gboolean success = filterx_object_set_subscript(vars, name, &cloned_value);
43+
44+
filterx_object_unref(cloned_value);
45+
filterx_object_unref(name);
46+
return success;
47+
}
48+
49+
FilterXObject *
50+
filterx_simple_function_vars(GPtrArray *args)
51+
{
52+
if (args && args->len != 0)
53+
{
54+
msg_error("filterx: vars() function does not take any arguments");
55+
return NULL;
56+
}
57+
58+
FilterXEvalContext *context = filterx_eval_get_context();
59+
FilterXObject *vars = filterx_json_object_new_empty();
60+
61+
if (filterx_scope_foreach_variable(context->scope, _add_to_dict, vars))
62+
return vars;
63+
64+
filterx_object_unref(vars);
65+
return NULL;
66+
}

lib/filterx/func-vars.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2024 Attila Szakacs
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As an additional exemption you are allowed to compile & link against the
19+
* OpenSSL libraries as published by the OpenSSL project. See the file
20+
* COPYING for details.
21+
*
22+
*/
23+
24+
#ifndef FILTERX_FUNC_VARS_H_INCLUDED
25+
#define FILTERX_FUNC_VARS_H_INCLUDED
26+
27+
#include "filterx/expr-function.h"
28+
29+
FilterXObject *filterx_simple_function_vars(GPtrArray *args);
30+
31+
#endif

tests/light/functional_tests/filterx/test_filterx.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from src.syslog_ng_config.renderer import render_statement
2828

2929

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

@@ -68,7 +68,8 @@ def create_config(config, filterx_expr, msg="foobar"):
6868
log {{
6969
source(genmsg);
7070
if {{
71-
filterx {{ {filterx_expr} \n}};
71+
filterx {{ {filterx_expr_1} \n}};
72+
{"filterx { " + filterx_expr_2 + " };" if filterx_expr_2 is not None else ""}
7273
destination(dest_true);
7374
}} else {{
7475
destination(dest_false);
@@ -1487,3 +1488,24 @@ def test_parse_csv_dialect(config, syslog_ng):
14871488
assert file_true.get_stats()["processed"] == 1
14881489
assert "processed" not in file_false.get_stats()
14891490
assert file_true.read_log() == '["PTHREAD \\"support initialized"]\n'
1491+
1492+
1493+
def test_vars(config, syslog_ng):
1494+
(file_true, file_false) = create_config(
1495+
config,
1496+
filterx_expr_1=r"""
1497+
$logmsg_variable = "foo";
1498+
scope_local_variable = "bar";
1499+
declare pipeline_level_variable = "baz";
1500+
""",
1501+
filterx_expr_2=r"""
1502+
log = otel_logrecord({"body": "foobar", "attributes": {"attribute": 42}});
1503+
js_array = json_array([1, 2, 3, [4, 5, 6]]);
1504+
$MSG = vars();
1505+
""",
1506+
)
1507+
syslog_ng.start(config)
1508+
1509+
assert file_true.get_stats()["processed"] == 1
1510+
assert "processed" not in file_false.get_stats()
1511+
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 commit comments

Comments
 (0)