Skip to content

Instantly share code, notes, and snippets.

@devsetgo
Last active November 8, 2021 05:31
Show Gist options
  • Save devsetgo/28c2edaca2d09e267dec46bb2e54b9e2 to your computer and use it in GitHub Desktop.
Save devsetgo/28c2edaca2d09e267dec46bb2e54b9e2 to your computer and use it in GitHub Desktop.
Loguru configuration with Starlette and Uvicorn.
import logging
from pathlib import Path
from loguru import logger
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
# set log level [DEBUG, INFO, WARNING, ERROR, CRITICAL]
LOGURU_LOGGING_LEVEL = "WARNING"
def config_log():
# remove default logger
logger.remove()
# set file path
log_path = Path.cwd().joinpath("log").joinpath("app_log.log")
# add new configuration
logger.add(
log_path, #log file path
level=LOGURU_LOGGING_LEVEL, #logging level
format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}", #format of log
enqueue=True, # set to true for async or multiprocessing logging
backtrace=False, # turn to false if in production to prevent data leaking
rotation="10 MB", #file size to rotate
retention="10 Days", # how long a the logging data persists
compression="zip", # log rotation compression
serialize=False, # if you want it JSON style, set to true. But also change the format
)
#intercept standard logging
class InterceptHandler(logging.Handler):
def emit(self, record):
# Get corresponding Loguru level if it exists
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message
frame, depth = logging.currentframe(), 2
while frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
logging.basicConfig(handlers=[InterceptHandler()], level=0)
def start_up():
config_log()
async def index_route(request):
logging.debug("logging")
logger.debug("logger")
logging.info("logging")
logger.info("logger")
logging.warning("logging")
logger.warning("logger")
logging.error("logging")
logger.error("logger")
logging.critical("logging")
logger.critical("logger")
return JSONResponse({"status": "UP"})
app = Starlette(on_startup=[start_up],routes=[
Route('/', index_route),
])
if __name__ == "__main__":
import uvicorn
# logging has to be lower case for Uvicorn
uvicorn.run(app, host="0.0.0.0", port=5000, debug=False, log_level=LOGURU_LOGGING_LEVEL.lower())
@memclutter
Copy link

but doesnt work with workers > 1

@devsetgo
Copy link
Author

devsetgo commented Jan 20, 2021

@memclutter Run it from the command line uvicorn app:app --port 5000 --workers 4. I don't believe you can specify workers in code.

Also, I run Uvicorn under Gunicorn as a general practice. You can read more about that in the Uvicorn documents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment