debug log
This commit is contained in:
219
analyze_nginx_logs.py
Normal file
219
analyze_nginx_logs.py
Normal file
@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
nginxログ分析: チェックイン・画像アップロード機能の使用状況を確認
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import re
|
||||
from collections import defaultdict, Counter
|
||||
from datetime import datetime
|
||||
|
||||
def analyze_nginx_logs():
|
||||
"""
|
||||
nginxログを分析してチェックイン・画像関連の活動を確認
|
||||
"""
|
||||
print("🔍 nginx ログ分析: チェックイン・画像アップロード機能")
|
||||
print("=" * 70)
|
||||
|
||||
# nginxログを取得
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['docker-compose', 'logs', '--tail=500', 'nginx'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd='/Volumes/PortableSSD1TB/main/GifuTabi/rogaining_srv_exdb-2/rogaining_srv'
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(f"❌ ログ取得エラー: {result.stderr}")
|
||||
return
|
||||
|
||||
log_lines = result.stdout.split('\n')
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 実行エラー: {e}")
|
||||
return
|
||||
|
||||
# 分析用パターン
|
||||
patterns = {
|
||||
'checkin_api': re.compile(r'(POST|GET).*/(checkin_from_rogapp|checkin|addCheckin)', re.I),
|
||||
'image_api': re.compile(r'(POST|GET).*/checkinimage', re.I),
|
||||
'bulk_upload': re.compile(r'(POST|GET).*/bulk_upload', re.I),
|
||||
'dart_client': re.compile(r'"Dart/[\d\.]+ \(dart:io\)"'),
|
||||
'api_access': re.compile(r'"(GET|POST|PUT|PATCH|DELETE) (/api/[^"]+)'),
|
||||
'status_codes': re.compile(r'" (\d{3}) \d+')
|
||||
}
|
||||
|
||||
# 分析結果
|
||||
results = {
|
||||
'checkin_requests': [],
|
||||
'image_requests': [],
|
||||
'bulk_upload_requests': [],
|
||||
'dart_requests': [],
|
||||
'api_endpoints': Counter(),
|
||||
'status_codes': Counter(),
|
||||
'client_ips': Counter()
|
||||
}
|
||||
|
||||
# ログ行の解析
|
||||
for line in log_lines:
|
||||
if not line.strip() or 'nginx-1' not in line:
|
||||
continue
|
||||
|
||||
# 各パターンをチェック
|
||||
if patterns['checkin_api'].search(line):
|
||||
results['checkin_requests'].append(line)
|
||||
|
||||
if patterns['image_api'].search(line):
|
||||
results['image_requests'].append(line)
|
||||
|
||||
if patterns['bulk_upload'].search(line):
|
||||
results['bulk_upload_requests'].append(line)
|
||||
|
||||
if patterns['dart_client'].search(line):
|
||||
results['dart_requests'].append(line)
|
||||
|
||||
# APIエンドポイント集計
|
||||
api_match = patterns['api_access'].search(line)
|
||||
if api_match:
|
||||
method, endpoint = api_match.groups()
|
||||
results['api_endpoints'][f"{method} {endpoint}"] += 1
|
||||
|
||||
# ステータスコード集計
|
||||
status_match = patterns['status_codes'].search(line)
|
||||
if status_match:
|
||||
results['status_codes'][status_match.group(1)] += 1
|
||||
|
||||
# クライアントIP集計
|
||||
ip_match = re.search(r'(\d+\.\d+\.\d+\.\d+) - -', line)
|
||||
if ip_match:
|
||||
results['client_ips'][ip_match.group(1)] += 1
|
||||
|
||||
# 結果表示
|
||||
print_analysis_results(results)
|
||||
|
||||
def print_analysis_results(results):
|
||||
"""
|
||||
分析結果を表示
|
||||
"""
|
||||
|
||||
# 1. チェックインAPI使用状況
|
||||
print(f"\n📍 チェックインAPI アクセス状況")
|
||||
print("-" * 50)
|
||||
if results['checkin_requests']:
|
||||
print(f"件数: {len(results['checkin_requests'])}件")
|
||||
for req in results['checkin_requests'][-5:]: # 最新5件
|
||||
print(f" {extract_log_info(req)}")
|
||||
else:
|
||||
print("❌ チェックインAPIへのアクセスなし")
|
||||
|
||||
# 2. 画像アップロードAPI使用状況
|
||||
print(f"\n🖼️ 画像アップロードAPI アクセス状況")
|
||||
print("-" * 50)
|
||||
if results['image_requests']:
|
||||
print(f"件数: {len(results['image_requests'])}件")
|
||||
for req in results['image_requests'][-5:]: # 最新5件
|
||||
print(f" {extract_log_info(req)}")
|
||||
else:
|
||||
print("❌ 画像アップロードAPIへのアクセスなし")
|
||||
|
||||
# 3. 一括アップロードAPI使用状況
|
||||
print(f"\n📤 一括アップロードAPI アクセス状況")
|
||||
print("-" * 50)
|
||||
if results['bulk_upload_requests']:
|
||||
print(f"件数: {len(results['bulk_upload_requests'])}件")
|
||||
for req in results['bulk_upload_requests'][-5:]: # 最新5件
|
||||
print(f" {extract_log_info(req)}")
|
||||
else:
|
||||
print("❌ 一括アップロードAPIへのアクセスなし")
|
||||
|
||||
# 4. Dartクライアント(スマホアプリ)の活動
|
||||
print(f"\n📱 スマホアプリ(Dart)アクセス状況")
|
||||
print("-" * 50)
|
||||
if results['dart_requests']:
|
||||
print(f"件数: {len(results['dart_requests'])}件")
|
||||
|
||||
# Dartクライアントが使用しているAPIエンドポイント
|
||||
dart_endpoints = Counter()
|
||||
for req in results['dart_requests']:
|
||||
api_match = re.search(r'"(GET|POST|PUT|PATCH|DELETE) (/api/[^"]+)', req)
|
||||
if api_match:
|
||||
method, endpoint = api_match.groups()
|
||||
dart_endpoints[f"{method} {endpoint}"] += 1
|
||||
|
||||
print("主要なAPIエンドポイント:")
|
||||
for endpoint, count in dart_endpoints.most_common(10):
|
||||
print(f" {endpoint}: {count}回")
|
||||
else:
|
||||
print("❌ スマホアプリからのアクセスなし")
|
||||
|
||||
# 5. 全体のAPI使用状況(Top 10)
|
||||
print(f"\n🌐 API使用状況 (Top 10)")
|
||||
print("-" * 50)
|
||||
for endpoint, count in results['api_endpoints'].most_common(10):
|
||||
print(f" {endpoint}: {count}回")
|
||||
|
||||
# 6. HTTPステータスコード分布
|
||||
print(f"\n📊 HTTPステータスコード分布")
|
||||
print("-" * 50)
|
||||
for status, count in results['status_codes'].most_common():
|
||||
status_emoji = get_status_emoji(status)
|
||||
print(f" {status_emoji} {status}: {count}回")
|
||||
|
||||
# 7. クライアントIP分布
|
||||
print(f"\n🌍 アクセス元IP分布")
|
||||
print("-" * 50)
|
||||
for ip, count in results['client_ips'].most_common(5):
|
||||
ip_type = "🏠 ローカル" if ip.startswith(('192.168', '172.', '127.')) else "🌐 外部"
|
||||
print(f" {ip_type} {ip}: {count}回")
|
||||
|
||||
def extract_log_info(log_line):
|
||||
"""
|
||||
ログ行から重要な情報を抽出
|
||||
"""
|
||||
# 時刻を抽出
|
||||
time_match = re.search(r'\[([^\]]+)\]', log_line)
|
||||
time_str = time_match.group(1) if time_match else "Unknown"
|
||||
|
||||
# メソッドとパスを抽出
|
||||
method_match = re.search(r'"(GET|POST|PUT|PATCH|DELETE) ([^"]+)', log_line)
|
||||
method_path = method_match.groups() if method_match else ("Unknown", "Unknown")
|
||||
|
||||
# ステータスコードを抽出
|
||||
status_match = re.search(r'" (\d{3}) \d+', log_line)
|
||||
status = status_match.group(1) if status_match else "Unknown"
|
||||
|
||||
# User Agentを抽出
|
||||
ua_match = re.search(r'"([^"]+)" "[^"]*"$', log_line)
|
||||
user_agent = ua_match.group(1) if ua_match else "Unknown"
|
||||
|
||||
return f"{time_str} | {method_path[0]} {method_path[1][:50]}... | {status} | {user_agent[:20]}..."
|
||||
|
||||
def get_status_emoji(status_code):
|
||||
"""
|
||||
HTTPステータスコードに対応する絵文字を返す
|
||||
"""
|
||||
if status_code.startswith('2'):
|
||||
return '✅'
|
||||
elif status_code.startswith('3'):
|
||||
return '🔀'
|
||||
elif status_code.startswith('4'):
|
||||
return '❌'
|
||||
elif status_code.startswith('5'):
|
||||
return '💥'
|
||||
else:
|
||||
return '❓'
|
||||
|
||||
def main():
|
||||
try:
|
||||
analyze_nginx_logs()
|
||||
print(f"\n✅ 分析完了")
|
||||
print(f"\n💡 結論:")
|
||||
print(f" ログから、チェックイン・画像アップロード機能の実際の使用状況を確認できます")
|
||||
print(f" スマホアプリ(Dart)の活動状況も把握可能です")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ エラー: {e}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user