バックエンド実装時に使用。DRY原則遵守。コーディング規約準拠。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
ログ設計の妥当性チェック。一般的なログ基準と日本国内法的要件(電子帳簿保存法・個人情報保護法等)に基づき、ログ設計・実装を検証する。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치 방법 보기설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
プロジェクトのログ設計が一般的な基準と法的要件を満たしているか体系的にチェックし、不足があれば実装パターンを提示する。
参照: セキュリティ関連のログルールは
documents/development/coding-rules/common-rules.mdSection 4 も併せて確認すること。
Step 1: 現状分析(既存のログ設定・出力を確認)
↓
Step 2: 一般的ログ基準チェック
↓
Step 3: 法的要件チェック
↓
Step 4: 不足箇所の実装パターン提示
↓
Step 5: レポート出力
以下を確認する:
| レベル | 用途 | 例 |
|---|---|---|
| ERROR | システム異常、復旧不可能なエラー | DB接続失敗、外部API障害、未処理例外 |
| WARN | 想定内だが注意が必要な事象 | リトライ発生、閾値超過、非推奨API使用 |
| INFO | ビジネス上重要なイベント | ユーザーログイン/ログアウト、決済完了、重要な状態遷移 |
| DEBUG | 開発・調査用の詳細情報 | リクエスト/レスポンス詳細、SQL実行詳細(本番では無効化) |
Spring Boot + Logback (JSON形式):
// logback-spring.xml で net.logstash.logback.encoder.LogstashEncoder を使用
// または logback-spring.xml で JSON パターンを定義
// 出力例:
// {
// "timestamp": "2025-01-08T10:00:00.000+09:00",
// "level": "INFO",
// "logger": "com.example.service.PaymentService",
// "message": "Payment completed",
// "traceId": "abc123",
// "userId": "user-001",
// "action": "PAYMENT_COMPLETE",
// "amount": 10000,
// "paymentId": "pay-001"
// }
@Slf4j
@Service
public class PaymentService {
public void completePayment(Payment payment) {
// MDC にトレース情報をセット
MDC.put("action", "PAYMENT_COMPLETE");
MDC.put("paymentId", payment.getId().toString());
log.info("Payment completed: amount={}", payment.getAmount());
MDC.clear();
}
}
Next.js (API Routes / Server Actions):
// lib/logger.ts - 構造化ログユーティリティ
import pino from 'pino';
export const logger = pino({
level: process.env.LOG_LEVEL || 'info',
formatters: {
level: (label) => ({ level: label }),
},
timestamp: pino.stdTimeFunctions.isoTime,
});
// 使用例: API Route
export async function POST(request: Request) {
const body = await request.json();
logger.info(
{ action: 'ORDER_CREATED', orderId: body.id, userId: session.userId },
'Order created'
);
}
ログに出力してはいけない情報:
マスキング実装例 (Java):
public class PiiMasker {
public static String maskEmail(String email) {
if (email == null) return "***";
int atIndex = email.indexOf('@');
if (atIndex < 0) return "***"; // @がない場合は全マスク
if (atIndex <= 1) return "***@" + email.substring(atIndex + 1);
return email.charAt(0) + "***@" + email.substring(atIndex + 1);
}
public static String maskPhone(String phone) {
if (phone == null || phone.length() < 4) return "****";
return "****" + phone.substring(phone.length() - 4);
}
public static String maskCardNumber(String cardNumber) {
if (cardNumber == null) return "****";
String digits = cardNumber.replaceAll("[^0-9]", "");
if (digits.length() < 4) return "****";
return "****-****-****-" + digits.substring(digits.length() - 4);
}
public static String maskMyNumber(String myNumber) {
// マイナンバーは12桁の数字。全桁マスクが原則(部分表示も不可)
if (myNumber == null) return "************";
return "************";
}
}
ユーザー入力をログ出力する際、改行コード(CR/LF)を含む文字列がそのまま出力されると、偽のログ行が挿入される(ログインジェクション/ログフォージング)。監査ログの信頼性を損なうため、必ずサニタイズする。
public static String sanitizeForLog(String input) {
if (input == null) return "";
return input.replaceAll("[\\r\\n]", " ");
}
// 使用例
log.info("User search: query={}", sanitizeForLog(userInput));
function sanitizeForLog(input: string): string {
return input.replace(/[\r\n]/g, ' ');
}
フロントエンド (Server-side only):
// 機密情報をクライアントサイドに送信しない
// - API RouteやServer Actionのログにのみ詳細情報を記録
// - クライアントには汎用エラーメッセージのみ返す
// - console.log/console.error は本番ビルドで除去する(eslint no-console)
| カテゴリ | ログ対象 | レベル |
|---|---|---|
| 認証 | ログイン成功/失敗、ログアウト、トークンリフレッシュ | INFO |
| 認可 | 権限不足によるアクセス拒否 | WARN |
| データ変更 | 重要データのCRUD操作(誰が・いつ・何を) | INFO |
| 決済 | 決済開始・完了・失敗 | INFO/ERROR |
| 外部連携 | 外部API呼び出し(リクエスト/レスポンス概要) | INFO |
| エラー | 未処理例外、システム障害 | ERROR |
該当条件: 電子的に授受した取引情報(注文書、請求書、領収書、見積書等に相当するデータ)を扱う場合
チェックリスト:
監査ログ実装パターン:
// 監査ログテーブル設計例
// audit_logs テーブル
// - id: UUID (PK)
// - entity_type: VARCHAR (対象エンティティ種別)
// - entity_id: UUID (対象エンティティID)
// - action: VARCHAR (CREATE/UPDATE/DELETE)
// - actor_id: UUID (操作者ID)
// - before_value: JSONB (変更前の値、NULLable)
// - after_value: JSONB (変更後の値)
// - created_at: TIMESTAMP WITH TIME ZONE (操作日時)
// Spring AOP で自動記録する実装パターン
@Aspect
@Component
@RequiredArgsConstructor
public class AuditLogAspect {
private final AuditLogRepository auditLogRepository;
@AfterReturning("@annotation(Auditable)")
public void logAudit(JoinPoint joinPoint) {
// 操作内容を自動記録
}
}
// 使用例
@Auditable
@Transactional
public OrderResponse createOrder(CreateOrderRequest request) {
// 注文作成処理
}
該当条件: 個人情報(氏名、メールアドレス、住所、電話番号等)を取り扱う場合
チェックリスト:
個人情報アクセスログ実装パターン:
// アクセスログ出力例
log.info("Personal data accessed: entity={}, entityId={}, fields={}, actor={}",
"Student", studentId, "name,email,phone", currentUserId);
該当条件: 広告・宣伝目的の電子メールを送信する場合
チェックリスト:
チェック結果に基づき、不足箇所について上記の実装パターンをプロジェクトのスタックに合わせて提示する。
チェック結果をMarkdownチェックリスト形式でコンソールに出力する:
## Log Design Check Report
### 一般的ログ基準
- [x] ログレベル基準が定義されている
- [ ] 構造化ログが導入されていない -> 実装パターンを提示
- [x] 機密情報マスキングが実装されている
### 法的要件(電子帳簿保存法)
- [x] 該当: 取引データを扱う
- [ ] タイムスタンプ要件: 未対応 -> 実装パターンを提示
- [x] 改ざん防止: 監査ログ実装済み
### 法的要件(個人情報保護法)
- [x] 該当: 個人情報を扱う
- [x] マスキング: 実装済み
- [ ] アクセスログ: 未実装 -> 実装パターンを提示
### 法的要件(特定電子メール法)
- [ ] 非該当(メール送信機能なし)
### Summary
- チェック項目: 12件
- 対応済み: 8件
- 要対応: 4件(実装パターン提示済み)
아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
バックエンド実装時に使用。DRY原則遵守。コーディング規約準拠。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use before implementing any feature, behavior change, or refactor - settles requirements and design, then gets the design independently reviewed and approved by the user before code is written
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
作業開始時に使用。mainブランチでの作業禁止。Issue先行作成必須。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
UI実装後の検証時に使用。agent-browser CLIでブラウザ上の動作を手動検証する。「UIを確認」「画面テスト」と言われたら使用(プロジェクトの E2E スイート実行は quality-check Step 5(推奨度・範囲で自動実施または確認)/ server-startup が担当)。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
DBマイグレーション作成時に使用。バージョン番号競合防止。mainブランチ確認必須。
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when independent tasks benefit from parallel work without shared state or sequential dependencies
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.