class RawRequestLogger
A logging utility class that captures and formats HTTP requests and responses in a human-readable format similar to reMarkable app logs, writing them to a file.
/tf/active/vicechatdev/e-ink-llm/cloudtest/raw_request_logger.py
13 - 63
simple
Purpose
This class provides structured logging for HTTP request/response cycles, particularly useful for debugging API interactions. It formats requests with method, URL, headers, and body content, handling both text and binary data intelligently. Large bodies are truncated with SHA256 hashes for verification. The logger creates a timestamped log file and appends each request with clear separators for easy reading.
Source Code
class RawRequestLogger:
"""Logs HTTP requests in the same format as reMarkable app logs"""
def __init__(self, log_file: str = "raw_requests.log"):
self.log_file = Path(log_file)
self.log_file.parent.mkdir(exist_ok=True)
# Clear log file
with open(self.log_file, 'w') as f:
f.write(f"=== RAW REQUEST LOG - {datetime.now().isoformat()} ===\n\n")
def log_request(self, method: str, url: str, headers: dict, body: bytes = None, response_status: int = None, response_text: str = None):
"""Log a request in raw format"""
with open(self.log_file, 'a') as f:
# Log request line
f.write(f"{method} {url}\n")
# Log headers
for key, value in headers.items():
f.write(f"{key}: {value}\n")
f.write("\n") # Empty line before body
# Log body if present
if body:
if len(body) > 1000:
# For large bodies, show first 500 and last 500 bytes
f.write(f"[BODY: {len(body)} bytes]\n")
f.write(f"First 500 bytes: {body[:500]}\n")
f.write(f"Last 500 bytes: {body[-500:]}\n")
f.write(f"SHA256: {hashlib.sha256(body).hexdigest()}\n")
else:
# For small bodies, show full content
try:
decoded = body.decode('utf-8')
f.write(f"[BODY: {len(body)} bytes - UTF-8]\n")
f.write(decoded)
f.write("\n")
except:
f.write(f"[BODY: {len(body)} bytes - BINARY]\n")
f.write(f"Hex: {body.hex()}\n")
else:
f.write("[NO BODY]\n")
# Log response if available
if response_status is not None:
f.write(f"\nRESPONSE: {response_status}\n")
if response_text:
f.write(f"Response body: {response_text}\n")
f.write("\n" + "="*80 + "\n\n")
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
bases |
- | - |
Parameter Details
log_file: Path to the log file where HTTP requests will be written. Defaults to 'raw_requests.log' in the current directory. The parent directory will be created if it doesn't exist. The file is cleared on instantiation with a timestamp header.
Return Value
Instantiation returns a RawRequestLogger object that maintains a file handle reference and provides the log_request method. The log_request method returns None as it performs side effects (file writing) only.
Class Interface
Methods
__init__(self, log_file: str = 'raw_requests.log')
Purpose: Initializes the logger, creates the log file directory if needed, and clears/initializes the log file with a timestamp header
Parameters:
log_file: Path to the log file (string). Defaults to 'raw_requests.log'. Parent directories are created automatically.
Returns: None (constructor)
log_request(self, method: str, url: str, headers: dict, body: bytes = None, response_status: int = None, response_text: str = None)
Purpose: Logs an HTTP request and optionally its response to the log file in a formatted, human-readable structure
Parameters:
method: HTTP method as a string (e.g., 'GET', 'POST', 'PUT', 'DELETE')url: Full URL of the request as a stringheaders: Dictionary of HTTP headers with string keys and valuesbody: Optional request body as bytes. If larger than 1000 bytes, only first/last 500 bytes are logged with SHA256 hash. If smaller, full content is logged (decoded as UTF-8 if possible, otherwise as hex)response_status: Optional HTTP response status code as an integer (e.g., 200, 404, 500)response_text: Optional response body as a string
Returns: None (performs file I/O side effect)
Attributes
| Name | Type | Description | Scope |
|---|---|---|---|
log_file |
pathlib.Path | Path object representing the log file location where all HTTP requests are written | instance |
Dependencies
pathlibdatetimehashlib
Required Imports
from pathlib import Path
from datetime import datetime
import hashlib
Usage Example
# Basic usage
logger = RawRequestLogger('api_requests.log')
# Log a simple GET request
logger.log_request(
method='GET',
url='https://api.example.com/users',
headers={'Authorization': 'Bearer token123', 'Content-Type': 'application/json'}
)
# Log a POST request with body and response
request_body = json.dumps({'name': 'John', 'email': 'john@example.com'}).encode('utf-8')
logger.log_request(
method='POST',
url='https://api.example.com/users',
headers={'Content-Type': 'application/json'},
body=request_body,
response_status=201,
response_text='{"id": 123, "name": "John"}'
)
# Log a request with binary data
binary_data = b'\x89PNG\r\n\x1a\n' + b'\x00' * 2000
logger.log_request(
method='PUT',
url='https://api.example.com/upload',
headers={'Content-Type': 'image/png'},
body=binary_data,
response_status=200
)
Best Practices
- Instantiate once per logging session to avoid repeatedly clearing the log file
- Be cautious when logging sensitive data (tokens, passwords) in headers or body - consider sanitizing before logging
- Monitor log file size when logging large request bodies, as files can grow quickly
- The log file is cleared on instantiation, so create a new instance with a different filename if you need to preserve previous logs
- For production use, consider implementing log rotation or size limits
- The class is not thread-safe; use separate instances or add locking if logging from multiple threads
- Binary data larger than 1000 bytes is automatically truncated with SHA256 hash for verification
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function logged_request 79.9% similar
-
function logged_request_v2 72.6% similar
-
function logged_request_v1 67.7% similar
-
class InvoiceExtractionLogger 51.1% similar
-
class RemarkableAuth 50.5% similar