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公式サイト.
Related Posts
Setup MCP Server Claude Code dan Use Case Praktis
Panduan lengkap tentang kemampuan MCP server Claude Code. Pelajari cara menghubungkan tool eksternal, mengonfigurasi server, dan contoh integrasi dunia nyata.
Menguasai Claude Code Hooks: Auto-Format, Auto-Test, dan Lainnya
Pelajari cara menyiapkan auto-formatting dan auto-testing dengan Claude Code hooks. Dilengkapi contoh konfigurasi praktis dan use case dunia nyata.
Panduan Lengkap Menulis CLAUDE.md: Best Practice untuk Konfigurasi Project
Panduan menyeluruh untuk menulis file CLAUDE.md yang efektif. Pelajari cara mengkomunikasikan tech stack, konvensi, dan struktur project untuk memaksimalkan kualitas output Claude Code.