Advanced

Designing Logging and Monitoring Infrastructure dengan Claude Code

Learn about designing logging and monitoring infrastructure using Claude Code. Includes practical code examples.

pembangunanにClaude Codeをpemanfaatan monitoringfondasi

environment produksi トラブルシューティング 、tepatなログ dan monitoring 不可欠.Claude Code struktur化ログ、分散トレーシング、メトリクス収集 fondasi 一括 pembangunan き、可観測性(Observability) 高いsistem efisien 実現.

implementasi struktur化ログ

> pino 使ったstruktur化ログ セットアップ buatkan.
> requestID、penggunaID、pemrosesan時間 含めて。
> 環境ご dan ログレベル peralihanられるよう.
// src/lib/logger.ts
import pino from 'pino';

export const logger = pino({
  level: process.env.LOG_LEVEL || (process.env.NODE_ENV === 'production' ? 'info' : 'debug'),
  transport: process.env.NODE_ENV !== 'production'
    ? { target: 'pino-pretty', options: { colorize: true } }
    : undefined,
  formatters: {
    level(label) {
      return { level: label };
    },
  },
  base: {
    service: process.env.SERVICE_NAME || 'my-app',
    env: process.env.NODE_ENV,
  },
  timestamp: pino.stdTimeFunctions.isoTime,
  redact: ['password', 'token', 'authorization', 'cookie'],
});

// requestスコープ ロガー
export function createRequestLogger(requestId: string, userId?: string) {
  return logger.child({
    requestId,
    userId,
  });
}

requestログmiddleware

// src/middleware/request-logger.ts
import { Request, Response, NextFunction } from 'express';
import { createRequestLogger } from '@/lib/logger';
import { randomUUID } from 'crypto';

export function requestLogger(req: Request, res: Response, next: NextFunction) {
  const requestId = (req.headers['x-request-id'] as string) || randomUUID();
  const start = Date.now();

  const log = createRequestLogger(requestId, req.user?.id);
  req.log = log;

  res.setHeader('X-Request-Id', requestId);

  log.info({
    method: req.method,
    url: req.url,
    userAgent: req.headers['user-agent'],
  }, 'Request started');

  res.on('finish', () => {
    const duration = Date.now() - start;
    const level = res.statusCode >= 500 ? 'error' : res.statusCode >= 400 ? 'warn' : 'info';

    log[level]({
      method: req.method,
      url: req.url,
      statusCode: res.statusCode,
      duration,
    }, 'Request completed');
  });

  next();
}

OpenTelemetryによる分散トレーシング

> OpenTelemetry 使った分散トレーシング konfigurasi.
> HTTP、DB、Redis呼び出し 自動計装 efektif.
// src/instrumentation.ts
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { Resource } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';

const sdk = new NodeSDK({
  resource: new Resource({
    [ATTR_SERVICE_NAME]: process.env.SERVICE_NAME || 'my-app',
    [ATTR_SERVICE_VERSION]: process.env.APP_VERSION || '1.0.0',
  }),
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
  }),
  metricReader: new PeriodicExportingMetricReader({
    exporter: new OTLPMetricExporter({
      url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/metrics',
    }),
    exportIntervalMillis: 30000,
  }),
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-http': { enabled: true },
      '@opentelemetry/instrumentation-express': { enabled: true },
      '@opentelemetry/instrumentation-pg': { enabled: true },
      '@opentelemetry/instrumentation-redis': { enabled: true },
    }),
  ],
});

sdk.start();

process.on('SIGTERM', () => {
  sdk.shutdown().then(() => process.exit(0));
});

収集 カスタムメトリクス

// src/lib/metrics.ts
import { metrics } from '@opentelemetry/api';

const meter = metrics.getMeter('my-app');

// requestカウンター
export const requestCounter = meter.createCounter('http_requests_total', {
  description: 'Total HTTP requests',
});

// responseタイム ヒストグラム
export const responseTime = meter.createHistogram('http_response_time_ms', {
  description: 'HTTP response time in milliseconds',
  unit: 'ms',
});

// アクティブpengguna数 ゲージ
export const activeUsers = meter.createUpDownCounter('active_users', {
  description: 'Number of active users',
});

// ビジネスメトリクス
export const orderCounter = meter.createCounter('orders_total', {
  description: 'Total orders placed',
});

// Usage example
export function recordRequest(method: string, path: string, statusCode: number, duration: number) {
  requestCounter.add(1, { method, path, statusCode: String(statusCode) });
  responseTime.record(duration, { method, path });
}

ヘルスチェックendpoint

// src/app/api/health/route.ts
import { NextResponse } from 'next/server';
import { prisma } from '@/lib/db';
import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL!);

export async function GET() {
  const checks = {
    status: 'ok' as 'ok' | 'degraded' | 'error',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    checks: {} as Record<string, { status: string; latency?: number }>,
  };

  // DBkoneksiチェック
  try {
    const start = Date.now();
    await prisma.$queryRaw`SELECT 1`;
    checks.checks.database = { status: 'ok', latency: Date.now() - start };
  } catch {
    checks.checks.database = { status: 'error' };
    checks.status = 'degraded';
  }

  // Rediskoneksiチェック
  try {
    const start = Date.now();
    await redis.ping();
    checks.checks.redis = { status: 'ok', latency: Date.now() - start };
  } catch {
    checks.checks.redis = { status: 'error' };
    checks.status = 'degraded';
  }

  const statusCode = checks.status === 'ok' ? 200 : 503;
  return NextResponse.json(checks, { status: statusCode });
}

errorトラッキング

// src/lib/error-tracker.ts
import { logger } from './logger';

export function trackError(error: Error, context?: Record<string, unknown>) {
  logger.error({
    err: {
      name: error.name,
      message: error.message,
      stack: error.stack,
    },
    ...context,
  }, 'Unhandled error');

  // Sentryなど 外部serviceへpengiriman
  if (process.env.SENTRY_DSN) {
    // Sentry.captureException(error, { extra: context });
  }
}

// グローバルerrorhandler
process.on('uncaughtException', (error) => {
  trackError(error, { type: 'uncaughtException' });
  process.exit(1);
});

process.on('unhandledRejection', (reason) => {
  trackError(reason instanceof Error ? reason : new Error(String(reason)), {
    type: 'unhandledRejection',
  });
});

Summary

Dengan Claude Code, struktur化ログ、分散トレーシング、メトリクス収集、ヘルスチェック 含むmonitoringfondasi efisien pembangunan bisa dilakukan.本番operasi diperlukanな可観測性 最初 dari 組み込むこ dan 、トラブルシューティング 時間 大幅 短縮 bisa dilakukan.pengembangan環境 pengaturan CLAUDE.md 記述 dan 、Claude Code 一貫 構成 generate.microservices monitoring microservices設計 juga bisa dijadikan referensi.

Untuk Claude Codeの詳細はAnthropic公式dokumenをご覧ください。OpenTelemetryの詳細, lihat OpenTelemetry公式サイト.

#Claude Code #ログ #monitoring #可観測性 #OpenTelemetry