@@ -130,6 +130,34 @@ TEST_CASE("program.c-prometheus", "[program-prometheus]") {
130
130
REQUIRE (connect (clientfd, (struct sockaddr *) &address, sizeof (address)) == 0 );
131
131
132
132
SECTION (" Prometheus - /metrics endpoint" ) {
133
+ // Build up the list of the fields in the response
134
+ char *metrics_names[] = {
135
+ " cachegrand_network_total_received_packets" ,
136
+ " cachegrand_network_total_received_data" ,
137
+ " cachegrand_network_total_sent_packets" ,
138
+ " cachegrand_network_total_sent_data" ,
139
+ " cachegrand_network_total_accepted_connections" ,
140
+ " cachegrand_network_total_active_connections" ,
141
+ " cachegrand_storage_total_written_data" ,
142
+ " cachegrand_storage_total_write_iops" ,
143
+ " cachegrand_storage_total_read_data" ,
144
+ " cachegrand_storage_total_read_iops" ,
145
+ " cachegrand_storage_total_open_files" ,
146
+
147
+ " cachegrand_network_per_minute_received_packets" ,
148
+ " cachegrand_network_per_minute_received_data" ,
149
+ " cachegrand_network_per_minute_sent_packets" ,
150
+ " cachegrand_network_per_minute_sent_data" ,
151
+ " cachegrand_network_per_minute_accepted_connections" ,
152
+ " cachegrand_storage_per_minute_written_data" ,
153
+ " cachegrand_storage_per_minute_write_iops" ,
154
+ " cachegrand_storage_per_minute_read_data" ,
155
+ " cachegrand_storage_per_minute_read_iops" ,
156
+
157
+ " cachegrand_uptime" ,
158
+ NULL ,
159
+ };
160
+
133
161
char request_template[] =
134
162
" GET /metrics HTTP/1.1\r\n "
135
163
" User-Agent: cachegrand-tests\r\n "
@@ -146,27 +174,102 @@ TEST_CASE("program.c-prometheus", "[program-prometheus]") {
146
174
buffer_send_data_len = strlen (buffer_send);
147
175
148
176
SECTION (" No env vars" ) {
177
+ char *new_line_ptr = NULL ;
178
+ int buffer_recv_length;
149
179
REQUIRE (send (clientfd, buffer_send, buffer_send_data_len, 0 ) == buffer_send_data_len);
150
- REQUIRE (recv (clientfd, buffer_recv, sizeof (buffer_recv), 0 ) > 0 );
180
+ REQUIRE ((buffer_recv_length = recv (clientfd, buffer_recv, sizeof (buffer_recv), 0 ) ) > 0 );
151
181
152
182
// Check that the response is a 200 OK and that the content type is text plain
153
183
REQUIRE (strncmp (buffer_recv, " HTTP/1.1 200 OK\r\n Content-Type: text/plain; charset=ASCII\r\n " ,
154
184
strlen (" HTTP/1.1 200 OK\r\n Content-Type: text/plain; charset=ASCII\r\n " )) == 0 );
155
185
156
- // TODO: should spot check some metrics
186
+ // Search for the end of the HTTP header
187
+ new_line_ptr = buffer_recv;
188
+ while ((new_line_ptr = (char *)memchr (
189
+ new_line_ptr + 1 ,
190
+ ' \n ' ,
191
+ (buffer_recv_length - ((new_line_ptr + 1 ) - buffer_recv))))) {
192
+ if (new_line_ptr - buffer_recv > 3 ) {
193
+ if (strncmp (new_line_ptr - 3 , " \r\n\r\n " , 4 ) == 0 ) {
194
+ break ;
195
+ }
196
+ }
197
+ }
198
+
199
+ // Ensure that has found the double new line at the end of the HTTP header
200
+ REQUIRE (new_line_ptr != NULL );
201
+
202
+ for (char **metric_name = metrics_names; *metric_name; ++metric_name) {
203
+ // Ensure that there is enough content in the buffer to contain the metric name, "{} ", at least 1 digit
204
+ // and then \n
205
+ REQUIRE ((buffer_recv_length - ((new_line_ptr + 1 ) - buffer_recv)) >= strlen (*metric_name) + 3 + 1 + 1 );
206
+ new_line_ptr++;
207
+
208
+ // Ensure that the next metric is the expected one
209
+ REQUIRE (strncmp (new_line_ptr, *metric_name, strlen (*metric_name)) == 0 );
210
+
211
+ // As there are no env labels, ensure that the metric name is followed by "{} "
212
+ REQUIRE (strncmp (new_line_ptr + strlen (*metric_name), " {} " , 3 ) == 0 );
213
+
214
+ // THere is always a new line at the end of the line, even the last line
215
+ REQUIRE ((new_line_ptr = (char *)memchr (new_line_ptr, ' \n ' , buffer_recv_length)) != NULL );
216
+ }
157
217
}
158
218
159
- // TODO: implement tests to validate that env vars are properly caught and reported in the page
160
- // SECTION("With env vars") {
161
- // REQUIRE(send(clientfd, buffer_send, buffer_send_data_len, 0) == buffer_send_data_len);
162
- // REQUIRE(recv(clientfd, buffer_recv, sizeof(buffer_recv), 0) > 0);
163
- //
164
- // // Check that the response is a 200 OK and that the content type is text plain
165
- // REQUIRE(strncmp(buffer_recv, "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=ASCII\r\n",
166
- // strlen("HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=ASCII\r\n")) == 0);
167
- //
168
- // // TODO: should spot check some metrics
169
- // }
219
+ SECTION (" With env vars" ) {
220
+ char *new_line_ptr = NULL ;
221
+ int buffer_recv_length;
222
+
223
+ char *expected_labels = " {label_1=\" value 1\" ,another_label=\" another value\" }" ;
224
+
225
+ // Set 2 env vars to use them as lables in the metrics
226
+ setenv (" CACHEGRAND_METRIC_ENV_LABEL_1" , " value 1" , 1 );
227
+ setenv (" CACHEGRAND_METRIC_ENV_ANOTHER_LABEL" , " another value" , 1 );
228
+
229
+ REQUIRE (send (clientfd, buffer_send, buffer_send_data_len, 0 ) == buffer_send_data_len);
230
+ REQUIRE ((buffer_recv_length = recv (clientfd, buffer_recv, sizeof (buffer_recv), 0 )) > 0 );
231
+
232
+ // Unset the labels before doing anything else
233
+ unsetenv (" CACHEGRAND_METRIC_ENV_LABEL_1" );
234
+ unsetenv (" CACHEGRAND_METRIC_ENV_ANOTHER_LABEL" );
235
+
236
+ // Check that the response is a 200 OK and that the content type is text plain
237
+ REQUIRE (strncmp (buffer_recv, " HTTP/1.1 200 OK\r\n Content-Type: text/plain; charset=ASCII\r\n " ,
238
+ strlen (" HTTP/1.1 200 OK\r\n Content-Type: text/plain; charset=ASCII\r\n " )) == 0 );
239
+
240
+ // Search for the end of the HTTP header
241
+ new_line_ptr = buffer_recv;
242
+ while ((new_line_ptr = (char *)memchr (
243
+ new_line_ptr + 1 ,
244
+ ' \n ' ,
245
+ (buffer_recv_length - ((new_line_ptr + 1 ) - buffer_recv))))) {
246
+ if (new_line_ptr - buffer_recv > 3 ) {
247
+ if (strncmp (new_line_ptr - 3 , " \r\n\r\n " , 4 ) == 0 ) {
248
+ break ;
249
+ }
250
+ }
251
+ }
252
+
253
+ // Ensure that has found the double new line at the end of the HTTP header
254
+ REQUIRE (new_line_ptr != NULL );
255
+
256
+ for (char **metric_name = metrics_names; *metric_name; ++metric_name) {
257
+ // Ensure that there is enough content in the buffer to contain the metric name, the labels, a space, at
258
+ // least 1 digit and then \n
259
+ REQUIRE ((buffer_recv_length - ((new_line_ptr + 1 ) - buffer_recv)) >=
260
+ strlen (*metric_name) + strlen (expected_labels) + 1 + 1 + 1 );
261
+ new_line_ptr++;
262
+
263
+ // Ensure that the next metric is the expected one
264
+ REQUIRE (strncmp (new_line_ptr, *metric_name, strlen (*metric_name)) == 0 );
265
+
266
+ // As there are no env labels, ensure that the metric name is followed by expected_labels
267
+ REQUIRE (strncmp (new_line_ptr + strlen (*metric_name), expected_labels, strlen (expected_labels)) == 0 );
268
+
269
+ // THere is always a new line at the end of the line, even the last line
270
+ REQUIRE ((new_line_ptr = (char *)memchr (new_line_ptr, ' \n ' , buffer_recv_length)) != NULL );
271
+ }
272
+ }
170
273
}
171
274
172
275
SECTION (" Prometheus - 404" ) {
0 commit comments