
Application Logging
- 452 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
application-logging is an agent skill that implements structured JSON logging with correlation IDs and central aggregation for developers who need production-debuggable services.
About
application-logging is a backend observability skill in aj-geddes/useful-ai-prompts for instrumenting services with structured logs, correlation IDs, level discipline, and centralized analysis. The quick-start ships a Winston logger with timestamped JSON formatting, service and environment defaultMeta, console and error.log transports, and guidance on LOG_LEVEL configuration. Six reference guides cover Node.js Winston patterns, Express HTTP request logging, Python structured logging, Flask integration, ELK stack setup, and Logstash configuration. Best-practice rules require request IDs, sensitive-data redaction, rotation, and centralized aggregation while forbidding secret logging and unbounded files. Reach for application-logging when standing up a new API, hardening production debuggability, or migrating from unstructured printf logs to JSON streams compatible with ELK or similar aggregators.
- Structured JSON logging
- Correlation and trace IDs
- Log level strategy
- PII redaction patterns
- Centralized aggregation readiness
Application Logging by the numbers
- 452 all-time installs (skills.sh)
- Ranked #930 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill application-loggingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 452 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
How do you add structured JSON logging to Node APIs?
Instrument services with structured logs, correlation IDs, log levels, redaction, and aggregation-friendly formats for debugging production incidents.
Who is it for?
Backend developers instrumenting Node.js or Python services who need structured logs, correlation IDs, and ELK-ready aggregation patterns.
Skip if: Teams seeking ML-based outlier scoring on metrics without first establishing structured log pipelines.
When should I use this skill?
User asks to set up structured logging, Winston JSON logs, correlation IDs, ELK stack, or Express/Flask request logging.
What you get
Winston or Python JSON logger setup, Express/Flask request logging middleware, ELK/Logstash configs, and redaction-ready log formats.
- JSON logger configuration
- HTTP request logging middleware
- ELK/Logstash setup references
By the numbers
- Includes 6 reference guides for Node, Express, Python, Flask, ELK, and Logstash
- Quick-start Winston logger configures console and error.log file transports
- Best-practice checklist lists 8 DO rules and 7 DON'T rules for production logging
Files
Application Logging
Table of Contents
Overview
Implement comprehensive structured logging with proper levels, context, and centralized aggregation for effective debugging and monitoring.
When to Use
- Application debugging
- Audit trail creation
- Performance analysis
- Compliance requirements
- Centralized log aggregation
Quick Start
Minimal working example:
// logger.js
const winston = require("winston");
const logFormat = winston.format.combine(
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
winston.format.errors({ stack: true }),
winston.format.json(),
);
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || "info",
format: logFormat,
defaultMeta: {
service: "api-service",
environment: process.env.NODE_ENV || "development",
},
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
),
}),
new winston.transports.File({
filename: "logs/error.log",
// ... (see reference guides for full implementation)Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Node.js Structured Logging with Winston | Node.js Structured Logging with Winston |
| Express HTTP Request Logging | Express HTTP Request Logging |
| Python Structured Logging | Python Structured Logging |
| Flask Integration | Flask Integration |
| ELK Stack Setup | ELK Stack Setup |
| Logstash Configuration | Logstash Configuration |
Best Practices
✅ DO
- Use structured JSON logging
- Include request IDs for tracing
- Log at appropriate levels
- Add context to error logs
- Implement log rotation
- Use timestamps consistently
- Aggregate logs centrally
- Filter sensitive data
❌ DON'T
- Log passwords or secrets
- Log at INFO for every operation
- Use unstructured messages
- Ignore log storage limits
- Skip context information
- Log to stdout in production
- Create unbounded log files
ELK Stack Setup
ELK Stack Setup
# docker-compose.yml
version: "3.8"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.0.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
logstash:
image: docker.elastic.co/logstash/logstash:8.0.0
ports:
- "5000:5000"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch
kibana:
image: docker.elastic.co/kibana/kibana:8.0.0
ports:
- "5601:5601"
environment:
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
depends_on:
- elasticsearch
volumes:
elasticsearch_data:Express HTTP Request Logging
Express HTTP Request Logging
// Express middleware
const express = require("express");
const expressWinston = require("express-winston");
const logger = require("./logger");
const app = express();
app.use(
expressWinston.logger({
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: "logs/http.log" }),
],
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json(),
),
meta: true,
msg: "HTTP {{req.method}} {{req.url}}",
expressFormat: true,
}),
);
app.get("/api/users/:id", (req, res) => {
const requestId = req.headers["x-request-id"] || Math.random().toString();
logger.info("User request started", { requestId, userId: req.params.id });
try {
const user = { id: req.params.id, name: "John Doe" };
logger.debug("User data retrieved", { requestId, user });
res.json(user);
} catch (error) {
logger.error("User retrieval failed", {
requestId,
error: error.message,
stack: error.stack,
});
res.status(500).json({ error: "Internal server error" });
}
});Flask Integration
Flask Integration
# Flask app
from flask import Flask, request, g
import uuid
import time
app = Flask(__name__)
@app.before_request
def before_request():
g.start_time = time.time()
g.request_id = request.headers.get('X-Request-ID', str(uuid.uuid4()))
@app.after_request
def after_request(response):
duration = time.time() - g.start_time
logger.info('HTTP Request', extra={
'method': request.method,
'path': request.path,
'status_code': response.status_code,
'duration_ms': duration * 1000,
'request_id': g.request_id
})
return response
@app.route('/api/orders/<order_id>')
def get_order(order_id):
logger.info('Order request', extra={
'order_id': order_id,
'request_id': g.request_id
})
try:
order = db.query(f'SELECT * FROM orders WHERE id = {order_id}')
logger.debug('Order retrieved', extra={'order_id': order_id})
return {'order': order}
except Exception as e:
logger.error('Order retrieval failed', extra={
'order_id': order_id,
'error': str(e),
'request_id': g.request_id
}, exc_info=True)
return {'error': 'Internal server error'}, 500Logstash Configuration
Logstash Configuration
# logstash.conf
input {
tcp {
port => 5000
codec => json
}
}
filter {
date {
match => [ "timestamp", "YYYY-MM-dd HH:mm:ss" ]
target => "@timestamp"
}
mutate {
add_field => { "[@metadata][index_name]" => "logs-%{+YYYY.MM.dd}" }
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "%{[@metadata][index_name]}"
}
}Node.js Structured Logging with Winston
Node.js Structured Logging with Winston
// logger.js
const winston = require("winston");
const logFormat = winston.format.combine(
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
winston.format.errors({ stack: true }),
winston.format.json(),
);
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || "info",
format: logFormat,
defaultMeta: {
service: "api-service",
environment: process.env.NODE_ENV || "development",
},
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
),
}),
new winston.transports.File({
filename: "logs/error.log",
level: "error",
}),
new winston.transports.File({
filename: "logs/combined.log",
}),
],
});
module.exports = logger;Python Structured Logging
Python Structured Logging
# logger_config.py
import logging
import json
from pythonjsonlogger import jsonlogger
import sys
class CustomJsonFormatter(jsonlogger.JsonFormatter):
def add_fields(self, log_record, record, message_dict):
super().add_fields(log_record, record, message_dict)
log_record['timestamp'] = self.formatTime(record)
log_record['service'] = 'api-service'
log_record['level'] = record.levelname
def setup_logging():
logger = logging.getLogger()
logger.setLevel(logging.INFO)
console_handler = logging.StreamHandler(sys.stdout)
formatter = CustomJsonFormatter()
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
logger = setup_logging()#!/bin/bash
# validate-api.sh - Validate API specification
# Usage: ./validate-api.sh <openapi_spec>
set -euo pipefail
SPEC_FILE="${{1:?Usage: $0 <openapi_spec>}}"
echo "Validating API spec: $SPEC_FILE"
# TODO: Add API validation
# - Validate OpenAPI/Swagger syntax
# - Check endpoint naming conventions
# - Verify response schemas
# - Check for required headers
# - Validate authentication definitions
echo "API validation complete."
# API Endpoint Scaffold
# TODO: Customize for your API framework
openapi: "3.0.3"
info:
title: "API Service"
version: "1.0.0"
paths:
/api/v1/resource:
get:
summary: "List resources"
# TODO: Define parameters and responses
responses:
"200":
description: "Success"
post:
summary: "Create resource"
# TODO: Define request body and responses
responses:
"201":
description: "Created"
Related skills
How it compares
Start with application-logging for log instrumentation and aggregation; add anomaly detection later for ML scoring on metrics derived from those logs.
FAQ
Which runtimes does application-logging cover?
application-logging provides a Winston quick start for Node.js plus six references for Express HTTP logging, Python structured logging, Flask integration, ELK stack setup, and Logstash configuration for centralized analysis.
What logging practices does application-logging require?
application-logging mandates structured JSON logs, request IDs for tracing, appropriate log levels, secret redaction, rotation, consistent timestamps, and centralized aggregation while avoiding password logging and unbounded stdout-only production setups.
Does application-logging include an ELK setup guide?
application-logging links references/elk-stack-setup.md and references/logstash-configuration.md among its six guides, covering ingestion and pipeline configuration after the Winston or Python logger quick start.