logging

GitHub

规范后端日志记录模式,涵盖 API 路由、辅助函数及服务操作的集中式请求作用域日志用法,支持中间件自动注入上下文与手动扩展。

.claude/skills/logging/SKILL.md elie222/inbox-zero

Trigger Scenarios

需要记录后端请求日志 实现结构化日志输出 调试后端服务

Install

npx skills add elie222/inbox-zero --skill logging -g -y
More Options

Non-standard path

npx skills add https://github.com/elie222/inbox-zero/tree/main/.claude/skills/logging -g -y

Use without installing

npx skills use elie222/inbox-zero@logging

指定 Agent (Claude Code)

npx skills add elie222/inbox-zero --skill logging -a claude-code -g -y

安装 repo 全部 skill

npx skills add elie222/inbox-zero --all -g -y

预览 repo 内 skill

npx skills add elie222/inbox-zero --list

SKILL.md

Frontmatter
{
    "name": "logging",
    "description": "How to do backend logging"
}

Logging

We use a centralized, request-scoped logging pattern where loggers are created by middleware and passed through the request/function chain.

API Route Logging (Primary Pattern)

Use middleware wrappers that automatically create loggers with request context:

import { withError, withAuth, withEmailAccount, withEmailProvider } from "@/utils/middleware";

// Basic route with error handling and logging
export const POST = withError("my-route", async (request) => {
  const logger = request.logger;
  logger.info("Processing request");
  // ...
});

// Authenticated route - logger includes userId
export const GET = withAuth("my-route", async (request) => {
  request.logger.info("User action"); // Already has userId context
  // ...
});

// Email account route - logger includes emailAccountId, email
export const POST = withEmailAccount("my-route", async (request) => {
  request.logger.info("Email action"); // Has userId, emailAccountId, email
  // ...
});

// Email provider route - same as email account, plus provides emailProvider
export const GET = withEmailProvider("my-route", async (request) => {
  request.logger.info("Provider action");
  const emails = await request.emailProvider.getMessages();
  // ...
});

The middleware automatically adds:

  • requestId - Unique ID for request tracing
  • url - Request URL
  • userId - For authenticated routes
  • emailAccountId, email - For email account routes

Enriching Logger Context

Add additional context within your route handler:

export const POST = withEmailAccount("digest", async (request) => {
  let logger = request.logger;
  
  const body = await request.json();
  logger = logger.with({ messageId: body.messageId });
  
  logger.info("Processing message");
  // ...
});

Helper Function Logging

Helper functions called from routes should receive the logger as a parameter instead of creating their own:

import type { Logger } from "@/utils/logger";

export async function processEmail(
  emailId: string,
  logger: Logger,
) {
  logger = logger.with({ emailId });
  logger.info("Processing email");
  // ...
}

Then call from your route:

export const POST = withEmailAccount("process", async (request) => {
  await processEmail(body.emailId, request.logger);
});

Server Action Logging

Server actions using actionClient receive the logger through context, similar to route middleware:

import { actionClient } from "@/utils/actions/safe-action";

export const createRuleAction = actionClient
  .metadata({ name: "createRule" })
  .inputSchema(createRuleBody)
  .action(
    async ({
      ctx: { emailAccountId, logger, provider },
      parsedInput: { name, actions },
    }) => {
      logger.info("Creating rule", { name });
      // ...
    },
  );

The actionClient context provides:

  • logger - Scoped logger with request context
  • emailAccountId - Current email account
  • provider - Email provider type

When to Use createScopedLogger

Use createScopedLogger only for code that doesn't run within a middleware chain (route or action):

import { createScopedLogger } from "@/utils/logger";

// Standalone scripts
const logger = createScopedLogger("script/migrate");

// Tests
const logger = createScopedLogger("test");

Don't use .with() for a global/file-level logger. Only use within a specific function.

Version History

  • 633a2ab Current 2026-08-20 17:14

Same Skill Collection

.claude/skills/agent-browser/SKILL.md
.claude/skills/changelog/SKILL.md
.claude/skills/cloud-dev-environment/SKILL.md
.claude/skills/code-simplifier/SKILL.md
.claude/skills/create-pr/SKILL.md
.claude/skills/explain-changes/SKILL.md
.claude/skills/fullstack-workflow/SKILL.md
.claude/skills/llm-test/SKILL.md
.claude/skills/llm/SKILL.md
.claude/skills/project-structure/SKILL.md
.claude/skills/qa-label/SKILL.md
.claude/skills/qa-new-flow/SKILL.md
.claude/skills/review-ai-prompt-changes/SKILL.md
.claude/skills/review/SKILL.md
.claude/skills/test-feature/SKILL.md
.claude/skills/testing/SKILL.md
.claude/skills/ui-components/SKILL.md
.claude/skills/update-packages/SKILL.md
clawhub/inbox-zero-api/SKILL.md
.claude/skills/prisma/SKILL.md
.claude/skills/qa-run/SKILL.md
.claude/skills/e2e/SKILL.md
.claude/skills/write-tests/SKILL.md
.claude/skills/wait/SKILL.md

Metadata

Files
0
Version
780453c
Hash
6957a55e
Indexed
2026-08-20 17:14

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-30 21:37
浙ICP备14020137号-1 $お客様$