Skip to content

Commit b58ced6

Browse files
hawkwolix0r
authored andcommitted
reduce error boilerplate with thiserror (#980)
The [`thiserror` crate][1] provides a `#[derive(Error)]` macro that can be used to generate `std::error::Error` implementations. Using this results in significantly less boilerplate required by most of the error types in the proxy, replacing almost all of the manual `Error` implementations. There were a few cases where the `Error` impl either required complex formatting logic (it has a conditional in it), or complex `source` logic (the `Arc`ed `SharedError` type). I left these alone, but was able to replace every other manual implementation of `std::error::Error`. No functional change. :) [1]: https://github.com/dtolnay/thiserror#deriveerror Signed-off-by: Eliza Weisman <[email protected]>
1 parent 6a2c892 commit b58ced6

File tree

44 files changed

+175
-342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+175
-342
lines changed

Cargo.lock

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ version = "0.1.0"
591591
dependencies = [
592592
"http",
593593
"linkerd-dns-name",
594+
"thiserror",
594595
]
595596

596597
[[package]]
@@ -608,6 +609,7 @@ dependencies = [
608609
"linkerd-error",
609610
"linkerd-opencensus",
610611
"regex",
612+
"thiserror",
611613
"tokio",
612614
"tonic",
613615
"tower",
@@ -672,6 +674,7 @@ dependencies = [
672674
"procinfo",
673675
"prost-types",
674676
"regex",
677+
"thiserror",
675678
"tokio",
676679
"tonic",
677680
"tower",
@@ -689,6 +692,7 @@ dependencies = [
689692
"linkerd-app-inbound",
690693
"linkerd-app-outbound",
691694
"linkerd-app-test",
695+
"thiserror",
692696
"tokio",
693697
"tokio-test",
694698
"tower",
@@ -708,6 +712,7 @@ dependencies = [
708712
"linkerd-app-core",
709713
"linkerd-app-test",
710714
"linkerd-io",
715+
"thiserror",
711716
"tokio",
712717
"tokio-test",
713718
"tower",
@@ -760,6 +765,7 @@ dependencies = [
760765
"linkerd-io",
761766
"linkerd-retry",
762767
"pin-project",
768+
"thiserror",
763769
"tokio",
764770
"tokio-test",
765771
"tower",
@@ -837,6 +843,7 @@ dependencies = [
837843
"linkerd-error",
838844
"linkerd-io",
839845
"linkerd-stack",
846+
"thiserror",
840847
"tokio",
841848
"tower",
842849
"tracing",
@@ -850,6 +857,7 @@ dependencies = [
850857
"linkerd-dns-name",
851858
"linkerd-error",
852859
"pin-project",
860+
"thiserror",
853861
"tokio",
854862
"tracing",
855863
"trust-dns-resolver",
@@ -859,6 +867,7 @@ dependencies = [
859867
name = "linkerd-dns-name"
860868
version = "0.1.0"
861869
dependencies = [
870+
"thiserror",
862871
"untrusted",
863872
"webpki",
864873
]
@@ -927,6 +936,7 @@ dependencies = [
927936
"pin-project",
928937
"quickcheck",
929938
"rand",
939+
"thiserror",
930940
"tokio",
931941
]
932942

@@ -980,6 +990,7 @@ dependencies = [
980990
"linkerd-dns-name",
981991
"ring",
982992
"rustls",
993+
"thiserror",
983994
"tracing",
984995
"untrusted",
985996
"webpki",
@@ -1122,6 +1133,7 @@ dependencies = [
11221133
"linkerd-timeout",
11231134
"pin-project",
11241135
"rand",
1136+
"thiserror",
11251137
"tokio",
11261138
"tokio-test",
11271139
"tower",
@@ -1156,6 +1168,7 @@ dependencies = [
11561168
"linkerd-error",
11571169
"linkerd-proxy-core",
11581170
"pin-project",
1171+
"thiserror",
11591172
"tower",
11601173
"tracing",
11611174
]
@@ -1181,6 +1194,7 @@ dependencies = [
11811194
"pin-project",
11821195
"prost-types",
11831196
"rand",
1197+
"thiserror",
11841198
"tokio",
11851199
"tonic",
11861200
"tower",
@@ -1325,6 +1339,7 @@ dependencies = [
13251339
"linkerd-error",
13261340
"linkerd-stack",
13271341
"pin-project",
1342+
"thiserror",
13281343
"tokio",
13291344
"tokio-test",
13301345
"tower",
@@ -1347,6 +1362,7 @@ dependencies = [
13471362
"linkerd-proxy-transport",
13481363
"linkerd-stack",
13491364
"rustls",
1365+
"thiserror",
13501366
"tokio",
13511367
"tokio-rustls",
13521368
"tower",
@@ -1369,6 +1385,7 @@ dependencies = [
13691385
"linkerd-error",
13701386
"linkerd-stack",
13711387
"rand",
1388+
"thiserror",
13721389
"tower",
13731390
"tracing",
13741391
]

linkerd/addr/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ publish = false
99
[dependencies]
1010
http = "0.2"
1111
linkerd-dns-name = { path = "../dns/name" }
12+
thiserror = "1.0"

linkerd/addr/src/lib.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#![deny(warnings, rust_2018_idioms)]
2-
32
use linkerd_dns_name::Name;
43
use std::{
54
fmt,
65
net::{IpAddr, SocketAddr},
76
str::FromStr,
87
};
8+
use thiserror::Error;
99

1010
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1111
pub enum Addr {
@@ -19,12 +19,14 @@ pub struct NameAddr {
1919
port: u16,
2020
}
2121

22-
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Error)]
2323
pub enum Error {
2424
/// The host is not a valid DNS name or IP address.
25+
#[error("address contains an invalid host")]
2526
InvalidHost,
2627

2728
/// The port is missing.
29+
#[error("address is missing a port")]
2830
MissingPort,
2931
}
3032

@@ -239,19 +241,6 @@ impl fmt::Display for NameAddr {
239241
}
240242
}
241243

242-
// === impl Error ===
243-
244-
impl fmt::Display for Error {
245-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246-
match self {
247-
Self::InvalidHost => write!(f, "address contains an invalid host"),
248-
Self::MissingPort => write!(f, "address is missing a port"),
249-
}
250-
}
251-
}
252-
253-
impl std::error::Error for Error {}
254-
255244
#[cfg(test)]
256245
mod tests {
257246
use super::*;

linkerd/app/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ linkerd-channel = { path = "../channel" }
2626
linkerd-opencensus = { path = "../opencensus" }
2727
linkerd-error = { path = "../error" }
2828
regex = "1.0.0"
29+
thiserror = "1.0"
2930
tokio = { version = "1", features = ["rt"] }
3031
tonic = { version = "0.4", default-features = false, features = ["prost"] }
3132
tower = "0.4"

linkerd/app/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ linkerd-stack-tracing = { path = "../../stack/tracing" }
6363
linkerd-tls = { path = "../../tls" }
6464
linkerd-trace-context = { path = "../../trace-context" }
6565
regex = "1.0.0"
66+
thiserror = "1.0"
6667
tokio = { version = "1", features = ["macros", "sync", "parking_lot"]}
6768
tonic = { version = "0.4", default-features = false, features = ["prost"] }
6869
tracing = "0.1.23"

linkerd/app/core/src/classify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use linkerd_error::Error;
33
use linkerd_http_classify as classify;
44
pub use linkerd_http_classify::{CanClassify, NewClassify};
55
use linkerd_proxy_http::HasH2Reason;
6-
use linkerd_timeout::error::ResponseTimeout;
6+
use linkerd_timeout::ResponseTimeout;
77
use std::borrow::Cow;
88
use tonic as grpc;
99
use tracing::trace;

linkerd/app/core/src/errors.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ use linkerd_error_metrics as metrics;
55
use linkerd_error_respond as respond;
66
pub use linkerd_error_respond::RespondLayer;
77
use linkerd_proxy_http::{ClientHandle, HasH2Reason};
8-
use linkerd_timeout::{error::ResponseTimeout, FailFastError};
8+
use linkerd_timeout::{FailFastError, ResponseTimeout};
99
use linkerd_tls as tls;
1010
use pin_project::pin_project;
1111
use std::pin::Pin;
1212
use std::task::{Context, Poll};
13+
use thiserror::Error;
1314
use tonic::{self as grpc, Code};
1415
use tracing::{debug, warn};
1516

@@ -28,7 +29,8 @@ pub struct LabelError(super::metrics::Direction);
2829

2930
pub type Label = (super::metrics::Direction, Reason);
3031

31-
#[derive(Copy, Clone, Debug)]
32+
#[derive(Copy, Clone, Debug, Error)]
33+
#[error("{}", self.message)]
3234
pub struct HttpError {
3335
http: http::StatusCode,
3436
grpc: Code,
@@ -453,11 +455,3 @@ impl HttpError {
453455
self.http
454456
}
455457
}
456-
457-
impl std::fmt::Display for HttpError {
458-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
459-
self.message.fmt(f)
460-
}
461-
}
462-
463-
impl std::error::Error for HttpError {}

linkerd/app/core/src/http_tracing.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use linkerd_error::Error;
22
use linkerd_opencensus::proto::trace::v1 as oc;
33
use linkerd_stack::layer;
44
use linkerd_trace_context::{self as trace_context, TraceContext};
5-
use std::{collections::HashMap, error, fmt, sync::Arc};
5+
use std::{collections::HashMap, sync::Arc};
6+
use thiserror::Error;
67
use tokio::sync::mpsc;
78

89
pub type OpenCensusSink = Option<mpsc::Sender<oc::Span>>;
@@ -19,25 +20,14 @@ pub struct SpanConverter {
1920
labels: Labels,
2021
}
2122

22-
#[derive(Debug)]
23+
#[derive(Debug, Error)]
24+
#[error("ID '{:?} should have {} bytes, but it has {}", self.id, self.expected_size, self.actual_size)]
2325
pub struct IdLengthError {
2426
id: Vec<u8>,
2527
expected_size: usize,
2628
actual_size: usize,
2729
}
2830

29-
impl error::Error for IdLengthError {}
30-
31-
impl fmt::Display for IdLengthError {
32-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33-
write!(
34-
f,
35-
"Id '{:?}' should have {} bytes but it has {}",
36-
self.id, self.expected_size, self.actual_size
37-
)
38-
}
39-
}
40-
4131
pub fn server<S>(
4232
sink: OpenCensusSink,
4333
labels: impl Into<Labels>,

linkerd/app/gateway/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ indexmap = "1.0"
1313
linkerd-app-core = { path = "../core" }
1414
linkerd-app-inbound = { path = "../inbound" }
1515
linkerd-app-outbound = { path = "../outbound" }
16+
thiserror = "1.0"
1617
tokio = { version = "1", features = ["sync"] }
1718
tower = { version = "0.4.5", default-features = false }
1819
tracing = "0.1.23"

linkerd/app/gateway/src/lib.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use std::{
2828
convert::{TryFrom, TryInto},
2929
fmt,
3030
};
31+
use thiserror::Error;
3132
use tracing::debug_span;
3233

3334
#[derive(Clone, Debug, Default)]
@@ -57,10 +58,12 @@ struct HttpTarget {
5758
version: http::Version,
5859
}
5960

60-
#[derive(Debug, Default)]
61+
#[derive(Debug, Default, Error)]
62+
#[error("a named target must be provided on gateway connections")]
6163
struct RefusedNoTarget(());
6264

63-
#[derive(Debug)]
65+
#[derive(Debug, Error)]
66+
#[error("the provided address could not be resolved: {}", self.0)]
6467
struct RefusedNotResolved(NameAddr);
6568

6669
#[allow(clippy::clippy::too_many_arguments)]
@@ -279,7 +282,7 @@ impl<E: Into<Error>> TryFrom<(Result<Option<http::Version>, E>, ClientInfo)> for
279282

280283
fn try_from(
281284
(version, client): (Result<Option<http::Version>, E>, ClientInfo),
282-
) -> Result<Self, Error> {
285+
) -> Result<Self, Self::Error> {
283286
match version {
284287
Ok(Some(version)) => Ok(Self { version, client }),
285288
Ok(None) => Err(RefusedNoTarget(()).into()),
@@ -338,23 +341,3 @@ impl<B> svc::stack::RecognizeRoute<http::Request<B>> for RouteHttp<HttpLegacy> {
338341
Err(RefusedNoTarget(()).into())
339342
}
340343
}
341-
342-
// === impl RefusedNoTarget ===
343-
344-
impl fmt::Display for RefusedNoTarget {
345-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346-
write!(f, "A named target must be provided on gateway connections")
347-
}
348-
}
349-
350-
impl std::error::Error for RefusedNoTarget {}
351-
352-
// === impl RefusedNotResolved ===
353-
354-
impl fmt::Display for RefusedNotResolved {
355-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356-
write!(f, "The provided address could not be resolved: {}", self.0)
357-
}
358-
}
359-
360-
impl std::error::Error for RefusedNotResolved {}

0 commit comments

Comments
 (0)