Skip to content

Commit

Permalink
Merge pull request #510 from sodomelle/filterx-set-timestamp-func
Browse files Browse the repository at this point in the history
Filterx set timestamp func
  • Loading branch information
alltilla authored Feb 19, 2025
2 parents 205b714 + 6bbcbb6 commit 0c505bb
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/filterx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set(FILTERX_HEADERS
filterx/func-len.h
filterx/func-sdata.h
filterx/func-set-fields.h
filterx/func-set-timestamp.h
filterx/func-str-transform.h
filterx/func-str.h
filterx/func-unset-empties.h
Expand Down Expand Up @@ -118,6 +119,7 @@ set(FILTERX_SOURCES
filterx/func-len.c
filterx/func-sdata.c
filterx/func-set-fields.c
filterx/func-set-timestamp.c
filterx/func-str-transform.c
filterx/func-str.c
filterx/func-unset-empties.c
Expand Down
2 changes: 2 additions & 0 deletions lib/filterx/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ filterxinclude_HEADERS = \
lib/filterx/func-len.h \
lib/filterx/func-sdata.h \
lib/filterx/func-set-fields.h \
lib/filterx/func-set-timestamp.h \
lib/filterx/func-str-transform.h \
lib/filterx/func-str.h \
lib/filterx/func-unset-empties.h \
Expand Down Expand Up @@ -121,6 +122,7 @@ filterx_sources = \
lib/filterx/func-len.c \
lib/filterx/func-sdata.c \
lib/filterx/func-set-fields.c \
lib/filterx/func-set-timestamp.c \
lib/filterx/func-str-transform.c \
lib/filterx/func-str.c \
lib/filterx/func-unset-empties.c \
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 @@ -39,6 +39,7 @@
#include "filterx/func-vars.h"
#include "filterx/func-unset-empties.h"
#include "filterx/func-set-fields.h"
#include "filterx/func-set-timestamp.h"
#include "filterx/func-str.h"
#include "filterx/func-str-transform.h"
#include "filterx/func-flatten.h"
Expand Down Expand Up @@ -156,6 +157,7 @@ _ctors_init(void)
g_assert(filterx_builtin_function_ctor_register("strftime", filterx_function_strftime_new));
g_assert(filterx_builtin_function_ctor_register("keys", filterx_function_keys_new));
g_assert(filterx_builtin_function_ctor_register("vars", filterx_function_vars_new));
g_assert(filterx_builtin_function_ctor_register("set_timestamp", filterx_function_set_timestamp_new));
}

static void
Expand Down
170 changes: 170 additions & 0 deletions lib/filterx/func-set-timestamp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* Copyright (c) 2025 Axoflow
* Copyright (c) 2025 Tamas Kosztyu <[email protected]>
*
* 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-set-timestamp.h"
#include "object-datetime.h"
#include "filterx/object-extractor.h"
#include "filterx/object-primitive.h"
#include "filterx/filterx-eval.h"

#define FILTERX_FUNC_SET_TIMESTAMP_USAGE "Usage: set_timestamp(datetime, stamp=[\"stamp\", \"recvd\"])"

typedef struct FilterXFunctionSetTimestamp_
{
FilterXFunction super;

FilterXExpr *datetime_expr;
LogMessageTimeStamp timestamp_idx;
} FilterXFunctionSetTimestamp;

static FilterXObject *
_set_timestamp_eval(FilterXExpr *s)
{
FilterXFunctionSetTimestamp *self = (FilterXFunctionSetTimestamp *) s;

FilterXObject *datetime_obj = filterx_expr_eval(self->datetime_expr);
if (!datetime_obj)
{
filterx_eval_push_error("Failed to evaluate second argument. " FILTERX_FUNC_SET_TIMESTAMP_USAGE, s, NULL);
return NULL;
}

UnixTime datetime = UNIX_TIME_INIT;

if (!filterx_object_extract_datetime(datetime_obj, &datetime))
{
filterx_object_unref(datetime_obj);
filterx_eval_push_error("Second argument must be of datetime type. " FILTERX_FUNC_SET_TIMESTAMP_USAGE, s, NULL);
return NULL;
}

filterx_object_unref(datetime_obj);

FilterXEvalContext *context = filterx_eval_get_context();
LogMessage *msg = context->msg;

msg->timestamps[self->timestamp_idx] = datetime;

return filterx_boolean_new(TRUE);
}

static void
_set_timestamp_free(FilterXExpr *s)
{
FilterXFunctionSetTimestamp *self = (FilterXFunctionSetTimestamp *) s;

filterx_expr_unref(self->datetime_expr);
filterx_function_free_method(&self->super);
}

static const gchar *
_extract_set_timestamp_idx_str(FilterXFunctionArgs *args, GError **error)
{
gboolean exists;
const gchar *idx_str = filterx_function_args_get_named_literal_string(args, "stamp", NULL, &exists);

if (!exists)
{
return "stamp";
}

return idx_str;
}

static FilterXExpr *
_extract_set_timestamp_datetime_expr(FilterXFunctionArgs *args, GError **error)
{
FilterXExpr *datetime_expr = filterx_function_args_get_expr(args, 0);
if (!datetime_expr)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"argument must be set: datetime. " FILTERX_FUNC_SET_TIMESTAMP_USAGE);
return NULL;
}

return datetime_expr;
}

static gboolean
_extract_set_timestamp_args(FilterXFunctionSetTimestamp *self, FilterXFunctionArgs *args, GError **error)
{
gsize len = filterx_function_args_len(args);

if (len != 1 && len != 2)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"invalid number of arguments. " FILTERX_FUNC_SET_TIMESTAMP_USAGE);
return FALSE;
}

self->datetime_expr = _extract_set_timestamp_datetime_expr(args, error);
if (!self->datetime_expr)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"First argument must be of datetime type. " FILTERX_FUNC_SET_TIMESTAMP_USAGE);
return FALSE;
}

const gchar *idx_str = _extract_set_timestamp_idx_str(args, error);
if (!idx_str)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"Second argument must be string type. " FILTERX_FUNC_SET_TIMESTAMP_USAGE);
return FALSE;
}

self->timestamp_idx = log_msg_lookup_time_stamp_name(idx_str);

if ((self->timestamp_idx != LM_TS_STAMP) && (self->timestamp_idx != LM_TS_RECVD))
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"Invalid timestamp type " FILTERX_FUNC_SET_TIMESTAMP_USAGE);
return FALSE;
}

return TRUE;
}

/* Takes reference of args */
FilterXExpr *
filterx_function_set_timestamp_new(FilterXFunctionArgs *args, GError **error)
{
FilterXFunctionSetTimestamp *self = g_new0(FilterXFunctionSetTimestamp, 1);
filterx_function_init_instance(&self->super, "set_timestamp");

self->super.super.eval = _set_timestamp_eval;
self->super.super.free_fn = _set_timestamp_free;

if (!_extract_set_timestamp_args(self, args, error) ||
!filterx_function_args_check(args, error))
goto error;

filterx_function_args_free(args);
return &self->super.super;

error:
filterx_function_args_free(args);
filterx_expr_unref(&self->super.super);
return NULL;
}
33 changes: 33 additions & 0 deletions lib/filterx/func-set-timestamp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2025 Axoflow
* Copyright (c) 2025 Tamas Kosztyu <[email protected]>
*
* 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_SET_TIMESTAMP_H_INCLUDED
#define FILTERX_FUNC_SET_TIMESTAMP_H_INCLUDED

#include "filterx-object.h"
#include "filterx/expr-function.h"

FilterXExpr *filterx_function_set_timestamp_new(FilterXFunctionArgs *args, GError **error);

#endif
2 changes: 1 addition & 1 deletion lib/filterx/object-datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#include "compat/json.h"

#define FILTERX_FUNC_STRPTIME_USAGE "Usage: strptime(time_str, format_str_1, ..., format_str_N)"
#define FILTERX_FUNC_STRFTIME_USAGE "Usage: strftime(fornat_str, datetime)"
#define FILTERX_FUNC_STRFTIME_USAGE "Usage: strftime(format_str, datetime)"

typedef struct _FilterXDateTime
{
Expand Down
9 changes: 9 additions & 0 deletions news/fx-feature-510.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
`set_timestamp()`: Added new filterx function to set the message timestamps.

Example usage:
```
set_timestamp(datetime, stamp="stamp");
```

Note: Second argument can be "stamp" or "recvd", based on the timestamp to be set.
Default is "stamp".
67 changes: 67 additions & 0 deletions tests/light/functional_tests/filterx/test_filterx.py
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,73 @@ def test_strptime_failure_result(config, syslog_ng):
assert file_true.read_log() == "null\n"


def test_set_timestamp_wrong_param_error_result(config, syslog_ng):
_ = create_config(
config, """
datetime = strptime("2000-01-01T00:00:00 +0200", "%Y-%m-%dT%H:%M:%S %z");
set_timestamp(datetime, bad_param); # wrong parameter
""",
)
with pytest.raises(Exception):
syslog_ng.start(config)


def test_set_timestamp_invalid_stamp_value_error_result(config, syslog_ng):
_ = create_config(
config, """
datetime = strptime("2000-01-01T00:00:00 +0200", "%Y-%m-%dT%H:%M:%S %z");
set_timestamp(datetime, stamp="processed"); # wrong parameter
""",
)
with pytest.raises(Exception):
syslog_ng.start(config)


def test_set_timestamp_set_stamp(config, syslog_ng):
(file_true, file_false) = create_config(
config, """
datetime = strptime("2000-01-01T00:00:00 +0200", "%Y-%m-%dT%H:%M:%S %z");
set_timestamp(datetime, stamp="stamp");
$MSG = $ISODATE;
""",
)
syslog_ng.start(config)

assert file_true.get_stats()["processed"] == 1
assert "processed" not in file_false.get_stats()
assert file_true.read_log() == "2000-01-01T00:00:00+02:00\n"


def test_set_timestamp_set_stamp_default(config, syslog_ng):
(file_true, file_false) = create_config(
config, """
datetime = strptime("2000-01-01T00:00:00 +0200", "%Y-%m-%dT%H:%M:%S %z");
set_timestamp(datetime);
$MSG = $ISODATE;
""",
)
syslog_ng.start(config)

assert file_true.get_stats()["processed"] == 1
assert "processed" not in file_false.get_stats()
assert file_true.read_log() == "2000-01-01T00:00:00+02:00\n"


def test_set_timestamp_set_recvd(config, syslog_ng):
(file_true, file_false) = create_config(
config, """
datetime = strptime("2000-01-01T00:00:00 +0200", "%Y-%m-%dT%H:%M:%S %z");
set_timestamp(datetime, stamp="recvd");
$MSG = $R_ISODATE;
""",
)
syslog_ng.start(config)

assert file_true.get_stats()["processed"] == 1
assert "processed" not in file_false.get_stats()
assert file_true.read_log() == "2000-01-01T00:00:00+02:00\n"


def test_len(config, syslog_ng):
(file_true, file_false) = create_config(
config, r"""
Expand Down

0 comments on commit 0c505bb

Please sign in to comment.