mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-03 19:42:55 +00:00
Display reqwest error source (#10004)
## Problem Reqwest errors don't include details about the inner source error. This means that we get opaque errors like: ``` receive body: error sending request for url (http://localhost:9898/v1/location_config) ``` Instead of the more helpful: ``` receive body: error sending request for url (http://localhost:9898/v1/location_config): operation timed out ``` Touches #9801. ## Summary of changes Include the source error for `reqwest::Error` wherever it's displayed.
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
//! ```text
|
//! ```text
|
||||||
//! .neon/safekeepers/<safekeeper id>
|
//! .neon/safekeepers/<safekeeper id>
|
||||||
//! ```
|
//! ```
|
||||||
|
use std::error::Error as _;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -26,7 +27,7 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum SafekeeperHttpError {
|
pub enum SafekeeperHttpError {
|
||||||
#[error("Reqwest error: {0}")]
|
#[error("request error: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
Transport(#[from] reqwest::Error),
|
Transport(#[from] reqwest::Error),
|
||||||
|
|
||||||
#[error("Error: {0}")]
|
#[error("Error: {0}")]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, error::Error as _};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use detach_ancestor::AncestorDetached;
|
use detach_ancestor::AncestorDetached;
|
||||||
@@ -25,10 +25,10 @@ pub struct Client {
|
|||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("send request: {0}")]
|
#[error("send request: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
SendRequest(reqwest::Error),
|
SendRequest(reqwest::Error),
|
||||||
|
|
||||||
#[error("receive body: {0}")]
|
#[error("receive body: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
ReceiveBody(reqwest::Error),
|
ReceiveBody(reqwest::Error),
|
||||||
|
|
||||||
#[error("receive error body: {0}")]
|
#[error("receive error body: {0}")]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::error::Error as _;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
@@ -350,7 +351,11 @@ impl std::fmt::Display for UploadError {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
Rejected(code) => write!(f, "server rejected the metrics with {code}"),
|
Rejected(code) => write!(f, "server rejected the metrics with {code}"),
|
||||||
Reqwest(e) => write!(f, "request failed: {e}"),
|
Reqwest(e) => write!(
|
||||||
|
f,
|
||||||
|
"request failed: {e}{}",
|
||||||
|
e.source().map(|e| format!(": {e}")).unwrap_or_default()
|
||||||
|
),
|
||||||
Cancelled => write!(f, "cancelled"),
|
Cancelled => write!(f, "cancelled"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
//! etc.
|
//! etc.
|
||||||
|
|
||||||
use reqwest::{IntoUrl, Method, StatusCode};
|
use reqwest::{IntoUrl, Method, StatusCode};
|
||||||
|
use std::error::Error as _;
|
||||||
use utils::{
|
use utils::{
|
||||||
http::error::HttpErrorBody,
|
http::error::HttpErrorBody,
|
||||||
id::{NodeId, TenantId, TimelineId},
|
id::{NodeId, TenantId, TimelineId},
|
||||||
@@ -26,7 +27,7 @@ pub struct Client {
|
|||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Failed to receive body (reqwest error).
|
/// Failed to receive body (reqwest error).
|
||||||
#[error("receive body: {0}")]
|
#[error("receive body: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
ReceiveBody(reqwest::Error),
|
ReceiveBody(reqwest::Error),
|
||||||
|
|
||||||
/// Status is not ok, but failed to parse body as `HttpErrorBody`.
|
/// Status is not ok, but failed to parse body as `HttpErrorBody`.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::error::Error as _;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{collections::HashMap, time::Duration};
|
use std::{collections::HashMap, time::Duration};
|
||||||
|
|
||||||
@@ -172,7 +173,7 @@ struct ComputeHookNotifyRequest {
|
|||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub(crate) enum NotifyError {
|
pub(crate) enum NotifyError {
|
||||||
// Request was not send successfully, e.g. transport error
|
// Request was not send successfully, e.g. transport error
|
||||||
#[error("Sending request: {0}")]
|
#[error("Sending request: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
Request(#[from] reqwest::Error),
|
Request(#[from] reqwest::Error),
|
||||||
// Request could not be serviced right now due to ongoing Operation in control plane, but should be possible soon.
|
// Request could not be serviced right now due to ongoing Operation in control plane, but should be possible soon.
|
||||||
#[error("Control plane tenant busy")]
|
#[error("Control plane tenant busy")]
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use crate::tenant_shard::ObservedState;
|
use crate::tenant_shard::ObservedState;
|
||||||
use pageserver_api::shard::TenantShardId;
|
use pageserver_api::shard::TenantShardId;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::HashMap, time::Duration};
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error as _;
|
||||||
|
use std::time::Duration;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use hyper::Uri;
|
use hyper::Uri;
|
||||||
@@ -17,11 +19,14 @@ pub(crate) struct PeerClient {
|
|||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub(crate) enum StorageControllerPeerError {
|
pub(crate) enum StorageControllerPeerError {
|
||||||
#[error("failed to deserialize error response with status code {0} at {1}: {2}")]
|
#[error(
|
||||||
|
"failed to deserialize error response with status code {0} at {1}: {2}{}",
|
||||||
|
.2.source().map(|e| format!(": {e}")).unwrap_or_default()
|
||||||
|
)]
|
||||||
DeserializationError(StatusCode, Url, reqwest::Error),
|
DeserializationError(StatusCode, Url, reqwest::Error),
|
||||||
#[error("storage controller peer API error ({0}): {1}")]
|
#[error("storage controller peer API error ({0}): {1}")]
|
||||||
ApiError(StatusCode, String),
|
ApiError(StatusCode, String),
|
||||||
#[error("failed to send HTTP request: {0}")]
|
#[error("failed to send HTTP request: {0}{}", .0.source().map(|e| format!(": {e}")).unwrap_or_default())]
|
||||||
SendError(reqwest::Error),
|
SendError(reqwest::Error),
|
||||||
#[error("Cancelled")]
|
#[error("Cancelled")]
|
||||||
Cancelled,
|
Cancelled,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::error::Error as _;
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
@@ -30,14 +32,18 @@ impl std::fmt::Display for Error {
|
|||||||
match &self.kind {
|
match &self.kind {
|
||||||
ErrorKind::RequestSend(e) => write!(
|
ErrorKind::RequestSend(e) => write!(
|
||||||
f,
|
f,
|
||||||
"Failed to send a request. Context: {}, error: {}",
|
"Failed to send a request. Context: {}, error: {}{}",
|
||||||
self.context, e
|
self.context,
|
||||||
|
e,
|
||||||
|
e.source().map(|e| format!(": {e}")).unwrap_or_default()
|
||||||
),
|
),
|
||||||
ErrorKind::BodyRead(e) => {
|
ErrorKind::BodyRead(e) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Failed to read a request body. Context: {}, error: {}",
|
"Failed to read a request body. Context: {}, error: {}{}",
|
||||||
self.context, e
|
self.context,
|
||||||
|
e,
|
||||||
|
e.source().map(|e| format!(": {e}")).unwrap_or_default()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ErrorKind::ResponseStatus(status) => {
|
ErrorKind::ResponseStatus(status) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user