Advanced

Claude Code के साथ Designing Logging and Monitoring Infrastructure

Claude Code का उपयोग करके designing logging and monitoring infrastructure सीखें। Practical code examples शामिल हैं।

monitoring基盤のbuildにClaude Codeをutilizationする

本番環境のトラブルシューティングには、appropriateなlogとmonitoringが不可欠 है।Claude Codeは構造化log、分散トレーシング、メトリクス収集の基盤を一括でbuildでき、可観測性(Observability)の高いシステムをefficiently実現し है।

構造化logのimplementation

> pinoを使った構造化logのsetupをबनाओ。
> requestID、userID、processing時बीचを含めて。
> 環境ごとにlogレベルを切り替えられる तरहして。
// 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,
  });
}

requestlogmiddleware

// 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を使った分散トレーシングをsettingsして。
> HTTP、DB、Redis呼び出しの自動計装を有効にして。
// 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',
});

// アクティブuser数のゲージ
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 });
}

ヘルスcheckendpoint

// 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 }>,
  };

  // DB接続check
  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';
  }

  // Redis接続check
  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へ送信
  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

Claude Code का उपयोग करके、構造化log、分散トレーシング、メトリクス収集、ヘルスcheckを含むmonitoring基盤をefficientlybuild किया जा सकता है。本番運用にज़रूरीな可観測性を最初 से組み込む बातで、トラブルシューティングの時बीचを大幅に短縮でき है।development environmentのsettingsはCLAUDE.mdに記述しておくと、Claude Codeが一貫した構成 generateし है।マイクロserviceでのmonitoringはマイクロservice設計भी reference के लिए देखें。

Claude Codeके details के लिएAnthropicofficial documentationदेखें。OpenTelemetryके details के लिएOpenTelemetry公式サイトをदेखें。

#Claude Code #log #monitoring #可観測性 #OpenTelemetry