1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::fmt::Write;
use std::sync::Arc;
use crate::extensions::{
Extension, ExtensionContext, ExtensionFactory, NextExecute, NextParseQuery,
};
use crate::parser::types::{ExecutableDocument, OperationType, Selection};
use crate::{PathSegment, Response, ServerResult, Variables};
#[cfg_attr(docsrs, doc(cfg(feature = "log")))]
pub struct Logger;
impl ExtensionFactory for Logger {
fn create(&self) -> Arc<dyn Extension> {
Arc::new(LoggerExtension)
}
}
struct LoggerExtension;
#[async_trait::async_trait]
impl Extension for LoggerExtension {
async fn parse_query(
&self,
ctx: &ExtensionContext<'_>,
query: &str,
variables: &Variables,
next: NextParseQuery<'_>,
) -> ServerResult<ExecutableDocument> {
let document = next.run(ctx, query, variables).await?;
let is_schema = document
.operations
.iter()
.filter(|(_, operation)| operation.node.ty == OperationType::Query)
.any(|(_, operation)| operation.node.selection_set.node.items.iter().any(|selection| matches!(&selection.node, Selection::Field(field) if field.node.name.node == "__schema")));
if !is_schema {
log::info!(
target: "async-graphql",
"[Execute] {}", ctx.stringify_execute_doc(&document, variables)
);
}
Ok(document)
}
async fn execute(
&self,
ctx: &ExtensionContext<'_>,
operation_name: Option<&str>,
next: NextExecute<'_>,
) -> Response {
let resp = next.run(ctx, operation_name).await;
if resp.is_err() {
for err in &resp.errors {
if !err.path.is_empty() {
let mut path = String::new();
for (idx, s) in err.path.iter().enumerate() {
if idx > 0 {
path.push('.');
}
match s {
PathSegment::Index(idx) => {
let _ = write!(&mut path, "{}", idx);
}
PathSegment::Field(name) => {
let _ = write!(&mut path, "{}", name);
}
}
}
log::error!(
target: "async-graphql",
"[Error] path={} message={}", path, err.message,
);
} else {
log::error!(
target: "async-graphql",
"[Error] message={}", err.message,
);
}
}
}
resp
}
}