html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/1175#issuecomment-762488336,https://api.github.com/repos/simonw/datasette/issues/1175,762488336,MDEyOklzc3VlQ29tbWVudDc2MjQ4ODMzNg==,758858,2021-01-18T21:59:28Z,2021-01-18T22:00:31Z,NONE,"I encountered your issue when trying to find a solution and came up with the following, maybe it can help.
```python
import logging.config
from typing import Tuple
import structlog
import uvicorn
from example.config import settings
shared_processors: Tuple[structlog.types.Processor, ...] = (
structlog.contextvars.merge_contextvars,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.processors.TimeStamper(fmt=""iso""),
)
logging_config = {
""version"": 1,
""disable_existing_loggers"": False,
""formatters"": {
""json"": {
""()"": structlog.stdlib.ProcessorFormatter,
""processor"": structlog.processors.JSONRenderer(),
""foreign_pre_chain"": shared_processors,
},
""console"": {
""()"": structlog.stdlib.ProcessorFormatter,
""processor"": structlog.dev.ConsoleRenderer(),
""foreign_pre_chain"": shared_processors,
},
**uvicorn.config.LOGGING_CONFIG[""formatters""],
},
""handlers"": {
""default"": {
""level"": ""DEBUG"",
""class"": ""logging.StreamHandler"",
""formatter"": ""json"" if not settings.debug else ""console"",
},
""uvicorn.access"": {
""level"": ""INFO"",
""class"": ""logging.StreamHandler"",
""formatter"": ""access"",
},
""uvicorn.default"": {
""level"": ""INFO"",
""class"": ""logging.StreamHandler"",
""formatter"": ""default"",
},
},
""loggers"": {
"""": {""handlers"": [""default""], ""level"": ""INFO""},
""uvicorn.error"": {
""handlers"": [""default"" if not settings.debug else ""uvicorn.default""],
""level"": ""INFO"",
""propagate"": False,
},
""uvicorn.access"": {
""handlers"": [""default"" if not settings.debug else ""uvicorn.access""],
""level"": ""INFO"",
""propagate"": False,
},
},
}
def setup_logging() -> None:
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
*shared_processors,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.AsyncBoundLogger,
cache_logger_on_first_use=True,
)
logging.config.dictConfig(logging_config)
```
And then it'll be run on the startup event:
```python
@app.on_event(""startup"")
async def startup_event() -> None:
setup_logging()
```
It depends on a setting called `debug` which controls if it should output the regular uvicorn logging or json. ","{""total_count"": 15, ""+1"": 7, ""-1"": 0, ""laugh"": 1, ""hooray"": 1, ""confused"": 0, ""heart"": 5, ""rocket"": 1, ""eyes"": 0}",779156520,