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