Line data Source code
1 : #include "fd_prometheus.h"
2 :
3 : #include "fd_metrics.h"
4 :
5 : #include "../topo/fd_topo.h"
6 : #include "../../ballet/http/fd_http_server.h"
7 :
8 0 : #define PRINT_LINK_IN (0)
9 0 : #define PRINT_LINK_OUT (1)
10 0 : #define PRINT_TILE (2)
11 :
12 : static void
13 : prometheus_print1( fd_topo_t const * topo,
14 : fd_http_server_t * http,
15 : char const * tile_name,
16 : ulong metrics_cnt,
17 : fd_metrics_meta_t const * metrics,
18 0 : int print_mode ) {
19 0 : for( ulong i=0UL; i<metrics_cnt; i++ ) {
20 0 : fd_metrics_meta_t const * metric = &metrics[ i ];
21 0 : fd_http_server_printf( http, "# HELP %s %s\n# TYPE %s %s\n", metric->name, metric->desc, metric->name, fd_metrics_meta_type_str( metric ) );
22 :
23 0 : for( ulong j=0UL; j<topo->tile_cnt; j++ ) {
24 0 : fd_topo_tile_t const * tile = &topo->tiles[ j ];
25 :
26 : /* FIXME: This is O(n^2) rather than O(n). */
27 0 : if( FD_LIKELY( tile_name!=NULL && strcmp( tile->name, tile_name ) ) ) continue;
28 :
29 0 : if( FD_LIKELY( metric->type==FD_METRICS_TYPE_COUNTER || metric->type==FD_METRICS_TYPE_GAUGE ) ) {
30 0 : if( FD_LIKELY( print_mode==PRINT_TILE ) ) {
31 0 : ulong value = *(fd_metrics_tile( tile->metrics ) + metric->offset);
32 0 : fd_http_server_printf( http, "%s{kind=\"%s\",kind_id=\"%lu\"} %lu\n", metric->name, tile->name, tile->kind_id, value );
33 0 : } else {
34 0 : if( FD_LIKELY( print_mode==PRINT_LINK_IN ) ) {
35 0 : ulong polled_in_idx = 0UL;
36 0 : for( ulong k=0UL; k<tile->in_cnt; k++ ) {
37 0 : if( FD_UNLIKELY( !tile->in_link_poll[ k ] ) ) continue;
38 :
39 0 : fd_topo_link_t const * link = &topo->links[ tile->in_link_id[ k ] ];
40 0 : ulong value = *(fd_metrics_link_in( tile->metrics, polled_in_idx ) + metric->offset );
41 0 : switch( metric->converter ) {
42 0 : case FD_METRICS_CONVERTER_NANOSECONDS:
43 0 : value = fd_metrics_convert_ticks_to_nanoseconds( value );
44 0 : break;
45 0 : case FD_METRICS_CONVERTER_NONE:
46 0 : break;
47 0 : default:
48 0 : FD_LOG_ERR(( "unknown converter %i", metric->converter ));
49 0 : }
50 0 : fd_http_server_printf( http, "%s{kind=\"%s\",kind_id=\"%lu\",link_kind=\"%s\",link_kind_id=\"%lu\"} %lu\n", metric->name, tile->name, tile->kind_id, link->name, link->kind_id, value );
51 0 : polled_in_idx++;
52 0 : }
53 0 : } else if( FD_LIKELY( print_mode==PRINT_LINK_OUT ) ) {
54 0 : ulong reliable_conns_idx = 0UL;
55 0 : for( ulong k=0UL; k<topo->tile_cnt; k++ ) {
56 0 : fd_topo_tile_t const * consumer_tile = &topo->tiles[ k ];
57 0 : for( ulong l=0UL; l<consumer_tile->in_cnt; l++ ) {
58 0 : for( ulong m=0UL; m<tile->out_cnt; m++ ) {
59 0 : if( FD_UNLIKELY( consumer_tile->in_link_id[ l ]==tile->out_link_id[ m ] && consumer_tile->in_link_reliable[ l ] ) ) {
60 0 : fd_topo_link_t const * link = &topo->links[ consumer_tile->in_link_id[ l ] ];
61 :
62 0 : ulong value = *(fd_metrics_link_out( tile->metrics, reliable_conns_idx ) + metric->offset );
63 0 : switch( metric->converter ) {
64 0 : case FD_METRICS_CONVERTER_NANOSECONDS:
65 0 : value = fd_metrics_convert_ticks_to_nanoseconds( value );
66 0 : break;
67 0 : case FD_METRICS_CONVERTER_NONE:
68 0 : break;
69 0 : default:
70 0 : FD_LOG_ERR(( "unknown converter %i", metric->converter ));
71 0 : }
72 0 : fd_http_server_printf( http, "%s{kind=\"%s\",kind_id=\"%lu\",link_kind=\"%s\",link_kind_id=\"%lu\"} %lu\n", metric->name, tile->name, tile->kind_id, link->name, link->kind_id, value );
73 0 : reliable_conns_idx++;
74 0 : }
75 0 : }
76 0 : }
77 0 : }
78 0 : }
79 0 : }
80 0 : } else if( FD_LIKELY( metric->type==FD_METRICS_TYPE_HISTOGRAM ) ) {
81 0 : fd_histf_t hist[1];
82 0 : if( FD_LIKELY( metric->converter==FD_METRICS_CONVERTER_SECONDS ) )
83 0 : FD_TEST( fd_histf_new( hist, fd_metrics_convert_seconds_to_ticks( metric->histogram.seconds.min ), fd_metrics_convert_seconds_to_ticks ( metric->histogram.seconds.max ) ) );
84 0 : else if( FD_LIKELY( metric->converter==FD_METRICS_CONVERTER_NONE ) )
85 0 : FD_TEST( fd_histf_new( hist, metric->histogram.none.min, metric->histogram.none.max ) );
86 0 : else FD_LOG_ERR(( "unknown converter %i", metric->converter ));
87 :
88 0 : ulong value = 0;
89 0 : char value_str[ 64 ];
90 0 : for( ulong k=0; k<FD_HISTF_BUCKET_CNT; k++ ) {
91 0 : value += *(fd_metrics_tile( tile->metrics ) + metric->offset + k);
92 :
93 0 : char * le;
94 0 : char le_str[ 64 ];
95 0 : if( FD_UNLIKELY( k==FD_HISTF_BUCKET_CNT-1UL ) ) le = "+Inf";
96 0 : else {
97 0 : ulong edge = fd_histf_right( hist, k );
98 0 : if( FD_LIKELY( metric->converter==FD_METRICS_CONVERTER_SECONDS ) ) {
99 0 : double edgef = fd_metrics_convert_ticks_to_seconds( edge-1 );
100 0 : FD_TEST( fd_cstr_printf_check( le_str, sizeof( le_str ), NULL, "%.17g", edgef ) );
101 0 : } else {
102 0 : FD_TEST( fd_cstr_printf_check( le_str, sizeof( le_str ), NULL, "%lu", edge-1 ) );
103 0 : }
104 0 : le = le_str;
105 0 : }
106 :
107 0 : FD_TEST( fd_cstr_printf_check( value_str, sizeof( value_str ), NULL, "%lu", value ));
108 0 : fd_http_server_printf( http, "%s_bucket{kind=\"%s\",kind_id=\"%lu\",le=\"%s\"} %s\n", metric->name, tile->name, tile->kind_id, le, value_str );
109 0 : }
110 :
111 0 : char sum_str[ 64 ];
112 0 : if( FD_LIKELY( metric->converter==FD_METRICS_CONVERTER_SECONDS ) ) {
113 0 : double sumf = fd_metrics_convert_ticks_to_seconds( *(fd_metrics_tile( tile->metrics ) + metric->offset + FD_HISTF_BUCKET_CNT) );
114 0 : FD_TEST( fd_cstr_printf_check( sum_str, sizeof( sum_str ), NULL, "%.17g", sumf ) );
115 0 : } else {
116 0 : FD_TEST( fd_cstr_printf_check( sum_str, sizeof( sum_str ), NULL, "%lu", *(fd_metrics_tile( tile->metrics ) + metric->offset + FD_HISTF_BUCKET_CNT) ));
117 0 : }
118 :
119 0 : fd_http_server_printf( http, "%s_sum{kind=\"%s\",kind_id=\"%lu\"} %s\n", metric->name, tile->name, tile->kind_id, sum_str );
120 0 : fd_http_server_printf( http, "%s_count{kind=\"%s\",kind_id=\"%lu\"} %s\n", metric->name, tile->name, tile->kind_id, value_str );
121 0 : }
122 0 : }
123 :
124 0 : if( FD_LIKELY( i!=metrics_cnt-1 ) ) fd_http_server_printf( http, "\n" );
125 0 : }
126 0 : }
127 :
128 : void
129 : fd_prometheus_format( fd_topo_t const * topo,
130 0 : fd_http_server_t * http ) {
131 0 : prometheus_print1( topo, http, NULL, FD_METRICS_ALL_TOTAL, FD_METRICS_ALL, PRINT_TILE );
132 0 : fd_http_server_printf( http, "\n" );
133 0 : prometheus_print1( topo, http, NULL, FD_METRICS_ALL_LINK_IN_TOTAL, FD_METRICS_ALL_LINK_IN, PRINT_LINK_IN );
134 0 : fd_http_server_printf( http, "\n" );
135 0 : prometheus_print1( topo, http, NULL, FD_METRICS_ALL_LINK_OUT_TOTAL, FD_METRICS_ALL_LINK_OUT, PRINT_LINK_OUT );
136 :
137 0 : for( ulong i=0UL; i<FD_METRICS_TILE_KIND_CNT; i++ ) {
138 0 : fd_http_server_printf( http, "\n" );
139 0 : prometheus_print1( topo, http, FD_METRICS_TILE_KIND_NAMES[ i ], FD_METRICS_TILE_KIND_SIZES[ i ], FD_METRICS_TILE_KIND_METRICS[ i ], PRINT_TILE );
140 0 : }
141 0 : }
|