一键导入
logging
Comprehensive logging standards for applications including structured logging, log levels, message formatting, and observability guidelines
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Comprehensive logging standards for applications including structured logging, log levels, message formatting, and observability guidelines
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Manage GitLab merge requests, issues, and pipelines from the command line using the glab CLI. Use when the user asks about GitLab MRs, issues, pipelines, labels, milestones, or needs to manage project work items via the command line.
Manage Bitbucket pull requests, issues, and repositories from the command line using the bkt CLI. Use when the user asks about Bitbucket PRs, issues, repos, pipelines, or needs to manage project work items via the command line.
Show ponytail's measured impact as a compact scoreboard: less code, less cost, more speed, from the benchmark medians. One-shot display, not a persistent mode, and not a per-repo number. Trigger: /ponytail-gain, "ponytail gain", "what does ponytail save", "show ponytail impact", "ponytail scoreboard".
Quick-reference card for all ponytail modes, skills, and commands. One-shot display, not a persistent mode. Trigger: /ponytail-help, "ponytail help", "what ponytail commands", "how do I use ponytail".
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
Build a compact mental model of recent project activity before any non-trivial task. Use proactively at the start of a session and before any investigation, planning, refactor, or multi-file change. Skip only for trivial fixes (typos, isolated docs, version bumps, mechanical refactors with a known target).
| name | logging |
| description | Comprehensive logging standards for applications including structured logging, log levels, message formatting, and observability guidelines |
Comprehensive logging guidelines for consistent, structured, and maintainable logging across the monorepo.
All logs MUST be structured (JSON-serializable) for efficient querying and analysis.
Include relevant context (request ID, user ID, session ID) in every log.
Use correct log levels to enable effective filtering.
Avoid expensive operations in log statements.
| Level | When to Use | Examples |
|---|---|---|
| ERROR | Application errors requiring attention | Unhandled exceptions, failed critical operations |
| WARN | Unexpected but recoverable situations | Retry attempts, deprecated usage, rate limiting |
| INFO | Significant application events | Request handling, job completion, config changes |
| DEBUG | Detailed diagnostic information | Variable values, execution paths, timing |
| TRACE | Very detailed debugging | Loop iterations, method entry/exit |
REQUIRED: All log messages MUST follow this pattern:
[SERVICE_OR_CLASS]: MESSAGE
The prefix should be the actual class name or service name enclosed in square brackets.
import { logger } from "@{{PROJECT_NAME}}/logging";
// ✅ GOOD - Structured with context
logger.info("[UserService]: User created", {
userId: user.id,
email: user.email,
source: "registration",
});
// ✅ GOOD - Error with stack trace
logger.error("[PaymentService]: Payment processing failed", {
error: err.message,
stack: err.stack,
orderId: order.id,
amount: order.total,
});
// ❌ BAD - String interpolation loses structure
logger.info(`User ${userId} created with email ${email}`);
// ❌ BAD - Missing context
logger.error("Payment failed");
import structlog
logger = structlog.get_logger()
# ✅ GOOD - Structured with context
logger.info("[UserService]: User created",
user_id=user.id,
email=user.email,
source="registration"
)
# ✅ GOOD - Error with exception
logger.error("[PaymentService]: Payment processing failed",
error=str(e),
order_id=order.id,
amount=order.total,
exc_info=True
)
# ❌ BAD - f-string loses structure
logger.info(f"User {user_id} created with email {email}")
// ✅ GOOD - Structured logging with named parameters
_logger.LogInformation("[UserService]: User created - UserId: {UserId}, Email: {Email}",
user.Id, user.Email);
// ✅ GOOD - Error with exception
_logger.LogError(ex, "[PaymentService]: Payment failed - OrderId: {OrderId}, Amount: {Amount}",
order.Id, order.Total);
// ❌ BAD - String interpolation
_logger.LogInformation($"User {userId} created with email {email}");
// ✅ GOOD - Structured with context
logger.Info("[UserService]: User created",
zap.String("userId", user.ID),
zap.String("email", user.Email),
zap.String("source", "registration"),
)
// ✅ GOOD - Error with stack
logger.Error("[PaymentService]: Payment failed",
zap.Error(err),
zap.String("orderId", order.ID),
zap.Float64("amount", order.Total),
)
// ❌ BAD - Printf style
logger.Info(fmt.Sprintf("User %s created", userId))
Always include request-scoped identifiers:
// Middleware sets context
const requestContext = {
requestId: req.headers["x-request-id"] || uuid(),
userId: req.user?.id,
sessionId: req.session?.id,
traceId: req.headers["x-trace-id"],
};
// All logs in request include context
logger.info("[OrderController]: Order submitted", {
...requestContext,
orderId: order.id,
itemCount: order.items.length,
});
For async operations, propagate correlation:
async function processOrder(order: Order, correlationId: string) {
logger.info("[OrderProcessor]: Starting order processing", {
correlationId,
orderId: order.id,
});
// Pass to downstream services
await inventoryService.reserve(order.items, { correlationId });
await paymentService.charge(order.total, { correlationId });
logger.info("[OrderProcessor]: Order processing complete", {
correlationId,
orderId: order.id,
duration: Date.now() - startTime,
});
}
const startTime = performance.now();
await expensiveOperation();
const duration = performance.now() - startTime;
logger.info("[DataProcessor]: Operation completed", {
operationType: "batch-import",
recordCount: records.length,
durationMs: Math.round(duration),
recordsPerSecond: Math.round(records.length / (duration / 1000)),
});
// Avoid expensive serialization unless needed
if (logger.isDebugEnabled()) {
logger.debug("[CacheService]: Cache contents", {
keys: cache.keys(),
size: cache.size,
hitRate: cache.stats.hitRate,
});
}
try {
await processPayment(order);
} catch (error) {
logger.error("[PaymentService]: Payment processing failed", {
error: error.message,
stack: error.stack,
errorCode: error.code,
// Business context
orderId: order.id,
userId: order.userId,
amount: order.total,
paymentMethod: order.paymentMethod,
// Request context
requestId: context.requestId,
// Recovery info
retryable: isRetryableError(error),
attemptNumber: attempt,
});
throw error;
}
// Tag errors for monitoring/alerting
logger.error("[AuthService]: Authentication failed", {
errorCategory: "SECURITY",
errorType: "INVALID_CREDENTIALS",
userId: attemptedUserId,
ipAddress: request.ip,
userAgent: request.headers["user-agent"],
});
const maskEmail = (email: string) => {
const [local, domain] = email.split("@");
return `${local.slice(0, 2)}***@${domain}`;
};
const maskCardNumber = (card: string) => {
return `****-****-****-${card.slice(-4)}`;
};
logger.info("[PaymentService]: Payment authorized", {
email: maskEmail(user.email), // "jo***@example.com"
cardNumber: maskCardNumber(card), // "****-****-****-1234"
amount: order.total,
});
Create a shared logging package for consistency:
packages/
└── logging/
├── src/
│ └── index.ts
├── package.json
└── README.md
// packages/logging/src/index.ts
import pino from "pino";
export const createLogger = (service: string) => {
return pino({
name: service,
level: process.env.LOG_LEVEL || "info",
formatters: {
level: (label) => ({ level: label }),
},
base: {
service,
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION,
},
});
};
// Usage in apps
// apps/{{APP_NAME_1}}/src/index.ts
import { createLogger } from "@{{PROJECT_NAME}}/logging";
const logger = createLogger("{{APP_NAME_1}}");
# .env
LOG_LEVEL=info # Minimum log level
LOG_FORMAT=json # json | pretty
LOG_DESTINATION=stdout # stdout | file | service
LOG_SERVICE_URL= # External logging service URL
import { trace, context } from "@opentelemetry/api";
function logWithTrace(level: string, message: string, data: object) {
const span = trace.getSpan(context.active());
const traceContext = span
? {
traceId: span.spanContext().traceId,
spanId: span.spanContext().spanId,
}
: {};
logger[level](message, { ...data, ...traceContext });
}
Is it an error that needs attention? → ERROR
Is it unexpected but handled? → WARN
Is it a significant business event? → INFO
Is it helpful for debugging? → DEBUG
Is it very detailed/verbose? → TRACE
.agents/skills/systematic-debugging/ for debugging workflows.agents/skills/verification-before-completion/ for testing logs