Skip to content

Commit ba63828

Browse files
committed
in_prometheus_textfile: add new Prometheus text file collector
Signed-off-by: Eduardo Silva <[email protected]>
1 parent 117f552 commit ba63828

File tree

3 files changed

+236
-0
lines changed

3 files changed

+236
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set(src
2+
prometheus_textfile.c)
3+
4+
FLB_PLUGIN(in_prometheus_textfile "${src}" "")
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2025 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 <glob.h>
21+
#include <sys/stat.h>
22+
23+
#include <fluent-bit/flb_info.h>
24+
#include <fluent-bit/flb_input.h>
25+
#include <fluent-bit/flb_input_plugin.h>
26+
#include <fluent-bit/flb_config_map.h>
27+
#include <fluent-bit/flb_file.h>
28+
#include <fluent-bit/flb_sds.h>
29+
#include <fluent-bit/flb_time.h>
30+
31+
#include <cmetrics/cmt_decode_prometheus.h>
32+
33+
#include "prometheus_textfile.h"
34+
35+
static int collect_metrics(struct prom_textfile *ctx)
36+
{
37+
int i;
38+
int ret;
39+
glob_t globbuf;
40+
char errbuf[256];
41+
struct stat st;
42+
struct mk_list *head;
43+
struct flb_slist_entry *entry;
44+
struct cmt *cmt = NULL;
45+
struct cmt_decode_prometheus_parse_opts opts = {0};
46+
flb_sds_t content;
47+
48+
/* cmetrics prometheus decoder options */
49+
opts.default_timestamp = cfl_time_now();
50+
opts.errbuf = errbuf;
51+
opts.errbuf_size = sizeof(errbuf);
52+
53+
/* iterate over configured paths */
54+
mk_list_foreach(head, ctx->path_list) {
55+
entry = mk_list_entry(head, struct flb_slist_entry, _head);
56+
57+
globbuf.gl_pathc = 0;
58+
globbuf.gl_pathv = NULL;
59+
60+
ret = glob(entry->str, 0, NULL, &globbuf);
61+
if (ret != 0) {
62+
globfree(&globbuf);
63+
continue;
64+
}
65+
66+
for (i = 0; i < globbuf.gl_pathc; i++) {
67+
ret = stat(globbuf.gl_pathv[i], &st);
68+
69+
/* only process regular files */
70+
if (ret == 0 && S_ISREG(st.st_mode)) {
71+
content = flb_file_read(globbuf.gl_pathv[i]);
72+
if (!content) {
73+
flb_plg_debug(ctx->ins, "cannot read %s", globbuf.gl_pathv[i]);
74+
continue;
75+
}
76+
77+
if (flb_sds_len(content) == 0) {
78+
flb_sds_destroy(content);
79+
continue;
80+
}
81+
82+
cmt = NULL;
83+
ret = cmt_decode_prometheus_create(&cmt,
84+
content,
85+
flb_sds_len(content),
86+
&opts);
87+
flb_sds_destroy(content);
88+
89+
if (ret == 0) {
90+
flb_input_metrics_append(ctx->ins, NULL, 0, cmt);
91+
cmt_decode_prometheus_destroy(cmt);
92+
}
93+
}
94+
else if (ret != 0) {
95+
flb_plg_error(ctx->ins, "error parsing %s: %s",
96+
globbuf.gl_pathv[i], errbuf);
97+
continue;
98+
}
99+
}
100+
globfree(&globbuf);
101+
}
102+
103+
return 0;
104+
}
105+
106+
static int cb_collect(struct flb_input_instance *ins,
107+
struct flb_config *config, void *data)
108+
{
109+
struct prom_textfile *ctx = data;
110+
111+
collect_metrics(ctx);
112+
113+
FLB_INPUT_RETURN(0);
114+
}
115+
116+
static int cb_init(struct flb_input_instance *ins,
117+
struct flb_config *config, void *data)
118+
{
119+
int ret;
120+
struct prom_textfile *ctx;
121+
122+
ctx = flb_calloc(1, sizeof(struct prom_textfile));
123+
if (!ctx) {
124+
flb_errno();
125+
return -1;
126+
}
127+
ctx->ins = ins;
128+
129+
ret = flb_input_config_map_set(ins, (void *) ctx);
130+
if (ret == -1) {
131+
flb_free(ctx);
132+
return -1;
133+
}
134+
135+
ctx->coll_fd = flb_input_set_collector_time(ins,
136+
cb_collect,
137+
ctx->scrape_interval,
138+
0, config);
139+
if (ctx->coll_fd < 0) {
140+
flb_free(ctx);
141+
return -1;
142+
}
143+
144+
flb_input_set_context(ins, ctx);
145+
return 0;
146+
}
147+
148+
static void cb_pause(void *data, struct flb_config *config)
149+
{
150+
struct prom_textfile *ctx = data;
151+
flb_input_collector_pause(ctx->coll_fd, ctx->ins);
152+
}
153+
154+
static void cb_resume(void *data, struct flb_config *config)
155+
{
156+
struct prom_textfile *ctx = data;
157+
flb_input_collector_resume(ctx->coll_fd, ctx->ins);
158+
}
159+
160+
static int cb_exit(void *data, struct flb_config *config)
161+
{
162+
struct prom_textfile *ctx = data;
163+
164+
if (!ctx) {
165+
return 0;
166+
}
167+
168+
flb_free(ctx);
169+
return 0;
170+
}
171+
172+
static struct flb_config_map config_map[] = {
173+
{
174+
FLB_CONFIG_MAP_CLIST, "path", NULL,
175+
0, FLB_TRUE, offsetof(struct prom_textfile, path_list),
176+
"Comma separated list of files or glob patterns to read"
177+
},
178+
{
179+
FLB_CONFIG_MAP_TIME, "scrape_interval", "10s",
180+
0, FLB_TRUE, offsetof(struct prom_textfile, scrape_interval),
181+
"Scraping interval"
182+
},
183+
/* EOF */
184+
{0}
185+
};
186+
187+
struct flb_input_plugin in_prometheus_textfile_plugin = {
188+
.name = "prometheus_textfile",
189+
.description = "Read Prometheus metrics from text files",
190+
.cb_init = cb_init,
191+
.cb_pre_run = NULL,
192+
.cb_collect = cb_collect,
193+
.cb_flush_buf = NULL,
194+
.cb_pause = cb_pause,
195+
.cb_resume = cb_resume,
196+
.cb_exit = cb_exit,
197+
.config_map = config_map,
198+
.flags = FLB_INPUT_THREADED | FLB_INPUT_CORO,
199+
};
200+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2025 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+
#ifndef FLB_IN_PROMETHEUS_TEXTFILE_H
21+
#define FLB_IN_PROMETHEUS_TEXTFILE_H
22+
23+
#include <fluent-bit/flb_input_plugin.h>
24+
25+
struct prom_textfile {
26+
int coll_fd; /* collector id */
27+
uint64_t scrape_interval; /* collection interval */
28+
struct mk_list *path_list; /* list of paths */
29+
struct flb_input_instance *ins; /* plugin instance */
30+
};
31+
32+
#endif

0 commit comments

Comments
 (0)