Skip to content

Commit c94ae80

Browse files
committed
logproto-prometheus-scraper-responder: First impl of a prometheus scraper responder with syslog-ng stats prometheus outptut response
Signed-off-by: Hofi <hofione@gmail.com>
1 parent fba9794 commit c94ae80

4 files changed

+197
-0
lines changed

lib/logproto/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(LOGPROTO_HEADERS
77
logproto/logproto-framed-server.h
88
logproto/logproto.h
99
logproto/logproto-http-server.h
10+
logproto/logproto-prometheus-scraper-responder.h
1011
logproto/logproto-record-server.h
1112
logproto/logproto-server.h
1213
logproto/logproto-text-client.h
@@ -21,6 +22,7 @@ set(LOGPROTO_SOURCES
2122
logproto/logproto-framed-client.c
2223
logproto/logproto-framed-server.c
2324
logproto/logproto-http-server.c
25+
logproto/logproto-prometheus-scraper-responder.c
2426
logproto/logproto-record-server.c
2527
logproto/logproto-server.c
2628
logproto/logproto-text-client.c

lib/logproto/Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ logprotoinclude_HEADERS = \
1212
lib/logproto/logproto-text-client.h \
1313
lib/logproto/logproto-text-server.h \
1414
lib/logproto/logproto-http-server.h \
15+
lib/logproto/logproto-prometheus-scraper-responder.h \
1516
lib/logproto/logproto-record-server.h \
1617
lib/logproto/logproto-builtins.h \
1718
lib/logproto/logproto.h
@@ -26,6 +27,7 @@ logproto_sources = \
2627
lib/logproto/logproto-text-client.c \
2728
lib/logproto/logproto-text-server.c \
2829
lib/logproto/logproto-http-server.c \
30+
lib/logproto/logproto-prometheus-scraper-responder.h \
2931
lib/logproto/logproto-record-server.c \
3032
lib/logproto/logproto-builtins.c
3133

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2025 One Identity
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As an additional exemption you are allowed to compile & link against the
19+
* OpenSSL libraries as published by the OpenSSL project. See the file
20+
* COPYING for details.
21+
*
22+
*/
23+
#include "logproto/logproto-prometheus-scraper-responder.h"
24+
#include "stats/stats-prometheus.h"
25+
#include "stats/stats-query-commands.h"
26+
#include "messages.h"
27+
28+
static void
29+
_generate_batched_response(const gchar *record, gpointer user_data)
30+
{
31+
gpointer *args = (gpointer *) user_data;
32+
//LogProtoPrometheusScraperResponder *self = (LogProtoPrometheusScraperResponder *)args[0];
33+
GString **batch = (GString **) args[1];
34+
35+
g_string_append_printf(*batch, "%s", record);
36+
}
37+
38+
static GString *
39+
_get_stats(LogProtoPrometheusScraperResponder *self)
40+
{
41+
GString *stats = NULL;
42+
gboolean cancelled = FALSE;
43+
44+
if (self->options->stat_type == STT_STAT)
45+
{
46+
gpointer args[] = {self, &stats};
47+
gboolean with_legacy = TRUE;
48+
stats_generate_prometheus(_generate_batched_response, args, with_legacy, &cancelled);
49+
}
50+
else
51+
stats = stats_execute_query_command("QUERY GET prometheus *", self, &cancelled);
52+
53+
return stats;
54+
}
55+
56+
static gboolean
57+
_check_headers(gchar *buffer_start, gsize buffer_bytes)
58+
{
59+
// TODO: add a generic header pareser to LogProtoHTTPServer and use it here
60+
gchar **lines = g_strsplit(buffer_start, "\n", 1);
61+
62+
// First line must be like 'GET /metrics HTTP/1.1\x0d\x0a'
63+
gchar *line = lines && lines[0] ? lines[0] : buffer_start;
64+
gchar **tokens = g_strsplit(line, " ", 3);
65+
66+
gboolean result = (tokens == NULL || tokens[0] == NULL || strcmp(tokens[0], "GET")
67+
|| tokens[1] == NULL || strcmp(tokens[1], "/metrics"));
68+
69+
// TODO: Check further headers as well to support options like compression, etc.
70+
if (FALSE == result)
71+
msg_error("Unknown request", evt_tag_str("http-server-response", line));
72+
73+
g_strfreev(tokens);
74+
g_strfreev(lines);
75+
return result;
76+
}
77+
78+
static GString *
79+
_process_data(LogProtoHTTPServer *s, LogProtoBufferedServerState *state,
80+
const guchar *buffer_start, gsize buffer_bytes)
81+
{
82+
LogProtoPrometheusScraperResponder *self = (LogProtoPrometheusScraperResponder *)s;
83+
GString *response_data = NULL;
84+
85+
if (_check_headers((gchar *)buffer_start, buffer_bytes))
86+
response_data = _get_stats(self);
87+
return response_data;
88+
}
89+
90+
void
91+
log_proto_prometheus_scraper_responer_init(LogProtoPrometheusScraperResponder *self, LogTransport *transport,
92+
const LogProtoPrometheusScraperResponderOptions *options)
93+
{
94+
log_proto_http_server_init((LogProtoHTTPServer *)self, transport, &options->super);
95+
self->options = options;
96+
self->super.data_processor = _process_data;
97+
}
98+
99+
LogProtoServer *
100+
log_proto_prometheus_scraper_responer_new(LogTransport *transport,
101+
const LogProtoPrometheusScraperResponderOptions *options)
102+
{
103+
LogProtoPrometheusScraperResponder *self = g_new0(LogProtoPrometheusScraperResponder, 1);
104+
105+
log_proto_prometheus_scraper_responer_init(self, transport, options);
106+
return &self->super.super.super.super;
107+
}
108+
109+
/* Options */
110+
111+
void
112+
log_proto_prometheus_scraper_responer_options_defaults(LogProtoPrometheusScraperResponderOptions *options)
113+
{
114+
memset(options, 0, sizeof(*options));
115+
options->stat_type = STT_STAT;
116+
}
117+
118+
void
119+
log_proto_prometheus_scraper_responer_options_init(LogProtoPrometheusScraperResponderOptions *options,
120+
GlobalConfig *cfg)
121+
{
122+
if (options->initialized)
123+
return;
124+
log_proto_server_options_init(&options->super, cfg);
125+
options->initialized = TRUE;
126+
}
127+
128+
void
129+
log_proto_prometheus_scraper_responer_destroy(LogProtoPrometheusScraperResponderOptions *options)
130+
{
131+
// if (options->destroy)
132+
// options->destroy(options);
133+
options->initialized = FALSE;
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) 2025 One Identity
3+
*
4+
* This library is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU Lesser General Public
6+
* License as published by the Free Software Foundation; either
7+
* version 2.1 of the License, or (at your option) any later version.
8+
*
9+
* This library is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public
15+
* License along with this library; if not, write to the Free Software
16+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*
18+
* As an additional exemption you are allowed to compile & link against the
19+
* OpenSSL libraries as published by the OpenSSL project. See the file
20+
* COPYING for details.
21+
*
22+
*/
23+
#ifndef LOGPROTO_PROMETHEUS_SCRAPER_RESPONDER_INCLUDED
24+
#define LOGPROTO_PROMETHEUS_SCRAPER_RESPONDER_INCLUDED
25+
26+
#include "logproto/logproto-http-server.h"
27+
28+
/* Stat type flags */
29+
#define STT_STAT 0x01
30+
#define STT_QUERY 0x02
31+
32+
/* options */
33+
typedef struct _LogProtoPrometheusScraperResponderOptions LogProtoPrometheusScraperResponderOptions;
34+
struct _LogProtoPrometheusScraperResponderOptions
35+
{
36+
LogProtoServerOptions /* LogProtoHTTPServerOptions */ super;
37+
guint8 stat_type;
38+
gboolean initialized;
39+
};
40+
41+
void log_proto_prometheus_scraper_responer_options_defaults(LogProtoPrometheusScraperResponderOptions *options);
42+
void log_proto_prometheus_scraper_responer_options_init(LogProtoPrometheusScraperResponderOptions *options,
43+
GlobalConfig *cfg);
44+
void log_proto_prometheus_scraper_responer_destroy(LogProtoPrometheusScraperResponderOptions *options);
45+
46+
/* LogProtoPrometheusScraperResponder */
47+
typedef struct _LogProtoPrometheusScraperResponder LogProtoPrometheusScraperResponder;
48+
struct _LogProtoPrometheusScraperResponder
49+
{
50+
LogProtoHTTPServer super;
51+
const LogProtoPrometheusScraperResponderOptions *options;
52+
};
53+
54+
LogProtoServer *log_proto_prometheus_scraper_responer_new(LogTransport *transport,
55+
const LogProtoPrometheusScraperResponderOptions *options);
56+
void log_proto_prometheus_scraper_responer_init(LogProtoPrometheusScraperResponder *self, LogTransport *transport,
57+
const LogProtoPrometheusScraperResponderOptions *options);
58+
59+
#endif

0 commit comments

Comments
 (0)