Skip to content

Commit 7343e64

Browse files
committed
input_chunk: count input log records per tag
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
1 parent ec4d24b commit 7343e64

1 file changed

Lines changed: 161 additions & 0 deletions

File tree

src/flb_input_chunk.c

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <monkey/mk_core.h>
4343
#include <string.h>
4444
#include <stdint.h>
45+
#include <limits.h>
4546

4647

4748
#ifdef FLB_HAVE_CHUNK_TRACE
@@ -56,6 +57,162 @@
5657

5758
#define FLB_INPUT_CHUNK_RAW_LOG_ROUTING (1 << 0)
5859

60+
static int logs_tag_records_metrics_enabled(struct flb_input_instance *in)
61+
{
62+
if (in->telemetry_metrics_logs_tag_records != -1) {
63+
return in->telemetry_metrics_logs_tag_records;
64+
}
65+
66+
return in->config->telemetry_metrics_logs_tag_records;
67+
}
68+
69+
static void update_logs_tag_records_untracked(struct flb_input_instance *in,
70+
uint64_t ts,
71+
size_t records,
72+
const char *reason)
73+
{
74+
if (!in->cmt_logs_tag_records_untracked || records == 0) {
75+
return;
76+
}
77+
78+
cmt_counter_add(in->cmt_logs_tag_records_untracked, ts, records,
79+
2, (char *[]) {(char *) flb_input_name(in),
80+
(char *) reason});
81+
}
82+
83+
static void update_logs_tag_records_metrics(struct flb_input_instance *in,
84+
uint64_t ts,
85+
size_t records,
86+
const char *tag,
87+
size_t tag_len)
88+
{
89+
int ret;
90+
int prefix_len;
91+
char value = 1;
92+
char prefix[32];
93+
char stack_key[256];
94+
char *key;
95+
size_t input_name_len;
96+
size_t key_len;
97+
size_t out_size;
98+
void *out_buf;
99+
const char *input_name;
100+
flb_sds_t tag_sds;
101+
struct flb_config *config;
102+
103+
if (records == 0 || logs_tag_records_metrics_enabled(in) != FLB_TRUE) {
104+
return;
105+
}
106+
107+
if (!in->cmt_logs_tag_records || !in->cmt_logs_tag_records_untracked) {
108+
return;
109+
}
110+
111+
config = in->config;
112+
113+
/* Enforce the tag length limit before allocating anything */
114+
if (config->telemetry_metrics_logs_tag_records_max_tag_length > 0 &&
115+
tag_len > (size_t) config->telemetry_metrics_logs_tag_records_max_tag_length) {
116+
update_logs_tag_records_untracked(in, ts, records, "tag_length_limit");
117+
return;
118+
}
119+
120+
input_name = flb_input_name(in);
121+
input_name_len = strlen(input_name);
122+
123+
/*
124+
* Build a NUL-free, unambiguous cardinality key using a numeric length
125+
* prefix: "<name_len>:<name><tag>". The hash table stores and compares
126+
* keys with NUL-terminated semantics (flb_strndup/strncmp), so the key
127+
* must not contain an embedded NUL separator. The length prefix keeps the
128+
* (name, tag) -> key mapping injective without relying on a delimiter byte
129+
* that could legitimately appear in a name or tag.
130+
*/
131+
prefix_len = snprintf(prefix, sizeof(prefix), "%zu:", input_name_len);
132+
if (prefix_len < 0 || (size_t) prefix_len >= sizeof(prefix)) {
133+
update_logs_tag_records_untracked(in, ts, records, "error");
134+
return;
135+
}
136+
137+
key_len = (size_t) prefix_len + input_name_len + tag_len;
138+
139+
/*
140+
* The hash table API takes the key length as an int. With max_tag_length
141+
* disabled (<= 0) an extremely large tag could otherwise overflow the
142+
* cast, so guard the key length explicitly.
143+
*/
144+
if (key_len > INT_MAX) {
145+
update_logs_tag_records_untracked(in, ts, records, "error");
146+
return;
147+
}
148+
149+
if (key_len <= sizeof(stack_key)) {
150+
key = stack_key;
151+
}
152+
else {
153+
key = flb_malloc(key_len);
154+
if (!key) {
155+
flb_errno();
156+
update_logs_tag_records_untracked(in, ts, records, "error");
157+
return;
158+
}
159+
}
160+
161+
memcpy(key, prefix, prefix_len);
162+
memcpy(key + prefix_len, input_name, input_name_len);
163+
memcpy(key + prefix_len + input_name_len, tag, tag_len);
164+
165+
pthread_mutex_lock(&config->telemetry_metrics_logs_tag_records_lock);
166+
167+
ret = flb_hash_table_get(config->telemetry_metrics_logs_tag_records_ht,
168+
key, (int) key_len, &out_buf, &out_size);
169+
if (ret == -1) {
170+
if (config->telemetry_metrics_logs_tag_records_max_series > 0 &&
171+
config->telemetry_metrics_logs_tag_records_series_count >=
172+
(size_t) config->telemetry_metrics_logs_tag_records_max_series) {
173+
pthread_mutex_unlock(&config->telemetry_metrics_logs_tag_records_lock);
174+
if (key != stack_key) {
175+
flb_free(key);
176+
}
177+
update_logs_tag_records_untracked(in, ts, records, "max_series");
178+
return;
179+
}
180+
181+
ret = flb_hash_table_add(config->telemetry_metrics_logs_tag_records_ht,
182+
key, (int) key_len, &value, sizeof(value));
183+
if (ret == -1) {
184+
pthread_mutex_unlock(&config->telemetry_metrics_logs_tag_records_lock);
185+
if (key != stack_key) {
186+
flb_free(key);
187+
}
188+
update_logs_tag_records_untracked(in, ts, records, "error");
189+
return;
190+
}
191+
192+
config->telemetry_metrics_logs_tag_records_series_count++;
193+
}
194+
195+
pthread_mutex_unlock(&config->telemetry_metrics_logs_tag_records_lock);
196+
197+
if (key != stack_key) {
198+
flb_free(key);
199+
}
200+
201+
/* cmetrics requires a NUL-terminated label value for the tag */
202+
tag_sds = flb_sds_create_len(tag, tag_len);
203+
if (!tag_sds) {
204+
flb_errno();
205+
update_logs_tag_records_untracked(in, ts, records, "error");
206+
return;
207+
}
208+
209+
cmt_counter_add(in->cmt_logs_tag_records, ts, records,
210+
2, (char *[]) {(char *) input_name,
211+
(char *) tag_sds});
212+
213+
flb_sds_destroy(tag_sds);
214+
}
215+
59216
struct input_chunk_raw {
60217
struct flb_input_instance *ins;
61218
int event_type;
@@ -2801,6 +2958,10 @@ static int input_chunk_append_raw(struct flb_input_instance *in,
28012958
cmt_counter_add(in->cmt_records, ts, ic->added_records,
28022959
1, (char *[]) {(char *) flb_input_name(in)});
28032960

2961+
if (event_type == FLB_INPUT_LOGS) {
2962+
update_logs_tag_records_metrics(in, ts, ic->added_records, tag, tag_len);
2963+
}
2964+
28042965
/* fluentbit_input_bytes_total */
28052966
cmt_counter_add(in->cmt_bytes, ts, buf_size,
28062967
1, (char *[]) {(char *) flb_input_name(in)});

0 commit comments

Comments
 (0)