Skip to content

Commit b68c4ee

Browse files
committed
add gzip compression option for prometheus exporter
1 parent 7b0c1ae commit b68c4ee

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

plugins/out_prometheus_exporter/prom_http.c

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919

2020
#include <fluent-bit/flb_output_plugin.h>
2121
#include <fluent-bit/flb_http_server.h>
22+
#include <fluent-bit/flb_gzip.h>
23+
#include <monkey/mk_http_parser.h>
24+
#include <string.h>
2225
#include "prom.h"
2326
#include "prom_http.h"
2427

@@ -157,10 +160,73 @@ static int http_server_mq_create(struct prom_http *ph)
157160
return 0;
158161
}
159162

163+
/* Check if client accepts gzip encoding */
164+
static int client_accepts_gzip(mk_request_t *request)
165+
{
166+
struct mk_http_header *header;
167+
const char *accept_encoding;
168+
size_t len;
169+
const char *p;
170+
const char *end;
171+
172+
/* Get Accept-Encoding header */
173+
header = mk_http_header_get(MK_HEADER_ACCEPT_ENCODING, request, NULL, 0);
174+
if (!header || header->val.len == 0) {
175+
return 0;
176+
}
177+
178+
accept_encoding = header->val.data;
179+
len = header->val.len;
180+
181+
/* Check if "gzip" is present in Accept-Encoding header (case-insensitive) */
182+
if (len < 4) {
183+
return 0;
184+
}
185+
186+
p = accept_encoding;
187+
end = accept_encoding + len;
188+
189+
/* Search for "gzip" token */
190+
while (p < end - 3) {
191+
/* Case-insensitive comparison for "gzip" */
192+
if ((p[0] == 'g' || p[0] == 'G') &&
193+
(p[1] == 'z' || p[1] == 'Z') &&
194+
(p[2] == 'i' || p[2] == 'I') &&
195+
(p[3] == 'p' || p[3] == 'P')) {
196+
/* Check if it's a complete token (not part of another word) */
197+
/* Check character before "gzip" */
198+
if (p > accept_encoding) {
199+
char prev = p[-1];
200+
if (prev != ',' && prev != ' ' && prev != '\t') {
201+
p++;
202+
continue;
203+
}
204+
}
205+
/* Check character after "gzip" */
206+
if (p + 4 < end) {
207+
char next = p[4];
208+
if (next != ',' && next != ' ' && next != '\t' && next != ';') {
209+
p++;
210+
continue;
211+
}
212+
}
213+
/* Found valid "gzip" token */
214+
return 1;
215+
}
216+
p++;
217+
}
218+
219+
return 0;
220+
}
221+
160222
/* HTTP endpoint: /metrics */
161223
static void cb_metrics(mk_request_t *request, void *data)
162224
{
163225
struct prom_http_buf *buf;
226+
void *compressed_data = NULL;
227+
size_t compressed_size = 0;
228+
int use_gzip = 0;
229+
int ret;
164230
(void) data;
165231

166232
buf = metrics_get_latest();
@@ -172,9 +238,35 @@ static void cb_metrics(mk_request_t *request, void *data)
172238

173239
buf->users++;
174240

241+
/* Check if client accepts gzip encoding */
242+
use_gzip = client_accepts_gzip(request);
243+
244+
/* Compress data if client supports gzip */
245+
if (use_gzip) {
246+
ret = flb_gzip_compress(buf->buf_data, buf->buf_size,
247+
&compressed_data, &compressed_size);
248+
if (ret != 0 || !compressed_data) {
249+
/* Compression failed, fall back to uncompressed */
250+
use_gzip = 0;
251+
if (compressed_data) {
252+
flb_free(compressed_data);
253+
compressed_data = NULL;
254+
}
255+
}
256+
}
257+
175258
mk_http_status(request, 200);
176259
flb_hs_add_content_type_to_req(request, FLB_HS_CONTENT_TYPE_PROMETHEUS);
177-
mk_http_send(request, buf->buf_data, buf->buf_size, NULL);
260+
261+
/* Add Content-Encoding header if compressed */
262+
if (use_gzip && compressed_data) {
263+
mk_http_header(request, "Content-Encoding", 16, "gzip", 4);
264+
mk_http_send(request, compressed_data, compressed_size, NULL);
265+
flb_free(compressed_data);
266+
} else {
267+
mk_http_send(request, buf->buf_data, buf->buf_size, NULL);
268+
}
269+
178270
mk_http_done(request);
179271

180272
buf->users--;

0 commit comments

Comments
 (0)