Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed โ fix this file immediately, don't defer. Only update for real, reproducible issues.
Confirm successful installation by checking the skill directory location:
.cursor/skills/python-logging-best-practices
Restart Cursor to activate python-logging-best-practices. Access via /python-logging-best-practices in your agent's command palette.
โ
Security Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed โ fix this file immediately, don't defer. Only update for real, reproducible issues.
When to Use This Skill
Use this skill when:
Setting up Python logging for any service or script
Configuring structured JSONL logging for analysis
Implementing log rotation
Choosing between lightweight (zero-dep) and full-featured logging
Adding logging to containerized, systemd, or local applications
Overview
Unified reference for Python logging patterns optimized for machine readability (Claude Code analysis) and operational reliability. Starts with the lightest viable approach and scales up only when needed.
Decision Heuristic: Start Light, Scale Up
Is it < 5 services on a single machine, < 1 event/sec?
YES โ Lightweight Pattern (print + JSONL telemetry)
NO โ Is it containerized / serverless?
YES โ stdout JSON (any library), no file rotation
NO โ Is OTel tracing required?
YES โ structlog + OTel
NO โ loguru (CLI tools) or stdlib RotatingFileHandler
Approach
Use Case
Pros
Cons
Lightweight
Small systemd services, self-hosted, single operator
This maps to the 12-Factor App's "treat logs as event streams" principle. journald handles ops (rotation, filtering, metadata), while the JSONL file serves domain telemetry for post-mortem analysis.
Architecture: Three-Concern Separation
Concern
Mechanism
Purpose
Lifecycle
Ops logging
print() โ journald
Human debugging, journalctl -u service -f
Managed by journald (auto-rotated)
Telemetry
JSONL file (telemetry.jsonl)
Structured audit trail, AI/LLM analysis
Append-only, rotated by size
State recovery
WAL file (optional)
Crash recovery for irreversible operations
Ephemeral, deleted on success
Complete Lightweight Example
"""Append-only JSONL telemetry logger with size-based rotation.
Zero external dependencies. Works with systemd journald for ops logging
and a separate JSONL file for structured machine-readable telemetry.
"""import json
from datetime import datetime, timezone
from pathlib import Path
TELEMETRY_PATH = Path(__file__).parent /"telemetry.jsonl"MAX_SIZE =10*1024*1024# 10 MBBACKUP_COUNT =3# Keep 3 rotated backups (~30MB total)deflog_event(event_type:str, data:dict)->None:"""Append a structured JSON line to telemetry.jsonl.""" entry ={"ts": datetime.now(timezone.utc).isoformat(),"type": event_type,**data,} line = json.dumps(entry, separators=(",",":"))+"\n"try:try:if TELEMETRY_PATH.stat().st_size > MAX_SIZE: _rotate()except FileNotFoundError:passwithopen(TELEMETRY_PATH,"a")as f: f.write(line)except OSError as e:# Fallback to stderr (captured by journald)print(f"[telemetry] write failed: {e}",file=__import__("sys").stderr, flush=True)def_rotate()->None:"""Rotate telemetry files: .jsonl โ .jsonl.1 โ .jsonl.2 โ .jsonl.3"""for i inrange(BACKUP_COUNT,1,-1): src = TELEMETRY_PATH.with_suffix(f".jsonl.{i -1}") dst = TELEMETRY_PATH.with_suffix(f".jsonl.{i}")if src.exists(): dst.unlink(missing_ok=True) src.rename(dst) backup = TELEMETRY_PATH.with_suffix(".jsonl.1") backup.unlink(missing_ok=True) TELEMETRY_PATH.rename(backup)# === Ops logging (goes to journald via stdout) ===deflog(msg:str)->None:"""Human-readable operational log line. Captured by journald.""" ts = datetime.now(timezone.utc).strftime("%H:%M:%S")print(f"[{ts}] {msg}", flush=True)
Usage:
# Operational (human reads via journalctl -u myservice -f)log("Refreshing token for account X")log("Switch: account A โ account B (reason: 5h breach)")# Telemetry (machine reads via jq/DuckDB/Claude Code)log_event("token_refresh",{"account":"X","expires_in_h":8.0,"token_fp":"abc12345"})log_event("account_switch",{"from":"A","to":"B","reason":"5h_breach"})
Never pass secrets through the logging pipeline. Log only a non-reversible fragment:
def_token_fingerprint(token:str)->str:"""Extract uniquely identifiable chars from a token's mid-section.
The prefix (sk-ant-oat01-) and suffix (...AA) are common across tokens.
Chars 14-22 (after the prefix) are the most unique per-token.
Middle-slice avoids leaking type-prefix metadata that prefix-based
approaches expose.
"""iflen(token)>25:return token[14:22]return token[:8]if token else""# Usage: log the fingerprint, never the tokenlog_event("token_refresh",{"account": name,"token_fp": _token_fingerprint(token)})
Why this is superior to regex redaction filters:
Approach
Security
Maintenance
Failure mode
Token fingerprinting (log only a slice)
Secret never enters logging pipeline
Zero โ works with any token format
Cannot fail โ nothing to redact
Regex redaction filter
Secret passes through, filtered on output
Must update regexes for new token formats
Silent miss = secret in logs
This aligns with OWASP Logging Cheat Sheet: "Ensure that no sensitive data is included in log entries." Major platforms (AWS, Stripe, GitHub) use separate non-secret identifiers or partial token display โ never full tokens with regex scrubbing.
Regex filters remain useful as a defense-in-depth backstop, not a primary control.
Health Endpoints as Observability
For small deployments, rich JSON health endpoints replace log aggregation:
@app.get("/api/status")defstatus():
Implementation Guide
Prerequisites
โบClaude Desktop or compatible AI client with skill support
โบClear understanding of task or problem to solve
โบWillingness to iterate and refine outputs
Time Estimate
15-45 minutes depending on use case complexity
Steps
1Install skill using provided installation command
2Test with simple use case relevant to your work
3Evaluate output quality and relevance
4Iterate on prompts to improve results
5Integrate into regular workflow if valuable
Common Pitfalls
โ Expecting perfect results without iteration
โ Not providing enough context in prompts
โ Using skill for tasks outside its intended scope
โ Accepting outputs without review and validation
Best Practices
โ Do
+Start with clear, specific prompts
+Provide relevant context and constraints
+Review and refine all outputs before using
+Iterate to improve output quality
+Document successful prompt patterns
โ Don't
โDon't use without understanding skill limitations
โDon't skip validation of outputs
โDon't share sensitive information in prompts
โDon't expect skill to replace human judgment
๐ก Pro Tips
โ Be specific about desired format and style
โ Ask for multiple options to choose from
โ Request explanations to understand reasoning
โ Combine AI efficiency with human expertise
When to Use This
โ Use when
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
โ Avoid when
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
Learning Path
1Familiarize yourself with skill capabilities and limitations
2Start with low-risk, non-critical tasks
3Progress to more complex and valuable use cases
4Build expertise through regular use and experimentation