Skip to content

Commit 38fbf70

Browse files
Fix linting issues: replace ambiguous Unicode characters and add timezone to datetime.now() calls
1 parent 9abfa3b commit 38fbf70

26 files changed

+135
-210
lines changed

QUICK_START_LOGGING.md

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
## ⚡ TL;DR - 3 Step Process
44

55
1. **Import the logger**: `from codegen.shared.logging.get_logger import get_logger`
6-
2. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
7-
3. **Enable telemetry**: `codegen config telemetry enable`
6+
1. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
7+
1. **Enable telemetry**: `codegen config telemetry enable`
88

99
**That's it!** Your logs automatically go to Grafana Cloud when telemetry is enabled.
1010

@@ -22,11 +22,14 @@ from codegen.shared.logging.get_logger import get_logger
2222
logger = get_logger(__name__)
2323

2424
# Find any existing console.print() or error handling and add:
25-
logger.info("Operation completed", extra={
26-
"operation": "command_name",
27-
"org_id": org_id, # if available
28-
"success": True
29-
})
25+
logger.info(
26+
"Operation completed",
27+
extra={
28+
"operation": "command_name",
29+
"org_id": org_id, # if available
30+
"success": True,
31+
},
32+
)
3033
```
3134

3235
### 2. Test the Integration Right Now
@@ -48,69 +51,56 @@ codegen config telemetry status
4851
## 📝 Copy-Paste Patterns
4952

5053
### Pattern 1: Operation Start/End
54+
5155
```python
5256
logger = get_logger(__name__)
5357

5458
# At start of function
55-
logger.info("Operation started", extra={
56-
"operation": "command.subcommand",
57-
"user_input": relevant_input
58-
})
59+
logger.info("Operation started", extra={"operation": "command.subcommand", "user_input": relevant_input})
5960

6061
# At end of function
61-
logger.info("Operation completed", extra={
62-
"operation": "command.subcommand",
63-
"success": True
64-
})
62+
logger.info("Operation completed", extra={"operation": "command.subcommand", "success": True})
6563
```
6664

6765
### Pattern 2: Error Handling
66+
6867
```python
6968
try:
7069
# your existing code
7170
pass
7271
except SomeSpecificError as e:
73-
logger.error("Specific error occurred", extra={
74-
"operation": "command.subcommand",
75-
"error_type": "specific_error",
76-
"error_details": str(e)
77-
}, exc_info=True)
72+
logger.error("Specific error occurred", extra={"operation": "command.subcommand", "error_type": "specific_error", "error_details": str(e)}, exc_info=True)
7873
# your existing error handling
7974
```
8075

8176
### Pattern 3: API Calls
77+
8278
```python
8379
# Before API call
84-
logger.info("Making API request", extra={
85-
"operation": "api.request",
86-
"endpoint": "agent/run",
87-
"org_id": org_id
88-
})
80+
logger.info("Making API request", extra={"operation": "api.request", "endpoint": "agent/run", "org_id": org_id})
8981

9082
# After successful API call
91-
logger.info("API request successful", extra={
92-
"operation": "api.request",
93-
"endpoint": "agent/run",
94-
"response_id": response.get("id"),
95-
"status_code": response.status_code
96-
})
83+
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
9784
```
9885

9986
## 🎯 What to Log (Priority Order)
10087

10188
### 🔥 High Priority (Add These First)
89+
10290
- **Operation start/end**: When commands begin/complete
10391
- **API calls**: Requests to your backend
10492
- **Authentication events**: Login/logout/token issues
10593
- **Errors**: Any exception or failure
10694
- **User actions**: Commands run, options selected
10795

10896
### ⭐ Medium Priority
97+
10998
- **Performance**: Duration of operations
11099
- **State changes**: Status updates, configuration changes
111100
- **External tools**: Claude CLI detection, git operations
112101

113102
### 💡 Low Priority (Nice to Have)
103+
114104
- **Debug info**: Internal state, validation steps
115105
- **User behavior**: Which features are used most
116106

@@ -163,15 +153,19 @@ def create(prompt: str, org_id: int | None = None, ...):
163153

164154
logger = get_logger(__name__)
165155

156+
166157
def _run_claude_interactive(resolved_org_id: int, no_mcp: bool | None) -> None:
167158
session_id = generate_session_id()
168159

169160
# ADD: Log session start
170-
logger.info("Claude session started", extra={
171-
"operation": "claude.session_start",
172-
"session_id": session_id[:8], # Short version for privacy
173-
"org_id": resolved_org_id
174-
})
161+
logger.info(
162+
"Claude session started",
163+
extra={
164+
"operation": "claude.session_start",
165+
"session_id": session_id[:8], # Short version for privacy
166+
"org_id": resolved_org_id,
167+
},
168+
)
175169

176170
# Your existing code...
177171

@@ -180,30 +174,23 @@ def _run_claude_interactive(resolved_org_id: int, no_mcp: bool | None) -> None:
180174
returncode = process.wait()
181175

182176
# ADD: Log session end
183-
logger.info("Claude session completed", extra={
184-
"operation": "claude.session_complete",
185-
"session_id": session_id[:8],
186-
"exit_code": returncode,
187-
"status": "COMPLETE" if returncode == 0 else "ERROR"
188-
})
177+
logger.info(
178+
"Claude session completed", extra={"operation": "claude.session_complete", "session_id": session_id[:8], "exit_code": returncode, "status": "COMPLETE" if returncode == 0 else "ERROR"}
179+
)
189180

190181
except Exception as e:
191182
# ADD: Log session error
192-
logger.error("Claude session failed", extra={
193-
"operation": "claude.session_error",
194-
"session_id": session_id[:8],
195-
"error": str(e)
196-
})
183+
logger.error("Claude session failed", extra={"operation": "claude.session_error", "session_id": session_id[:8], "error": str(e)})
197184
```
198185

199186
## 🧪 Verification
200187

201188
After making changes:
202189

203190
1. **Run the command**: Execute your enhanced CLI command
204-
2. **Check telemetry status**: `codegen config telemetry status`
205-
3. **Look for logs in Grafana Cloud**: Search for your operation names
206-
4. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
191+
1. **Check telemetry status**: `codegen config telemetry status`
192+
1. **Look for logs in Grafana Cloud**: Search for your operation names
193+
1. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
207194

208195
## 🚀 Progressive Enhancement
209196

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
"""Claude Code integration commands."""
2-

src/codegen/cli/commands/claude/claude_log_utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import re
66
from pathlib import Path
7-
from typing import Dict, Any, Optional
7+
from typing import Any, Optional
88

99

1010
def get_hyphenated_cwd() -> str:
@@ -39,7 +39,7 @@ def get_claude_session_log_path(session_id: str) -> Path:
3939
return log_file
4040

4141

42-
def parse_jsonl_line(line: str) -> Optional[Dict[str, Any]]:
42+
def parse_jsonl_line(line: str) -> Optional[dict[str, Any]]:
4343
"""Parse a single line from a JSONL file.
4444
4545
Args:
@@ -85,13 +85,13 @@ def read_existing_log_lines(log_path: Path) -> int:
8585
return 0
8686

8787
try:
88-
with open(log_path, "r", encoding="utf-8") as f:
88+
with open(log_path, encoding="utf-8") as f:
8989
return sum(1 for _ in f)
9090
except (OSError, UnicodeDecodeError):
9191
return 0
9292

9393

94-
def validate_log_entry(log_entry: Dict[str, Any]) -> bool:
94+
def validate_log_entry(log_entry: dict[str, Any]) -> bool:
9595
"""Validate a log entry before sending to API.
9696
9797
Args:
@@ -112,7 +112,7 @@ def validate_log_entry(log_entry: Dict[str, Any]) -> bool:
112112
return True
113113

114114

115-
def format_log_for_api(log_entry: Dict[str, Any]) -> Dict[str, Any]:
115+
def format_log_for_api(log_entry: dict[str, Any]) -> dict[str, Any]:
116116
"""Format a log entry for sending to the API.
117117
118118
Args:

src/codegen/cli/commands/claude/claude_log_watcher.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
"""Claude Code session log watcher implementation."""
22

3-
import time
43
import threading
5-
from pathlib import Path
6-
from typing import Optional, Callable, Dict, Any
7-
8-
from .quiet_console import console
4+
import time
5+
from typing import Any, Callable, Optional
96

10-
from .claude_log_utils import get_claude_session_log_path, parse_jsonl_line, read_existing_log_lines, validate_log_entry, format_log_for_api
7+
from .claude_log_utils import format_log_for_api, get_claude_session_log_path, parse_jsonl_line, read_existing_log_lines, validate_log_entry
118
from .claude_session_api import send_claude_session_log
9+
from .quiet_console import console
1210

1311

1412
class ClaudeLogWatcher:
1513
"""Watches Claude Code session log files for new entries and sends them to the API."""
1614

17-
def __init__(self, session_id: str, org_id: Optional[int] = None, poll_interval: float = 1.0, on_log_entry: Optional[Callable[[Dict[str, Any]], None]] = None):
15+
def __init__(self, session_id: str, org_id: Optional[int] = None, poll_interval: float = 1.0, on_log_entry: Optional[Callable[[dict[str, Any]], None]] = None):
1816
"""Initialize the log watcher.
1917
2018
Args:
@@ -106,7 +104,7 @@ def _check_for_new_entries(self) -> None:
106104
except Exception as e:
107105
console.print(f"⚠️ Error reading log file: {e}", style="yellow")
108106

109-
def _read_new_lines(self, start_line: int, end_line: int) -> list[Dict[str, Any]]:
107+
def _read_new_lines(self, start_line: int, end_line: int) -> list[dict[str, Any]]:
110108
"""Read new lines from the log file.
111109
112110
Args:
@@ -119,7 +117,7 @@ def _read_new_lines(self, start_line: int, end_line: int) -> list[Dict[str, Any]
119117
entries = []
120118

121119
try:
122-
with open(self.log_path, "r", encoding="utf-8") as f:
120+
with open(self.log_path, encoding="utf-8") as f:
123121
lines = f.readlines()
124122

125123
# Read only the new lines
@@ -135,7 +133,7 @@ def _read_new_lines(self, start_line: int, end_line: int) -> list[Dict[str, Any]
135133

136134
return entries
137135

138-
def _process_log_entry(self, log_entry: Dict[str, Any]) -> None:
136+
def _process_log_entry(self, log_entry: dict[str, Any]) -> None:
139137
"""Process a single log entry.
140138
141139
Args:
@@ -161,7 +159,7 @@ def _process_log_entry(self, log_entry: Dict[str, Any]) -> None:
161159
# Send to API
162160
self._send_log_entry(formatted_entry)
163161

164-
def _send_log_entry(self, log_entry: Dict[str, Any]) -> None:
162+
def _send_log_entry(self, log_entry: dict[str, Any]) -> None:
165163
"""Send a log entry to the API.
166164
167165
Args:
@@ -181,7 +179,7 @@ def _send_log_entry(self, log_entry: Dict[str, Any]) -> None:
181179
self.total_send_failures += 1
182180
console.print(f"⚠️ Failed to send log entry: {e}", style="yellow")
183181

184-
def get_stats(self) -> Dict[str, Any]:
182+
def get_stats(self) -> dict[str, Any]:
185183
"""Get watcher statistics.
186184
187185
Returns:
@@ -204,9 +202,9 @@ class ClaudeLogWatcherManager:
204202
"""Manages multiple log watchers for different sessions."""
205203

206204
def __init__(self):
207-
self.watchers: Dict[str, ClaudeLogWatcher] = {}
205+
self.watchers: dict[str, ClaudeLogWatcher] = {}
208206

209-
def start_watcher(self, session_id: str, org_id: Optional[int] = None, poll_interval: float = 1.0, on_log_entry: Optional[Callable[[Dict[str, Any]], None]] = None) -> bool:
207+
def start_watcher(self, session_id: str, org_id: Optional[int] = None, poll_interval: float = 1.0, on_log_entry: Optional[Callable[[dict[str, Any]], None]] = None) -> bool:
210208
"""Start a log watcher for a session.
211209
212210
Args:
@@ -252,7 +250,7 @@ def get_active_sessions(self) -> list[str]:
252250
"""
253251
return list(self.watchers.keys())
254252

255-
def get_watcher_stats(self, session_id: str) -> Optional[Dict[str, Any]]:
253+
def get_watcher_stats(self, session_id: str) -> Optional[dict[str, Any]]:
256254
"""Get stats for a specific watcher.
257255
258256
Args:
@@ -265,7 +263,7 @@ def get_watcher_stats(self, session_id: str) -> Optional[Dict[str, Any]]:
265263
return self.watchers[session_id].get_stats()
266264
return None
267265

268-
def get_all_stats(self) -> Dict[str, Dict[str, Any]]:
266+
def get_all_stats(self) -> dict[str, dict[str, Any]]:
269267
"""Get stats for all active watchers.
270268
271269
Returns:

src/codegen/cli/commands/claude/claude_session_api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
from typing import Optional
66

77
import requests
8-
from .quiet_console import console
98

109
from codegen.cli.api.endpoints import API_ENDPOINT
1110
from codegen.cli.auth.token_manager import get_current_token
1211
from codegen.cli.utils.org import resolve_org_id
1312

13+
from .quiet_console import console
14+
1415

1516
class ClaudeSessionAPIError(Exception):
1617
"""Exception raised for Claude session API errors."""

src/codegen/cli/commands/claude/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ def signal_handler(signum, frame):
290290
console.print("✅ Claude Code finished successfully", style="green")
291291

292292
except FileNotFoundError:
293-
logger.error(
293+
logger.exception(
294294
"Claude Code executable not found",
295295
extra={"operation": "claude.interactive", "org_id": resolved_org_id, "claude_session_id": session_id, "error_type": "claude_executable_not_found", **_get_session_context()},
296296
)

src/codegen/cli/commands/claude/quiet_console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import io
1010
import os
11+
1112
from rich.console import Console
1213

1314

@@ -30,4 +31,3 @@ def _create_console() -> Console:
3031

3132
# Shared console used across Claude CLI modules
3233
console = _create_console()
33-

src/codegen/cli/commands/config/telemetry.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
"""Telemetry configuration commands."""
22

33
import json
4-
from pathlib import Path
54

65
import typer
76
from rich.console import Console
8-
from rich.panel import Panel
9-
from rich.syntax import Syntax
107
from rich.table import Table
118

129
from codegen.cli.telemetry import update_telemetry_consent

src/codegen/cli/commands/org/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
from .main import org
44

5-
__all__ = ["org"]
5+
__all__ = ["org"]

0 commit comments

Comments
 (0)