Improve the error message of Tracing extension.
This commit is contained in:
parent
44a1869112
commit
5c293ffdc2
64
src/error.rs
64
src/error.rs
|
@ -1,5 +1,6 @@
|
|||
use crate::{Pos, QueryPathNode, Value};
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ops::Deref;
|
||||
use thiserror::Error;
|
||||
|
||||
/// An error in the format of an input value.
|
||||
|
@ -382,6 +383,27 @@ pub struct RuleError {
|
|||
pub message: String,
|
||||
}
|
||||
|
||||
impl Display for RuleError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
for (idx, loc) in self.locations.iter().enumerate() {
|
||||
if idx == 0 {
|
||||
write!(f, "[")?;
|
||||
} else {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
|
||||
write!(f, "{}:{}", loc.line, loc.column)?;
|
||||
|
||||
if idx == self.locations.len() - 1 {
|
||||
write!(f, "] ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "{}", self.message)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// An error serving a GraphQL query.
|
||||
#[derive(Debug, Error, PartialEq)]
|
||||
pub enum Error {
|
||||
|
@ -403,9 +425,45 @@ pub enum Error {
|
|||
},
|
||||
|
||||
/// The query statement verification failed.
|
||||
#[error("Rule error")]
|
||||
#[error("Rule error:\n{errors}")]
|
||||
Rule {
|
||||
/// List of errors.
|
||||
errors: Vec<RuleError>,
|
||||
errors: RuleErrors,
|
||||
},
|
||||
}
|
||||
|
||||
/// A collection of RuleError.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct RuleErrors(Vec<RuleError>);
|
||||
|
||||
impl From<Vec<RuleError>> for RuleErrors {
|
||||
fn from(errors: Vec<RuleError>) -> Self {
|
||||
Self(errors)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for RuleErrors {
|
||||
type Target = Vec<RuleError>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for RuleErrors {
|
||||
type Item = RuleError;
|
||||
type IntoIter = std::vec::IntoIter<RuleError>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RuleErrors {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
for err in &self.0 {
|
||||
writeln!(f, " {}", err)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ impl Extension for Logger {
|
|||
}
|
||||
}
|
||||
Error::Rule { errors } => {
|
||||
for error in errors {
|
||||
for error in errors.iter() {
|
||||
let locations = error
|
||||
.locations
|
||||
.iter()
|
||||
|
|
|
@ -46,69 +46,69 @@ impl Extension for Tracing {
|
|||
fn parse_end(&mut self, _document: &ExecutableDocument) {
|
||||
self.parse
|
||||
.take()
|
||||
.unwrap()
|
||||
.with_subscriber(|(id, d)| d.exit(id));
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
}
|
||||
|
||||
fn validation_start(&mut self) {
|
||||
let parent = self.root.as_ref().unwrap();
|
||||
let validation_span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent,
|
||||
Level::INFO,
|
||||
"validation"
|
||||
);
|
||||
validation_span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.validation.replace(validation_span);
|
||||
if let Some(parent) = &self.root {
|
||||
let validation_span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent,
|
||||
Level::INFO,
|
||||
"validation"
|
||||
);
|
||||
validation_span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.validation.replace(validation_span);
|
||||
}
|
||||
}
|
||||
|
||||
fn validation_end(&mut self) {
|
||||
self.validation
|
||||
.take()
|
||||
.unwrap()
|
||||
.with_subscriber(|(id, d)| d.exit(id));
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
}
|
||||
|
||||
fn execution_start(&mut self) {
|
||||
let parent = self.root.as_ref().unwrap();
|
||||
let execute_span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent,
|
||||
Level::INFO,
|
||||
"execute"
|
||||
);
|
||||
execute_span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.execute.replace(execute_span);
|
||||
if let Some(parent) = &self.root {
|
||||
let execute_span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent,
|
||||
Level::INFO,
|
||||
"execute"
|
||||
);
|
||||
execute_span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.execute.replace(execute_span);
|
||||
}
|
||||
}
|
||||
|
||||
fn execution_end(&mut self) {
|
||||
self.execute
|
||||
.take()
|
||||
.unwrap()
|
||||
.with_subscriber(|(id, d)| d.exit(id));
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
|
||||
self.root
|
||||
.take()
|
||||
.unwrap()
|
||||
.with_subscriber(|(id, d)| d.exit(id));
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
}
|
||||
|
||||
fn resolve_start(&mut self, info: &ResolveInfo<'_>) {
|
||||
let parent_span = match info.resolve_id.parent {
|
||||
Some(parent_id) if parent_id > 0 => self.fields.get(&parent_id).unwrap(),
|
||||
_ => self.execute.as_ref().unwrap(),
|
||||
Some(parent_id) if parent_id > 0 => self.fields.get(&parent_id),
|
||||
_ => self.execute.as_ref(),
|
||||
};
|
||||
|
||||
let span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent_span,
|
||||
Level::INFO,
|
||||
"field",
|
||||
id = %info.resolve_id.current,
|
||||
path = %info.path_node
|
||||
);
|
||||
span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.fields.insert(info.resolve_id.current, span);
|
||||
if let Some(parent_span) = parent_span {
|
||||
let span = span!(
|
||||
target: "async_graphql::graphql",
|
||||
parent: parent_span,
|
||||
Level::INFO,
|
||||
"field",
|
||||
id = %info.resolve_id.current,
|
||||
path = %info.path_node
|
||||
);
|
||||
span.with_subscriber(|(id, d)| d.enter(id));
|
||||
self.fields.insert(info.resolve_id.current, span);
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_end(&mut self, info: &ResolveInfo<'_>) {
|
||||
|
@ -118,6 +118,24 @@ impl Extension for Tracing {
|
|||
}
|
||||
|
||||
fn error(&mut self, err: &Error) {
|
||||
tracing::error!(target: "async_graphql::graphql", error = %err);
|
||||
tracing::error!(target: "async_graphql::graphql", error = %err.to_string());
|
||||
|
||||
for span in self.fields.values() {
|
||||
span.with_subscriber(|(id, d)| d.exit(id));
|
||||
}
|
||||
self.fields.clear();
|
||||
|
||||
self.execute
|
||||
.take()
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
self.validation
|
||||
.take()
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
self.parse
|
||||
.take()
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
self.root
|
||||
.take()
|
||||
.and_then(|span| span.with_subscriber(|(id, d)| d.exit(id)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ impl Serialize for Error {
|
|||
}
|
||||
Error::Rule { errors } => {
|
||||
let mut seq = serializer.serialize_seq(Some(errors.len()))?;
|
||||
for error in errors {
|
||||
for error in errors.iter() {
|
||||
seq.serialize_element(&serde_json::json!({
|
||||
"message": error.message,
|
||||
"locations": error.locations.iter().map(|pos| serde_json::json!({"line": pos.line, "column": pos.column})).collect_vec(),
|
||||
|
|
|
@ -89,7 +89,9 @@ pub fn check_rules(
|
|||
}
|
||||
|
||||
if !ctx.errors.is_empty() {
|
||||
return Err(Error::Rule { errors: ctx.errors });
|
||||
return Err(Error::Rule {
|
||||
errors: ctx.errors.into(),
|
||||
});
|
||||
}
|
||||
Ok(CheckResult {
|
||||
cache_control,
|
||||
|
|
|
@ -355,7 +355,9 @@ where
|
|||
let mut visitor = factory();
|
||||
visit(&mut visitor, &mut ctx, doc);
|
||||
if !ctx.errors.is_empty() {
|
||||
return Err(Error::Rule { errors: ctx.errors });
|
||||
return Err(Error::Rule {
|
||||
errors: ctx.errors.into(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ pub async fn test_input_validator_string_min_length() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -90,6 +91,7 @@ pub async fn test_input_validator_string_min_length() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -183,6 +185,7 @@ pub async fn test_input_validator_string_max_length() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -200,6 +203,7 @@ pub async fn test_input_validator_string_max_length() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -320,6 +324,7 @@ pub async fn test_input_validator_string_email() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -338,6 +343,7 @@ pub async fn test_input_validator_string_email() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -468,6 +474,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: field_error_msg.clone()
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -486,6 +493,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: object_error_msg.clone()
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -503,6 +511,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -521,6 +530,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -578,6 +588,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -596,6 +607,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -637,6 +649,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -655,6 +668,7 @@ pub async fn test_input_validator_string_mac() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -715,6 +729,7 @@ pub async fn test_input_validator_int_range() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -732,6 +747,7 @@ pub async fn test_input_validator_int_range() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -820,6 +836,7 @@ pub async fn test_input_validator_int_less_than() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -837,6 +854,7 @@ pub async fn test_input_validator_int_less_than() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -927,6 +945,7 @@ pub async fn test_input_validator_int_greater_than() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -944,6 +963,7 @@ pub async fn test_input_validator_int_greater_than() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1027,6 +1047,7 @@ pub async fn test_input_validator_int_nonzero() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1044,6 +1065,7 @@ pub async fn test_input_validator_int_nonzero() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1128,6 +1150,7 @@ pub async fn test_input_validator_int_equal() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1145,6 +1168,7 @@ pub async fn test_input_validator_int_equal() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1244,6 +1268,7 @@ pub async fn test_input_validator_list_max_length() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1261,6 +1286,7 @@ pub async fn test_input_validator_list_max_length() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1360,6 +1386,7 @@ pub async fn test_input_validator_list_min_length() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1377,6 +1404,7 @@ pub async fn test_input_validator_list_min_length() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1484,6 +1512,7 @@ pub async fn test_input_validator_operator_or() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1501,6 +1530,7 @@ pub async fn test_input_validator_operator_or() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1601,6 +1631,7 @@ pub async fn test_input_validator_operator_and() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1618,6 +1649,7 @@ pub async fn test_input_validator_operator_and() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
@ -1724,6 +1756,7 @@ pub async fn test_input_validator_variable() {
|
|||
}),
|
||||
message: field_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1741,6 +1774,7 @@ pub async fn test_input_validator_variable() {
|
|||
}),
|
||||
message: object_error_msg
|
||||
})
|
||||
.into()
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user