用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tools-only/X-Skills --skill setup-logging命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | setup-logging |
| description | Set up API request logging |
| shortcut | logs |
Implement production-grade structured logging with correlation IDs, request/response capture, PII redaction, and integration with log aggregation platforms.
Use /setup-logging when you need to:
DON'T use this when:
This command implements Structured JSON logging with Winston/Bunyan as the primary approach because:
Alternative considered: Plain text logging
Alternative considered: Binary logging protocols (gRPC, protobuf)
Alternative considered: Managed logging services (Datadog, Loggly)
Before running this command:
Set up Winston (Node.js) or structlog (Python) with JSON formatting and appropriate transports.
Generate unique request IDs and propagate through entire request lifecycle and downstream services.
Capture HTTP method, path, headers, body, status code, and response time with configurable verbosity.
Identify and mask sensitive data (passwords, tokens, credit cards, SSNs) before logging.
Set up log rotation, compression, and shipping to centralized log aggregation platform.
The command generates:
logger.js or logger.py - Core logging configuration and utilitieslogging-middleware.js - Express/FastAPI middleware for request loggingpii-redactor.js - PII detection and masking utilitieslog-shipping-config.json - Fluentd/Filebeat/Logstash configurationlogger.test.js - Test suite for logging functionalityREADME.md - Integration guide and best practices// logger.js - Winston configuration with correlation IDs
const winston = require('winston');
const { v4: uuidv4 } = require('uuid');
const cls = require('cls-hooked');
// Create namespace for correlation ID context
const namespace = cls.createNamespace('request-context');
// Custom format for correlation ID
const correlationIdFormat = winston.format((info) => {
const correlationId = namespace.get('correlationId');
if (correlationId) {
info.correlationId = correlationId;
}
return info;
});
// Custom format for sanitizing sensitive data
const sanitizeFormat = winston.format((info) => {
if (info.meta && typeof info.meta === 'object') {
info.meta = sanitizeSensitiveData(info.meta);
}
if (info.req && info.req.headers) {
info.req.headers = sanitizeHeaders(info.req.headers);
}
info;
});
logger = winston.({
: process.. || ,
: winston..(
winston..({ : }),
(),
(),
winston..({ : }),
winston..()
),
: {
: process.. || ,
: process.. || ,
: process.. ||
},
: [
winston..({
: winston..(
winston..(),
winston..( {
corrId = correlationId ? : ;
;
})
)
}),
winston..({
: ,
: ,
: ,
:
}),
winston..({
: ,
: ,
:
})
],
:
});
() {
sensitiveKeys = [, , , , , , , ];
sanitized = { ...obj };
( key .(sanitized)) {
lowerKey = key.();
(sensitiveKeys.( lowerKey.(sensitive))) {
sanitized[key] = ;
} ( sanitized[key] === && sanitized[key] !== ) {
sanitized[key] = (sanitized[key]);
}
}
sanitized;
}
() {
sanitized = { ...headers };
sensitiveHeaders = [, , , ];
( header sensitiveHeaders) {
(sanitized[header]) {
sanitized[header] = ;
}
}
sanitized;
}
() {
namespace.( {
correlationId = req.[] || ();
namespace.(, correlationId);
res.(, correlationId);
();
});
}
() {
startTime = .();
logger.(, {
: req.,
: req.,
: req.,
: req.,
: req.(),
: req.?.,
: (req) ? (req.) :
});
originalSend = res.;
res. = () {
res. = originalSend;
duration = .() - startTime;
statusCode = res.;
logger.(, {
: req.,
: req.,
statusCode,
duration,
: req.?.,
: data?. || ,
: (req, statusCode) ? (.(data)) :
});
res.(data);
};
();
}
() {
logBodyPaths = [, ];
req. !== && logBodyPaths.( req..(path));
}
() {
statusCode >= || req..();
}
. = {
logger,
correlationIdMiddleware,
requestLoggingMiddleware,
namespace
};
# logger.py - Structlog configuration with PII redaction
import logging
import structlog
import uuid
import re
from contextvars import ContextVar
from typing import Any, Dict
from fastapi import Request, Response
import time
# Context variable for correlation ID
correlation_id_var: ContextVar[str] = ContextVar('correlation_id', default=None)
# PII patterns for redaction
PII_PATTERNS = {
'email': re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'),
'ssn': re.compile(r'\b\d{3}-\d{2}-\d{4}\b'),
'credit_card': re.compile(r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b'),
'phone': re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b'),
'ip_address': re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
}
SENSITIVE_KEYS = ['password', 'token', 'secret', 'api_key', 'authorization', 'credit_card', 'ssn', 'cvv']
def redact_pii(data: Any) -> Any:
"""Recursively redact PII from data structures"""
(data, ):
redacted = {}
key, value data.items():
(sensitive key.lower() sensitive SENSITIVE_KEYS):
redacted[key] =
:
redacted[key] = redact_pii(value)
redacted
(data, ):
[redact_pii(item) item data]
(data, ):
redacted_str = data
pattern_name, pattern PII_PATTERNS.items():
pattern_name == :
redacted_str = pattern.sub( m: , redacted_str)
:
redacted_str = pattern.sub(, redacted_str)
redacted_str
data
():
correlation_id = correlation_id_var.get()
correlation_id:
event_dict[] = correlation_id
event_dict
():
os
event_dict[] = os.getenv(, )
event_dict[] = os.getenv(, )
event_dict[] = os.getenv(, )
event_dict
structlog.configure(
processors=[
structlog.contextvars.merge_contextvars,
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
add_correlation_id,
add_service_context,
structlog.processors.TimeStamper(fmt=),
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=,
)
logging.basicConfig(
=,
level=logging.INFO,
handlers=[
logging.StreamHandler(),
logging.FileHandler()
]
)
logger = structlog.get_logger()
:
():
.app = app
.logger = structlog.get_logger()
():
scope[] != :
.app(scope, receive, send)
correlation_id = (uuid.uuid4())
correlation_id_var.(correlation_id)
request = Request(scope, receive)
start_time = time.time()
body = ._get_body(request)
.logger.info(
,
method=request.method,
path=request.url.path,
query_params=(request.query_params),
client_ip=request.client.host request.client ,
user_agent=request.headers.get(),
body=redact_pii(body) ._should_log_body(request)
)
status_code =
response_body =
():
status_code, response_body
message[] == :
status_code = message[]
headers = (message.get(, []))
headers.append((, correlation_id.encode()))
message[] = headers
message[] == :
response_body += message.get(, )
send(message)
:
.app(scope, receive, send_wrapper)
:
duration = time.time() - start_time
.logger.info(
,
method=request.method,
path=request.url.path,
status_code=status_code,
duration_ms=(duration * , ),
response_size=(response_body),
response=redact_pii(response_body.decode()) ._should_log_response(status_code)
)
() -> :
:
request.json()
:
{}
() -> :
sensitive_paths = [, ]
(request.url.path.startswith(path) path sensitive_paths)
() -> :
status_code >=
fastapi FastAPI
app = FastAPI()
app.add_middleware(RequestLoggingMiddleware)
():
logger.info(, user_id=user_id)
:
user = {: user_id, : , : }
logger.info(, user_id=user_id)
redact_pii(user)
Exception e:
logger.error(, user_id=user_id, error=(e))
# filebeat.yml - Filebeat configuration for log shipping
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/api/combined.log
json.keys_under_root: true
json.add_error_key: true
fields:
service: api-gateway
datacenter: us-east-1
fields_under_root: true
- type: log
enabled: true
paths:
- /var/log/api/error.log
json.keys_under_root: true
json.add_error_key: true
fields:
service: api-gateway
datacenter: us-east-1
log_level: error
fields_under_root: true
# Processors for enrichment
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- add_docker_metadata:
[]
# docker-compose.yml - Complete ELK stack for log aggregation
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.10.0
container_name: elasticsearch
environment:
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.security.enabled=false
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
networks:
- logging
logstash:
image: docker.elastic.co/logstash/logstash:8.10.0
container_name: logstash
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5044:5044"
networks:
- logging
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:8.10.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
| Error | Cause | Solution |
|---|---|---|
| "Log file not writable" | Permission issues | Ensure log directory has correct permissions, run with appropriate user |
| "Disk space full" | Logs not rotated | Implement log rotation, compress old logs, ship to remote storage |
| "PII detected in logs" | Incomplete redaction rules | Review and update PII patterns, audit existing logs |
| "High logging latency" | Synchronous file writes | Use async logging, buffer writes, or log to separate thread |
| "Lost correlation IDs" | Missing middleware or context propagation | Ensure middleware order is correct, propagate context to async operations |
Log Levels
debug: Verbose output for development (not in production)info: General operational messages (default)warn: Unexpected but handled conditionserror: Errors requiring attentionfatal: Critical errors causing service failureLog Rotation
PII Redaction Strategies
DO:
DON'T:
TIPS:
Logging Overhead
Optimization Strategies
Volume Management
GDPR Requirements
HIPAA Requirements
SOC 2 Requirements
Logs Not Appearing
# Check log file permissions
ls -la /var/log/api/
# Verify logging middleware is registered
# Check application startup logs
# Test logger directly
curl -X POST http://localhost:3000/api/test -d '{"test": "data"}'
tail -f /var/log/api/combined.log
Missing Correlation IDs
# Verify correlation ID middleware is first
# Check middleware order in application
# Test correlation ID propagation
curl -H "X-Correlation-Id: test-123" http://localhost:3000/api/test
grep "test-123" /var/log/api/combined.log
PII Leaking into Logs
# Search for common PII patterns
grep -E '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b' /var/log/api/combined.log
grep -E '\b\d{3}-\d{2}-\d{4}\b' /var/log/api/combined.log
# Review and update redaction rules
# Audit existing logs and delete if necessary
High Disk Usage from Logs
# Check log directory size
du -sh /var/log/api/
# Review log rotation configuration
cat /etc/logrotate.d/api
# Manually rotate logs
logrotate -f /etc/logrotate.d/api
# Enable compression and reduce retention
/create-monitoring - Visualize log data with dashboards and alerts/add-rate-limiting - Log rate limit violations for security analysis/api-security-scanner - Audit security-relevant log events/api-error-handler - Integrate error handling with structured logging