Jspv structlog auto config fix (#907)

<!-- .github/pull_request_template.md -->

## Description
PR from user jspv, running it through our branch to test CI/CD

## DCO Affirmation
I affirm that all code in every commit of this pull request conforms to
the terms of the Topoteretes Developer Certificate of Origin.

---------

Signed-off-by: Diego B Theuerkauf <diego.theuerkauf@tuebingen.mpg.de>
Co-authored-by: Boris <boris@topoteretes.com>
Co-authored-by: vasilije <vas.markovic@gmail.com>
Co-authored-by: Vasilije <8619304+Vasilije1990@users.noreply.github.com>
Co-authored-by: Hande <159312713+hande-k@users.noreply.github.com>
Co-authored-by: Matea Pesic <80577904+matea16@users.noreply.github.com>
Co-authored-by: hajdul88 <52442977+hajdul88@users.noreply.github.com>
Co-authored-by: Daniel Molnar <soobrosa@gmail.com>
Co-authored-by: Diego Baptista Theuerkauf <34717973+diegoabt@users.noreply.github.com>
Co-authored-by: Dmitrii Galkin <36552323+dm1tryG@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: lxobr <122801072+lxobr@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions@users.noreply.github.com>
Co-authored-by: jspv <jspvgithub@twinleaf.xyz>
This commit is contained in:
Igor Ilic 2025-06-11 15:26:23 +02:00 committed by GitHub
parent 1c5ea46378
commit 0005266018
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 72 additions and 75 deletions

View file

@ -4,7 +4,7 @@ import sys
import argparse
import cognee
import asyncio
from cognee.shared.logging_utils import get_logger, get_log_file_location
from cognee.shared.logging_utils import get_logger, setup_logging, get_log_file_location
import importlib.util
from contextlib import redirect_stdout
import mcp.types as types
@ -20,7 +20,6 @@ from cognee.modules.storage.utils import JSONEncoder
mcp = FastMCP("Cognee")
logger = get_logger()
log_file = get_log_file_location()
@mcp.tool()
@ -91,7 +90,7 @@ async def cognee_add_developer_rules(
tasks.append(asyncio.create_task(cognify_task(abs_path)))
else:
logger.warning(f"Skipped missing developer rule file: {abs_path}")
log_file = get_log_file_location()
return [
types.TextContent(
type="text",
@ -173,6 +172,7 @@ async def cognify(data: str, graph_model_file: str = None, graph_model_name: str
)
)
log_file = get_log_file_location()
text = (
f"Background process launched due to MCP timeout limitations.\n"
f"To check current cognify status use the cognify_status tool\n"
@ -234,6 +234,7 @@ async def codify(repo_path: str) -> list:
asyncio.create_task(codify_task(repo_path))
log_file = get_log_file_location()
text = (
f"Background process launched due to MCP timeout limitations.\n"
f"To check current codify status use the codify_status tool\n"
@ -454,6 +455,8 @@ async def main():
if __name__ == "__main__":
logger = setup_logging()
try:
asyncio.run(main())
except Exception as e:

View file

@ -1,9 +1,20 @@
# ruff: noqa: E402
from cognee.version import get_cognee_version
# NOTE: __version__ extraction must be at the top of the __init__.py otherwise
# there will be circular import issues
__version__ = get_cognee_version()
# Load environment variable settings has to be before setting up logging for LOG_LEVEL value
import dotenv
dotenv.load_dotenv(override=True)
# NOTE: Log level can be set with the LOG_LEVEL env variable
from cognee.shared.logging_utils import setup_logging
logger = setup_logging()
from .api.v1.add import add
from .api.v1.delete import delete
from .api.v1.cognify import cognify
@ -18,7 +29,3 @@ from cognee.modules.visualization.cognee_network_visualization import (
# Pipelines
from .modules import pipelines
import dotenv
dotenv.load_dotenv(override=True)

View file

@ -3,7 +3,7 @@
import os
import uvicorn
from cognee.shared.logging_utils import get_logger
from cognee.shared.logging_utils import get_logger, setup_logging
import sentry_sdk
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse, Response
@ -195,4 +195,5 @@ def start_api_server(host: str = "0.0.0.0", port: int = 8000):
if __name__ == "__main__":
logger = setup_logging()
start_api_server()

View file

@ -2,7 +2,7 @@ import os
import pathlib
import asyncio
from uuid import NAMESPACE_OID, uuid5
from cognee.shared.logging_utils import get_logger
from cognee.shared.logging_utils import get_logger, setup_logging
from cognee.modules.observability.get_observe import get_observe
from cognee.api.v1.search import SearchType, search
@ -97,4 +97,5 @@ if __name__ == "__main__":
for file in search_results:
print(file["name"])
logger = setup_logging(name="code_graph_pipeline")
asyncio.run(main())

View file

@ -2,7 +2,7 @@ from cognee.modules.visualization.cognee_network_visualization import (
cognee_network_visualization,
)
from cognee.infrastructure.databases.graph import get_graph_engine
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import get_logger, setup_logging, ERROR
import asyncio
@ -28,7 +28,7 @@ async def visualize_graph(destination_file_path: str = None):
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:

View file

@ -1,5 +1,5 @@
import asyncio
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import get_logger, setup_logging, ERROR
from typing import List
from cognee.infrastructure.databases.graph import get_graph_engine
@ -144,6 +144,7 @@ async def code_description_to_code_part(
if __name__ == "__main__":
logger = setup_logging(log_level=ERROR)
async def main():
query = "I am looking for a class with blue eyes"

View file

@ -1,6 +1,5 @@
import os
import sys
import threading
import logging
import structlog
import traceback
@ -10,6 +9,7 @@ from pathlib import Path
import importlib.metadata
from cognee import __version__ as cognee_version
from typing import Protocol
# Export common log levels
DEBUG = logging.DEBUG
@ -27,11 +27,8 @@ log_levels = {
"NOTSET": logging.NOTSET,
}
# Track if logging has been configured
_is_configured = False
# Create a lock for thread-safe initialization
_setup_lock = threading.Lock()
# Track if structlog logging has been configured
_is_structlog_configured = False
# Path to logs directory
LOGS_DIR = Path(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs"))
@ -128,45 +125,27 @@ class PlainFileHandler(logging.FileHandler):
self.flush()
class LoggerInterface:
def info(self, msg, *args, **kwargs):
pass
def warning(self, msg, *args, **kwargs):
pass
def error(self, msg, *args, **kwargs):
pass
def critical(self, msg, *args, **kwargs):
pass
def debug(self, msg, *args, **kwargs):
pass
class LoggerInterface(Protocol):
def info(self, msg: str, *args, **kwargs) -> None: ...
def warning(self, msg: str, *args, **kwargs) -> None: ...
def error(self, msg: str, *args, **kwargs) -> None: ...
def critical(self, msg: str, *args, **kwargs) -> None: ...
def debug(self, msg: str, *args, **kwargs) -> None: ...
def get_logger(name=None, level=None) -> LoggerInterface:
"""Get a configured structlog logger.
"""Get a logger.
Args:
name: Logger name (default: None, uses __name__)
level: Logging level (default: None)
Returns:
A configured structlog logger instance
If `setup_logging()` has not been called, returns a standard Python logger.
If `setup_logging()` has been called, returns a structlog logger.
"""
global _is_configured
# Always first check if logger is already configured to not use threading lock if not necessary
if not _is_configured:
# Use threading lock to make sure setup_logging can be called only once
with _setup_lock:
# Unfortunately we also need a second check in case lock was entered twice at the same time
if not _is_configured:
setup_logging(level)
_is_configured = True
return structlog.get_logger(name if name else __name__)
if _is_structlog_configured:
return structlog.get_logger(name if name else __name__)
else:
logger = logging.getLogger(name if name else __name__)
if level is not None:
logger.setLevel(level)
return logger
def cleanup_old_logs(logs_dir, max_files):
@ -177,9 +156,8 @@ def cleanup_old_logs(logs_dir, max_files):
logs_dir: Directory containing log files
max_files: Maximum number of log files to keep
"""
logger = structlog.get_logger()
try:
logger = structlog.get_logger()
# Get all .log files in the directory (excluding README and other files)
log_files = [f for f in logs_dir.glob("*.log") if f.is_file()]
@ -211,6 +189,7 @@ def setup_logging(log_level=None, name=None):
Returns:
A configured structlog logger instance
"""
global _is_structlog_configured
log_level = log_level if log_level else log_levels[os.getenv("LOG_LEVEL", "INFO")]
@ -260,9 +239,11 @@ def setup_logging(log_level=None, name=None):
logger = structlog.get_logger()
logger.error(
"Uncaught exception",
"Exception",
exc_info=(exc_type, exc_value, traceback),
)
# Hand back to the original hook → prints traceback and exits
sys.__excepthook__(exc_type, exc_value, traceback)
# Install exception handlers
sys.excepthook = handle_exception
@ -325,6 +306,7 @@ def setup_logging(log_level=None, name=None):
if log_level > logging.DEBUG:
import warnings
from sqlalchemy.exc import SAWarning
warnings.filterwarnings(
@ -337,6 +319,9 @@ def setup_logging(log_level=None, name=None):
# Clean up old log files, keeping only the most recent ones
cleanup_old_logs(LOGS_DIR, MAX_LOG_FILES)
# Mark logging as configured
_is_structlog_configured = True
# Get a configured logger and log system information
logger = structlog.get_logger(name if name else __name__)
logger.info(
@ -352,7 +337,7 @@ def setup_logging(log_level=None, name=None):
def get_log_file_location():
# Get the root logger
"""Return the file path of the log file in use, if any."""
root_logger = logging.getLogger()
# Loop through handlers to find the FileHandler

View file

@ -2,7 +2,7 @@ import argparse
import asyncio
import cognee
from cognee import SearchType
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import setup_logging, ERROR
from cognee.api.v1.cognify.code_graph_pipeline import run_code_graph_pipeline
@ -41,7 +41,7 @@ def parse_args():
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
args = parse_args()

View file

@ -1,8 +1,8 @@
import cognee
import asyncio
from cognee.shared.logging_utils import get_logger, ERROR
import cognee
from cognee.api.v1.search import SearchType
from cognee.shared.logging_utils import setup_logging, ERROR
job_1 = """
CV 1: Relevant
@ -191,7 +191,7 @@ async def main(enable_steps):
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
rebuild_kg = True
retrieve = True

View file

@ -1,7 +1,7 @@
import asyncio
import cognee
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import setup_logging, ERROR
from cognee.modules.pipelines import Task, run_tasks
from cognee.tasks.temporal_awareness import build_graph_with_temporal_awareness
from cognee.infrastructure.databases.relational import (
@ -74,7 +74,7 @@ async def main():
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:

View file

@ -1,7 +1,7 @@
import os
import asyncio
import pathlib
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import setup_logging, ERROR
import cognee
from cognee.api.v1.search import SearchType
@ -46,7 +46,7 @@ async def main():
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:

View file

@ -1,11 +1,10 @@
import cognee
import asyncio
from cognee.shared.logging_utils import get_logger
import os
import cognee
from cognee.api.v1.search import SearchType
from cognee.api.v1.visualize.visualize import visualize_graph
from cognee.shared.logging_utils import setup_logging
text_1 = """
1. Audi
@ -75,7 +74,7 @@ async def main():
if __name__ == "__main__":
logger = get_logger()
logger = setup_logging()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

View file

@ -1,6 +1,6 @@
import cognee
import asyncio
from cognee.shared.logging_utils import get_logger
from cognee.shared.logging_utils import setup_logging
import os
import textwrap
from cognee.api.v1.search import SearchType
@ -92,7 +92,7 @@ async def main():
if __name__ == "__main__":
logger = get_logger()
logger = setup_logging()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

View file

@ -1,6 +1,6 @@
import asyncio
import cognee
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import setup_logging, ERROR
from cognee.api.v1.search import SearchType
# Prerequisites:
@ -67,7 +67,7 @@ async def main():
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:

View file

@ -2,7 +2,7 @@ import os
import asyncio
import cognee
from cognee.api.v1.visualize.visualize import visualize_graph
from cognee.shared.logging_utils import get_logger, ERROR
from cognee.shared.logging_utils import setup_logging, ERROR
text_a = """
AI is revolutionizing financial services through intelligent fraud detection
@ -39,6 +39,6 @@ async def main():
if __name__ == "__main__":
logger = get_logger(level=ERROR)
logger = setup_logging(log_level=ERROR)
loop = asyncio.new_event_loop()
asyncio.run(main())