Skip to content

Commit 6aae15e

Browse files
committed
http_server: new /api/v2/metrics endpoint
Signed-off-by: Eduardo Silva <[email protected]>
1 parent 25c2804 commit 6aae15e

File tree

7 files changed

+372
-2
lines changed

7 files changed

+372
-2
lines changed

src/http_server/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ set(src
1212
# api/v1
1313
add_subdirectory(api/v1)
1414

15+
# api/v2
16+
add_subdirectory(api/v2)
17+
1518
include_directories(${MONKEY_INCLUDE_DIR})
1619
add_library(flb-http-server STATIC ${src})
17-
target_link_libraries(flb-http-server monkey-core-static api-v1)
20+
target_link_libraries(flb-http-server monkey-core-static api-v1 api-v2)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# api/v2
2+
set(src
3+
metrics.c
4+
register.c
5+
)
6+
7+
include_directories(${MONKEY_INCLUDE_DIR})
8+
add_library(api-v2 STATIC ${src})
9+
target_link_libraries(api-v2 monkey-core-static fluent-bit-static)

src/http_server/api/v2/metrics.c

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2022 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_info.h>
21+
#include <fluent-bit/flb_pack.h>
22+
#include <fluent-bit/flb_input.h>
23+
#include <fluent-bit/flb_filter.h>
24+
#include <fluent-bit/flb_output.h>
25+
#include <fluent-bit/flb_sds.h>
26+
#include <fluent-bit/flb_version.h>
27+
#include <fluent-bit/flb_time.h>
28+
#include "metrics.h"
29+
30+
#include <fluent-bit/flb_http_server.h>
31+
32+
#define null_check(x) do { if (!x) { goto error; } else {sds = x;} } while (0)
33+
34+
pthread_key_t hs_metrics_v2_key;
35+
36+
static struct mk_list *hs_metrics_v2_key_create()
37+
{
38+
struct mk_list *metrics_list = NULL;
39+
40+
metrics_list = flb_malloc(sizeof(struct mk_list));
41+
if (metrics_list == NULL) {
42+
flb_errno();
43+
return NULL;
44+
}
45+
mk_list_init(metrics_list);
46+
pthread_setspecific(hs_metrics_v2_key, metrics_list);
47+
48+
return metrics_list;
49+
}
50+
51+
static void hs_metrics_v2_key_destroy(void *data)
52+
{
53+
struct mk_list *metrics_list = (struct mk_list*) data;
54+
struct mk_list *tmp;
55+
struct mk_list *head;
56+
struct flb_hs_buf *entry;
57+
58+
if (metrics_list == NULL) {
59+
return;
60+
}
61+
mk_list_foreach_safe(head, tmp, metrics_list) {
62+
entry = mk_list_entry(head, struct flb_hs_buf, _head);
63+
if (entry != NULL) {
64+
if (entry->raw_data != NULL) {
65+
cmt_destroy(entry->raw_data);
66+
entry->raw_data = NULL;
67+
}
68+
mk_list_del(&entry->_head);
69+
flb_free(entry);
70+
}
71+
}
72+
73+
flb_free(metrics_list);
74+
}
75+
76+
/* Return the newest metrics buffer */
77+
static struct flb_hs_buf *metrics_get_latest()
78+
{
79+
struct flb_hs_buf *buf;
80+
struct mk_list *metrics_list;
81+
82+
metrics_list = pthread_getspecific(hs_metrics_v2_key);
83+
if (!metrics_list) {
84+
return NULL;
85+
}
86+
87+
if (mk_list_size(metrics_list) == 0) {
88+
return NULL;
89+
}
90+
91+
buf = mk_list_entry_last(metrics_list, struct flb_hs_buf, _head);
92+
return buf;
93+
}
94+
95+
/* Delete unused metrics, note that we only care about the latest node */
96+
static int cleanup_metrics()
97+
{
98+
int c = 0;
99+
struct mk_list *tmp;
100+
struct mk_list *head;
101+
struct mk_list *metrics_list;
102+
struct flb_hs_buf *last;
103+
struct flb_hs_buf *entry;
104+
105+
metrics_list = pthread_getspecific(hs_metrics_v2_key);
106+
if (!metrics_list) {
107+
return -1;
108+
}
109+
110+
last = metrics_get_latest();
111+
if (!last) {
112+
return -1;
113+
}
114+
115+
mk_list_foreach_safe(head, tmp, metrics_list) {
116+
entry = mk_list_entry(head, struct flb_hs_buf, _head);
117+
if (entry != last && entry->users == 0) {
118+
mk_list_del(&entry->_head);
119+
cmt_destroy(entry->raw_data);
120+
flb_free(entry);
121+
c++;
122+
}
123+
}
124+
125+
return c;
126+
}
127+
128+
/*
129+
* Callback invoked every time some metrics are received through a message queue channel.
130+
* This function runs in a Monkey HTTP thread worker and it purpose is to take the metrics
131+
* data and store it somewhere so then it can be available by the end-points upon
132+
* HTTP client requests.
133+
*/
134+
static void cb_mq_metrics(mk_mq_t *queue, void *data, size_t size)
135+
{
136+
int ret;
137+
size_t off = 0;
138+
struct cmt *cmt;
139+
struct flb_hs_buf *buf;
140+
struct mk_list *metrics_list = NULL;
141+
142+
metrics_list = pthread_getspecific(hs_metrics_v2_key);
143+
if (!metrics_list) {
144+
metrics_list = hs_metrics_v2_key_create();
145+
if (metrics_list == NULL) {
146+
return;
147+
}
148+
}
149+
150+
/* decode cmetrics */
151+
ret = cmt_decode_msgpack_create(&cmt, data, size, &off);
152+
if (ret != 0) {
153+
return;
154+
}
155+
156+
buf = flb_malloc(sizeof(struct flb_hs_buf));
157+
if (!buf) {
158+
flb_errno();
159+
return;
160+
}
161+
buf->users = 0;
162+
buf->data = NULL;
163+
164+
/* Store CMetrics context as the raw_data */
165+
buf->raw_data = cmt;
166+
buf->raw_size = 0;
167+
168+
mk_list_add(&buf->_head, metrics_list);
169+
cleanup_metrics();
170+
}
171+
172+
/* API: expose metrics in Prometheus format /api/v2/metrics/prometheus */
173+
static void cb_metrics_prometheus(mk_request_t *request, void *data)
174+
{
175+
struct cmt *cmt;
176+
struct flb_hs_buf *buf;
177+
cfl_sds_t payload;
178+
179+
buf = metrics_get_latest();
180+
if (!buf) {
181+
mk_http_status(request, 404);
182+
mk_http_done(request);
183+
return;
184+
}
185+
186+
cmt = (struct cmt *) buf->raw_data;
187+
188+
/* convert CMetrics to text */
189+
payload = cmt_encode_prometheus_create(cmt, CMT_FALSE);
190+
if (!payload) {
191+
mk_http_status(request, 500);
192+
mk_http_done(request);
193+
return;
194+
}
195+
196+
buf->users++;
197+
198+
mk_http_status(request, 200);
199+
flb_hs_add_content_type_to_req(request, FLB_HS_CONTENT_TYPE_PROMETHEUS);
200+
mk_http_send(request, payload, cfl_sds_len(payload), NULL);
201+
mk_http_done(request);
202+
203+
cmt_encode_prometheus_destroy(payload);
204+
205+
buf->users--;
206+
}
207+
208+
/* API: expose built-in metrics /api/v1/metrics (JSON format) */
209+
static void cb_metrics(mk_request_t *request, void *data)
210+
{
211+
struct cmt *cmt;
212+
struct flb_hs_buf *buf;
213+
cfl_sds_t payload;
214+
215+
buf = metrics_get_latest();
216+
if (!buf) {
217+
mk_http_status(request, 404);
218+
mk_http_done(request);
219+
return;
220+
}
221+
222+
cmt = (struct cmt *) buf->raw_data;
223+
224+
/* convert CMetrics to text */
225+
payload = cmt_encode_text_create(cmt);
226+
if (!payload) {
227+
mk_http_status(request, 500);
228+
mk_http_done(request);
229+
return;
230+
}
231+
232+
buf->users++;
233+
234+
mk_http_status(request, 200);
235+
mk_http_send(request, payload, cfl_sds_len(payload), NULL);
236+
mk_http_done(request);
237+
238+
cmt_encode_text_destroy(payload);
239+
240+
buf->users--;
241+
}
242+
243+
/* Perform registration */
244+
int api_v2_metrics(struct flb_hs *hs)
245+
{
246+
247+
pthread_key_create(&hs_metrics_v2_key, hs_metrics_v2_key_destroy);
248+
249+
/* Create a message queue */
250+
hs->qid_metrics_v2 = mk_mq_create(hs->ctx, "/metrics_v2",
251+
cb_mq_metrics, NULL);
252+
/* HTTP end-points */
253+
mk_vhost_handler(hs->ctx, hs->vid, "/api/v2/metrics/prometheus",
254+
cb_metrics_prometheus, hs);
255+
256+
mk_vhost_handler(hs->ctx, hs->vid, "/api/v2/metrics", cb_metrics, hs);
257+
258+
return 0;
259+
}

src/http_server/api/v2/metrics.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2022 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_HS_API_V2_METRICS_H
21+
#define FLB_HS_API_V2_METRICS_H
22+
23+
#include <fluent-bit/flb_info.h>
24+
#include <fluent-bit/flb_http_server.h>
25+
26+
int api_v2_metrics(struct flb_hs *hs);
27+
28+
#endif

src/http_server/api/v2/register.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2023 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_info.h>
21+
#include <fluent-bit/flb_http_server.h>
22+
23+
#include "metrics.h"
24+
25+
int api_v2_registration(struct flb_hs *hs)
26+
{
27+
api_v2_metrics(hs);
28+
return 0;
29+
}

src/http_server/api/v2/register.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2+
3+
/* Fluent Bit
4+
* ==========
5+
* Copyright (C) 2015-2023 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_API_V2_REG_H
21+
#define FLB_API_V2_REG_H
22+
23+
#include <fluent-bit/flb_info.h>
24+
#include <fluent-bit/flb_http_server.h>
25+
26+
int api_v2_registration(struct flb_hs *hs);
27+
28+
#endif

0 commit comments

Comments
 (0)