Skip to content

Commit

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

#include "func-update-metric.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_UPDATE_METRIC_USAGE "update_metric(\"key\", labels={\"key\": \"value\"}, increment=1, level=0)"

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

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

static gboolean
_get_increment(FilterXFunctionUpdateMetric *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("metric increment must be an integer", self->increment.expr, increment_obj);

filterx_object_unref(increment_obj);
return success;
}

static FilterXObject *
_eval(FilterXExpr *s)
{
FilterXFunctionUpdateMetric *self = (FilterXFunctionUpdateMetric *) 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 update_metric()", filterx_format_last_error());
filterx_eval_clear_errors();
}

return filterx_boolean_new(TRUE);
}

static void
_free(FilterXExpr *s)
{
FilterXFunctionUpdateMetric *self = (FilterXFunctionUpdateMetric *) 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(FilterXFunctionUpdateMetric *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_UPDATE_METRIC_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_UPDATE_METRIC_USAGE);
return FALSE;
}

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

return TRUE;
}

static gboolean
_extract_level_arg(FilterXFunctionUpdateMetric *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_UPDATE_METRIC_USAGE);
return FALSE;
}

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

return TRUE;
}

static gboolean
_init_metrics(FilterXFunctionUpdateMetric *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(FilterXFunctionUpdateMetric *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_UPDATE_METRIC_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_update_metric_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error)
{
FilterXFunctionUpdateMetric *self = g_new0(FilterXFunctionUpdateMetric, 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(update_metric, filterx_function_update_metric_new);
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/func-update-metric.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(update_metric),
};

gboolean
Expand Down

0 comments on commit d3d37cc

Please sign in to comment.