2323#include " brpc/controller.h"
2424#include " butil/strings/string_piece.h"
2525#include " echo.pb.h"
26+ #include " bvar/multi_dimension.h"
2627
2728int main (int argc, char * argv[]) {
2829 testing::InitGoogleTest (&argc, argv);
@@ -45,7 +46,13 @@ enum STATE {
4546 HELP = 0 ,
4647 TYPE,
4748 GAUGE,
48- SUMMARY
49+ SUMMARY,
50+ COUNTER,
51+ // When meets a line with a gauge/counter with labels, we have no
52+ // idea the next line is a new HELP or the same gauge/counter just
53+ // with different labels
54+ HELP_OR_GAUGE,
55+ HELP_OR_COUNTER,
4956};
5057
5158TEST (PrometheusMetrics, sanity) {
@@ -54,10 +61,22 @@ TEST(PrometheusMetrics, sanity) {
5461 ASSERT_EQ (0 , server.AddService (&echo_svc, brpc::SERVER_DOESNT_OWN_SERVICE));
5562 ASSERT_EQ (0 , server.Start (" 127.0.0.1:8614" , NULL ));
5663
57- brpc::Server server2;
58- DummyEchoServiceImpl echo_svc2;
59- ASSERT_EQ (0 , server2.AddService (&echo_svc2, brpc::SERVER_DOESNT_OWN_SERVICE));
60- ASSERT_EQ (0 , server2.Start (" 127.0.0.1:8615" , NULL ));
64+ const std::list<std::string> labels = {" label1" , " label2" };
65+ bvar::MultiDimension<bvar::Adder<uint32_t > > my_madder (" madder" , labels);
66+ bvar::Adder<uint32_t >* my_adder1 = my_madder.get_stats ({" val1" , " val2" });
67+ ASSERT_TRUE (my_adder1);
68+ *my_adder1 << 1 << 2 ;
69+ bvar::Adder<uint32_t >* my_adder2 = my_madder.get_stats ({" val2" , " val3" });
70+ ASSERT_TRUE (my_adder1);
71+ *my_adder2 << 3 << 4 ;
72+
73+ bvar::MultiDimension<bvar::LatencyRecorder > my_mlat (" mlat" , labels);
74+ bvar::LatencyRecorder* my_lat1 = my_mlat.get_stats ({" val1" , " val2" });
75+ ASSERT_TRUE (my_lat1);
76+ *my_lat1 << 1 << 2 ;
77+ bvar::LatencyRecorder* my_lat2 = my_mlat.get_stats ({" val2" , " val3" });
78+ ASSERT_TRUE (my_lat2);
79+ *my_lat2 << 3 << 4 ;
6180
6281 brpc::Channel channel;
6382 brpc::ChannelOptions channel_opts;
@@ -68,19 +87,22 @@ TEST(PrometheusMetrics, sanity) {
6887 channel.CallMethod (NULL , &cntl, NULL , NULL , NULL );
6988 ASSERT_FALSE (cntl.Failed ());
7089 std::string res = cntl.response_attachment ().to_string ();
71-
90+ LOG (INFO) << " output: \n " << res;
7291 size_t start_pos = 0 ;
7392 size_t end_pos = 0 ;
93+ size_t label_start = 0 ;
7494 STATE state = HELP;
7595 char name_help[128 ];
7696 char name_type[128 ];
7797 char type[16 ];
7898 int matched = 0 ;
79- int gauge_num = 0 ;
99+ int num = 0 ;
80100 bool summary_sum_gathered = false ;
81101 bool summary_count_gathered = false ;
82102 bool has_ever_summary = false ;
83103 bool has_ever_gauge = false ;
104+ bool has_ever_counter = false ; // brought in by mvar latency recorder
105+ std::unordered_set<std::string> metric_name_set;
84106
85107 while ((end_pos = res.find (' \n ' , start_pos)) != butil::StringPiece::npos) {
86108 res[end_pos] = ' \0 ' ; // safe;
@@ -98,21 +120,52 @@ TEST(PrometheusMetrics, sanity) {
98120 state = GAUGE;
99121 } else if (strcmp (type, " summary" ) == 0 ) {
100122 state = SUMMARY;
123+ } else if (strcmp (type, " counter" ) == 0 ) {
124+ state = COUNTER;
101125 } else {
102- ASSERT_TRUE (false );
126+ ASSERT_TRUE (false ) << " invalid type: " << type ;
103127 }
128+ ASSERT_EQ (0 , metric_name_set.count (name_type)) << " second TYPE line for metric name "
129+ << name_type;
130+ metric_name_set.insert (name_help);
104131 break ;
132+ case HELP_OR_GAUGE:
133+ case HELP_OR_COUNTER:
134+ matched = sscanf (res.data () + start_pos, " # HELP %s" , name_help);
135+ // Try to figure out current line is a new COMMENT or not
136+ if (matched == 1 ) {
137+ state = HELP;
138+ } else {
139+ state = state == HELP_OR_GAUGE ? GAUGE : COUNTER;
140+ }
141+ res[end_pos] = ' \n ' ; // revert to original
142+ continue ; // do not jump to next line
105143 case GAUGE:
106- matched = sscanf (res.data () + start_pos, " %s %d" , name_type, &gauge_num);
144+ case COUNTER:
145+ matched = sscanf (res.data () + start_pos, " %s %d" , name_type, &num);
107146 ASSERT_EQ (2 , matched);
108- ASSERT_STREQ (name_type, name_help);
109- state = HELP;
110- has_ever_gauge = true ;
147+ if (state == GAUGE) {
148+ has_ever_gauge = true ;
149+ }
150+ if (state == COUNTER) {
151+ has_ever_counter = true ;
152+ }
153+ label_start = butil::StringPiece (name_type).find (" {" );
154+ if (label_start == strlen (name_help)) { // mvar
155+ ASSERT_EQ (name_type[strlen (name_type) - 1 ], ' }' );
156+ ASSERT_TRUE (strncmp (name_type, name_help, strlen (name_help)) == 0 );
157+ state = state == GAUGE ? HELP_OR_GAUGE : HELP_OR_COUNTER;
158+ } else if (label_start == butil::StringPiece::npos) { // var
159+ ASSERT_STREQ (name_type, name_help);
160+ state = HELP;
161+ } else { // invalid
162+ ASSERT_TRUE (false );
163+ }
111164 break ;
112165 case SUMMARY:
113166 if (butil::StringPiece (res.data () + start_pos, end_pos - start_pos).find (" quantile=" )
114167 == butil::StringPiece::npos) {
115- matched = sscanf (res.data () + start_pos, " %s %d" , name_type, &gauge_num );
168+ matched = sscanf (res.data () + start_pos, " %s %d" , name_type, &num );
116169 ASSERT_EQ (2 , matched);
117170 ASSERT_TRUE (strncmp (name_type, name_help, strlen (name_help)) == 0 );
118171 if (butil::StringPiece (name_type).ends_with (" _sum" )) {
@@ -138,7 +191,7 @@ TEST(PrometheusMetrics, sanity) {
138191 }
139192 start_pos = end_pos + 1 ;
140193 }
141- ASSERT_TRUE (has_ever_gauge && has_ever_summary);
194+ ASSERT_TRUE (has_ever_gauge && has_ever_summary && has_ever_counter );
142195 ASSERT_EQ (0 , server.Stop (0 ));
143196 ASSERT_EQ (0 , server.Join ());
144197}
0 commit comments