Coverage Report

Created: 2026-06-07 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/plugins/processor_sampling/sampling_conditions.c
Line
Count
Source
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2026 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include <fluent-bit/flb_processor_plugin.h>
21
22
#include "sampling.h"
23
#include "sampling_cond_attribute.h"
24
25
struct sampling_condition *cond_status_codes_create(struct sampling *ctx,
26
                                                    struct sampling_conditions *sampling_conditions,
27
                                                    struct cfl_variant *settings);
28
29
static int condition_type_str_to_int(char *type_str)
30
0
{
31
0
    if (strcasecmp(type_str, "status_code") == 0) {
32
0
        return SAMPLING_COND_STATUS_CODE;
33
0
    }
34
0
    else if (strcasecmp(type_str, "latency") == 0) {
35
0
        return SAMPLING_COND_LATENCY;
36
0
    }
37
0
    else if (strcasecmp(type_str, "string_attribute") == 0) {
38
0
        return SAMPLING_COND_STRING_ATTRIBUTE;
39
0
    }
40
0
    else if (strcasecmp(type_str, "numeric_attribute") == 0) {
41
0
        return SAMPLING_COND_NUMERIC_ATTRIBUTE;
42
0
    }
43
0
    else if (strcasecmp(type_str, "boolean_attribute") == 0) {
44
0
        return SAMPLING_COND_BOOLEAN_ATTRIBUTE;
45
0
    }
46
0
    else if (strcasecmp(type_str, "span_count") == 0) {
47
0
        return SAMPLING_COND_SPAN_COUNT;
48
0
    }
49
0
    else if (strcasecmp(type_str, "trace_state") == 0) {
50
0
        return SAMPLING_COND_TRACE_STATE;
51
0
    }
52
53
0
    return -1;
54
0
}
55
56
void sampling_conditions_destroy(struct sampling_conditions *sampling_conditions)
57
0
{
58
0
    struct cfl_list *tmp;
59
0
    struct cfl_list *head;
60
0
    struct sampling_condition *sampling_condition;
61
62
0
    if (!sampling_conditions) {
63
0
        return;
64
0
    }
65
66
0
    cfl_list_foreach_safe(head, tmp, &sampling_conditions->list) {
67
0
        sampling_condition = cfl_list_entry(head, struct sampling_condition, _head);
68
0
        if (sampling_condition->type == SAMPLING_COND_STATUS_CODE) {
69
0
            cond_status_codes_destroy(sampling_condition);
70
0
        }
71
0
        else if (sampling_condition->type == SAMPLING_COND_LATENCY) {
72
0
            cond_latency_destroy(sampling_condition);
73
0
        }
74
0
        else if (sampling_condition->type == SAMPLING_COND_STRING_ATTRIBUTE) {
75
0
            cond_string_attr_destroy(sampling_condition);
76
0
        }
77
0
        else if (sampling_condition->type == SAMPLING_COND_NUMERIC_ATTRIBUTE) {
78
0
            cond_numeric_attr_destroy(sampling_condition);
79
0
        }
80
0
        else if (sampling_condition->type == SAMPLING_COND_BOOLEAN_ATTRIBUTE) {
81
0
            cond_boolean_attr_destroy(sampling_condition);
82
0
        }
83
0
        else if (sampling_condition->type == SAMPLING_COND_SPAN_COUNT) {
84
0
            cond_span_count_destroy(sampling_condition);
85
0
        }
86
0
        else if (sampling_condition->type == SAMPLING_COND_TRACE_STATE) {
87
0
            cond_trace_state_destroy(sampling_condition);
88
0
        }
89
90
0
        cfl_list_del(&sampling_condition->_head);
91
0
        flb_free(sampling_condition);
92
0
    }
93
94
0
    flb_free(sampling_conditions);
95
0
}
96
97
int sampling_conditions_check(struct sampling *ctx, struct sampling_conditions *sampling_conditions,
98
                              struct trace_entry *trace_entry, struct ctrace_span *span)
99
0
{
100
0
    int ret;
101
0
    struct cfl_list *tmp;
102
0
    struct cfl_list *head;
103
0
    struct sampling_condition *sampling_condition;
104
105
0
    if (!sampling_conditions) {
106
0
        return FLB_TRUE;
107
0
    }
108
109
0
    cfl_list_foreach_safe(head, tmp, &sampling_conditions->list) {
110
0
        sampling_condition = cfl_list_entry(head, struct sampling_condition, _head);
111
112
0
        ret = FLB_FALSE;
113
114
0
        if (sampling_condition->type == SAMPLING_COND_STATUS_CODE) {
115
0
            ret = cond_status_codes_check(sampling_condition, span);
116
0
        }
117
0
        else if (sampling_condition->type == SAMPLING_COND_LATENCY) {
118
0
            ret = cond_latency_check(sampling_condition, span);
119
0
        }
120
0
        else if (sampling_condition->type == SAMPLING_COND_STRING_ATTRIBUTE) {
121
0
            ret = cond_attr_check(sampling_condition, span, ATTRIBUTE_TYPE_STRING);
122
0
        }
123
0
        else if (sampling_condition->type == SAMPLING_COND_NUMERIC_ATTRIBUTE) {
124
0
            ret = cond_attr_check(sampling_condition, span, ATTRIBUTE_TYPE_NUMERIC);
125
0
        }
126
0
        else if (sampling_condition->type == SAMPLING_COND_BOOLEAN_ATTRIBUTE) {
127
0
            ret = cond_attr_check(sampling_condition, span, ATTRIBUTE_TYPE_BOOLEAN);
128
0
        }
129
0
        else if (sampling_condition->type == SAMPLING_COND_SPAN_COUNT) {
130
0
            ret = cond_span_count_check(sampling_condition, trace_entry, span);
131
0
        }
132
0
        else if (sampling_condition->type == SAMPLING_COND_TRACE_STATE) {
133
0
            ret = cond_trace_state_check(sampling_condition, span);
134
0
        }
135
136
0
        if (ret == FLB_TRUE) {
137
0
            return FLB_TRUE;
138
0
        }
139
0
    }
140
141
    /* no matches, trace will be dropped */
142
0
    return FLB_FALSE;
143
0
}
144
145
struct sampling_conditions *sampling_conditions_create(struct sampling *ctx, struct cfl_variant *conditions)
146
0
{
147
0
    int i;
148
0
    int type;
149
0
    char *type_str;
150
0
    void *cond_ptr = NULL;
151
0
    struct sampling_conditions *sampling_cond;
152
0
    struct cfl_variant *type_settings;
153
0
    struct cfl_variant *condition_settings;
154
155
0
    if (!conditions) {
156
0
        return NULL;
157
0
    }
158
159
0
    if (conditions->type != CFL_VARIANT_ARRAY) {
160
0
        flb_plg_error(ctx->ins, "conditions must be an array");
161
0
        return NULL;
162
0
    }
163
164
0
    sampling_cond = flb_calloc(1, sizeof(struct sampling_conditions));
165
0
    if (!sampling_cond) {
166
0
        flb_errno();
167
0
        return NULL;
168
0
    }
169
0
    cfl_list_init(&sampling_cond->list);
170
171
    /* iterate conditions */
172
0
    for (i = 0; i < conditions->data.as_array->entry_count; i++) {
173
0
        condition_settings = conditions->data.as_array->entries[i];
174
0
        if (condition_settings->type != CFL_VARIANT_KVLIST) {
175
0
            flb_plg_error(ctx->ins, "condition must be a map");
176
0
            sampling_conditions_destroy(sampling_cond);
177
0
            return NULL;
178
0
        }
179
180
0
        type_settings = cfl_kvlist_fetch(condition_settings->data.as_kvlist, "type");
181
0
        if (!type_settings) {
182
0
            flb_plg_error(ctx->ins, "condition must have a 'type' key");
183
0
            sampling_conditions_destroy(sampling_cond);
184
0
            return NULL;
185
0
        }
186
187
0
        if (type_settings->type != CFL_VARIANT_STRING) {
188
0
            flb_plg_error(ctx->ins, "condition 'type' must be a string");
189
0
            sampling_conditions_destroy(sampling_cond);
190
0
            return NULL;
191
0
        }
192
193
0
        type_str = type_settings->data.as_string;
194
0
        type = condition_type_str_to_int(type_str);
195
0
        if (type == -1) {
196
0
            flb_plg_error(ctx->ins, "unknown condition type '%s'", type_str);
197
0
            sampling_conditions_destroy(sampling_cond);
198
0
            return NULL;
199
0
        }
200
201
0
        cond_ptr = NULL;
202
0
        switch (type) {
203
0
        case SAMPLING_COND_STATUS_CODE:
204
0
            cond_ptr = cond_status_codes_create(ctx, sampling_cond, condition_settings);
205
0
            break;
206
0
        case SAMPLING_COND_LATENCY:
207
0
            cond_ptr = cond_latency_create(ctx, sampling_cond, condition_settings);
208
0
            break;
209
0
        case SAMPLING_COND_STRING_ATTRIBUTE:
210
0
            cond_ptr = cond_string_attr_create(ctx, sampling_cond, condition_settings);
211
0
            break;
212
0
        case SAMPLING_COND_NUMERIC_ATTRIBUTE:
213
0
            cond_ptr = cond_numeric_attr_create(ctx, sampling_cond, condition_settings);
214
0
            break;
215
0
        case SAMPLING_COND_BOOLEAN_ATTRIBUTE:
216
0
            cond_ptr = cond_boolean_attr_create(ctx, sampling_cond, condition_settings);
217
0
            break;
218
0
        case SAMPLING_COND_SPAN_COUNT:
219
0
            cond_ptr = cond_span_count_create(ctx, sampling_cond, condition_settings);
220
0
            break;
221
0
        case SAMPLING_COND_TRACE_STATE:
222
0
            cond_ptr = cond_trace_state_create(ctx, sampling_cond, condition_settings);
223
0
            break;
224
0
        default:
225
0
            sampling_conditions_destroy(sampling_cond);
226
0
            return NULL;
227
0
        }
228
229
0
        if (!cond_ptr) {
230
0
            flb_plg_error(ctx->ins, "failed to create condition type '%s'", type_str);
231
0
            sampling_conditions_destroy(sampling_cond);
232
0
            return NULL;
233
0
        }
234
0
    }
235
236
0
    return sampling_cond;
237
0
}
238