Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use structlog and enable persisting logs in JSONL format #332

Merged
merged 6 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ package-lock.json
*.temp

# Log files
*.log
*.log*
logs/
npm-debug.log*
yarn-debug.log*
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ COPY ./backend .
# Copy the frontend build
COPY --from=builder /frontend/dist ./ui

ENTRYPOINT [ "uvicorn", "app.server:app", "--host", "0.0.0.0" ]
ENTRYPOINT [ "uvicorn", "app.server:app", "--host", "0.0.0.0", "--log-config", "log_config.json" ]
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ COPY . .

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --start-interval=1s --retries=3 CMD [ "curl", "-f", "http://localhost:8000/health" ]

ENTRYPOINT [ "uvicorn", "app.server:app", "--host", "0.0.0.0" ]
ENTRYPOINT [ "uvicorn", "app.server:app", "--host", "0.0.0.0", "--log-config", "log_config.json" ]
2 changes: 1 addition & 1 deletion backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ build_ui:
TEST_FILE ?= tests/unit_tests/

start:
poetry run uvicorn app.server:app --reload --port 8100
poetry run uvicorn app.server:app --reload --port 8100 --log-config log_config.json

migrate:
migrate -database postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DB)?sslmode=disable -path ./migrations up
Expand Down
18 changes: 18 additions & 0 deletions backend/app/lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import asyncpg
import orjson
import structlog
from fastapi import FastAPI

_pg_pool = None
Expand All @@ -26,6 +27,23 @@ async def _init_connection(conn) -> None:

@asynccontextmanager
async def lifespan(app: FastAPI):
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.stdlib.render_to_log_kwargs,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)

global _pg_pool

_pg_pool = await asyncpg.create_pool(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/llms.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import logging
import os
from functools import lru_cache
from urllib.parse import urlparse

import boto3
import httpx
import structlog
from langchain_anthropic import ChatAnthropic
from langchain_community.chat_models import BedrockChat, ChatFireworks
from langchain_community.chat_models.ollama import ChatOllama
from langchain_google_vertexai import ChatVertexAI
from langchain_openai import AzureChatOpenAI, ChatOpenAI

logger = logging.getLogger(__name__)
logger = structlog.get_logger(__name__)


@lru_cache(maxsize=4)
Expand Down
4 changes: 2 additions & 2 deletions backend/app/server.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import logging
import os
from pathlib import Path

import orjson
import structlog
from fastapi import FastAPI, Form, UploadFile
from fastapi.exceptions import HTTPException
from fastapi.staticfiles import StaticFiles
Expand All @@ -13,7 +13,7 @@
from app.lifespan import lifespan
from app.upload import convert_ingestion_input_to_blob, ingest_runnable

logger = logging.getLogger(__name__)
logger = structlog.get_logger(__name__)

app = FastAPI(title="OpenGPTs API", lifespan=lifespan)

Expand Down
4 changes: 2 additions & 2 deletions backend/app/stream.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import logging
from typing import Any, AsyncIterator, Dict, Optional, Sequence, Union

import orjson
import structlog
from langchain_core.messages import AnyMessage, BaseMessage, message_chunk_to_message
from langchain_core.runnables import Runnable, RunnableConfig
from langserve.serialization import WellKnownLCSerializer

logger = logging.getLogger(__name__)
logger = structlog.get_logger(__name__)

MessagesStream = AsyncIterator[Union[list[AnyMessage], str]]

Expand Down
70 changes: 70 additions & 0 deletions backend/log_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"default": {
"()": "uvicorn.logging.DefaultFormatter",
"fmt": "%(asctime)s - %(name)s - %(levelprefix)s %(message)s"
},
"access": {
"()": "uvicorn.logging.AccessFormatter",
"fmt": "%(asctime)s - %(name)s - %(levelprefix)s %(client_addr)s - \"%(request_line)s\" %(status_code)s"
},
"json": {
"()": "pythonjsonlogger.jsonlogger.JsonFormatter"
}
},
"handlers": {
"default": {
"formatter": "default",
"class": "logging.StreamHandler",
"stream": "ext://sys.stderr"
},
"access": {
"formatter": "access",
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
},
"file": {
"formatter": "json",
"class": "logging.handlers.RotatingFileHandler",
"filename": "./app.log",
"mode": "a+",
"maxBytes": 10000000,
"backupCount": 1
}
},
"root": {
"handlers": [
"default",
"file"
],
"level": "INFO"
},
"loggers": {
"app": {
"handlers": [
"default",
"file"
],
"level": "INFO",
"propagate": false
},
"uvicorn": {
"handlers": [
"default",
"file"
],
"level": "INFO",
"propagate": false
},
"uvicorn.access": {
"handlers": [
"access",
"file"
],
"level": "INFO",
"propagate": false
}
}
}
37 changes: 35 additions & 2 deletions backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ asyncpg = "^0.29.0"
langchain-core = "^0.1.44"
pyjwt = {extras = ["crypto"], version = "^2.8.0"}
langchain-anthropic = "^0.1.8"
structlog = "^24.1.0"
python-json-logger = "^2.0.7"

[tool.poetry.group.dev.dependencies]
uvicorn = "^0.23.2"
Expand Down
Loading