From example-skills
Implement structured logging, error hierarchies, and observability patterns for production systems. Covers structured JSON logging, error classification, correlation IDs, and alerting integration. Triggers on logging architecture, error handling strategy, or observability requests.
npx claudepluginhub organvm-iv-taxis/a-i--skills --plugin document-skillsThis skill uses the workspace's default tool permissions.
Build systems that are debuggable in production through structured logging and intentional error handling.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Designs, implements, and audits WCAG 2.2 AA accessible UIs for Web (ARIA/HTML5), iOS (SwiftUI traits), and Android (Compose semantics). Audits code for compliance gaps.
Build systems that are debuggable in production through structured logging and intentional error handling.
class AppError(Exception):
"""Base error for the application."""
def __init__(self, message: str, code: str = "INTERNAL_ERROR", status: int = 500):
self.message = message
self.code = code
self.status = status
super().__init__(message)
class NotFoundError(AppError):
def __init__(self, entity: str, id: str):
super().__init__(f"{entity} '{id}' not found", code="NOT_FOUND", status=404)
class ValidationError(AppError):
def __init__(self, field: str, reason: str):
super().__init__(f"Invalid {field}: {reason}", code="VALIDATION_ERROR", status=400)
class ExternalServiceError(AppError):
def __init__(self, service: str, detail: str):
super().__init__(f"{service} error: {detail}", code="EXTERNAL_ERROR", status=502)
| Category | Retry? | Log Level | Alert? |
|---|---|---|---|
| Validation error | No | WARNING | No |
| Not found | No | INFO | No |
| Auth failure | No | WARNING | Rate-based |
| Transient external | Yes | WARNING | After retries |
| Persistent external | No | ERROR | Yes |
| Internal bug | No | CRITICAL | Immediate |
import structlog
import logging
def configure_logging(log_level: str = "INFO", json_output: bool = True):
processors = [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
]
if json_output:
processors.append(structlog.processors.JSONRenderer())
else:
processors.append(structlog.dev.ConsoleRenderer())
structlog.configure(
processors=processors,
wrapper_class=structlog.make_filtering_bound_logger(
getattr(logging, log_level.upper())
),
context_class=dict,
logger_factory=structlog.PrintLoggerFactory(),
)
log = structlog.get_logger()
import structlog
from contextvars import ContextVar
request_id_var: ContextVar[str] = ContextVar("request_id", default="")
# Bind context per request
structlog.contextvars.bind_contextvars(
request_id=request_id,
user_id=user.id,
organ="IV",
)
# All subsequent log calls include this context
log.info("processing_request", path="/api/skills", method="GET")
# Output: {"event": "processing_request", "request_id": "abc-123", "user_id": "u42", "path": "/api/skills", ...}
| Level | Purpose | Example |
|---|---|---|
| DEBUG | Detailed flow tracing | Query parameters, cache hits |
| INFO | Business events | User created, skill activated |
| WARNING | Recoverable issues | Retry attempt, deprecated usage |
| ERROR | Failures needing attention | External service down, data inconsistency |
| CRITICAL | System-level failures | Database unreachable, out of memory |
import uuid
from starlette.middleware.base import BaseHTTPMiddleware
class CorrelationMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
structlog.contextvars.bind_contextvars(request_id=request_id)
log.info("request_started",
method=request.method,
path=request.url.path,
)
try:
response = await call_next(request)
log.info("request_completed",
status=response.status_code,
)
response.headers["X-Request-ID"] = request_id
return response
except Exception as e:
log.error("request_failed", error=str(e), exc_info=True)
raise
finally:
structlog.contextvars.unbind_contextvars("request_id")
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(AppError)
async def app_error_handler(request: Request, exc: AppError):
log.warning("app_error", code=exc.code, message=exc.message)
return JSONResponse(
status_code=exc.status,
content={"error": {"code": exc.code, "message": exc.message}},
)
@app.exception_handler(Exception)
async def unhandled_error_handler(request: Request, exc: Exception):
log.error("unhandled_error", error=str(exc), exc_info=True)
return JSONResponse(
status_code=500,
content={"error": {"code": "INTERNAL_ERROR", "message": "An unexpected error occurred"}},
)
async def process_skill(skill_id: str):
log.info("skill_processing_started", skill_id=skill_id)
try:
result = await validate_skill(skill_id)
log.info("skill_processing_completed", skill_id=skill_id, status=result.status)
return result
except ValidationError as e:
log.warning("skill_validation_failed", skill_id=skill_id, error=e.message)
raise
except Exception as e:
log.error("skill_processing_failed", skill_id=skill_id, error=str(e), exc_info=True)
raise
SENSITIVE_KEYS = {"password", "token", "secret", "api_key", "authorization"}
def sanitize_log_data(data: dict) -> dict:
return {
k: "***REDACTED***" if k.lower() in SENSITIVE_KEYS else v
for k, v in data.items()
}
import time
from contextlib import contextmanager
@contextmanager
def log_duration(operation: str, **extra):
start = time.perf_counter()
try:
yield
finally:
duration_ms = (time.perf_counter() - start) * 1000
log.info(f"{operation}_duration", duration_ms=round(duration_ms, 2), **extra)
{
"timestamp": "2026-03-20T10:58:00Z",
"level": "info",
"event": "request_completed",
"request_id": "abc-123",
"method": "GET",
"path": "/api/skills",
"status": 200,
"duration_ms": 42.5,
"service": "a-i--skills",
"organ": "IV"
}
Always include: timestamp, level, event, service, request_id. Optionally: user_id, organ, duration_ms, error.
log.info("x", user=id) not log.info(f"user {id}")except: pass