2022-05-02 18:00:00+00:00

In production GraphQL APIs, tracking user actions and auditing database queries is a key security requirement. If you write auditing logic directly inside every resolver function, your codebase will contain duplicate code, making maintenance difficult. Ariadne supports custom middlewares that intercept the GraphQL execution loop, allowing developers to extract metadata, inspect queries, and log audits in a centralized layer.

By designing GraphQL middleware, you can inspect incoming queries and log database transactions.


1. Creating the GraphQL Audit Middleware

We write a middleware class that inspects query info, logs requests, and checks resolver execution speeds:

# middleware.py
import time
import logging

logging.basicConfig(level=logging.INFO)

def audit_middleware(resolver, obj, info, **kwargs):
    # Retrieve user authentication context
    context = info.context
    user = context.get("user", "Anonymous")
    
    # Track resolver execution duration
    start_time = time.time()
    result = resolver(obj, info, **kwargs)
    duration = time.time() - start_time
    
    # Log audit trail
    logging.info(
        f"User: {user} | Resolver: {info.field_name} | Target: {info.parent_type.name} | Duration: {duration:.4f}s"
    )
    return result

2. Registering Middleware in Ariadne

We pass the middleware to the schema execution endpoint: graphql_sync(schema, data, middleware=[audit_middleware]). This ensures that every resolver call is audited, providing a clean security audit trail.