prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Improve errors logging
  Right now errors are being caught by GraphQL core and sent into the `errors` fields of the GraphQL response. Unfortunately that makes things harder to debug locally; we should print better exceptions locally, by using one of the following options:
  
  ```python
      def process_result(
          self, request: HttpRequest, result: ExecutionResult
      ) -> GraphQLHTTPResponse:
          data: GraphQLHTTPResponse = {"data": result.data}
  
              for error in result.errors:
                  actual_error = error.original_error or error
  
                  traceback.print_exception(
                      type(actual_error), actual_error, actual_error.__traceback__
                  )
  
          return data
  ```
  
  ```python
      def process_result(self, request, result):
          data = super().process_result(request, result)
  
          # Log errors
          if result.errors:
              for error in result.errors:
                  try:
                      if isinstance(error, GraphQLError) and error.original_error:
                          raise error.original_error
                      else:
                          raise error
                  except Exception as error:
                      logger.exception(error)
  
          return data
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `strawberry/schema/schema.py`
  Content:
  ```
  1 from typing import Any, Dict, List, Optional, Sequence, Type, Union
  2 
  3 from graphql import (
  4     ExecutionContext as GraphQLExecutionContext,
  5     GraphQLSchema,
  6     get_introspection_query,
  7     parse,
  8     validate_schema,
  9 )
  10 from graphql.subscription import subscribe
  11 from graphql.type.directives import specified_directives
  12 
  13 from strawberry.custom_scalar import ScalarDefinition
  14 from strawberry.enum import EnumDefinition
  15 from strawberry.extensions import Extension
  16 from strawberry.schema.schema_converter import GraphQLCoreConverter
  17 from strawberry.types import ExecutionResult
  18 from strawberry.types.types import TypeDefinition
  19 from strawberry.union import StrawberryUnion
  20 
  21 from ..middleware import DirectivesMiddleware, Middleware
  22 from ..printer import print_schema
  23 from .execute import execute, execute_sync
  24 
  25 
  26 class Schema:
  27     def __init__(
  28         self,
  29         # TODO: can we make sure we only allow to pass something that has been decorated?
  30         query: Type,
  31         mutation: Optional[Type] = None,
  32         subscription: Optional[Type] = None,
  33         directives=(),
  34         types=(),
  35         extensions: Sequence[Type[Extension]] = (),
  36         execution_context_class: Optional[Type[GraphQLExecutionContext]] = None,
  37     ):
  38         self.extensions = extensions
  39         self.execution_context_class = execution_context_class
  40         self.schema_converter = GraphQLCoreConverter()
  41 
  42         query_type = self.schema_converter.from_object_type(query)
  43         mutation_type = (
  44             self.schema_converter.from_object_type(mutation) if mutation else None
  45         )
  46         subscription_type = (
  47             self.schema_converter.from_object_type(subscription)
  48             if subscription
  49             else None
  50         )
  51 
  52         self.middleware: List[Middleware] = [DirectivesMiddleware(directives)]
  53 
  54         directives = [
  55             self.schema_converter.from_directive(directive.directive_definition)
  56             for directive in directives
  57         ]
  58 
  59         self._schema = GraphQLSchema(
  60             query=query_type,
  61             mutation=mutation_type,
  62             subscription=subscription_type if subscription else None,
  63             directives=specified_directives + directives,
  64             types=list(map(self.schema_converter.from_object_type, types)),
  65         )
  66 
  67         # Validate schema early because we want developers to know about
  68         # possible issues as soon as possible
  69         errors = validate_schema(self._schema)
  70         if errors:
  71             formatted_errors = "\n\n".join(f"❌ {error.message}" for error in errors)
  72             raise ValueError(f"Invalid Schema. Errors:\n\n{formatted_errors}")
  73 
  74         self.query = self.schema_converter.type_map[query_type.name]
  75 
  76     def get_type_by_name(
  77         self, name: str
  78     ) -> Optional[
  79         Union[TypeDefinition, ScalarDefinition, EnumDefinition, StrawberryUnion]
  80     ]:
  81         if name in self.schema_converter.type_map:
  82             return self.schema_converter.type_map[name].definition
  83 
  84         return None
  85 
  86     async def execute(
  87         self,
  88         query: str,
  89         variable_values: Optional[Dict[str, Any]] = None,
  90         context_value: Optional[Any] = None,
  91         root_value: Optional[Any] = None,
  92         operation_name: Optional[str] = None,
  93         validate_queries: bool = True,
  94     ) -> ExecutionResult:
  95         result = await execute(
  96             self._schema,
  97             query,
  98             variable_values=variable_values,
  99             root_value=root_value,
  100             context_value=context_value,
  101             operation_name=operation_name,
  102             additional_middlewares=self.middleware,
  103             extensions=self.extensions,
  104             execution_context_class=self.execution_context_class,
  105             validate_queries=validate_queries,
  106         )
  107 
  108         return ExecutionResult(
  109             data=result.data,
  110             errors=result.errors,
  111             extensions=result.extensions,
  112         )
  113 
  114     def execute_sync(
  115         self,
  116         query: str,
  117         variable_values: Optional[Dict[str, Any]] = None,
  118         context_value: Optional[Any] = None,
  119         root_value: Optional[Any] = None,
  120         operation_name: Optional[str] = None,
  121         validate_queries: bool = True,
  122     ) -> ExecutionResult:
  123         result = execute_sync(
  124             self._schema,
  125             query,
  126             variable_values=variable_values,
  127             root_value=root_value,
  128             context_value=context_value,
  129             operation_name=operation_name,
  130             additional_middlewares=self.middleware,
  131             extensions=self.extensions,
  132             execution_context_class=self.execution_context_class,
  133             validate_queries=validate_queries,
  134         )
  135 
  136         return ExecutionResult(
  137             data=result.data,
  138             errors=result.errors,
  139             extensions=result.extensions,
  140         )
  141 
  142     async def subscribe(
  143         self,
  144         query: str,
  145         variable_values: Optional[Dict[str, Any]] = None,
  146         context_value: Optional[Any] = None,
  147         root_value: Optional[Any] = None,
  148         operation_name: Optional[str] = None,
  149     ):
  150         return await subscribe(
  151             self._schema,
  152             parse(query),
  153             root_value=root_value,
  154             context_value=context_value,
  155             variable_values=variable_values,
  156             operation_name=operation_name,
  157         )
  158 
  159     def as_str(self) -> str:
  160         return print_schema(self)
  161 
  162     __str__ = as_str
  163 
  164     def introspect(self) -> Dict[str, Any]:
  165         """Return the introspection query result for the current schema
  166 
  167         Raises:
  168             ValueError: If the introspection query fails due to an invalid schema
  169         """
  170         introspection = self.execute_sync(get_introspection_query())
  171         if introspection.errors or not introspection.data:
  172             raise ValueError(f"Invalid Schema. Errors {introspection.errors!r}")
  173 
  174         return introspection.data
  175
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/strawberry/schema/schema.py b/strawberry/schema/schema.py
  --- a/strawberry/schema/schema.py
  +++ b/strawberry/schema/schema.py
  @@ -1,3 +1,4 @@
  +import logging
   from typing import Any, Dict, List, Optional, Sequence, Type, Union
   
   from graphql import (
  @@ -7,6 +8,7 @@
       parse,
       validate_schema,
   )
  +from graphql.error import GraphQLError
   from graphql.subscription import subscribe
   from graphql.type.directives import specified_directives
   
  @@ -23,6 +25,9 @@
   from .execute import execute, execute_sync
   
   
  +logger = logging.getLogger("strawberry.execution")
  +
  +
   class Schema:
       def __init__(
           self,
  @@ -83,6 +88,11 @@
   
           return None
   
  +    def process_errors(self, errors: List[GraphQLError]) -> None:
  +        for error in errors:
  +            actual_error = error.original_error or error
  +            logger.error(actual_error, exc_info=actual_error)
  +
       async def execute(
           self,
           query: str,
  @@ -105,6 +115,9 @@
               validate_queries=validate_queries,
           )
   
  +        if result.errors:
  +            self.process_errors(result.errors)
  +
           return ExecutionResult(
               data=result.data,
               errors=result.errors,
  @@ -133,6 +146,9 @@
               validate_queries=validate_queries,
           )
   
  +        if result.errors:
  +            self.process_errors(result.errors)
  +
           return ExecutionResult(
               data=result.data,
               errors=result.errors,
  
verification_info: {"golden_diff": "diff --git a/strawberry/schema/schema.py b/strawberry/schema/schema.py\n--- a/strawberry/schema/schema.py\n+++ b/strawberry/schema/schema.py\n@@ -1,3 +1,4 @@\n+import logging\n from typing import Any, Dict, List, Optional, Sequence, Type, Union\n \n from graphql import (\n@@ -7,6 +8,7 @@\n     parse,\n     validate_schema,\n )\n+from graphql.error import GraphQLError\n from graphql.subscription import subscribe\n from graphql.type.directives import specified_directives\n \n@@ -23,6 +25,9 @@\n from .execute import execute, execute_sync\n \n \n+logger = logging.getLogger(\"strawberry.execution\")\n+\n+\n class Schema:\n     def __init__(\n         self,\n@@ -83,6 +88,11 @@\n \n         return None\n \n+    def process_errors(self, errors: List[GraphQLError]) -> None:\n+        for error in errors:\n+            actual_error = error.original_error or error\n+            logger.error(actual_error, exc_info=actual_error)\n+\n     async def execute(\n         self,\n         query: str,\n@@ -105,6 +115,9 @@\n             validate_queries=validate_queries,\n         )\n \n+        if result.errors:\n+            self.process_errors(result.errors)\n+\n         return ExecutionResult(\n             data=result.data,\n             errors=result.errors,\n@@ -133,6 +146,9 @@\n             validate_queries=validate_queries,\n         )\n \n+        if result.errors:\n+            self.process_errors(result.errors)\n+\n         return ExecutionResult(\n             data=result.data,\n             errors=result.errors,\n", "issue": "Improve errors logging\nRight now errors are being caught by GraphQL core and sent into the `errors` fields of the GraphQL response. Unfortunately that makes things harder to debug locally; we should print better exceptions locally, by using one of the following options:\r\n\r\n```python\r\n    def process_result(\r\n        self, request: HttpRequest, result: ExecutionResult\r\n    ) -> GraphQLHTTPResponse:\r\n        data: GraphQLHTTPResponse = {\"data\": result.data}\r\n\r\n            for error in result.errors:\r\n                actual_error = error.original_error or error\r\n\r\n                traceback.print_exception(\r\n                    type(actual_error), actual_error, actual_error.__traceback__\r\n                )\r\n\r\n        return data\r\n```\r\n\r\n```python\r\n    def process_result(self, request, result):\r\n        data = super().process_result(request, result)\r\n\r\n        # Log errors\r\n        if result.errors:\r\n            for error in result.errors:\r\n                try:\r\n                    if isinstance(error, GraphQLError) and error.original_error:\r\n                        raise error.original_error\r\n                    else:\r\n                        raise error\r\n                except Exception as error:\r\n                    logger.exception(error)\r\n\r\n        return data\r\n```\n", "before_files": [{"content": "from typing import Any, Dict, List, Optional, Sequence, Type, Union\n\nfrom graphql import (\n    ExecutionContext as GraphQLExecutionContext,\n    GraphQLSchema,\n    get_introspection_query,\n    parse,\n    validate_schema,\n)\nfrom graphql.subscription import subscribe\nfrom graphql.type.directives import specified_directives\n\nfrom strawberry.custom_scalar import ScalarDefinition\nfrom strawberry.enum import EnumDefinition\nfrom strawberry.extensions import Extension\nfrom strawberry.schema.schema_converter import GraphQLCoreConverter\nfrom strawberry.types import ExecutionResult\nfrom strawberry.types.types import TypeDefinition\nfrom strawberry.union import StrawberryUnion\n\nfrom ..middleware import DirectivesMiddleware, Middleware\nfrom ..printer import print_schema\nfrom .execute import execute, execute_sync\n\n\nclass Schema:\n    def __init__(\n        self,\n        # TODO: can we make sure we only allow to pass something that has been decorated?\n        query: Type,\n        mutation: Optional[Type] = None,\n        subscription: Optional[Type] = None,\n        directives=(),\n        types=(),\n        extensions: Sequence[Type[Extension]] = (),\n        execution_context_class: Optional[Type[GraphQLExecutionContext]] = None,\n    ):\n        self.extensions = extensions\n        self.execution_context_class = execution_context_class\n        self.schema_converter = GraphQLCoreConverter()\n\n        query_type = self.schema_converter.from_object_type(query)\n        mutation_type = (\n            self.schema_converter.from_object_type(mutation) if mutation else None\n        )\n        subscription_type = (\n            self.schema_converter.from_object_type(subscription)\n            if subscription\n            else None\n        )\n\n        self.middleware: List[Middleware] = [DirectivesMiddleware(directives)]\n\n        directives = [\n            self.schema_converter.from_directive(directive.directive_definition)\n            for directive in directives\n        ]\n\n        self._schema = GraphQLSchema(\n            query=query_type,\n            mutation=mutation_type,\n            subscription=subscription_type if subscription else None,\n            directives=specified_directives + directives,\n            types=list(map(self.schema_converter.from_object_type, types)),\n        )\n\n        # Validate schema early because we want developers to know about\n        # possible issues as soon as possible\n        errors = validate_schema(self._schema)\n        if errors:\n            formatted_errors = \"\\n\\n\".join(f\"\u274c {error.message}\" for error in errors)\n            raise ValueError(f\"Invalid Schema. Errors:\\n\\n{formatted_errors}\")\n\n        self.query = self.schema_converter.type_map[query_type.name]\n\n    def get_type_by_name(\n        self, name: str\n    ) -> Optional[\n        Union[TypeDefinition, ScalarDefinition, EnumDefinition, StrawberryUnion]\n    ]:\n        if name in self.schema_converter.type_map:\n            return self.schema_converter.type_map[name].definition\n\n        return None\n\n    async def execute(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n        validate_queries: bool = True,\n    ) -> ExecutionResult:\n        result = await execute(\n            self._schema,\n            query,\n            variable_values=variable_values,\n            root_value=root_value,\n            context_value=context_value,\n            operation_name=operation_name,\n            additional_middlewares=self.middleware,\n            extensions=self.extensions,\n            execution_context_class=self.execution_context_class,\n            validate_queries=validate_queries,\n        )\n\n        return ExecutionResult(\n            data=result.data,\n            errors=result.errors,\n            extensions=result.extensions,\n        )\n\n    def execute_sync(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n        validate_queries: bool = True,\n    ) -> ExecutionResult:\n        result = execute_sync(\n            self._schema,\n            query,\n            variable_values=variable_values,\n            root_value=root_value,\n            context_value=context_value,\n            operation_name=operation_name,\n            additional_middlewares=self.middleware,\n            extensions=self.extensions,\n            execution_context_class=self.execution_context_class,\n            validate_queries=validate_queries,\n        )\n\n        return ExecutionResult(\n            data=result.data,\n            errors=result.errors,\n            extensions=result.extensions,\n        )\n\n    async def subscribe(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n    ):\n        return await subscribe(\n            self._schema,\n            parse(query),\n            root_value=root_value,\n            context_value=context_value,\n            variable_values=variable_values,\n            operation_name=operation_name,\n        )\n\n    def as_str(self) -> str:\n        return print_schema(self)\n\n    __str__ = as_str\n\n    def introspect(self) -> Dict[str, Any]:\n        \"\"\"Return the introspection query result for the current schema\n\n        Raises:\n            ValueError: If the introspection query fails due to an invalid schema\n        \"\"\"\n        introspection = self.execute_sync(get_introspection_query())\n        if introspection.errors or not introspection.data:\n            raise ValueError(f\"Invalid Schema. Errors {introspection.errors!r}\")\n\n        return introspection.data\n", "path": "strawberry/schema/schema.py"}], "after_files": [{"content": "import logging\nfrom typing import Any, Dict, List, Optional, Sequence, Type, Union\n\nfrom graphql import (\n    ExecutionContext as GraphQLExecutionContext,\n    GraphQLSchema,\n    get_introspection_query,\n    parse,\n    validate_schema,\n)\nfrom graphql.error import GraphQLError\nfrom graphql.subscription import subscribe\nfrom graphql.type.directives import specified_directives\n\nfrom strawberry.custom_scalar import ScalarDefinition\nfrom strawberry.enum import EnumDefinition\nfrom strawberry.extensions import Extension\nfrom strawberry.schema.schema_converter import GraphQLCoreConverter\nfrom strawberry.types import ExecutionResult\nfrom strawberry.types.types import TypeDefinition\nfrom strawberry.union import StrawberryUnion\n\nfrom ..middleware import DirectivesMiddleware, Middleware\nfrom ..printer import print_schema\nfrom .execute import execute, execute_sync\n\n\nlogger = logging.getLogger(\"strawberry.execution\")\n\n\nclass Schema:\n    def __init__(\n        self,\n        # TODO: can we make sure we only allow to pass something that has been decorated?\n        query: Type,\n        mutation: Optional[Type] = None,\n        subscription: Optional[Type] = None,\n        directives=(),\n        types=(),\n        extensions: Sequence[Type[Extension]] = (),\n        execution_context_class: Optional[Type[GraphQLExecutionContext]] = None,\n    ):\n        self.extensions = extensions\n        self.execution_context_class = execution_context_class\n        self.schema_converter = GraphQLCoreConverter()\n\n        query_type = self.schema_converter.from_object_type(query)\n        mutation_type = (\n            self.schema_converter.from_object_type(mutation) if mutation else None\n        )\n        subscription_type = (\n            self.schema_converter.from_object_type(subscription)\n            if subscription\n            else None\n        )\n\n        self.middleware: List[Middleware] = [DirectivesMiddleware(directives)]\n\n        directives = [\n            self.schema_converter.from_directive(directive.directive_definition)\n            for directive in directives\n        ]\n\n        self._schema = GraphQLSchema(\n            query=query_type,\n            mutation=mutation_type,\n            subscription=subscription_type if subscription else None,\n            directives=specified_directives + directives,\n            types=list(map(self.schema_converter.from_object_type, types)),\n        )\n\n        # Validate schema early because we want developers to know about\n        # possible issues as soon as possible\n        errors = validate_schema(self._schema)\n        if errors:\n            formatted_errors = \"\\n\\n\".join(f\"\u274c {error.message}\" for error in errors)\n            raise ValueError(f\"Invalid Schema. Errors:\\n\\n{formatted_errors}\")\n\n        self.query = self.schema_converter.type_map[query_type.name]\n\n    def get_type_by_name(\n        self, name: str\n    ) -> Optional[\n        Union[TypeDefinition, ScalarDefinition, EnumDefinition, StrawberryUnion]\n    ]:\n        if name in self.schema_converter.type_map:\n            return self.schema_converter.type_map[name].definition\n\n        return None\n\n    def process_errors(self, errors: List[GraphQLError]) -> None:\n        for error in errors:\n            actual_error = error.original_error or error\n            logger.error(actual_error, exc_info=actual_error)\n\n    async def execute(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n        validate_queries: bool = True,\n    ) -> ExecutionResult:\n        result = await execute(\n            self._schema,\n            query,\n            variable_values=variable_values,\n            root_value=root_value,\n            context_value=context_value,\n            operation_name=operation_name,\n            additional_middlewares=self.middleware,\n            extensions=self.extensions,\n            execution_context_class=self.execution_context_class,\n            validate_queries=validate_queries,\n        )\n\n        if result.errors:\n            self.process_errors(result.errors)\n\n        return ExecutionResult(\n            data=result.data,\n            errors=result.errors,\n            extensions=result.extensions,\n        )\n\n    def execute_sync(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n        validate_queries: bool = True,\n    ) -> ExecutionResult:\n        result = execute_sync(\n            self._schema,\n            query,\n            variable_values=variable_values,\n            root_value=root_value,\n            context_value=context_value,\n            operation_name=operation_name,\n            additional_middlewares=self.middleware,\n            extensions=self.extensions,\n            execution_context_class=self.execution_context_class,\n            validate_queries=validate_queries,\n        )\n\n        if result.errors:\n            self.process_errors(result.errors)\n\n        return ExecutionResult(\n            data=result.data,\n            errors=result.errors,\n            extensions=result.extensions,\n        )\n\n    async def subscribe(\n        self,\n        query: str,\n        variable_values: Optional[Dict[str, Any]] = None,\n        context_value: Optional[Any] = None,\n        root_value: Optional[Any] = None,\n        operation_name: Optional[str] = None,\n    ):\n        return await subscribe(\n            self._schema,\n            parse(query),\n            root_value=root_value,\n            context_value=context_value,\n            variable_values=variable_values,\n            operation_name=operation_name,\n        )\n\n    def as_str(self) -> str:\n        return print_schema(self)\n\n    __str__ = as_str\n\n    def introspect(self) -> Dict[str, Any]:\n        \"\"\"Return the introspection query result for the current schema\n\n        Raises:\n            ValueError: If the introspection query fails due to an invalid schema\n        \"\"\"\n        introspection = self.execute_sync(get_introspection_query())\n        if introspection.errors or not introspection.data:\n            raise ValueError(f\"Invalid Schema. Errors {introspection.errors!r}\")\n\n        return introspection.data\n", "path": "strawberry/schema/schema.py"}]}