Skip to main content

Custom Cloud Logging handler for FastAPI applications deployed in Google App Engine. Groups logs coming from the same request lifecycle and propagates the maximum log level throughout the request lifecycle using middleware and context management.

Project description

fastapi-gae-logging

Custom Cloud Logging handler for FastAPI applications deployed in Google App Engine to ease out logs analysis and monitoring through Google Cloud Log Explorer.

What problem does this package solve? Why do we need this?

When deploying FastAPI applications on Google App Engine, I encountered several challenges with logging and observability even when using the official package for this purpose, google-cloud-logging.

  • Scattered Logs: Logs generated during a single request lifecycle were scattered across different log entries, making it difficult to trace the entire flow of a request, especially when troubleshooting issues.

  • Log Severity Mismatch: The severity level of logs was not properly propagated throughout the request lifecycle. This meant that if an error occurred at any point in the request, the earlier logs did not reflect the severity of the final outcome, making it harder to identify problematic requests.

  • Payload Logging Issues: Capturing and logging request payloads was cumbersome, requiring extra logging in the handlers and extra deployments. This led to incomplete logs, making it harder to reproduce issues or analyze request content.

  • Inconsistent Log Structures: The default logging setup lacked a consistent structure, which made it challenging to filter, search, and analyze logs in the Google Cloud Log Explorer.

So what does it do?

The fastapi-gae-logging module addresses these problems by:

  • Grouping Logs by Request: All logs generated during a request's lifecycle are grouped together, allowing for a complete view of the request flow in the Google Cloud Log Explorer. This makes it much easier to trace and troubleshoot issues.

  • Log Level Propagation: The maximum log level observed during a request's lifecycle is propagated, ensuring that logs associated with a failed request reflect the appropriate severity. This improves the accuracy and utility of log searches based on severity.

  • Structured Payload Logging: Request payloads are captured and logged in a structured format, even for non-dictionary JSON payloads. This ensures that all relevant request data is available for analysis, improving the ability to diagnose issues.

Install

pip install fastapi-gae-logging

Features:

  • Request Logs Grouping: Groups logs from the same request lifecycle to simplify log analysis using Google Cloud Log Explorer. The logger name for grouping can be customized and defaults to the Google Cloud Project ID with '-request-logger' as a suffix.
  • Request Maximum Log Level Propagation: Propagates the maximum log level throughout the request lifecycle, making it easier to search logs based on the severity of an issue.
  • Request Payload Logging:
    • Logs the payload of a request as part of the parent log in request-grouped logs.
    • Assumes the payload is a valid JSON - basically what Python's json.loads() can parse - otherwise, it is discarded.
    • Logs the payload as a dictionary using the google-cloud-logging's log_struct method. If the payload is not a dictionary, then it is wrapped in a dummy keyword to construct one. The dummy keyword follows the format: <original_type_of_payload>__payload_wrapper. For example, if the payload is a list, which still a valid JSON which Python's json.loads() will parse just fine, then the payload list will be wrapped in a virtual dictionary under the key list_payload_wrapper. The dictionary is logged alongside the parent log in request-grouped logs and ends up in the jsonPayload field.

API

  • FastAPIGAELoggingHandler class: A custom Cloud Logging Handler for FastAPI applications to use with the official google-cloud-logging library.

Example of usage

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.exceptions import HTTPException
import logging
import os

app = FastAPI()

if os.getenv('GAE_ENV', '').startswith('standard'):
    import google.cloud.logging
    from google.cloud.logging_v2.handlers import setup_logging
    from fastapi_gae_logging import FastAPIGAELoggingHandler

    client = google.cloud.logging.Client()
    gae_log_handler = FastAPIGAELoggingHandler(app=app, client=client)
    setup_logging(handler=gae_log_handler)

logging.getLogger().setLevel(logging.DEBUG)

@app.get("/info")
def info():
    logging.debug("this is a debug")
    logging.info("this is an info")
    return JSONResponse(
        content={"message": "info"}
    )

@app.get("/warning")
async def warning():
    logging.debug("this is a debug")
    logging.info("this is an info")
    logging.warning("this is a warning")
    return JSONResponse(
        content={"message": "warning"}
    )

@app.get("/error")
def error():
    logging.debug("this is a debug")
    logging.info("this is an info")
    logging.warning("this is a warning")
    logging.error("this is an error")
    return JSONResponse(
        content={"message": "error"}
    )

@app.get("/exception")
def exception():
    logging.debug("this is a debug")
    logging.info("this is an info")
    logging.error("this is an error")
    raise ValueError("This is a value error")

@app.get("/http_exception")
def http_exception():
    logging.debug("this is a debug")
    logging.info("this is an info")
    raise HTTPException(
        status_code=404,
        detail={"error": "Resource not found"}
    )

@app.post("/post_payload")
def post_payload(payload: Any = Body(None)):
    logging.debug("this is an debug")
    logging.info(payload)
    return JSONResponse(content={"mirror_response": payload}, status_code=200)

How it looks in Google Cloud Log Explorer

Logger selection

alt text

Groupped logs with propagated log severity to the parent log

alt text

Grouped logs in request with payload

alt text

Dependencies

This tool is built upon the following packages:

  • fastapi: A modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
  • google-cloud-logging: Google Cloud Logging API client library for logging and managing logs in Google Cloud Platform.

Implementation Concept

  • Middleware Integration: A custom middleware integrates into FastAPI to intercept requests and log data after processing.The custom middleware is added to the FastAPI application during the initialization of the FastAPIGAELoggingHandler.
  • Context Management: Uses context variables to manage request-specific data and metadata such as request payload, Google Cloud trace ID, start time of the incoming request and the maximum log level observed during the request lifecycle.
  • Log Interception: A logging filter intercepts log records, injecting trace information and adjusting the maximum log level based on observed log severity.
  • Cloud Logging: Utilizes Google Cloud Logging to group logs by request and propagate the maximum log level, enhancing observability and troubleshooting.
  • Structured Logging: Parent log of the request-response lifecycle is structured and sent to Google Cloud Logging with additional context, such as the request method, URL, and user agent after the request has been processed and served.

Roadmap

  • Allow for opting out of the dictionary enforcement of logged payload.
  • Allow for opting out of request payload logging at all.
  • Explore other fields in Google Cloud Logs. Investigate and consider utilizing additional fields available in Google Cloud Logs that may allow for more goodies.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_gae_logging-0.0.3.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

fastapi_gae_logging-0.0.3-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_gae_logging-0.0.3.tar.gz.

File metadata

  • Download URL: fastapi_gae_logging-0.0.3.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.5

File hashes

Hashes for fastapi_gae_logging-0.0.3.tar.gz
Algorithm Hash digest
SHA256 de2a1d166d31edc7878295d0526e826df08f09115159c7464c4a7e2932fd130c
MD5 7aeb57541b5b1b33cbdbc8f033c768b5
BLAKE2b-256 03c328f6fd065a737798ddf93613ad6b02d17ed60a324f74bf7fabea4dd110e6

See more details on using hashes here.

File details

Details for the file fastapi_gae_logging-0.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_gae_logging-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 c5d0fc210b0b51f20946a8565c61ef9cd1d2abe8342bffd98f1c35a069910d95
MD5 48ede28fbfbca56bf816f873fde32f7f
BLAKE2b-256 860d0f9803cdd5b9c0223b2de63cc8c78ec9bed8262f12db4d1ab87cc29bfcda

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page