スキル一覧に戻る
JanSzewczyk

structured-logging

by JanSzewczyk

This is Next.js Szumplate, an open source template for enterprise projects! It is packed with features that will help you create an efficient, maintainable and enjoyable application.

1🍴 0📅 2026年1月18日
GitHubで見るManusで実行

SKILL.md


name: structured-logging version: 1.0.0 lastUpdated: 2026-01-18 description: Structured logging patterns with Pino for Next.js applications. Covers log levels, context enrichment, child loggers, and production best practices. tags: [logging, pino, observability, debugging, monitoring] author: Szum Tech Team allowed-tools: Read, Write, Edit, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__get-library-docs context: fork agent: general-purpose user-invocable: true examples:

  • How to add logging to a server action
  • What log level should I use
  • Create a child logger with context
  • Log errors with stack traces

Structured Logging Skill

Structured logging patterns with Pino for Next.js applications.

Reference Files:

Project Configuration

The logger is configured in lib/logger.ts:

import pino from "pino";

const logger = pino({
  level: process.env.LOG_LEVEL || "info",
  transport:
    process.env.NODE_ENV === "development"
      ? {
          target: "pino-pretty",
          options: {
            colorize: true,
            translateTime: "SYS:standard",
            ignore: "pid,hostname"
          }
        }
      : undefined,
  formatters: {
    level: (label) => ({ level: label.toUpperCase() })
  },
  timestamp: pino.stdTimeFunctions.isoTime
});

export function createLogger(context: Record<string, unknown>) {
  return logger.child(context);
}

export default logger;

Quick Start

Basic Logging

import logger from "~/lib/logger";

// Simple message
logger.info("Server started");

// With context object
logger.info({ port: 3000 }, "Server started");

// Error logging
logger.error({ error, userId }, "Failed to process request");

Module-Specific Logger

import { createLogger } from "~/lib/logger";

const logger = createLogger({ module: "user-service" });

// All logs include { module: "user-service" }
logger.info({ userId: "123" }, "User created");
// Output: { module: "user-service", userId: "123", msg: "User created" }

Log Levels

LevelWhen to UseExample
fatalApp crash, unrecoverableDatabase connection lost
errorOperation failedUser creation failed
warnUnexpected but recoverableRate limit approaching
infoNormal operationsUser logged in
debugDevelopment detailsRequest payload
traceFine-grained debuggingFunction entry/exit

Usage

logger.fatal({ error }, "Database connection lost, shutting down");
logger.error({ userId, errorCode: error.code }, "Failed to update user");
logger.warn({ requestCount, limit }, "Rate limit 80% reached");
logger.info({ userId }, "User logged in successfully");
logger.debug({ payload }, "Processing request");
logger.trace({ functionName: "processData" }, "Entering function");

Key Patterns

Always Log Context Objects First

// ✅ Good - context object first, then message
logger.info({ userId, action: "login" }, "User authenticated");

// ❌ Bad - no context
logger.info("User authenticated");

// ❌ Bad - string interpolation
logger.info(`User ${userId} authenticated`);

Error Logging

import { categorizeDbError, DbError } from "~/lib/firebase/errors";

try {
  await updateUser(userId, data);
} catch (error) {
  const dbError = categorizeDbError(error, "User");

  logger.error({
    userId,
    errorCode: dbError.code,
    isRetryable: dbError.isRetryable,
    operation: "updateUser"
  }, "Failed to update user");

  return [dbError, null];
}

Database Operations

const logger = createLogger({ module: "user-db" });

export async function getUserById(id: string) {
  logger.debug({ userId: id }, "Fetching user");

  try {
    const user = await db.collection("users").doc(id).get();

    if (!user.exists) {
      logger.warn({ userId: id }, "User not found");
      return [DbError.notFound("User"), null];
    }

    logger.info({ userId: id }, "User fetched successfully");
    return [null, transformUser(user)];
  } catch (error) {
    const dbError = categorizeDbError(error, "User");
    logger.error({
      userId: id,
      errorCode: dbError.code,
      isRetryable: dbError.isRetryable
    }, "Database error fetching user");
    return [dbError, null];
  }
}

Server Actions

const logger = createLogger({ module: "user-actions" });

export async function updateProfile(data: ProfileData): ActionResponse {
  const { userId } = await auth();

  if (!userId) {
    logger.warn({ action: "updateProfile" }, "Unauthorized access attempt");
    return { success: false, error: "Unauthorized" };
  }

  logger.info({ userId, action: "updateProfile" }, "Starting profile update");

  const [error] = await updateUserProfile(userId, data);

  if (error) {
    logger.error({
      userId,
      errorCode: error.code,
      action: "updateProfile"
    }, "Profile update failed");
    return { success: false, error: error.message };
  }

  logger.info({ userId, action: "updateProfile" }, "Profile updated successfully");
  return { success: true, data: null };
}

Environment Configuration

# .env.local
LOG_LEVEL=debug  # Development: see all logs

# .env.production
LOG_LEVEL=info   # Production: info and above

File Locations

PurposeLocation
Logger setuplib/logger.ts
Feature loggersCreate in feature modules
Log level configdata/env/server.ts
  • firebase-firestore - Database logging patterns
  • server-actions - Action logging patterns
  • t3-env-validation - LOG_LEVEL configuration

スコア

総合スコア

75/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

レビュー

💬

レビュー機能は近日公開予定です