Skip to content

Commit

Permalink
metrics-probe/filterx: implement metrics_probe()
Browse files Browse the repository at this point in the history
Signed-off-by: Attila Szakacs <[email protected]>
  • Loading branch information
alltilla committed Jul 22, 2024
1 parent b8807ec commit 46d21f7
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 1 deletion.
193 changes: 193 additions & 0 deletions modules/metrics-probe/filterx/metrics-probe-filterx.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,196 @@
*/

#include "metrics-probe-filterx.h"
#include "filterx/filterx-metrics.h"
#include "filterx/expr-literal.h"
#include "filterx/filterx-eval.h"
#include "filterx/object-primitive.h"
#include "stats/stats.h"

#define FILTERX_FUNC_METRICS_PROBE_USAGE "metrics_probe(\"key\", labels={\"key\": \"value\"}, increment=1, level=0)"

typedef struct FilterXFunctionMetricsProbe_
{
FilterXFunction super;
FilterXMetrics *metrics;
gint level;

struct
{
FilterXExpr *expr;
gint64 value;
} increment;
} FilterXFunctionMetricsProbe;

static gboolean
_get_increment(FilterXFunctionMetricsProbe *self, gint64 *increment)
{
if (!self->increment.expr)
{
*increment = self->increment.value;
return TRUE;
}

FilterXObject *increment_obj = filterx_expr_eval_typed(self->increment.expr);
if (!increment_obj)
return FALSE;

gboolean success = filterx_integer_unwrap(increment_obj, increment);
if (!success)
filterx_eval_push_error("metrics increment must be an integer", self->increment.expr, increment_obj);

filterx_object_unref(increment_obj);
return success;
}

static FilterXObject *
_eval(FilterXExpr *s)
{
FilterXFunctionMetricsProbe *self = (FilterXFunctionMetricsProbe *) s;

gboolean success = FALSE;

gint64 increment;
if (!_get_increment(self, &increment))
goto exit;

StatsCounterItem *counter = filterx_metrics_get_stats_counter(self->metrics);
if (!counter)
goto exit;

stats_counter_add(counter, increment);
success = TRUE;

exit:
if (!success)
{
msg_error("FilterX: Failed to process metrics_probe()", filterx_format_last_error());
filterx_eval_clear_errors();
}

return filterx_boolean_new(TRUE);
}

static void
_free(FilterXExpr *s)
{
FilterXFunctionMetricsProbe *self = (FilterXFunctionMetricsProbe *) s;

if (self->metrics)
filterx_metrics_free(self->metrics);
filterx_expr_unref(self->increment.expr);

filterx_function_free_method(&self->super);
}

static gboolean
_extract_increment_arg(FilterXFunctionMetricsProbe *self, FilterXFunctionArgs *args, GError **error)
{
self->increment.value = 1;
self->increment.expr = filterx_function_args_get_named_expr(args, "increment");

if (self->increment.expr && filterx_expr_is_literal(self->increment.expr))
{
FilterXObject *increment_obj = filterx_expr_eval_typed(self->increment.expr);
if (!increment_obj)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"failed to evaluate increment. " FILTERX_FUNC_METRICS_PROBE_USAGE);
return FALSE;
}

gboolean success = filterx_integer_unwrap(increment_obj, &self->increment.value);
filterx_object_unref(increment_obj);
if (!success)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"failed to set increment, increment must be integer. " FILTERX_FUNC_METRICS_PROBE_USAGE);
return FALSE;
}

filterx_expr_unref(self->increment.expr);
self->increment.expr = NULL;
}

return TRUE;
}

static gboolean
_extract_level_arg(FilterXFunctionMetricsProbe *self, FilterXFunctionArgs *args, GError **error)
{
gboolean exists;
gboolean arg_error;
self->level = filterx_function_args_get_named_literal_integer(args, "level", &exists, &arg_error);

if (arg_error)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"failed to set level, level must be a literal integer. " FILTERX_FUNC_METRICS_PROBE_USAGE);
return FALSE;
}

if (!exists)
self->level = STATS_LEVEL0;

return TRUE;
}

static gboolean
_init_metrics(FilterXFunctionMetricsProbe *self, FilterXFunctionArgs *args, GError **error)
{
FilterXExpr *key = filterx_function_args_get_expr(args, 0);
FilterXExpr *labels = filterx_function_args_get_named_expr(args, "labels");

self->metrics = filterx_metrics_new(0, key, labels);

filterx_expr_unref(key);
filterx_expr_unref(labels);

return !!self->metrics;
}

static gboolean
_extract_args(FilterXFunctionMetricsProbe *self, FilterXFunctionArgs *args, GError **error)
{
if (filterx_function_args_len(args) != 1)
{
g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL,
"invalid number of arguments. " FILTERX_FUNC_METRICS_PROBE_USAGE);
return FALSE;
}

if (!_extract_increment_arg(self, args, error))
return FALSE;

if (!_extract_level_arg(self, args, error))
return FALSE;

if (!_init_metrics(self, args, error))
return FALSE;

return TRUE;
}

FilterXFunction *
filterx_function_metrics_probe_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error)
{
FilterXFunctionMetricsProbe *self = g_new0(FilterXFunctionMetricsProbe, 1);
filterx_function_init_instance(&self->super, function_name);

self->super.super.eval = _eval;
self->super.super.free_fn = _free;

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

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

error:
filterx_function_args_free(args);
filterx_expr_unref(&self->super.super);
return NULL;
}

FILTERX_FUNCTION(metrics_probe, filterx_function_metrics_probe_new);
7 changes: 7 additions & 0 deletions modules/metrics-probe/filterx/metrics-probe-filterx.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@
#ifndef METRICS_PROBE_FILTERX_H_INCLUDED
#define METRICS_PROBE_FILTERX_H_INCLUDED

#include "filterx/expr-function.h"

FILTERX_FUNCTION_DECLARE(metrics_probe);

FilterXFunction *filterx_function_metrics_probe_new(const gchar *function_name, FilterXFunctionArgs *args,
GError **error);

#endif
5 changes: 4 additions & 1 deletion modules/metrics-probe/metrics-probe-plugin.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2023 Attila Szakacs
* Copyright (c) 2024 Axoflow
* Copyright (c) 2023-2024 Attila Szakacs <[email protected]>
*
* 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
Expand All @@ -23,6 +24,7 @@
#include "cfg-parser.h"
#include "plugin.h"
#include "plugin-types.h"
#include "filterx/metrics-probe-filterx.h"

extern CfgParser metrics_probe_parser;

Expand All @@ -33,6 +35,7 @@ static Plugin metrics_probe_plugins[] =
.name = "metrics-probe",
.parser = &metrics_probe_parser,
},
FILTERX_FUNCTION_PLUGIN(metrics_probe),
};

gboolean
Expand Down

0 comments on commit 46d21f7

Please sign in to comment.