Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tools-only/X-Skills --skill setup-logging명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Index of Build Systems Skills
Coordination patterns for distributed dataflow systems including barriers, epochs, and distributed snapshots
Windowing, sessionization, time-series aggregation, and late data handling for streaming systems
SOC 직업 분류 기준
SKILL.md 표시 중
| 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