Skip to content

Commit 3a06e71

Browse files
Metrics exposure (#334)
* Added ability to observe http connection metrics.
1 parent 85ecd8d commit 3a06e71

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

include/aws/http/connection.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ typedef void(aws_http2_on_remote_settings_change_fn)(
105105
size_t num_settings,
106106
void *user_data);
107107

108+
/**
109+
* Callback invoked on each statistics sample.
110+
*
111+
* connection_nonce is unique to each connection for disambiguation of each callback per connection.
112+
*/
113+
typedef void(
114+
aws_http_statistics_observer_fn)(size_t connection_nonce, const struct aws_array_list *stats_list, void *user_data);
115+
108116
/**
109117
* Configuration options for connection monitoring
110118
*/
@@ -121,6 +129,17 @@ struct aws_http_connection_monitoring_options {
121129
* as unhealthy.
122130
*/
123131
uint32_t allowable_throughput_failure_interval_seconds;
132+
133+
/**
134+
* invoked on each statistics publish by the underlying IO channel. Install this callback to receive the statistics
135+
* for observation. This field is optional.
136+
*/
137+
aws_http_statistics_observer_fn *statistics_observer_fn;
138+
139+
/**
140+
* user_data to be passed to statistics_observer_fn.
141+
*/
142+
void *statistics_observer_user_data;
124143
};
125144

126145
/**

source/connection_monitor.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ static void s_process_statistics(
6969
}
7070
}
7171

72+
if (impl->options.statistics_observer_fn) {
73+
impl->options.statistics_observer_fn(
74+
(size_t)(uintptr_t)(context), stats_list, impl->options.statistics_observer_user_data);
75+
}
76+
7277
struct aws_channel *channel = context;
7378

7479
uint64_t bytes_per_second = 0;

tests/test_connection_monitor.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,52 @@ static struct http_monitor_test_stats_event s_test_rw_above_events[] = {
284284
.expected_throughput = 1000,
285285
},
286286
};
287+
288+
struct observer_cb_data {
289+
bool invoked;
290+
size_t nonce;
291+
size_t number_of_stats;
292+
struct aws_crt_statistics_socket socket_stats;
293+
struct aws_crt_statistics_http1_channel http_stats;
294+
};
295+
static void s_observer_cb(size_t connection_nonce, const struct aws_array_list *stats, void *user_data) {
296+
struct observer_cb_data *cb_data = user_data;
297+
cb_data->invoked = true;
298+
cb_data->nonce = connection_nonce;
299+
cb_data->number_of_stats = aws_array_list_length(stats);
300+
301+
for (size_t i = 0; i < cb_data->number_of_stats; ++i) {
302+
struct aws_crt_statistics_base *base_ptr = NULL;
303+
aws_array_list_get_at(stats, (void **)&base_ptr, i);
304+
305+
if (base_ptr->category == AWSCRT_STAT_CAT_SOCKET) {
306+
cb_data->socket_stats = *(struct aws_crt_statistics_socket *)base_ptr;
307+
}
308+
309+
if (base_ptr->category == AWSCRT_STAT_CAT_HTTP1_CHANNEL) {
310+
cb_data->http_stats = *(struct aws_crt_statistics_http1_channel *)base_ptr;
311+
}
312+
}
313+
}
287314
static int s_test_http_connection_monitor_rw_above(struct aws_allocator *allocator, void *ctx) {
288315
(void)ctx;
289316

317+
struct observer_cb_data cb_data;
318+
AWS_ZERO_STRUCT(cb_data);
319+
s_test_options.statistics_observer_fn = s_observer_cb;
320+
s_test_options.statistics_observer_user_data = &cb_data;
290321
int result = s_do_http_monitoring_test(
291322
allocator, &s_test_options, s_test_rw_above_events, AWS_ARRAY_SIZE(s_test_rw_above_events));
292323
ASSERT_TRUE(result == AWS_OP_SUCCESS);
324+
ASSERT_TRUE(cb_data.invoked);
325+
ASSERT_TRUE(cb_data.nonce > 0);
326+
ASSERT_UINT_EQUALS(2U, cb_data.number_of_stats);
327+
ASSERT_UINT_EQUALS(s_test_rw_above_events[0].socket_stats.bytes_written, cb_data.socket_stats.bytes_written);
328+
ASSERT_UINT_EQUALS(s_test_rw_above_events[0].socket_stats.bytes_read, cb_data.socket_stats.bytes_read);
329+
ASSERT_UINT_EQUALS(
330+
s_test_rw_above_events[0].http_stats.current_outgoing_stream_id, cb_data.http_stats.current_outgoing_stream_id);
331+
ASSERT_UINT_EQUALS(
332+
s_test_rw_above_events[0].http_stats.current_incoming_stream_id, cb_data.http_stats.current_incoming_stream_id);
293333

294334
return AWS_OP_SUCCESS;
295335
}

0 commit comments

Comments
 (0)