Skip to content

Commit 371fd01

Browse files
author
dori
committed
refactor: code review changes
1 parent 8a9a72c commit 371fd01

File tree

7 files changed

+245
-566
lines changed

7 files changed

+245
-566
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,3 @@ Thumbs.db
159159
*.db
160160
*.sqlite
161161
*.sqlite3
162-
conversations.db
163-
test.db

judge_mcp_flow.md

Lines changed: 0 additions & 484 deletions
This file was deleted.

src/mcp_as_a_judge/db/conversation_history_service.py

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
3. Managing session-based conversation history
88
"""
99

10-
import logging
10+
from mcp_as_a_judge.config import Config
11+
from mcp_as_a_judge.logging_config import get_logger
1112

12-
from ..config import Config
1313
from . import ConversationHistoryDB, ConversationRecord, create_database_provider
1414

1515
# Set up logger
16-
logger = logging.getLogger(__name__)
16+
logger = get_logger(__name__)
1717

1818

1919
class ConversationHistoryService:
@@ -129,6 +129,32 @@ def format_context_for_llm(self, context_records: list[ConversationRecord]) -> s
129129

130130
return formatted_context
131131

132+
async def enrich_with_context(self, session_id: str, base_prompt: str) -> str:
133+
"""
134+
Enrich a base prompt with conversation history context.
135+
136+
Args:
137+
session_id: Session identifier
138+
base_prompt: Original prompt to enrich
139+
140+
Returns:
141+
Enriched prompt with conversation history context
142+
"""
143+
logger.info(
144+
f"🔄 Starting context enrichment for session {session_id}, base_prompt: {base_prompt}"
145+
)
146+
147+
context_records = await self.load_context_for_enrichment(session_id)
148+
context_text = self.format_context_for_llm(context_records)
149+
150+
enriched_prompt = f"{context_text}\n## Current Request\n{base_prompt}"
151+
152+
logger.info(
153+
f"🎯 Context enrichment completed for session {session_id}, enriched_prompt: {enriched_prompt}"
154+
)
155+
156+
return enriched_prompt
157+
132158
### TEST-ONLY METHODS
133159
async def get_session_summary(self, session_id: str) -> dict:
134160
"""
@@ -157,36 +183,3 @@ async def get_session_summary(self, session_id: str) -> dict:
157183
"context_enrichment_count": self.config.database.context_enrichment_count,
158184
"max_context_records": self.config.database.max_context_records,
159185
}
160-
161-
162-
# Convenience functions for easy integration with existing tools
163-
164-
165-
async def enrich_with_context(
166-
service: ConversationHistoryService, session_id: str, base_prompt: str
167-
) -> str:
168-
"""
169-
Enrich a base prompt with conversation history context.
170-
171-
Args:
172-
service: ConversationHistoryService instance
173-
session_id: Session identifier
174-
base_prompt: Original prompt to enrich
175-
176-
Returns:
177-
Enriched prompt with conversation history context
178-
"""
179-
logger.info(
180-
f"🔄 Starting context enrichment for session {session_id}, base_prompt: {base_prompt}"
181-
)
182-
183-
context_records = await service.load_context_for_enrichment(session_id)
184-
context_text = service.format_context_for_llm(context_records)
185-
186-
enriched_prompt = f"{context_text}\n## Current Request\n{base_prompt}"
187-
188-
logger.info(
189-
f"🎯 Context enrichment completed for session {session_id}, enriched_prompt: {enriched_prompt}"
190-
)
191-
192-
return enriched_prompt

src/mcp_as_a_judge/db/providers/sqlite.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
It supports both in-memory (:memory:) and file-based SQLite storage.
66
"""
77

8-
import logging
98
import uuid
109
from datetime import datetime, timedelta
1110

1211
from sqlalchemy import create_engine
1312
from sqlmodel import Session, SQLModel, asc, desc, select
1413

14+
from mcp_as_a_judge.logging_config import get_logger
15+
1516
from ..interface import ConversationHistoryDB, ConversationRecord
1617

1718
# Set up logger
18-
logger = logging.getLogger(__name__)
19+
logger = get_logger(__name__)
1920

2021

2122
class SQLiteProvider(ConversationHistoryDB):
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
"""
2+
Central logging configuration for MCP as a Judge.
3+
4+
This module provides centralized logging setup with colored output and
5+
consistent formatting across the entire application.
6+
"""
7+
8+
import logging
9+
import sys
10+
from datetime import datetime
11+
from typing import Any, ClassVar
12+
13+
14+
class ColoredFormatter(logging.Formatter):
15+
"""Custom formatter that adds colors to log levels and formats messages."""
16+
17+
# ANSI color codes
18+
COLORS: ClassVar[dict[str, str]] = {
19+
"DEBUG": "\033[36m", # Cyan
20+
"INFO": "\033[32m", # Green
21+
"WARNING": "\033[33m", # Yellow
22+
"ERROR": "\033[31m", # Red
23+
"CRITICAL": "\033[35m", # Magenta
24+
}
25+
RESET = "\033[0m" # Reset color
26+
27+
def format(self, record: logging.LogRecord) -> str:
28+
"""Format log record with colors and custom format."""
29+
# Get color for log level
30+
level_color = self.COLORS.get(record.levelname, "")
31+
32+
# Format: [level_with_color] [module:linenumber] [iso-date] [message]
33+
colored_level = f"{level_color}{record.levelname}{self.RESET}"
34+
35+
# Get module name (remove package prefix for cleaner output)
36+
module_name = record.name
37+
if module_name.startswith("mcp_as_a_judge."):
38+
module_name = module_name[len("mcp_as_a_judge.") :]
39+
40+
# Format timestamp as ISO date
41+
timestamp = datetime.fromtimestamp(record.created).isoformat()
42+
43+
# Build the formatted message
44+
formatted_message = f"[{colored_level}] [{module_name}:{record.lineno}] [{timestamp}] {record.getMessage()}"
45+
46+
# Handle exceptions
47+
if record.exc_info:
48+
formatted_message += "\n" + self.formatException(record.exc_info)
49+
50+
return formatted_message
51+
52+
53+
def setup_logging(level: int = logging.INFO) -> None:
54+
"""
55+
Set up centralized logging configuration for the entire application.
56+
57+
Args:
58+
level: Logging level (default: INFO)
59+
"""
60+
# Create custom formatter
61+
formatter = ColoredFormatter()
62+
63+
# Create handler for stderr (so it's visible in development tools like Cursor)
64+
handler = logging.StreamHandler(sys.stderr)
65+
handler.setFormatter(formatter)
66+
67+
# Configure root logger
68+
root_logger = logging.getLogger()
69+
root_logger.setLevel(level)
70+
71+
# Clear any existing handlers to avoid duplicates
72+
root_logger.handlers.clear()
73+
74+
# Add our custom handler
75+
root_logger.addHandler(handler)
76+
77+
# Configure specific loggers for our application
78+
configure_application_loggers(level)
79+
80+
81+
def configure_application_loggers(level: int = logging.INFO) -> None:
82+
"""
83+
Configure specific loggers for MCP as a Judge application components.
84+
85+
Args:
86+
level: Logging level to set for application loggers
87+
"""
88+
# List of application-specific loggers to configure
89+
app_loggers = [
90+
"mcp_as_a_judge.server",
91+
"mcp_as_a_judge.conversation_history_service",
92+
"mcp_as_a_judge.db.conversation_history_service",
93+
"mcp_as_a_judge.db.providers.in_memory",
94+
"mcp_as_a_judge.db.providers.sqlite",
95+
"mcp_as_a_judge.messaging",
96+
"mcp_as_a_judge.llm_client",
97+
"mcp_as_a_judge.config",
98+
]
99+
100+
# Set level for each application logger
101+
for logger_name in app_loggers:
102+
logger = logging.getLogger(logger_name)
103+
logger.setLevel(level)
104+
105+
106+
def get_logger(name: str) -> logging.Logger:
107+
"""
108+
Get a logger instance with the given name.
109+
110+
This is a convenience function that ensures consistent logger naming
111+
across the application.
112+
113+
Args:
114+
name: Logger name (typically __name__ from the calling module)
115+
116+
Returns:
117+
Configured logger instance
118+
"""
119+
return logging.getLogger(name)
120+
121+
122+
def log_startup_message(config: Any) -> None:
123+
"""
124+
Log application startup message with configuration details.
125+
126+
Args:
127+
config: Application configuration object
128+
"""
129+
logger = get_logger("mcp_as_a_judge.server")
130+
logger.info(
131+
"🚀 MCP Judge server starting with conversation history logging enabled"
132+
)
133+
logger.info(
134+
f"📊 Configuration: max_context_records={config.database.max_context_records}, "
135+
f"context_enrichment_count={config.database.context_enrichment_count}"
136+
)
137+
138+
139+
def log_tool_execution(
140+
tool_name: str, session_id: str, additional_info: str = ""
141+
) -> None:
142+
"""
143+
Log tool execution start with consistent formatting.
144+
145+
Args:
146+
tool_name: Name of the tool being executed
147+
session_id: Session identifier
148+
additional_info: Additional information to log
149+
"""
150+
logger = get_logger("mcp_as_a_judge.server")
151+
152+
# Map tool names to emojis for better visibility
153+
tool_emojis = {
154+
"build_workflow": "🔧",
155+
"judge_coding_plan": "⚖️",
156+
"judge_code_change": "🔍",
157+
"raise_obstacle": "🚧",
158+
"raise_missing_requirements": "❓",
159+
}
160+
161+
emoji = tool_emojis.get(tool_name, "🛠️")
162+
logger.info(f"{emoji} {tool_name} called for session {session_id}")
163+
164+
if additional_info:
165+
logger.info(f" {additional_info}")
166+
167+
168+
def log_error(error: Exception, context: str = "") -> None:
169+
"""
170+
Log error with consistent formatting and context.
171+
172+
Args:
173+
error: Exception that occurred
174+
context: Additional context about where the error occurred
175+
"""
176+
logger = get_logger("mcp_as_a_judge.server")
177+
178+
if context:
179+
logger.error(f"❌ Error in {context}: {error!s}")
180+
else:
181+
logger.error(f"❌ Error: {error!s}")

0 commit comments

Comments
 (0)