Skip to content

Commit ecd5a27

Browse files
committed
feat: add native Prometheus metrics exporter to stats server
Add a built-in Prometheus exposition format endpoint to the uWSGI stats server, eliminating the need for external sidecar exporters like uwsgi_exporter. Metric names are compatible with timonwong/uwsgi_exporter for drop-in replacement. GET /metrics returns Prometheus text format (42 metrics covering global, socket, worker, app, core, and cache stats). All other paths return JSON as before. The prometheus path is configurable via --stats-prometheus-path. The HTTP stats layer is split into uwsgi_stats_read_request() and uwsgi_stats_send_http_header() with an enum uwsgi_stats_format for clean format selection. Includes integration tests for both JSON and Prometheus endpoints.
1 parent 8d116f7 commit ecd5a27

13 files changed

Lines changed: 1178 additions & 25 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ core/dot_h.c
2929
/uWSGI.egg-info/
3030
check/check_*
3131
!check/*.c
32+
33+
# ralphex progress logs
34+
.ralphex/progress/

core/emperor.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2528,7 +2528,12 @@ static void emperor_send_stats(int fd) {
25282528
}
25292529

25302530
if (uwsgi.stats_http) {
2531-
if (uwsgi_send_http_stats(client_fd)) {
2531+
enum uwsgi_stats_format fmt;
2532+
if (uwsgi_stats_read_request(client_fd, &fmt)) {
2533+
close(client_fd);
2534+
return;
2535+
}
2536+
if (uwsgi_stats_send_http_header(client_fd, UWSGI_STATS_FORMAT_JSON)) {
25322537
close(client_fd);
25332538
return;
25342539
}

core/stats.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,17 +365,33 @@ void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
365365
return;
366366
}
367367

368+
enum uwsgi_stats_format fmt = UWSGI_STATS_FORMAT_JSON;
368369
if (uwsgi.stats_http) {
369-
if (uwsgi_send_http_stats(client_fd)) {
370+
if (uwsgi_stats_read_request(client_fd, &fmt)) {
370371
close(client_fd);
371372
return;
372373
}
373374
}
374375

375-
struct uwsgi_stats *us = func();
376+
struct uwsgi_stats *us;
377+
switch (fmt) {
378+
case UWSGI_STATS_FORMAT_PROMETHEUS:
379+
us = uwsgi_master_generate_stats_prometheus();
380+
break;
381+
default:
382+
us = func();
383+
break;
384+
}
385+
376386
if (!us)
377387
goto end;
378388

389+
if (uwsgi.stats_http) {
390+
if (uwsgi_stats_send_http_header(client_fd, fmt)) {
391+
goto end0;
392+
}
393+
}
394+
379395
size_t remains = us->pos;
380396
off_t pos = 0;
381397
while (remains > 0) {

0 commit comments

Comments
 (0)