awslabs / dynein

DynamoDB CLI written in Rust.
https://github.com/awslabs/dynein
Apache License 2.0
360 stars 37 forks source link

chore: handle SdkError to show error message #255

Closed ryota-sakamoto closed 2 months ago

ryota-sakamoto commented 2 months ago

Issue #, if available:

fix #247. In this PR, we introduce useful error message.

[2024-06-17T15:29:52Z ERROR dy::control] service error occurred: ErrorMetadata { code: Some("ValidationException"), message: Some("1 validation error detected: Value 'a' at 'tableName' failed to satisfy constraint: Member must have length greater than or equal to 3"), extras: Some({"aws_request_id": "xxx"}) }
[2024-06-17T15:28:16Z ERROR dy::control] an error occurred: DispatchFailure(DispatchFailure { source: ConnectorError { kind: Other(None), source: InvalidConfiguration(InvalidConfiguration { source: "ProfileFile provider could not be built: profile `a` was not defined: could not find source profile a referenced from the root profile" }), connection: Unknown } })

Best way to show human readable message is to use original error but we cannot retrieve it as mentioned in https://github.com/awslabs/aws-sdk-rust/discussions/1076. So we show rust error code instead.

Description of changes:

We can imagine some patters to handle SdkError to show error message.

  1. Use fmt in SdkError

This pattern is easy to handle the error but it won't give us useful information.

error!("{}", e);
[2024-06-17T14:23:19Z ERROR dy::control] service error
  1. Use debug from SdkError

It will give us useful information but a lot of informations is shown so we are hard to understand shortly what the issue occur. Also detailed informations are covered by debug message.

error!("{:?}", e);
[2024-06-17T14:24:21Z ERROR dy::control] ServiceError(ServiceError { source: Unhandled(Unhandled { source: ErrorMetadata { code: Some("ValidationException"), message: Some("1 validation error detected: Value 'a' at 'tableName' failed to satisfy constraint: Member must have length greater than or equal to 3"), extras: Some({"aws_request_id": "xxx"}) }, meta: ErrorMetadata { code: Some("ValidationException"), message: Some("1 validation error detected: Value 'a' at 'tableName' failed to satisfy constraint: Member must have length greater than or equal to 3"), extras: Some({"aws_request_id": "xxx"}) } }), raw: Response { status: StatusCode(400), headers: Headers { headers: {"server": HeaderValue { _private: H0("Server") }, "date": HeaderValue { _private: H0("Mon, 17 Jun 2024 14:24:21 GMT") }, "content-type": HeaderValue { _private: H0("application/x-amz-json-1.0") }, "content-length": HeaderValue { _private: H0("205") }, "connection": HeaderValue { _private: H0("keep-alive") }, "x-amzn-requestid": HeaderValue { _private: H0("xxx") }, "x-amz-crc32": HeaderValue { _private: H0("540347094") }} }, body: SdkBody { inner: Once(Some(b"{\"__type\":\"com.amazon.coral.validate#ValidationException\",\"message\":\"1 validation error detected: Value 'a' at 'tableName' failed to satisfy constraint: Member must have length greater than or equal to 3\"}")), retryable: true }, extensions: Extensions { extensions_02x: Extensions, extensions_1x: Extensions } } })
  1. Use meta() from ServiceError

It will give us enough informations but we need to consider other error such as DispatchFailure.

error!("{}", e.into_service_error().meta());
[2024-06-17T14:29:55Z ERROR dy::control] Error { code: "ValidationException", message: "1 validation error detected: Value 'a' at 'tableName' failed to satisfy constraint: Member must have length greater than or equal to 3", aws_request_id: "xxx" }

While DispatchFailure occur, we just got Error.

[2024-06-17T14:40:15Z ERROR dy::control] Error
  1. Use meta() from ServiceError and use debug from other error

As mentioned, if we use debug message, a lot of informations is shown. As for other error, it will give us enough informations.

[2024-06-17T14:41:48Z ERROR dy::control] DispatchFailure(DispatchFailure { source: ConnectorError { kind: Other(None), source: InvalidConfiguration(InvalidConfiguration { source: "ProfileFile provider could not be built: profile `a` was not defined: could not find source profile a referenced from the root profile" }), connection: Unknown } })

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.