Skip to content

Instantly share code, notes, and snippets.

@Kludex
Created December 5, 2022 08:58
Show Gist options
  • Save Kludex/8e6d30de151f1d756c3c7364811c9429 to your computer and use it in GitHub Desktop.
Save Kludex/8e6d30de151f1d756c3c7364811c9429 to your computer and use it in GitHub Desktop.
Uvicorn logging for prod & dev
import logging
import sys
from typing import List
import structlog
import uvicorn
from fastapi import FastAPI
from structlog.stdlib import ProcessorFormatter
from structlog.types import Processor
shared_processors: List[Processor] = [
structlog.stdlib.add_log_level,
structlog.processors.CallsiteParameterAdder(
{
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.LINENO,
}
),
structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S.%f"),
]
structlog_processors = shared_processors + []
# Remove _record & _from_structlog.
logging_processors: List[Processor] = [ProcessorFormatter.remove_processors_meta]
if sys.stderr.isatty():
console_renderer = structlog.dev.ConsoleRenderer()
logging_processors.append(console_renderer)
structlog_processors.append(console_renderer)
else:
json_renderer = structlog.processors.JSONRenderer(indent=1, sort_keys=True)
structlog_processors.append(json_renderer)
logging_processors.append(json_renderer)
structlog.configure(
processors=structlog_processors,
wrapper_class=structlog.stdlib.BoundLogger,
# logger_factory=structlog.stdlib.LoggerFactory(),
logger_factory=structlog.PrintLoggerFactory(sys.stderr),
context_class=dict,
cache_logger_on_first_use=True,
)
formatter = ProcessorFormatter(
# These run ONLY on `logging` entries that do NOT originate within
# structlog.
foreign_pre_chain=shared_processors,
# These run on ALL entries after the pre_chain is done.
processors=logging_processors,
)
handler = logging.StreamHandler(sys.stderr)
# Use OUR `ProcessorFormatter` to format all `logging` entries.
handler.setFormatter(formatter)
logging.basicConfig(handlers=[handler], level=logging.INFO)
logger = logging.getLogger("uvicorn.error")
logger.handlers = [handler]
logger.propagate = False
app = FastAPI()
@app.get("/")
def home():
structlog.get_logger().info("This is now being logged.")
structlog.stdlib.get_logger(__name__).info("With foo on attributes...", foo="bar")
logging.getLogger().info("Logging something...", {"potato": "potato"})
if __name__ == "__main__":
uvicorn.run("main:app", reload=True, host="0.0.0.0", access_log=False)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment