2020-05-22 03:58:49 +00:00
|
|
|
use crate::extensions::{Extension, ResolveInfo};
|
|
|
|
use crate::Error;
|
2020-05-27 12:47:22 +00:00
|
|
|
use async_graphql_parser::query::{Definition, Document, OperationDefinition, Selection};
|
2020-05-22 03:58:49 +00:00
|
|
|
use itertools::Itertools;
|
2020-05-27 12:47:22 +00:00
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
2020-05-22 03:58:49 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
/// Logger extension
|
2020-05-27 12:47:22 +00:00
|
|
|
pub struct Logger {
|
|
|
|
id: Uuid,
|
|
|
|
enabled: AtomicBool,
|
|
|
|
}
|
2020-05-22 03:58:49 +00:00
|
|
|
|
|
|
|
impl Default for Logger {
|
|
|
|
fn default() -> Self {
|
2020-05-27 12:47:22 +00:00
|
|
|
Self {
|
|
|
|
id: Uuid::new_v4(),
|
|
|
|
enabled: AtomicBool::new(true),
|
|
|
|
}
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Extension for Logger {
|
2020-05-27 12:47:22 +00:00
|
|
|
fn parse_end(&self, query_source: &str, document: &Document) {
|
|
|
|
let mut is_schema = false;
|
|
|
|
|
|
|
|
for definition in document.definitions() {
|
|
|
|
if let Definition::Operation(operation) = &definition.node {
|
|
|
|
let selection_set = match &operation.node {
|
|
|
|
OperationDefinition::Query(query) => &query.selection_set,
|
|
|
|
OperationDefinition::SelectionSet(selection_set) => &selection_set.node,
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
is_schema = selection_set.items.iter().any(|selection| {
|
|
|
|
if let Selection::Field(field) = &selection.node {
|
|
|
|
if field.name.as_str() == "__schema" {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
false
|
|
|
|
});
|
|
|
|
if is_schema {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if is_schema {
|
|
|
|
self.enabled.store(false, Ordering::Relaxed);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
info!(target: "async-graphql", "query, id: {}, source: \"{}\"", self.id, query_source);
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_start(&self, info: &ResolveInfo<'_>) {
|
2020-05-27 12:47:22 +00:00
|
|
|
if !self.enabled.load(Ordering::Relaxed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trace!(target: "async-graphql", "resolve start, id: {}, path: \"{}\"", self.id, info.path_node);
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn resolve_end(&self, info: &ResolveInfo<'_>) {
|
2020-05-27 12:47:22 +00:00
|
|
|
if !self.enabled.load(Ordering::Relaxed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
trace!(target: "async-graphql", "resolve end, id: {}, path: \"{}\"", self.id, info.path_node);
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn error(&self, err: &Error) {
|
|
|
|
match err {
|
|
|
|
Error::Parse(err) => {
|
2020-05-27 12:47:22 +00:00
|
|
|
error!(target: "async-graphql", "parse error, id: {}, [{}:{}] {}", self.id, err.pos.line, err.pos.column, err)
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
Error::Query { pos, path, err } => {
|
|
|
|
if let Some(path) = path {
|
2020-05-27 12:47:22 +00:00
|
|
|
error!(target: "async-graphql", "query error, id: {}, path: \"{}\", [{}:{}] {}", self.id, path, pos.line, pos.column, err)
|
2020-05-22 03:58:49 +00:00
|
|
|
} else {
|
2020-05-27 12:47:22 +00:00
|
|
|
error!(target: "async-graphql", "query error, id: {}, [{}:{}] {}", self.id, pos.line, pos.column, err)
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Error::Rule { errors } => {
|
|
|
|
for error in errors {
|
|
|
|
let locations = error
|
|
|
|
.locations
|
|
|
|
.iter()
|
|
|
|
.map(|pos| format!("{}:{}", pos.line, pos.column))
|
|
|
|
.join(", ");
|
2020-05-27 12:47:22 +00:00
|
|
|
error!(target: "async-graphql", "validation error, id: {}, [{}] {}", self.id, locations, error.message)
|
2020-05-22 03:58:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|