Claude Sonnet 4×GitHub Copilot実装完全ガイド - 実践的開発手法とコード例【技術深掘り編】¶
はじめに¶
本記事は「AIエージェント開発革命2025」の技術深掘り編として、Claude Sonnet 4とGitHub Copilotの実装詳細に焦点を当てます。実際のコード例、詳細な設定手順、パフォーマンス最適化、そして実践的なトラブルシューティングまで包括的に解説します。
この記事のポイント¶
高度なエージェント実装
TypeScript/Pythonでの実装例とベストプラクティス
:material-settings-box: 詳細設定ガイド
MCP設定、認証、プロジェクト統合の完全手順
トラブルシューティング
よくある問題と解決策、デバッグ手法
パフォーマンス最適化
レスポンス速度とリソース使用量の最適化技術
Claude Code CLI環境構築¶
1. 初期セットアップと認証¶
# Claude Code CLIインストール
npm install -g @anthropic/claude-cli
# 認証設定
claude auth login
# または環境変数設定
export ANTHROPIC_API_KEY="your-api-key-here"
# プロジェクト初期化
claude init --template advanced
2. CLAUDE.mdプロジェクト設定¶
# CLAUDE.md - プロジェクト設定例
## Project Context
- **Framework**: React + TypeScript + Node.js
- **Database**: PostgreSQL with Prisma ORM
- **Testing**: Jest + React Testing Library
- **CI/CD**: GitHub Actions + Docker
## Development Guidelines
- Use ESLint + Prettier for code formatting
- Follow conventional commits
- Write comprehensive tests for all features
- Document public APIs with TSDoc
## Agent Behaviors
- Always run tests before suggesting code changes
- Prioritize type safety and error handling
- Include comprehensive logging for debugging
- Follow existing code patterns and conventions
## Custom Tools
- `@database-agent`: PostgreSQL optimization and queries
- `@security-agent`: Security audit and vulnerability scanning
- `@test-agent`: Automated test generation and coverage analysis
3. カスタムエージェント設定¶
{
"agents": {
"database-expert": {
"description": "PostgreSQL最適化エキスパート",
"context": "@database-schema.md @performance-requirements.md",
"tools": ["sql_analyzer", "performance_profiler"],
"personality": "detail-oriented, performance-focused"
},
"security-specialist": {
"description": "セキュリティ監査スペシャリスト",
"context": "@security-policies.md @compliance-requirements.md",
"tools": ["vulnerability_scanner", "code_analyzer"],
"personality": "security-first, thorough"
}
}
}
GitHub Copilot統合実装¶
1. VS Code拡張設定¶
// settings.json
{
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false
},
"github.copilot.advanced": {
"debug.overrideEngine": "claude-sonnet-4",
"authProvider": "github"
},
"github.copilot.editor.enableAutoCompletions": true,
"github.copilot.experimental": {
"chat.codeGeneration": true,
"chat.multiTurn": true
}
}
2. カスタムプロンプト設定¶
// copilot-config.ts
interface CopilotConfiguration {
model: 'claude-sonnet-4' | 'gpt-4o' | 'gpt-4.1';
temperature: number;
maxTokens: number;
context: {
codebase: boolean;
documentation: boolean;
tests: boolean;
};
}
const config: CopilotConfiguration = {
model: 'claude-sonnet-4',
temperature: 0.2,
maxTokens: 4096,
context: {
codebase: true,
documentation: true,
tests: true
}
};
// プロジェクト固有プロンプト
export const PROJECT_PROMPTS = {
codeGeneration: `
Generate TypeScript code following our project conventions:
- Use strict type checking
- Include comprehensive error handling
- Add JSDoc comments for public APIs
- Follow our naming conventions: camelCase for variables, PascalCase for types
- Use async/await instead of Promises.then()
`,
testGeneration: `
Generate Jest tests with:
- Comprehensive test coverage (happy path + edge cases)
- Proper mocking of external dependencies
- Clear test descriptions and assertions
- Setup and teardown for database tests
`
};
エージェント開発実装例¶
1. TypeScript実装 - 自律コーディングエージェント¶
// src/agents/CodingAgent.ts
import { ClaudeCodeClient } from '@anthropic/claude-code';
import { GitHubService } from '../services/GitHubService';
import { TestRunner } from '../services/TestRunner';
export class AutonomousCodingAgent {
private claude: ClaudeCodeClient;
private github: GitHubService;
private testRunner: TestRunner;
constructor(apiKey: string, githubToken: string) {
this.claude = new ClaudeCodeClient({ apiKey });
this.github = new GitHubService(githubToken);
this.testRunner = new TestRunner();
}
async resolveIssue(issueNumber: number): Promise<{
success: boolean;
prUrl?: string;
error?: string;
}> {
try {
// 1. Issue内容を取得・分析
const issue = await this.github.getIssue(issueNumber);
const analysis = await this.claude.analyze({
prompt: `
Analyze this GitHub issue and create an implementation plan:
Title: ${issue.title}
Description: ${issue.body}
Labels: ${issue.labels.map(l => l.name).join(', ')}
Provide:
1. Problem analysis
2. Implementation approach
3. File changes required
4. Test strategy
`,
model: 'claude-sonnet-4',
extendedThinking: true
});
// 2. 実装コード生成
const implementation = await this.generateImplementation(analysis);
// 3. テスト生成・実行
const tests = await this.generateTests(implementation);
const testResults = await this.testRunner.run(tests);
if (!testResults.success) {
throw new Error(`Tests failed: ${testResults.errors.join(', ')}`);
}
// 4. Pull Request作成
const prUrl = await this.createPullRequest(
issueNumber,
implementation,
tests,
analysis.summary
);
return { success: true, prUrl };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
private async generateImplementation(analysis: any): Promise<CodeImplementation[]> {
const implementations: CodeImplementation[] = [];
for (const fileChange of analysis.fileChanges) {
const code = await this.claude.generate({
prompt: `
Generate ${fileChange.language} code for:
File: ${fileChange.path}
Purpose: ${fileChange.purpose}
Requirements: ${fileChange.requirements.join(', ')}
Follow project conventions and include:
- Comprehensive error handling
- Type safety (if TypeScript)
- Proper logging
- Performance optimization
`,
context: {
files: await this.getRelatedFiles(fileChange.path),
codebase: true
}
});
implementations.push({
path: fileChange.path,
content: code,
language: fileChange.language
});
}
return implementations;
}
private async generateTests(implementations: CodeImplementation[]): Promise<TestSuite[]> {
const testSuites: TestSuite[] = [];
for (const impl of implementations) {
if (impl.language === 'typescript' || impl.language === 'javascript') {
const testCode = await this.claude.generate({
prompt: `
Generate comprehensive Jest tests for this code:
${impl.content}
Include:
- Unit tests for all public methods
- Integration tests for complex workflows
- Edge case testing
- Mock external dependencies
- 90%+ code coverage
`
});
testSuites.push({
path: impl.path.replace(/\.(ts|js)$/, '.test.$1'),
content: testCode,
type: 'jest'
});
}
}
return testSuites;
}
private async createPullRequest(
issueNumber: number,
implementations: CodeImplementation[],
tests: TestSuite[],
summary: string
): Promise<string> {
// 新しいブランチ作成
const branchName = `fix/issue-${issueNumber}-${Date.now()}`;
await this.github.createBranch(branchName);
// ファイル変更をコミット
for (const impl of implementations) {
await this.github.updateFile(impl.path, impl.content, `Implement ${impl.path}`);
}
for (const test of tests) {
await this.github.updateFile(test.path, test.content, `Add tests for ${test.path}`);
}
// Pull Request作成
const prUrl = await this.github.createPullRequest({
title: `Fix #${issueNumber}: ${summary}`,
body: `
## 概要
${summary}
## 変更内容
${implementations.map(i => `- \`${i.path}\`: ${i.purpose || '実装追加'}`).join('\n')}
## テスト
${tests.map(t => `- \`${t.path}\`: ${t.type}テスト追加`).join('\n')}
## 確認事項
- [ ] 全テストが通過
- [ ] コードレビュー完了
- [ ] ドキュメント更新(必要な場合)
Closes #${issueNumber}
`,
base: 'main',
head: branchName
});
return prUrl;
}
}
// 使用例
const agent = new AutonomousCodingAgent(
process.env.ANTHROPIC_API_KEY!,
process.env.GITHUB_TOKEN!
);
// GitHub Issue #123を自動解決
agent.resolveIssue(123).then(result => {
if (result.success) {
console.log(`Pull Request created: ${result.prUrl}`);
} else {
console.error(`Failed to resolve issue: ${result.error}`);
}
});
2. Python実装 - MCP統合エージェント¶
# agents/mcp_integration_agent.py
import asyncio
import json
from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from pathlib import Path
import anthropic
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
@dataclass
class MCPServer:
name: str
command: str
args: List[str]
env: Dict[str, str] = None
class MCPIntegrationAgent:
def __init__(self, anthropic_api_key: str):
self.client = anthropic.Anthropic(api_key=anthropic_api_key)
self.mcp_servers: Dict[str, ClientSession] = {}
async def initialize_mcp_servers(self, servers: List[MCPServer]):
"""MCP サーバーを初期化して接続"""
for server in servers:
try:
server_params = StdioServerParameters(
command=server.command,
args=server.args,
env=server.env or {}
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
self.mcp_servers[server.name] = session
# サーバーの利用可能なツールを確認
tools = await session.list_tools()
print(f"Connected to {server.name}: {len(tools.tools)} tools available")
except Exception as e:
print(f"Failed to connect to {server.name}: {e}")
async def execute_with_mcp_tools(self, prompt: str, server_names: List[str] = None) -> str:
"""MCP ツールを使用してタスクを実行"""
# 利用可能なツールを収集
available_tools = {}
target_servers = server_names or list(self.mcp_servers.keys())
for server_name in target_servers:
if server_name in self.mcp_servers:
session = self.mcp_servers[server_name]
tools = await session.list_tools()
available_tools[server_name] = tools.tools
# Claude に利用可能なツールと共にプロンプトを送信
tools_description = self._format_tools_for_claude(available_tools)
enhanced_prompt = f"""
{prompt}
利用可能なMCPツール:
{tools_description}
必要に応じてこれらのツールを使用してタスクを完了してください。
ツールを使用する場合は、JSON形式で以下のように指定してください:
{{"tool_call": {{"server": "server_name", "tool": "tool_name", "arguments": {{...}}}}}}
"""
# Claude APIを呼び出し
response = self.client.messages.create(
model="claude-3-sonnet-20241022",
max_tokens=4096,
messages=[{"role": "user", "content": enhanced_prompt}]
)
response_text = response.content[0].text
# ツール呼び出しを解析・実行
updated_response = await self._process_tool_calls(response_text)
return updated_response
async def _process_tool_calls(self, response: str) -> str:
"""レスポンス内のツール呼び出しを処理"""
import re
# JSON形式のツール呼び出しを検索
tool_call_pattern = r'\{"tool_call":\s*\{[^}]+\}\}'
tool_calls = re.findall(tool_call_pattern, response)
updated_response = response
for call_json in tool_calls:
try:
call_data = json.loads(call_json)
tool_call = call_data["tool_call"]
server_name = tool_call["server"]
tool_name = tool_call["tool"]
arguments = tool_call.get("arguments", {})
if server_name in self.mcp_servers:
session = self.mcp_servers[server_name]
result = await session.call_tool(tool_name, arguments)
# ツール呼び出し結果でレスポンスを更新
result_text = f"ツール実行結果 ({server_name}/{tool_name}): {result.content}"
updated_response = updated_response.replace(call_json, result_text)
except Exception as e:
error_text = f"ツール実行エラー: {e}"
updated_response = updated_response.replace(call_json, error_text)
return updated_response
def _format_tools_for_claude(self, tools_by_server: Dict[str, List]) -> str:
"""ツール情報をClaude用にフォーマット"""
formatted = []
for server_name, tools in tools_by_server.items():
formatted.append(f"**{server_name}:**")
for tool in tools:
formatted.append(f" - {tool.name}: {tool.description}")
if hasattr(tool, 'inputSchema'):
formatted.append(f" 引数: {json.dumps(tool.inputSchema, ensure_ascii=False)}")
return "\n".join(formatted)
# 使用例
async def main():
# MCP サーバー設定
servers = [
MCPServer(
name="filesystem",
command="python",
args=["-m", "mcp_server_filesystem"],
env={"PYTHONPATH": "."}
),
MCPServer(
name="database",
command="node",
args=["mcp-server-postgres.js"],
env={"DB_CONNECTION_STRING": "postgresql://localhost/mydb"}
),
MCPServer(
name="web_search",
command="python",
args=["-m", "mcp_server_web_search"],
env={"SEARCH_API_KEY": "your-search-api-key"}
)
]
# エージェント初期化
agent = MCPIntegrationAgent(
anthropic_api_key="your-anthropic-api-key"
)
# MCP サーバー接続
await agent.initialize_mcp_servers(servers)
# タスク実行例
result = await agent.execute_with_mcp_tools(
"プロジェクトのREADME.mdファイルを読み取り、データベースから関連する統計情報を取得して、最新の市場動向を検索してレポートを作成してください。",
server_names=["filesystem", "database", "web_search"]
)
print("実行結果:")
print(result)
if __name__ == "__main__":
asyncio.run(main())
高度な設定とカスタマイズ¶
1. GitHub Actions統合¶
# .github/workflows/ai-agent-ci.yml
name: AI Agent CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
ai-code-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Claude Code CLI
run: |
npm install -g @anthropic/claude-cli
claude auth login --api-key "${{ secrets.ANTHROPIC_API_KEY }}"
- name: AI Code Review
run: |
claude review --format json --output review-results.json
- name: Upload Review Results
uses: actions/upload-artifact@v4
with:
name: ai-review-results
path: review-results.json
automated-testing:
runs-on: ubuntu-latest
needs: ai-code-review
steps:
- uses: actions/checkout@v4
- name: Generate AI Tests
env:
ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
run: |
claude generate-tests --coverage 90 --output tests/generated/
- name: Run Generated Tests
run: |
npm test -- tests/generated/
- name: Coverage Report
run: |
npm run coverage -- --coverageDirectory=coverage/ai-generated
auto-deploy:
runs-on: ubuntu-latest
needs: [ai-code-review, automated-testing]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: AI Deployment Validation
env:
ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
run: |
claude validate-deployment --environment production
- name: Deploy with AI Monitoring
run: |
# デプロイ処理...
claude monitor-deployment --duration 300 --alerts-webhook "${{ secrets.SLACK_WEBHOOK }}"
2. 詳細パフォーマンス設定¶
{
"claude_code_config": {
"performance": {
"cache": {
"enabled": true,
"ttl": 3600,
"max_size": "500MB",
"strategy": "lru"
},
"concurrency": {
"max_parallel_requests": 5,
"request_queue_size": 50,
"timeout": 30000
},
"optimization": {
"context_compression": true,
"incremental_updates": true,
"smart_batching": true
}
},
"quality": {
"code_standards": {
"eslint_config": ".eslintrc.js",
"prettier_config": ".prettierrc",
"typescript_strict": true
},
"testing": {
"min_coverage": 85,
"auto_generate_tests": true,
"test_frameworks": ["jest", "vitest", "playwright"]
}
},
"security": {
"scan_dependencies": true,
"check_secrets": true,
"validate_inputs": true,
"audit_logs": true
}
}
}
トラブルシューティング¶
1. よくある問題と解決策¶
// troubleshooting/DiagnosticTools.ts
export class ClaudeCodeDiagnostics {
async diagnoseConnection(): Promise<DiagnosticResult> {
const results: DiagnosticResult = {
apiConnection: false,
modelAccess: false,
mcpServers: {},
githubIntegration: false,
recommendations: []
};
try {
// API接続テスト
const client = new ClaudeCodeClient();
await client.ping();
results.apiConnection = true;
// モデルアクセステスト
const response = await client.complete({
prompt: "Test connection",
model: "claude-sonnet-4",
maxTokens: 10
});
results.modelAccess = !!response;
} catch (error) {
results.recommendations.push({
issue: "API接続エラー",
solution: "ANTHROPIC_API_KEYを確認し、ネットワーク接続をチェックしてください",
error: error.message
});
}
// MCP サーバー診断
for (const serverName of this.getConfiguredMCPServers()) {
try {
const isHealthy = await this.checkMCPServerHealth(serverName);
results.mcpServers[serverName] = isHealthy;
if (!isHealthy) {
results.recommendations.push({
issue: `MCP サーバー "${serverName}" が応答しません`,
solution: `サーバーを再起動するか、設定を確認してください`,
command: `claude mcp restart ${serverName}`
});
}
} catch (error) {
results.mcpServers[serverName] = false;
results.recommendations.push({
issue: `MCP サーバー "${serverName}" エラー`,
solution: `設定ファイルとログを確認してください`,
error: error.message
});
}
}
return results;
}
async optimizePerformance(): Promise<OptimizationResult> {
const analysis = await this.analyzePerformance();
const optimizations: Optimization[] = [];
// レスポンス時間が遅い場合
if (analysis.averageResponseTime > 5000) {
optimizations.push({
type: "cache",
description: "レスポンスキャッシュを有効化",
impact: "50-70%高速化",
implementation: "config.cache.enabled = true"
});
}
// メモリ使用量が多い場合
if (analysis.memoryUsage > 1000) {
optimizations.push({
type: "memory",
description: "コンテキスト圧縮を有効化",
impact: "30-40%メモリ削減",
implementation: "config.optimization.context_compression = true"
});
}
// 同時リクエスト数の最適化
if (analysis.concurrentRequests > 10) {
optimizations.push({
type: "concurrency",
description: "並行処理数を調整",
impact: "安定性向上",
implementation: `config.concurrency.max_parallel_requests = ${Math.ceil(analysis.concurrentRequests * 0.7)}`
});
}
return {
current_performance: analysis,
optimizations,
estimated_improvement: this.calculateEstimatedImprovement(optimizations)
};
}
async generateDebugReport(): Promise<string> {
const diagnostic = await this.diagnoseConnection();
const performance = await this.optimizePerformance();
const logs = await this.collectRecentLogs();
return `
# Claude Code Debug Report
Generated: ${new Date().toISOString()}
## Connection Status
- API Connection: ${diagnostic.apiConnection ? '✅' : '❌'}
- Model Access: ${diagnostic.modelAccess ? '✅' : '❌'}
- GitHub Integration: ${diagnostic.githubIntegration ? '✅' : '❌'}
## MCP Servers
${Object.entries(diagnostic.mcpServers)
.map(([name, status]) => `- ${name}: ${status ? '✅' : '❌'}`)
.join('\n')}
## Performance Analysis
- Average Response Time: ${performance.current_performance.averageResponseTime}ms
- Memory Usage: ${performance.current_performance.memoryUsage}MB
- Cache Hit Rate: ${performance.current_performance.cacheHitRate}%
## Recommendations
${diagnostic.recommendations
.map(rec => `- **${rec.issue}**: ${rec.solution}`)
.join('\n')}
## Recent Errors
${logs.errors.slice(0, 5).map(error => `- ${error.timestamp}: ${error.message}`).join('\n')}
## Optimization Suggestions
${performance.optimizations
.map(opt => `- ${opt.description} (${opt.impact})`)
.join('\n')}
`;
}
}
// 使用例
const diagnostics = new ClaudeCodeDiagnostics();
// 問題診断
diagnostics.diagnoseConnection().then(result => {
console.log('Diagnostic Results:', result);
if (result.recommendations.length > 0) {
console.log('\n推奨アクション:');
result.recommendations.forEach(rec => {
console.log(`- ${rec.solution}`);
if (rec.command) {
console.log(` 実行: ${rec.command}`);
}
});
}
});
// デバッグレポート生成
diagnostics.generateDebugReport().then(report => {
console.log(report);
});
2. ログ解析と監視¶
# monitoring/claude_monitor.py
import asyncio
import json
import logging
from datetime import datetime, timedelta
from typing import List, Dict, Any
from dataclasses import dataclass, asdict
import aiofiles
import psutil
@dataclass
class PerformanceMetric:
timestamp: datetime
response_time: float
memory_usage: float
cpu_usage: float
cache_hit_rate: float
error_rate: float
class ClaudeCodeMonitor:
def __init__(self, log_file: str = "claude_code.log"):
self.log_file = log_file
self.metrics: List[PerformanceMetric] = []
self.alerts: List[Dict[str, Any]] = []
# ログ設定
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_file),
logging.StreamHandler()
]
)
self.logger = logging.getLogger('ClaudeCodeMonitor')
async def collect_metrics(self) -> PerformanceMetric:
"""現在のパフォーマンスメトリクスを収集"""
# システムメトリクス
cpu_usage = psutil.cpu_percent(interval=1)
memory = psutil.virtual_memory()
memory_usage = memory.percent
# Claude Code固有メトリクス(ログから解析)
response_time = await self._calculate_avg_response_time()
cache_hit_rate = await self._calculate_cache_hit_rate()
error_rate = await self._calculate_error_rate()
metric = PerformanceMetric(
timestamp=datetime.now(),
response_time=response_time,
memory_usage=memory_usage,
cpu_usage=cpu_usage,
cache_hit_rate=cache_hit_rate,
error_rate=error_rate
)
self.metrics.append(metric)
# 古いメトリクスを削除(24時間以上前)
cutoff_time = datetime.now() - timedelta(hours=24)
self.metrics = [m for m in self.metrics if m.timestamp > cutoff_time]
return metric
async def _calculate_avg_response_time(self) -> float:
"""過去1時間の平均レスポンス時間を計算"""
try:
async with aiofiles.open(self.log_file, 'r') as f:
content = await f.read()
# レスポンス時間のログエントリを解析
import re
response_time_pattern = r'response_time:(\d+\.?\d*)ms'
matches = re.findall(response_time_pattern, content)
if matches:
times = [float(match) for match in matches[-100:]] # 最新100件
return sum(times) / len(times)
return 0.0
except Exception:
return 0.0
async def _calculate_cache_hit_rate(self) -> float:
"""キャッシュヒット率を計算"""
try:
async with aiofiles.open(self.log_file, 'r') as f:
content = await f.read()
cache_hits = content.count('cache:hit')
cache_misses = content.count('cache:miss')
total = cache_hits + cache_misses
return (cache_hits / total * 100) if total > 0 else 0.0
except Exception:
return 0.0
async def _calculate_error_rate(self) -> float:
"""エラー率を計算"""
try:
async with aiofiles.open(self.log_file, 'r') as f:
content = await f.read()
error_count = content.count('ERROR')
total_requests = content.count('REQUEST')
return (error_count / total_requests * 100) if total_requests > 0 else 0.0
except Exception:
return 0.0
async def check_alerts(self, metric: PerformanceMetric):
"""アラート条件をチェック"""
alerts = []
# レスポンス時間アラート
if metric.response_time > 10000: # 10秒以上
alerts.append({
'type': 'performance',
'severity': 'critical',
'message': f'レスポンス時間が異常に長い: {metric.response_time}ms',
'recommendation': 'キャッシュ設定を確認し、不要なコンテキストを削減してください'
})
# メモリ使用量アラート
if metric.memory_usage > 90:
alerts.append({
'type': 'resource',
'severity': 'warning',
'message': f'メモリ使用量が高い: {metric.memory_usage}%',
'recommendation': 'コンテキスト圧縮を有効化するか、並行処理数を削減してください'
})
# エラー率アラート
if metric.error_rate > 5: # 5%以上
alerts.append({
'type': 'error',
'severity': 'critical',
'message': f'エラー率が高い: {metric.error_rate}%',
'recommendation': 'ログを確認し、根本原因を特定してください'
})
# キャッシュヒット率アラート
if metric.cache_hit_rate < 50: # 50%未満
alerts.append({
'type': 'cache',
'severity': 'info',
'message': f'キャッシュヒット率が低い: {metric.cache_hit_rate}%',
'recommendation': 'キャッシュTTLを調整するか、キャッシュサイズを増やしてください'
})
for alert in alerts:
alert['timestamp'] = datetime.now().isoformat()
self.alerts.append(alert)
self.logger.warning(f"ALERT: {alert['message']}")
return alerts
async def generate_report(self) -> Dict[str, Any]:
"""パフォーマンスレポートを生成"""
if not self.metrics:
return {"error": "メトリクスデータがありません"}
recent_metrics = self.metrics[-100:] # 最新100件
avg_response_time = sum(m.response_time for m in recent_metrics) / len(recent_metrics)
avg_memory_usage = sum(m.memory_usage for m in recent_metrics) / len(recent_metrics)
avg_cache_hit_rate = sum(m.cache_hit_rate for m in recent_metrics) / len(recent_metrics)
avg_error_rate = sum(m.error_rate for m in recent_metrics) / len(recent_metrics)
return {
"report_generated": datetime.now().isoformat(),
"period": "過去24時間",
"summary": {
"average_response_time": f"{avg_response_time:.2f}ms",
"average_memory_usage": f"{avg_memory_usage:.1f}%",
"average_cache_hit_rate": f"{avg_cache_hit_rate:.1f}%",
"average_error_rate": f"{avg_error_rate:.2f}%"
},
"recent_alerts": len([a for a in self.alerts if
datetime.fromisoformat(a['timestamp']) > datetime.now() - timedelta(hours=1)]),
"recommendations": self._generate_recommendations(recent_metrics),
"detailed_metrics": [asdict(m) for m in recent_metrics[-20:]] # 最新20件の詳細
}
def _generate_recommendations(self, metrics: List[PerformanceMetric]) -> List[str]:
"""メトリクスに基づく推奨事項を生成"""
recommendations = []
avg_response = sum(m.response_time for m in metrics) / len(metrics)
avg_cache_hit = sum(m.cache_hit_rate for m in metrics) / len(metrics)
avg_error = sum(m.error_rate for m in metrics) / len(metrics)
if avg_response > 5000:
recommendations.append("レスポンス時間が長いため、コンテキスト圧縮またはキャッシュの有効化を検討してください")
if avg_cache_hit < 70:
recommendations.append("キャッシュヒット率が低いため、キャッシュ戦略の見直しを推奨します")
if avg_error > 2:
recommendations.append("エラー率が高いため、入力検証とエラーハンドリングの強化が必要です")
return recommendations
# 使用例
async def main():
monitor = ClaudeCodeMonitor()
# 監視ループ
while True:
try:
# メトリクス収集
metric = await monitor.collect_metrics()
# アラートチェック
alerts = await monitor.check_alerts(metric)
# 1時間ごとにレポート生成
if datetime.now().minute == 0:
report = await monitor.generate_report()
print(json.dumps(report, indent=2, ensure_ascii=False))
# 5分間待機
await asyncio.sleep(300)
except KeyboardInterrupt:
print("監視を停止します...")
break
except Exception as e:
monitor.logger.error(f"監視エラー: {e}")
await asyncio.sleep(60) # エラー時は1分待機
if __name__ == "__main__":
asyncio.run(main())
パフォーマンス最適化¶
1. コンテキスト管理最適化¶
// optimization/ContextManager.ts
export class SmartContextManager {
private contextCache: Map<string, CachedContext> = new Map();
private compressionRatio: number = 0.7;
async optimizeContext(context: string, maxTokens: number): Promise<string> {
const contextHash = this.hashContext(context);
// キャッシュチェック
if (this.contextCache.has(contextHash)) {
const cached = this.contextCache.get(contextHash)!;
if (Date.now() - cached.timestamp < 3600000) { // 1時間有効
return cached.optimizedContext;
}
}
let optimizedContext = context;
// トークン数が上限を超える場合は圧縮
const tokenCount = this.countTokens(context);
if (tokenCount > maxTokens) {
optimizedContext = await this.compressContext(context, maxTokens);
}
// 関連性の低い情報を除去
optimizedContext = await this.removeIrrelevantInfo(optimizedContext);
// 重要な情報を強調
optimizedContext = this.highlightImportantInfo(optimizedContext);
// キャッシュに保存
this.contextCache.set(contextHash, {
originalContext: context,
optimizedContext,
timestamp: Date.now(),
compressionRatio: context.length / optimizedContext.length
});
return optimizedContext;
}
private async compressContext(context: string, maxTokens: number): Promise<string> {
// セクション別に重要度を分析
const sections = this.parseIntoSections(context);
const scoredSections = await this.scoreRelevance(sections);
// 重要度順にソートして必要な分だけ選択
scoredSections.sort((a, b) => b.score - a.score);
let compressedContext = "";
let currentTokens = 0;
for (const section of scoredSections) {
const sectionTokens = this.countTokens(section.content);
if (currentTokens + sectionTokens <= maxTokens * this.compressionRatio) {
compressedContext += section.content + "\n";
currentTokens += sectionTokens;
}
}
return compressedContext;
}
private parseIntoSections(context: string): Section[] {
// コンテキストを論理的なセクションに分割
const sections: Section[] = [];
const lines = context.split('\n');
let currentSection: Section = { type: 'general', content: '', startLine: 0 };
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// コードブロックの検出
if (line.startsWith('```')) {
if (currentSection.content) {
sections.push(currentSection);
}
currentSection = { type: 'code', content: line + '\n', startLine: i };
}
// 見出しの検出
else if (line.startsWith('#')) {
if (currentSection.content) {
sections.push(currentSection);
}
currentSection = { type: 'heading', content: line + '\n', startLine: i };
}
// エラーメッセージの検出
else if (line.includes('Error') || line.includes('Exception')) {
if (currentSection.content) {
sections.push(currentSection);
}
currentSection = { type: 'error', content: line + '\n', startLine: i };
}
else {
currentSection.content += line + '\n';
}
}
if (currentSection.content) {
sections.push(currentSection);
}
return sections;
}
private async scoreRelevance(sections: Section[]): Promise<ScoredSection[]> {
// セクションの重要度スコアリング
return sections.map(section => {
let score = 0;
// タイプ別基本スコア
switch (section.type) {
case 'error': score += 10; break;
case 'code': score += 8; break;
case 'heading': score += 6; break;
case 'general': score += 3; break;
}
// キーワードボーナス
const importantKeywords = ['error', 'bug', 'fix', 'implement', 'TODO', 'FIXME'];
for (const keyword of importantKeywords) {
if (section.content.toLowerCase().includes(keyword.toLowerCase())) {
score += 2;
}
}
// 長さペナルティ(長すぎるセクションは重要度を下げる)
if (section.content.length > 1000) {
score -= Math.floor(section.content.length / 1000);
}
return { ...section, score };
});
}
}
2. リクエスト最適化¶
// optimization/RequestOptimizer.ts
export class RequestOptimizer {
private requestQueue: RequestQueue = new RequestQueue();
private batchProcessor: BatchProcessor = new BatchProcessor();
async optimizeRequest(request: ClaudeRequest): Promise<ClaudeResponse> {
// リクエストの種類を分析
const requestType = this.analyzeRequestType(request);
switch (requestType) {
case 'batch_suitable':
return this.batchProcessor.addToBatch(request);
case 'high_priority':
return this.executeImmediate(request);
case 'cacheable':
return this.executeWithCaching(request);
default:
return this.requestQueue.enqueue(request);
}
}
private analyzeRequestType(request: ClaudeRequest): RequestType {
// コード生成系は並列処理可能
if (request.prompt.includes('generate') && request.prompt.includes('code')) {
return 'batch_suitable';
}
// エラー修正は高優先度
if (request.prompt.includes('error') || request.prompt.includes('fix')) {
return 'high_priority';
}
// 説明系はキャッシュ可能
if (request.prompt.includes('explain') || request.prompt.includes('what is')) {
return 'cacheable';
}
return 'standard';
}
async executeWithCaching(request: ClaudeRequest): Promise<ClaudeResponse> {
const cacheKey = this.generateCacheKey(request);
// キャッシュチェック
const cached = await this.cache.get(cacheKey);
if (cached && !this.isCacheExpired(cached)) {
return cached.response;
}
// 新しいリクエスト実行
const response = await this.executeRequest(request);
// キャッシュに保存
await this.cache.set(cacheKey, {
response,
timestamp: Date.now(),
ttl: this.calculateTTL(request)
});
return response;
}
}
パフォーマンス最適化のポイント
- コンテキスト圧縮: 不要な情報を除去し、重要な情報のみを保持
- リクエストバッチング: 類似したリクエストをまとめて処理
- インテリジェントキャッシング: リクエストの種類に応じたキャッシュ戦略
- 並列処理最適化: I/Oバウンドなタスクの効率的な並列実行
まとめ¶
- 実装レベルの深掘り - TypeScript/Pythonでの具体的な実装例を提供
- 詳細設定ガイド - MCP統合、GitHub Actions、パフォーマンス設定の完全手順
- 実践的トラブルシューティング - 診断ツール、監視システム、最適化手法
- プロダクションレディ - セキュリティ、品質管理、監視を含む本格運用対応
Claude Sonnet 4×GitHub Copilotの真の実力を引き出すには、これらの実装詳細と最適化技術の理解が不可欠です。本記事の技術を活用して、次世代のAIエージェント開発を実現してください。