Skip to content

Commit 31b5dd6

Browse files
bretambrosegraebm
andauthored
Stat (#152)
* Base statistics gathering and monitoring * Control rate of HTTP/1 writes (#180) * HTTP/1 only writes 1 message at a time. This avoids bloating memory with unsent messages. This also helps improve the accuracy of our upload stats. Still needs tweaking to deal with websocket upgrade edge-cases. * Install websocket handler the moment 101 response comes in, do not wait for stream to complete. Remove hacks where 101 response completed a stream, no 1xx response should complete a stream. * Simplify confusing list logic. Remove the server-only `waiting_stream_list`. Do a simple scan over available streams to find the next one to work on. This is O(N) when pipelining, but I hear that no one does HTTP/1 pipelining, so in that case O(N=1). We can always re-optimize if we have data that pipelining is super popular and this is a hotspot. * Update * Windows warning Co-authored-by: Michael Graeb <[email protected]>
1 parent 5e33ddf commit 31b5dd6

31 files changed

+2498
-468
lines changed

include/aws/http/connection.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ typedef void(
5656
typedef void(
5757
aws_http_on_client_connection_shutdown_fn)(struct aws_http_connection *connection, int error_code, void *user_data);
5858

59+
/**
60+
* Configuration options for connection monitoring
61+
*/
62+
struct aws_http_connection_monitoring_options {
63+
64+
/**
65+
* minimum required throughput of the connection. Throughput is only measured against the interval of time where
66+
* there is actual io to perform. Read and write throughput are measured and checked independently of one another.
67+
*/
68+
uint64_t minimum_throughput_bytes_per_second;
69+
70+
/*
71+
* amount of time, in seconds, throughput is allowed to drop below the minimum before the connection is shut down
72+
* as unhealthy.
73+
*/
74+
uint32_t allowable_throughput_failure_interval_seconds;
75+
};
76+
5977
/**
6078
* Supported proxy authentication modes
6179
*/
@@ -158,6 +176,12 @@ struct aws_http_client_connection_options {
158176
*/
159177
const struct aws_http_proxy_options *proxy_options;
160178

179+
/**
180+
* Optional
181+
* Configuration options related to connection health monitoring
182+
*/
183+
const struct aws_http_connection_monitoring_options *monitoring_options;
184+
161185
/**
162186
* Optional.
163187
* A default size is set by AWS_HTTP_CLIENT_CONNECTION_OPTIONS_INIT.

include/aws/http/connection_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct aws_http_connection_manager_options {
4848
const struct aws_socket_options *socket_options;
4949
const struct aws_tls_connection_options *tls_connection_options;
5050
const struct aws_http_proxy_options *proxy_options;
51+
const struct aws_http_connection_monitoring_options *monitoring_options;
5152
struct aws_byte_cursor host;
5253
uint16_t port;
5354

include/aws/http/http.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
* permissions and limitations under the License.
1717
*/
1818

19+
#include <aws/common/logging.h>
1920
#include <aws/http/exports.h>
20-
2121
#include <aws/io/io.h>
2222

23+
#define AWS_C_HTTP_PACKAGE_ID 2
24+
2325
enum aws_http_errors {
24-
AWS_ERROR_HTTP_UNKNOWN = 0x0800,
26+
AWS_ERROR_HTTP_UNKNOWN = AWS_ERROR_ENUM_BEGIN_RANGE(AWS_C_HTTP_PACKAGE_ID),
2527
AWS_ERROR_HTTP_HEADER_NOT_FOUND,
2628
AWS_ERROR_HTTP_INVALID_HEADER_FIELD,
2729
AWS_ERROR_HTTP_INVALID_HEADER_NAME,
@@ -46,17 +48,18 @@ enum aws_http_errors {
4648
AWS_ERROR_HTTP_SERVER_CLOSED,
4749
AWS_ERROR_HTTP_PROXY_TLS_CONNECT_FAILED,
4850
AWS_ERROR_HTTP_CONNECTION_MANAGER_SHUTTING_DOWN,
51+
AWS_ERROR_HTTP_CHANNEL_THROUGHPUT_FAILURE,
4952
AWS_ERROR_HTTP_PROTOCOL_ERROR,
5053
AWS_ERROR_HTTP_STREAM_CLOSED,
5154
AWS_ERROR_HTTP_STREAM_IDS_EXHAUSTED,
5255
AWS_ERROR_HTTP_INVALID_FRAME_SIZE,
5356
AWS_ERROR_HTTP_COMPRESSION,
5457

55-
AWS_ERROR_HTTP_END_RANGE = 0x0C00,
58+
AWS_ERROR_HTTP_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_HTTP_PACKAGE_ID)
5659
};
5760

5861
enum aws_http_log_subject {
59-
AWS_LS_HTTP_GENERAL = 0x800,
62+
AWS_LS_HTTP_GENERAL = AWS_LOG_SUBJECT_BEGIN_RANGE(AWS_C_HTTP_PACKAGE_ID),
6063
AWS_LS_HTTP_CONNECTION,
6164
AWS_LS_HTTP_ENCODER,
6265
AWS_LS_HTTP_DECODER,

include/aws/http/private/connection_impl.h

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,10 @@ struct aws_http_make_request_options;
3030
struct aws_http_request_handler_options;
3131
struct aws_http_stream;
3232

33-
typedef int(aws_client_bootstrap_new_socket_channel_fn)(
34-
struct aws_client_bootstrap *bootstrap,
35-
const char *host_name,
36-
uint16_t port,
37-
const struct aws_socket_options *options,
38-
aws_client_bootstrap_on_channel_setup_fn *setup_callback,
39-
aws_client_bootstrap_on_channel_shutdown_fn *shutdown_callback,
40-
void *user_data);
41-
42-
typedef int(aws_client_bootstrap_new_tls_socket_channel_fn)(
43-
struct aws_client_bootstrap *bootstrap,
44-
const char *host_name,
45-
uint16_t port,
46-
const struct aws_socket_options *options,
47-
const struct aws_tls_connection_options *connection_options,
48-
aws_client_bootstrap_on_channel_setup_fn *setup_callback,
49-
aws_client_bootstrap_on_channel_shutdown_fn *shutdown_callback,
50-
void *user_data);
33+
typedef int aws_client_bootstrap_new_socket_channel_fn(struct aws_socket_channel_bootstrap_options *options);
5134

5235
struct aws_http_connection_system_vtable {
5336
aws_client_bootstrap_new_socket_channel_fn *new_socket_channel;
54-
aws_client_bootstrap_new_tls_socket_channel_fn *new_tls_socket_channel;
5537
};
5638

5739
struct aws_http_connection_vtable {
@@ -90,6 +72,9 @@ struct aws_http_connection {
9072
* aws_http_streams will also acquire holds on their connection for the duration of their lifetime */
9173
struct aws_atomic_var refcount;
9274

75+
/* Starts at either 1 or 2, increments by two with each new stream */
76+
struct aws_atomic_var next_stream_id;
77+
9378
union {
9479
struct aws_http_connection_client_data {
9580
uint8_t delete_me; /* exists to prevent "empty struct" errors */
@@ -113,6 +98,7 @@ struct aws_http_client_bootstrap {
11398
struct aws_allocator *alloc;
11499
bool is_using_tls;
115100
size_t initial_window_size;
101+
struct aws_http_connection_monitoring_options monitoring_options;
116102
void *user_data;
117103
aws_http_on_client_connection_setup_fn *on_setup;
118104
aws_http_on_client_connection_shutdown_fn *on_shutdown;
@@ -137,6 +123,20 @@ int aws_http_client_connect_internal(
137123
AWS_HTTP_API
138124
void aws_http_connection_acquire(struct aws_http_connection *connection);
139125

126+
/**
127+
* Allow tests to fake stats data
128+
*/
129+
AWS_HTTP_API
130+
struct aws_crt_statistics_http1_channel *aws_h1_connection_get_statistics(struct aws_http_connection *connection);
131+
132+
/**
133+
* Gets the next available stream id within the connection. Valid for creating both h1 and h2 streams.
134+
*
135+
* Returns 0 if there was an error.
136+
*/
137+
AWS_HTTP_API
138+
uint32_t aws_http_connection_get_next_stream_id(struct aws_http_connection *connection);
139+
140140
AWS_EXTERN_C_END
141141

142142
#endif /* AWS_HTTP_CONNECTION_IMPL_H */
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef AWS_HTTP_HTTP_MONITOR_H
2+
#define AWS_HTTP_HTTP_MONITOR_H
3+
4+
/*
5+
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License").
8+
* You may not use this file except in compliance with the License.
9+
* A copy of the License is located at
10+
*
11+
* http://aws.amazon.com/apache2.0
12+
*
13+
* or in the "license" file accompanying this file. This file is distributed
14+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
15+
* express or implied. See the License for the specific language governing
16+
* permissions and limitations under the License.
17+
*/
18+
19+
#include <aws/http/connection.h>
20+
#include <aws/http/http.h>
21+
22+
struct aws_allocator;
23+
struct aws_crt_statistics_handler;
24+
25+
/*
26+
* Needed by tests
27+
*/
28+
struct aws_statistics_handler_http_connection_monitor_impl {
29+
struct aws_http_connection_monitoring_options options;
30+
31+
uint64_t throughput_failure_time_ms;
32+
uint32_t last_incoming_stream_id;
33+
uint32_t last_outgoing_stream_id;
34+
uint64_t last_measured_throughput;
35+
};
36+
37+
AWS_EXTERN_C_BEGIN
38+
39+
/**
40+
* Creates a new http connection monitor that regularly checks the connection's throughput and shuts the connection
41+
* down if the a minimum threshold is not met for a configurable number of seconds.
42+
*/
43+
AWS_HTTP_API
44+
struct aws_crt_statistics_handler *aws_crt_statistics_handler_new_http_connection_monitor(
45+
struct aws_allocator *allocator,
46+
struct aws_http_connection_monitoring_options *options);
47+
48+
/**
49+
* Validates monitoring options to ensure they are sensible
50+
*/
51+
AWS_HTTP_API
52+
bool aws_http_connection_monitoring_options_is_valid(const struct aws_http_connection_monitoring_options *options);
53+
54+
AWS_EXTERN_C_END
55+
56+
#endif /* AWS_HTTP_HTTP_MONITOR_H */

include/aws/http/private/h2_connection.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ struct aws_h2_connection {
5151
/* New `aws_h2_stream *` that haven't moved to `thread_data` yet */
5252
struct aws_linked_list pending_stream_list;
5353

54-
/* Refers to the next stream id to vend */
55-
uint32_t next_stream_id;
56-
5754
/* If non-zero, reason to immediately reject new streams. (ex: closing) */
5855
int new_stream_error_code;
5956

include/aws/http/private/h2_stream.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
AWS_LOGF_##level( \
2828
AWS_LS_HTTP_STREAM, \
2929
"id=%" PRIu32 " connection=%p state=%s: " text, \
30-
(stream)->id, \
30+
(stream)->base.id, \
3131
(void *)(stream)->base.owning_connection, \
3232
aws_h2_stream_state_to_str((stream)->thread_data.state), \
3333
__VA_ARGS__)
@@ -48,8 +48,6 @@ enum aws_h2_stream_state {
4848
struct aws_h2_stream {
4949
struct aws_http_stream base;
5050

51-
uint32_t id;
52-
5351
struct aws_linked_list_node node;
5452

5553
/* Only the event-loop thread may touch this data */

include/aws/http/private/request_response_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct aws_http_stream {
3636
struct aws_allocator *alloc;
3737
struct aws_http_connection *owning_connection;
3838

39+
uint32_t id;
40+
3941
bool manual_window_management;
4042

4143
void *user_data;

include/aws/http/request_response.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,12 @@ int aws_http_stream_send_response(struct aws_http_stream *stream, struct aws_htt
647647
AWS_HTTP_API
648648
void aws_http_stream_update_window(struct aws_http_stream *stream, size_t increment_size);
649649

650+
/**
651+
* Gets the Http/2 id associated with a stream. Even h1 streams have an id (using the same allocation procedure
652+
* as http/2) for easier tracking purposes.
653+
*/
654+
uint32_t aws_http_stream_get_id(struct aws_http_stream *stream);
655+
650656
AWS_EXTERN_C_END
651657

652658
#endif /* AWS_HTTP_REQUEST_RESPONSE_H */

include/aws/http/statistics.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#ifndef AWS_HTTP_STATISTICS_H
2+
#define AWS_HTTP_STATISTICS_H
3+
4+
/*
5+
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License").
8+
* You may not use this file except in compliance with the License.
9+
* A copy of the License is located at
10+
*
11+
* http://aws.amazon.com/apache2.0
12+
*
13+
* or in the "license" file accompanying this file. This file is distributed
14+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
15+
* express or implied. See the License for the specific language governing
16+
* permissions and limitations under the License.
17+
*/
18+
19+
#include <aws/http/http.h>
20+
21+
#include <aws/common/statistics.h>
22+
23+
enum aws_crt_http_statistics_category {
24+
AWSCRT_STAT_CAT_HTTP1_CHANNEL = AWS_CRT_STATISTICS_CATEGORY_BEGIN_RANGE(AWS_C_HTTP_PACKAGE_ID),
25+
};
26+
27+
/**
28+
* A statistics struct for http handlers. Tracks the actual amount of time that incoming and outgoing requests are
29+
* waiting for their IO to complete.
30+
*/
31+
struct aws_crt_statistics_http1_channel {
32+
aws_crt_statistics_category_t category;
33+
34+
uint64_t pending_outgoing_stream_ms;
35+
uint64_t pending_incoming_stream_ms;
36+
37+
uint32_t current_outgoing_stream_id;
38+
uint32_t current_incoming_stream_id;
39+
};
40+
41+
AWS_EXTERN_C_BEGIN
42+
43+
/**
44+
* Initializes a http channel handler statistics struct
45+
*/
46+
AWS_HTTP_API
47+
int aws_crt_statistics_http1_channel_init(struct aws_crt_statistics_http1_channel *stats);
48+
49+
/**
50+
* Cleans up a http channel handler statistics struct
51+
*/
52+
AWS_HTTP_API
53+
void aws_crt_statistics_http1_channel_cleanup(struct aws_crt_statistics_http1_channel *stats);
54+
55+
/**
56+
* Resets a http channel handler statistics struct's statistics
57+
*/
58+
AWS_HTTP_API
59+
void aws_crt_statistics_http1_channel_reset(struct aws_crt_statistics_http1_channel *stats);
60+
61+
AWS_EXTERN_C_END
62+
63+
#endif /* AWS_HTTP_STATISTICS_H */

0 commit comments

Comments
 (0)