From improve-logging
Audit and improve logging quality across a codebase. Use when the user asks to "improve logging", "fix log levels", "add logging", "review our logs", "make logging consistent", "we have bad logging", or anything about log messages being unclear, missing, or at the wrong severity. Produces a prioritized list of recommendations — does not edit files directly.
npx claudepluginhub dan323/easier-life-skills --plugin improve-loggingThis skill uses the workspace's default tool permissions.
Audit a codebase's logging and produce a prioritized list of recommendations covering three areas: missing log statements, incorrect severity levels, and poor message quality. Also enforces (or proposes) a consistent logging pattern across the whole application.
Applies Acme Corporation brand guidelines including colors, fonts, layouts, and messaging to generated PowerPoint, Excel, and PDF documents.
Builds DCF models with sensitivity analysis, Monte Carlo simulations, and scenario planning for investment valuation and risk assessment.
Calculates profitability (ROE, margins), liquidity (current ratio), leverage, efficiency, and valuation (P/E, EV/EBITDA) ratios from financial statements in CSV, JSON, text, or Excel for investment analysis.
Audit a codebase's logging and produce a prioritized list of recommendations covering three areas: missing log statements, incorrect severity levels, and poor message quality. Also enforces (or proposes) a consistent logging pattern across the whole application.
This skill is read-only. It produces a recommendation report. It does not edit any file.
# Identify languages
find . -maxdepth 4 -not -path "*/.git/*" -not -path "*/node_modules/*" \
-not -path "*/vendor/*" -not -path "*/.venv/*" \
\( -name "*.py" -o -name "*.java" -o -name "*.kt" -o -name "*.ts" \
-o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.go" \
-o -name "*.rs" -o -name "*.cs" -o -name "*.rb" \) \
| sed 's/.*\.//' | sort | uniq -c | sort -rn | head -10
Detect the logging framework in use per language:
| Language | Frameworks to detect |
|---|---|
| Python | import logging, from loguru, import structlog |
| Java/Kotlin | import org.slf4j, import org.apache.logging, import io.github.oshai |
| TypeScript/JS | import winston, import pino, console.log/warn/error |
| Go | import "log", "go.uber.org/zap", "github.com/sirupsen/logrus" |
| C# | ILogger, Microsoft.Extensions.Logging, Serilog, NLog |
| Ruby | Rails.logger, Logger.new |
# Python
grep -rn "import logging\|from loguru\|import structlog" --include="*.py" . | head -5
# Java/Kotlin
grep -rn "import org.slf4j\|import org.apache.logging\|LoggerFactory\|KotlinLogging" \
--include="*.java" --include="*.kt" . | head -5
# TypeScript/JS
grep -rn "require.*winston\|require.*pino\|import.*winston\|import.*pino\|console\.\(log\|warn\|error\|info\|debug\)" \
--include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" . | head -5
# Go
grep -rn '"log"\|"go.uber.org/zap"\|"github.com/sirupsen/logrus"\|"golang.org/x/exp/slog"' \
--include="*.go" . | head -5
Sample up to 20 existing log call sites to understand the current pattern (or absence of one):
# Python example — find log calls
grep -rn "logger\.\|logging\." --include="*.py" . | head -20
# Java/Kotlin example
grep -rn "log\.\(info\|debug\|warn\|error\|trace\)" --include="*.java" --include="*.kt" . | head -20
# Go example
grep -rn "log\.\|logger\.\|zap\.\|logrus\." --include="*.go" . | head -20
Read 3–5 representative files where logging is present to understand:
log.Info("done", "user_id", id))? Which fields appear consistently?Every log call must include at minimum:
| Field | Purpose | When required |
|---|---|---|
| Event name | What happened (the message) | Always |
request_id / trace_id | Correlate logs across a request | Any code that handles an incoming request (HTTP, gRPC, queue consumer) |
user_id | Who triggered the action | Any user-facing operation where a user ID is in scope |
error / err | The error value or message | Any log at WARN or ERROR level |
If the codebase already uses these fields consistently, document them as required. If not, include them in the proposed pattern. Flag any log call that is in request-scoped code but omits request_id / trace_id as an inconsistency (Phase 3d).
Recommended patterns by framework:
Python (structlog or logging):
log = structlog.get_logger(__name__)
log.info("order.placed", order_id=order_id, user_id=user_id)
# Message: noun.verb snake_case, context as keyword args
Go (zap or slog):
logger.Info("order placed", zap.String("order_id", orderID), zap.String("user_id", userID))
// Message: lowercase prose, context as typed fields
Java/Kotlin (SLF4J):
log.info("Order placed: orderId={}, userId={}", orderId, userId);
// Message: sentence case prose, context via SLF4J placeholders
TypeScript/JS (pino or winston):
logger.info({ orderId, userId }, 'Order placed')
// pino style: context object first, message second
Look for code paths that almost certainly should be logged but aren't. Focus on high-value locations:
Error handlers with no log:
# Python
grep -rn "except " --include="*.py" -A 3 . | grep -v "log\|logger\|print" | head -20
# Java
grep -rn "catch\s*(" --include="*.java" -A 3 . | grep -v "log\.\|LOG\.\|logger\." | head -20
# Go
grep -rn "if err != nil" --include="*.go" -A 2 . | grep -v "log\.\|logger\." | head -20
# TypeScript
grep -rn "catch\s*(" --include="*.ts" --include="*.js" -A 3 . | grep -v "console\.\|logger\.\|log\." | head -20
Important operations with no surrounding log — use these grep patterns to find high-value functions, then read them to check whether they log:
# Functions whose names signal state changes or side effects
grep -rn "def \(create\|update\|delete\|remove\|send\|publish\|process\|handle\|execute\|run\|dispatch\)_" \
--include="*.py" .
grep -rn "func \(create\|update\|delete\|remove\|send\|publish\|process\|handle\|execute\|run\|dispatch\)[A-Z]" \
--include="*.go" .
grep -rn "^\s*\(public\|private\|protected\).*\(create\|update\|delete\|send\|process\|handle\)[A-Z]" \
--include="*.java" --include="*.kt" .
grep -rn "^\(export \)\?\(async \)\?function \(create\|update\|delete\|send\|process\|handle\)" \
--include="*.ts" --include="*.js" .
Also check these locations regardless of name:
handlers/, controllers/, routes/, views/)jobs/, workers/, tasks/, cron/)init(), signal handlers)Flag an operation as missing a log if:
For each log call found, evaluate whether the level matches the situation. Apply these rules:
| Level | When to use | Common mistakes |
|---|---|---|
DEBUG | Implementation details useful during development; disabled in production | Using DEBUG for events that operators need to see in prod |
INFO | Normal, expected application flow; key business events | Logging every row in a loop as INFO; using INFO for recoverable errors |
WARN | Something unexpected happened but the application recovered; a condition that may cause problems later | Using WARN for actual errors; using WARN for routine things |
ERROR | An operation failed and requires attention; may affect a user or data | Swallowing errors silently; logging errors as WARN |
FATAL / CRITICAL | Application cannot continue; imminent shutdown | Overusing FATAL for recoverable errors |
Exception handling rules — apply these precisely when reading error-handling paths:
| Situation | Correct level | Rationale |
|---|---|---|
| Exception caught and re-raised | ERROR | The operation failed; the caller sees an exception. Log here so there is at least one record even if callers don't. |
| Exception caught and handled (request still succeeds) | WARN | Something unexpected happened but was recovered from. |
| Exception caught and swallowed (no re-raise, no response change) | Flag as missing log | Silent swallowing hides failures entirely. Always log before swallowing. |
| Expected, routine condition (e.g. cache miss, 404 lookup) | DEBUG or no log | Not an error; high-volume events at WARN/ERROR pollute alerting. |
HTTP status code → log level mapping — when code sets or returns an HTTP status, the log level should follow:
| Status range | Log level | Rationale |
|---|---|---|
| 2xx | INFO (or no log if framework logs requests) | Success — normal flow |
| 3xx | DEBUG | Redirect — expected, low value |
| 4xx (client error) | WARN | Client made a bad request; server is fine |
| 5xx (server error) | ERROR | Server failed; needs attention |
# HTTP responses logged at wrong level (Python/Flask/FastAPI)
grep -rn "status_code\s*=\s*[45][0-9][0-9]\|return.*[45][0-9][0-9]" --include="*.py" -A 3 . | \
grep "logger\.\(debug\|info\|warning\)"
# 5xx logged at warn instead of error (JS/TS)
grep -rn "res\.status(5[0-9][0-9])" --include="*.ts" --include="*.js" -A 5 . | \
grep "console\.warn\|logger\.warn"
# 4xx logged at error (over-alerting)
grep -rn "res\.status(4[0-9][0-9])" --include="*.ts" --include="*.js" -A 5 . | \
grep "console\.error\|logger\.error"
Also scan for:
# Errors logged at INFO or WARN (Python)
grep -rn "logger\.info\|logging\.info\|logger\.warning" --include="*.py" . | grep -i "error\|fail\|exception\|crash"
# Exceptions caught and logged at DEBUG
grep -rn "\.debug(" --include="*.java" --include="*.kt" . | grep -i "exception\|error\|fail"
# console.log used for errors in JS/TS
grep -rn "console\.log" --include="*.ts" --include="*.js" . | grep -i "error\|fail\|exception"
Read through error-handling paths in representative files — grep catches obvious mismatches, but reading reveals the subtler ones (e.g. a re-raise with no preceding log).
Scan for log calls that should be deleted entirely rather than improved. Flag all matches — these are the highest-priority recommendations because sensitive data in logs is a security incident waiting to happen.
Sensitive data:
# Common sensitive field names in log arguments
grep -rn "password\|passwd\|secret\|api_key\|apikey\|token\|credential\|ssn\|credit_card\|cvv\|private_key" \
--include="*.py" --include="*.java" --include="*.ts" --include="*.js" --include="*.go" --include="*.rb" . \
| grep -i "log\|logger\|print\|console" | head -30
Flag any log call that passes a sensitive field as a parameter or includes it in the message string. Include a clear explanation of the security risk (e.g. "API keys in logs are stored in plain text and accessible to anyone with log access, including log aggregation services").
Debug artifacts: print() in Python, console.log() / console.debug() in JS/TS, fmt.Println() in Go, System.out.println() in Java — these are almost never intentional in production code. Flag all of them.
Log spam: log calls inside tight loops (for/while) that fire on every iteration. A single INFO log per item in a large batch creates millions of log entries. Suggest replacing with a summary log after the loop (e.g. "Processed N items in Xms").
Redundant logs: multiple log calls at the same level for the same event within a few lines, where one clearly subsumes the other.
A good log message answers: what happened, in what context, and why does it matter?
Flag messages that:
"Error", "Something went wrong", "Failed", "null", "done", "ok""User not found" when the user ID is in scopelog.error("NullPointerException", e) adds nothing# Vague messages (Python)
grep -rn "logger\.\w\+(['\"].\{1,20\}['\"])" --include="*.py" . | \
grep -i '"error"\|"fail"\|"exception"\|"done"\|"ok"\|"success"\|"null"'
# Very short messages (Java)
grep -rn 'log\.\w\+("\w\{1,10\}")' --include="*.java" . | head -20
For files with message quality issues, read the surrounding code to suggest a better message that includes the relevant context variables.
Compare each log call against the pattern established in Phase 2:
request_id, or a WARN/ERROR log that omits error/errGroup all findings into a single report. Order: Remove → Missing logs → Wrong level → Poor messages → Inconsistencies.
Put Remove first because sensitive data in logs is an immediate security risk — it must be addressed before any other improvement.
Within each section, order by file. For each finding include the file path, line number, the current code (if any), and a concrete suggested improvement.
Use this format:
## Logging Improvement Report
### Established Pattern
[State the detected or proposed pattern here. If proposed, prefix with "⚡ No consistent pattern found — proposing:"]
Example:
logger.info("order.placed", order_id=order_id, amount=amount)
# noun.verb message, structured keyword args, module-level logger
---
### 1. Remove (N findings)
**src/auth/login.py:14** — sensitive field in log
Current: `logger.info("login success", extra={"user_id": user.id, "password": password})`
Remove: the `password` field from the extra dict
Why: passwords in logs are stored in plain text and accessible to everyone with log access, including log aggregation services
**src/debug/util.py:8** — debug artifact
Current: `print(f"Login attempt for {username}")`
Action: Replace with `logger.info("auth.login_attempt", username=username)` or remove
Why: print() bypasses the logging framework and cannot be filtered or silenced in production
---
### 2. Missing Log Statements (N findings)
**src/payments/processor.py:88** — error path with no log
Context: `except StripeError as e:`
Add: `logger.error("payment.charge_failed", order_id=order_id, error=str(e))`
Why: stripe failures are silent — operators have no visibility when charges fail
**src/jobs/email_sender.py:34** — external call with no failure log
Context: `response = smtp.send(msg)`
Add (on failure): `logger.error("email.send_failed", recipient=msg.to, error=str(e))`
---
### 3. Incorrect Log Levels (N findings)
**src/auth/login.py:52** — ERROR logged as WARNING
Current: `logger.warning("Login failed for user %s", user_id)`
Suggest: `logger.error("auth.login_failed", user_id=user_id)`
Why: a failed login attempt is an error worth alerting on, not just a warning
**src/cache/client.py:19** — DEBUG in a tight loop producing log spam
Current: `logger.debug("Cache miss for key %s", key)` (called on every request)
Suggest: Remove or gate behind a feature flag; emit a summary metric instead
---
### 4. Poor Message Quality (N findings)
**src/api/users.py:101**
Current: `logger.error("Error")`
Suggest: `logger.error("user.fetch_failed", user_id=user_id, error=str(e))`
Why: "Error" is unactionable — which user, which operation, what went wrong?
**src/db/connection.py:14**
Current: `logger.info("Connected")`
Suggest: `logger.info("db.connected", host=host, port=port, database=db_name)`
Why: context needed for debugging connection issues across environments
---
### 5. Inconsistencies (N findings)
**src/orders/service.py:67** — unstructured message where structured is the norm
Current: `logger.info(f"Order {order_id} placed by {user_id}")`
Suggest: `logger.info("order.placed", order_id=order_id, user_id=user_id)`
---
### Summary
| Category | Count |
|-----------------------|-------|
| Remove | 2 |
| Missing log statements| 4 |
| Incorrect log levels | 3 |
| Poor message quality | 6 |
| Inconsistencies | 5 |
| **Total** |**20** |
### Recommended next steps
- Address "Remove" immediately — sensitive data in logs is a security incident waiting to happen.
- Address "Missing log statements" next — silent error paths are the highest operational risk.
- Apply the established pattern to all new log calls going forward.
- Consider adding a linting rule to enforce log level discipline in CI.
If no issues are found in a section, omit that section entirely rather than writing "No issues found."
If the codebase has fewer than 5 log calls total, lead with the pattern proposal and focus the report on where to add logging rather than what to fix.