Skip to content

Commit

Permalink
filter: Implement label key-value filtering
Browse files Browse the repository at this point in the history
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
  • Loading branch information
cosmo0920 committed May 9, 2024
1 parent f0b16e9 commit f6770ef
Show file tree
Hide file tree
Showing 2 changed files with 331 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/cmetrics/cmt_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@ int cmt_filter(struct cmt *dst, struct cmt *src,
void *compare_ctx, int (*compare)(void *compare_ctx, const char *str, size_t slen),
int flags);

int cmt_filter_with_label_pair(struct cmt *dst, struct cmt *src,
const char *label_key,
const char *label_value);

#endif
327 changes: 327 additions & 0 deletions src/cmt_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,300 @@ static int filter_context_label_key(struct cmt *dst, struct cmt *src,
return CMT_FILTER_SUCCESS;
}

static int filter_get_label_index(struct cmt_map *src, const char *label_key)
{
struct cfl_list *head;
struct cmt_map_label *label;
size_t index = 0;

cfl_list_foreach(head, &src->label_keys) {
label = cfl_list_entry(head, struct cmt_map_label, _head);
if (strcasecmp(label->name, label_key) == 0) {
return index;
}

index++;
}

return -1;
}

int metrics_check_label_value_existence(struct cmt_metric *metric,
size_t label_index,
const char *label_value)
{
struct cfl_list *iterator;
size_t index;
struct cmt_map_label *label = NULL;

index = 0;

cfl_list_foreach(iterator, &metric->labels) {
label = cfl_list_entry(iterator, struct cmt_map_label, _head);

if (label_index == index) {
break;
}

index++;
}

if (label_index != index) {
return CMT_FALSE;
}

if (label == NULL) {
return CMT_FALSE;
}

if (label->name == NULL) {
return CMT_FALSE;
}

if (strncasecmp(label->name, label_value, strlen(label->name)) == 0) {
return CMT_TRUE;
}

return CMT_FALSE;
}

static int metrics_map_drop_label_value_pairs(struct cmt_map *map,
size_t label_index,
const char *label_value)
{
struct cfl_list *head;
struct cmt_metric *metric;
int result;

result = CMT_FALSE;

cfl_list_foreach(head, &map->metrics) {
metric = cfl_list_entry(head, struct cmt_metric, _head);

result = metrics_check_label_value_existence(metric,
label_index,
label_value);

if (result == CMT_TRUE) {
result = CMT_TRUE;
break;
}
}

if (result == CMT_TRUE) {
cmt_map_metric_destroy(metric);
}

return result;
}

static int filter_context_label_key_value(struct cmt *dst, struct cmt *src,
const char *label_key, const char *label_value)
{
int ret;
char **labels = NULL;
struct cfl_list *head;
struct cmt_map *map;
struct cmt_counter *counter;
struct cmt_gauge *gauge;
struct cmt_untyped *untyped;
struct cmt_histogram *histogram;
struct cmt_summary *summary;
size_t index = 0;

/* Counters */
cfl_list_foreach(head, &src->counters) {
counter = cfl_list_entry(head, struct cmt_counter, _head);

ret = cmt_cat_copy_label_keys(counter->map, (char **) &labels);
if (ret == -1) {
return -1;
}

map = cmt_map_create(CMT_COUNTER, &counter->opts,
counter->map->label_count,
labels, (void *) counter);
free(labels);
if (!map) {
cmt_log_error(src, "unable to allocate map for counter");
return -1;
}

ret = cmt_cat_copy_map(&counter->opts, map, counter->map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

index = filter_get_label_index(map, label_key);
if (index != -1) {
metrics_map_drop_label_value_pairs(map, index, label_value);
}

ret = cmt_cat_counter(dst, counter, map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

cmt_map_destroy(map);
}

/* Gauges */
cfl_list_foreach(head, &src->gauges) {
gauge = cfl_list_entry(head, struct cmt_gauge, _head);

ret = cmt_cat_copy_label_keys(gauge->map, (char **) &labels);
if (ret == -1) {
return -1;
}

map = cmt_map_create(CMT_GAUGE, &gauge->opts,
gauge->map->label_count,
labels, (void *) gauge);
free(labels);
if (!map) {
cmt_log_error(src, "unable to allocate map for gauge");
return -1;
}

ret = cmt_cat_copy_map(&gauge->opts, map, gauge->map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

index = filter_get_label_index(map, label_key);
if (index != -1) {
metrics_map_drop_label_value_pairs(map, index, label_value);
}

ret = cmt_cat_gauge(dst, gauge, map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

cmt_map_destroy(map);
}

/* Untyped */
cfl_list_foreach(head, &src->untypeds) {
untyped = cfl_list_entry(head, struct cmt_untyped, _head);

ret = cmt_cat_copy_label_keys(untyped->map, (char **) &labels);
if (ret == -1) {
return -1;
}

map = cmt_map_create(CMT_UNTYPED, &gauge->opts,
untyped->map->label_count,
labels, (void *) untyped);
free(labels);
if (!map) {
cmt_log_error(src, "unable to allocate map for untyped");
return -1;
}

ret = cmt_cat_copy_map(&untyped->opts, map, untyped->map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

index = filter_get_label_index(map, label_key);
if (index != -1) {
metrics_map_drop_label_value_pairs(map, index, label_value);
}

ret = cmt_cat_untyped(dst, untyped, map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

cmt_map_destroy(map);
}

/* Histogram */
cfl_list_foreach(head, &src->histograms) {
histogram = cfl_list_entry(head, struct cmt_histogram, _head);

ret = cmt_cat_copy_label_keys(histogram->map, (char **) &labels);
if (ret == -1) {
return -1;
}

map = cmt_map_create(CMT_HISTOGRAM, &histogram->opts,
histogram->map->label_count,
labels, (void *) histogram);
free(labels);
if (!map) {
cmt_log_error(src, "unable to allocate map for histogram");
return -1;
}

ret = cmt_cat_copy_map(&histogram->opts, map, histogram->map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

index = filter_get_label_index(map, label_key);
if (index != -1) {
metrics_map_drop_label_value_pairs(map, index, label_value);
}

ret = cmt_cat_histogram(dst, histogram, map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

cmt_map_destroy(map);
}

/* Summary */
cfl_list_foreach(head, &src->summaries) {
summary = cfl_list_entry(head, struct cmt_summary, _head);

ret = cmt_cat_copy_label_keys(summary->map, (char **) &labels);
if (ret == -1) {
return -1;
}

map = cmt_map_create(CMT_SUMMARY, &summary->opts,
summary->map->label_count,
labels, (void *) summary);
free(labels);
if (!map) {
cmt_log_error(src, "unable to allocate map for summary");
return -1;
}

ret = cmt_cat_copy_map(&summary->opts, map, summary->map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

index = filter_get_label_index(map, label_key);
if (index != -1) {
metrics_map_drop_label_value_pairs(map, index, label_value);
}

ret = cmt_cat_summary(dst, summary, map);
if (ret == -1) {
cmt_map_destroy(map);
return -1;
}

cmt_map_destroy(map);
}

return CMT_FILTER_SUCCESS;
}

static int compare_fqname(struct cmt_opts *src, const char *fqname,
void *compare_ctx, int (*compare)(void *compare_ctx, const char *str, size_t slen),
int flags)
Expand Down Expand Up @@ -287,6 +581,39 @@ static int filter_context_fqname(struct cmt *dst, struct cmt *src,
return CMT_FILTER_SUCCESS;
}

int cmt_filter_with_label_pair(struct cmt *dst, struct cmt *src,
const char *label_key,
const char *label_value)
{
int ret = CMT_FILTER_SUCCESS;

if (!dst) {
return CMT_FILTER_INVALID_ARGUMENT;
}

if (!src) {
return CMT_FILTER_INVALID_ARGUMENT;
}

if (label_key == NULL) {
return CMT_FILTER_INVALID_ARGUMENT;
}

if (label_value == NULL) {
return CMT_FILTER_INVALID_ARGUMENT;
}

if (label_key != NULL && label_value != NULL) {
ret = filter_context_label_key_value(dst, src, label_key, label_value);
}

if (ret != CMT_FILTER_SUCCESS) {
return CMT_FILTER_FAILED_OPERATION;
}

return ret;
}

int cmt_filter(struct cmt *dst, struct cmt *src,
const char *fqname, const char *label_key,
void *compare_ctx, int (*compare)(void *compare_ctx, const char *str, size_t slen),
Expand Down

0 comments on commit f6770ef

Please sign in to comment.