diff --git a/CODEOWNERS b/CODEOWNERS index 25e1e00101..b262e11f9c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,6 +5,8 @@ /codegen-server/ @smithy-lang/smithy-rs-server /rust-runtime/aws-smithy-http-server/ @smithy-lang/smithy-rs-server /rust-runtime/aws-smithy-legacy-http-server/ @smithy-lang/smithy-rs-server +/rust-runtime/aws-smithy-http-server-metrics @smithy-lang/smithy-rs-server +/rust-runtime/aws-smithy-http-server-metrics-macro @smithy-lang/smithy-rs-server # Python Server /codegen-server-test/python/ @smithy-lang/smithy-rs-server diff --git a/examples/pokemon-service/tests/snapshots/metrics_test__metrics_content_via_tcp.snap b/examples/pokemon-service/tests/snapshots/metrics_test__metrics_content_via_tcp.snap index 72108aae4e..05bb93a71d 100644 --- a/examples/pokemon-service/tests/snapshots/metrics_test__metrics_content_via_tcp.snap +++ b/examples/pokemon-service/tests/snapshots/metrics_test__metrics_content_via_tcp.snap @@ -2,6 +2,6 @@ source: pokemon-service/tests/metrics_test.rs expression: metrics_output --- -{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"found"},{"Name":"outstanding_requests"},{"Name":"http_status_code"},{"Name":"error"},{"Name":"fault"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"found":1,"outstanding_requests":1,"http_status_code":200,"error":0,"fault":0,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","requested_pokemon_name":"pikachu","service":"PokemonService","service_version":"2024-03-18","operation":"GetPokemonSpecies","request_id":"[request_id]} -{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"authenticated"},{"Name":"outstanding_requests"},{"Name":"http_status_code"},{"Name":"error"},{"Name":"fault"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"authenticated":0,"outstanding_requests":1,"http_status_code":401,"error":1,"fault":0,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","user":"ash","service":"PokemonService","service_version":"2024-03-18","operation":"GetStorage","request_id":"[request_id]} -{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"supported_region"},{"Name":"outstanding_requests"},{"Name":"http_status_code"},{"Name":"error"},{"Name":"fault"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"supported_region":0,"outstanding_requests":1,"http_status_code":500,"error":0,"fault":1,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","requested_region":"trigger500","service":"PokemonService","service_version":"2024-03-18","operation":"CapturePokemon","request_id":"[request_id]} +{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"found"},{"Name":"outstanding_requests"},{"Name":"success"},{"Name":"client_error"},{"Name":"server_error"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"found":1,"outstanding_requests":1,"success":1,"client_error":0,"server_error":0,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","requested_pokemon_name":"pikachu","service":"PokemonService","service_version":"2024-03-18","operation":"GetPokemonSpecies","request_id":"[request_id],"http_status_code":"200"} +{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"authenticated"},{"Name":"outstanding_requests"},{"Name":"success"},{"Name":"client_error"},{"Name":"server_error"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"authenticated":0,"outstanding_requests":1,"success":0,"client_error":1,"server_error":0,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","user":"ash","service":"PokemonService","service_version":"2024-03-18","operation":"GetStorage","request_id":"[request_id],"http_status_code":"401"} +{"_aws":{"CloudWatchMetrics":[{"Namespace":"Ns","Dimensions":[[]],"Metrics":[{"Name":"supported_region"},{"Name":"outstanding_requests"},{"Name":"success"},{"Name":"client_error"},{"Name":"server_error"},{"Name":"operation_time","Unit":"Milliseconds"}]}],"Timestamp":"[timestamp]},"supported_region":0,"outstanding_requests":1,"success":0,"client_error":0,"server_error":1,"operation_time":"[operation_time],"test_request_metric":"test request metric","test_response_metric":"test response metric","requested_region":"trigger500","service":"PokemonService","service_version":"2024-03-18","operation":"CapturePokemon","request_id":"[request_id],"http_status_code":"500"} diff --git a/rust-runtime/aws-smithy-http-server-metrics/src/default.rs b/rust-runtime/aws-smithy-http-server-metrics/src/default.rs index 011e21b18f..805c6be234 100644 --- a/rust-runtime/aws-smithy-http-server-metrics/src/default.rs +++ b/rust-runtime/aws-smithy-http-server-metrics/src/default.rs @@ -74,11 +74,13 @@ pub struct DefaultRequestMetrics { #[metrics] #[derive(Default, Debug)] pub struct DefaultResponseMetrics { - pub(crate) http_status_code: Option, + pub(crate) http_status_code: Option, + /// Success indicator (1 if 2xx status code, 0 otherwise) + pub(crate) success: Option, /// Client error indicator (1 if 4xx status code, 0 otherwise) - pub(crate) error: Option, - /// Server fault indicator (1 if 5xx status code, 0 otherwise) - pub(crate) fault: Option, + pub(crate) client_error: Option, + /// Server error indicator (1 if 5xx status code, 0 otherwise) + pub(crate) server_error: Option, /// Wallclock time from pre-deserialization of the model input to post-serialization of the model output pub(crate) operation_time: Option, } @@ -103,8 +105,9 @@ pub struct DefaultRequestMetricsConfig { pub struct DefaultResponseMetricsConfig { pub(crate) disable_all: bool, pub(crate) disable_http_status_code: bool, - pub(crate) disable_error: bool, - pub(crate) disable_fault: bool, + pub(crate) disable_success: bool, + pub(crate) disable_client_error: bool, + pub(crate) disable_server_error: bool, pub(crate) disable_operation_time: bool, } diff --git a/rust-runtime/aws-smithy-http-server-metrics/src/layer/builder.rs b/rust-runtime/aws-smithy-http-server-metrics/src/layer/builder.rs index 52389f57c7..4b49759222 100644 --- a/rust-runtime/aws-smithy-http-server-metrics/src/layer/builder.rs +++ b/rust-runtime/aws-smithy-http-server-metrics/src/layer/builder.rs @@ -44,50 +44,62 @@ macro_rules! impl_disable_methods { self } - /// Disable the `request_id` metric + /// Disable the default `outstanding_requests` metric + pub fn disable_default_outstanding_requests_metric(mut self) -> Self { + self.default_req_metrics_config.disable_outstanding_requests = true; + self + } + + /// Disable the default `request_id` metric pub fn disable_default_request_id_metric(mut self) -> Self { self.default_req_metrics_config.disable_request_id = true; self } - /// Disable the `operation_name` metric + /// Disable the default `operation_name` metric pub fn disable_default_operation_metric(mut self) -> Self { self.default_req_metrics_config.disable_operation = true; self } - /// Disable the `service_name` metric + /// Disable the default `service_name` metric pub fn disable_default_service_metric(mut self) -> Self { self.default_req_metrics_config.disable_service = true; self } - /// Disable the `service_version` metric + /// Disable the default `service_version` metric pub fn disable_default_service_version_metric(mut self) -> Self { self.default_req_metrics_config.disable_service_version = true; self } - /// Disable the `http_status_code` metric + /// Disable the default `http_status_code` metric pub fn disable_default_http_status_code_metric(mut self) -> Self { self.default_res_metrics_config.disable_http_status_code = true; self } - /// Disable the `error` metric - pub fn disable_error_metric(mut self) -> Self { - self.default_res_metrics_config.disable_error = true; + /// Disable the default `success` metric + pub fn disable_default_success_metric(mut self) -> Self { + self.default_res_metrics_config.disable_success = true; + self + } + + /// Disable the default `client_error` metric + pub fn disable_default_client_error_metric(mut self) -> Self { + self.default_res_metrics_config.disable_client_error = true; self } - /// Disable the `fault` metric - pub fn disable_fault_metric(mut self) -> Self { - self.default_res_metrics_config.disable_fault = true; + /// Disable the default `server_error` metric + pub fn disable_default_server_error_metric(mut self) -> Self { + self.default_res_metrics_config.disable_server_error = true; self } - /// Disable the `operation_time` metric - pub fn disable_operation_time_metric(mut self) -> Self { + /// Disable the default `operation_time` metric + pub fn disable_default_operation_time_metric(mut self) -> Self { self.default_res_metrics_config.disable_operation_time = true; self } diff --git a/rust-runtime/aws-smithy-http-server-metrics/src/lib.rs b/rust-runtime/aws-smithy-http-server-metrics/src/lib.rs index de8cf0835e..6815d6b096 100644 --- a/rust-runtime/aws-smithy-http-server-metrics/src/lib.rs +++ b/rust-runtime/aws-smithy-http-server-metrics/src/lib.rs @@ -173,8 +173,9 @@ //! | Metric | Description | //! |--------|-------------| //! | `http_status_code` | HTTP status code of the response | -//! | `error` | Client error indicator (4xx status code) | -//! | `fault` | Server fault indicator (5xx status code) | +//! | `success` | Success indicator (2xx status code) | +//! | `client_error` | Client error indicator (4xx status code) | +//! | `server_error` | Server error indicator (5xx status code) | //! | `operation_time` | Timestamp that denotes operation time from pre-deserialization to post-serialization | //! //! # Platform support diff --git a/rust-runtime/aws-smithy-http-server-metrics/src/plugin.rs b/rust-runtime/aws-smithy-http-server-metrics/src/plugin.rs index ac4d1ab334..b448e27ca9 100644 --- a/rust-runtime/aws-smithy-http-server-metrics/src/plugin.rs +++ b/rust-runtime/aws-smithy-http-server-metrics/src/plugin.rs @@ -307,20 +307,30 @@ fn get_default_response_metrics( operation_time: Option, ) -> DefaultResponseMetrics { let status = res.status(); - let status_code = status.as_u16(); - let error = if (400..500).contains(&status_code) { - Some(1) + let success = if status.is_success() { + Some(true) } else { - Some(0) + Some(false) }; - let fault = if status_code >= 500 { Some(1) } else { Some(0) }; + let client_error = if status.is_client_error() { + Some(true) + } else { + Some(false) + }; + + let server_error = if status.is_server_error() { + Some(true) + } else { + Some(false) + }; DefaultResponseMetrics { - http_status_code: Some(status_code), - error, - fault, + http_status_code: Some(status.as_str().into()), + success, + client_error, + server_error, operation_time, } } @@ -361,8 +371,13 @@ fn configure_default_response_metrics( http_status_code: metrics .http_status_code .filter(|_| !config.disable_http_status_code), - error: metrics.error.filter(|_| !config.disable_error), - fault: metrics.fault.filter(|_| !config.disable_fault), + success: metrics.success.filter(|_| !config.disable_success), + client_error: metrics + .client_error + .filter(|_| !config.disable_client_error), + server_error: metrics + .server_error + .filter(|_| !config.disable_server_error), operation_time: metrics .operation_time .filter(|_| !config.disable_operation_time),