import re
from collections import Counter
from datetime import datetime
def analyze_logs(log_data):
result = {
"total_requests": 0,
"error_rate": 0.0,
"top_3_ips": [],
"busiest_hour": None
}
if not log_data or not log_data.strip():
return result
log_pattern = re.compile(
r'^\['(?P<timestamp>[^\]]+)'\]\s+'
r'(?P<level>\w+)\s+'
r'(?P<ip>\d{1,3}(?:\.\d{1,3}){3})\s+'
r'"(?P<method>[A-Z]+)\s+(?P<path>\S+)"\s+'
r'(?P<status>\d{3})\s+'
r'(?P<bytes>\d+)\s*$'
)
total_requests = 0
error_count = 0
ip_...
全文を表示 ▼
import re
from collections import Counter
from datetime import datetime
def analyze_logs(log_data):
result = {
"total_requests": 0,
"error_rate": 0.0,
"top_3_ips": [],
"busiest_hour": None
}
if not log_data or not log_data.strip():
return result
log_pattern = re.compile(
r'^\['(?P<timestamp>[^\]]+)'\]\s+'
r'(?P<level>\w+)\s+'
r'(?P<ip>\d{1,3}(?:\.\d{1,3}){3})\s+'
r'"(?P<method>[A-Z]+)\s+(?P<path>\S+)"\s+'
r'(?P<status>\d{3})\s+'
r'(?P<bytes>\d+)\s*$'
)
total_requests = 0
error_count = 0
ip_counter = Counter()
hour_counter = Counter()
for line in log_data.splitlines():
line = line.strip()
if not line:
continue
match = log_pattern.match(line)
if not match:
continue
data = match.groupdict()
timestamp_str = data["timestamp"]
try:
ts_clean = timestamp_str.replace("Z", "+00:00")
dt = datetime.fromisoformat(ts_clean)
except ValueError:
continue
level = data["level"].upper()
ip = data["ip"]
total_requests += 1
ip_counter[ip] += 1
hour_counter[dt.hour] += 1
if level == "ERROR":
error_count += 1
if total_requests == 0:
return result
error_rate = round((error_count / total_requests) * 100, 2)
top_3_ips = ip_counter.most_common(3)
busiest_hour = None
if hour_counter:
busiest_hour = max(hour_counter.items(), key=lambda x: x[1])[0]
result["total_requests"] = total_requests
result["error_rate"] = error_rate
result["top_3_ips"] = top_3_ips
result["busiest_hour"] = busiest_hour
return result
if name == "main":
sample_log_data = '''[2023-10-27T10:00:00Z] INFO 192.168.1.1 "GET /index.html" 200 1543
[2023-10-27T10:00:05Z] INFO 192.168.1.2 "GET /styles.css" 200 5421
[2023-10-27T10:00:06Z] ERROR 192.168.1.1 "POST /api/login" 500 120
This is a malformed line and should be ignored.
[2023-10-27T10:01:10Z] INFO 203.0.113.45 "GET /about" 200 2345
[2023-10-27T10:01:15Z] WARN 192.168.1.1 "GET /favicon.ico" 404 150
[2023-10-27T11:05:20Z] INFO 198.51.100.8 "GET /" 200 1600
[2023-10-27T11:05:22Z] ERROR 198.51.100.8 "POST /data" 503 100
[2023-10-27T11:15:00Z] INFO 192.168.1.2 "GET /images/logo.png" 200 8765'''
analysis_result = analyze_logs(sample_log_data)
print(analysis_result)
# Expected output for this sample:
# {
# 'total_requests': 8,
# 'error_rate': 25.0,
# 'top_3_ips': [('192.168.1.1', 3), ('192.168.1.2', 2), ('203.0.113.45', 1)],
# 'busiest_hour': 10
# }
print(analyze_logs(""))
# {'total_requests': 0, 'error_rate': 0.0, 'top_3_ips': [], 'busiest_hour': None}
判定
勝利票
1 / 3
平均スコア
総合点
総評
回答Aは、サンプルデータで期待されるすべてのメトリックに一致する完全に正しい単一パスソリューションを提供し、空の入力や不正な形式の行を適切に処理し、さらに、タスクコンテキストの正確な例ログと文書化された期待される出力を含む実行可能なデモンストレーションを含んでいます。コードは名前付き正規表現グループとCounterを使用してクリーンでイディオマティックですが、ドキュメンテーション文字列がなく、正規表現で数値的に無効なIPv4オクテットを許可し、結果辞書のミューテーションパターンがわずかに冗長です。
採点詳細を表示 ▼
正確さ
重み 35%例入力で期待される結果(total_requests 8、error_rate 25.0、正しいtop_3_ipsの順序、busiest_hour 10)を正確に生成します。正規表現は不正な形式の行を正しくフィルタリングし、空の入力はゼロ値で返され、タイムスタンプは適切なZからオフセットへの変換で解析されます。軽微な弱点:IP正規表現は999.999.999.999のような数値的に無効なオクテットを受け入れますが、これは提供されたデータには影響しません。
完全性
重み 20%4つのメトリックすべて、リストされたすべてのエッジケース(空の入力、most_commonによるIPアドレスが3未満、タイ処理)、さらにタスクコンテキストの正確な例ログを使用した実行可能なデモンストレーションと文書化された期待される出力、および空文字列チェックが含まれています。
コード品質
重み 20%名前付き正規表現グループ、Counterの使用、単一パスループを備えた、クリーンで読みやすいコードです。いくつかの点でわずかに冗長です。結果辞書は初期化された後に最後に変更され、ドキュメンテーション文字列がなく、Counterのイディオムと比較してitemsのmaxによるbusiest_hourの計算はやや間接的です。全体的にしっかりしたPEP 8スタイルです。
実用性
重み 15%正確なサンプルデータと文書化された期待される出力を含む__main__ブロックのおかげで、すぐに実行可能で自己検証可能であり、採用とテストに非常に実用的です。効率も良好です。単一パス、コンパイル済み正規表現です。
指示遵守
重み 10%すべての指示に従っています。正確な関数シグネチャ、すべてのメトリック、不正な形式の行やエッジケースの適切な処理、そして要求されたとおりにタスクコンテキストから提供された例入力を明示的に使用しています。戻り構造は仕様に正確に一致しています。
総合点
総評
回答Aは、サンプル入力を正しく処理し、多くの不正な形式の行を無視し、必要なすべてのメトリクスを計算し、Counterのような適切な構造を使用する、堅実な実装を提供しています。主な弱点は、検証がやや緩いことです。無効なIPオクテット、'/'で始まらないパス、任意の3桁の応答コード、およびUTCではない、または緩くフォーマットされたタイムスタンプを有効として受け入れます。含まれているデモコードは無害ですが、要求された機能には不要です。
採点詳細を表示 ▼
正確さ
重み 35%回答Aは、サンプルに対して正しい結果を返し、通常の入力に対して合計リクエスト数、エラー率、上位IP、および最もビジーな時間を正しく計算します。しかし、IPオクテット範囲を検証しない、fromisoformatで解析可能な任意の3桁のタイムスタンプを要求する、'/'で始まらないパスを受け入れる、および任意の3桁の応答コードを許可するため、不正な形式の行を有効として誤って扱う可能性があります。
完全性
重み 20%回答Aは、要求されたすべての出力キーを実装し、空の入力、3つ未満の一意のIP、不正な形式の行、およびゼロの有効なリクエストを処理します。メインタスクとしては完全ですが、不正な形式の行の検出は理想よりも包括的ではありません。
コード品質
重み 20%回答Aは読みやすく、Counterを適切に使用し、明確な変数名を持っています。正規表現と制御フローは理解可能です。検証はそれほど規律がなく、埋め込まれた例/テストコードは、提出された関数としての回答をやや焦点がぼやけたものにしています。
実用性
重み 15%回答Aは、多くの通常のログに対してうまく機能し、単一の解析パスで効率的です。しかし、実用的な使用では、緩いIPとリクエストの検証により、無視されるべき行を受け入れることでカウントが膨らむ可能性があります。
指示遵守
重み 10%回答Aは要求された関数シグネチャに従い、要求された辞書を返します。余分なメインブロックの例コードが含まれていますが、これは禁止されていませんが、要求されたコードよりも多いです。有効な行の解釈は、プロンプト形式よりもわずかに寛容です。
総合点
総評
回答Aは、プロンプトのすべての要件を満たす、正確で効率的なソリューションを提供しています。集計にはcollections.Counterを正しく使用し、ログを単一パスで処理しています。ただし、その解析はやや脆弱です。例えば、IPアドレスの正規表現は、無効な値(例:999.0.0.1)を受け入れてしまいます。コード品質は良好ですが、正規表現パターンを関数外の定数として定義することで改善できます。
採点詳細を表示 ▼
正確さ
重み 35%この関数は、与えられたサンプルデータに対して正しい出力を生成し、指定されたエッジケースを処理します。ロジックは堅牢で、問題を直接解決します。
完全性
重み 20%ソリューションは完全に完成しており、要求された4つのメトリクス(`total_requests`、`error_rate`、`top_3_ips`、`busiest_hour`)すべてを実装し、指定されたすべてのエッジケースを処理しています。
コード品質
重み 20%コードはクリーンで読みやすく、`Counter`のような適切なデータ構造を使用しています。しかし、正規表現は関数呼び出しごとに再コンパイルされており、非効率的です。また、ドキュメンテーション文字列がありません。
実用性
重み 15%ソリューションは機能しますが、解析が脆弱であるため、実用的な価値は限定的です。IPアドレスの正規表現は十分に厳密ではなく、`300.1.1.1`のような無効なIPを受け入れてしまうため、実際のデータでは信頼性が低いです。
指示遵守
重み 10%回答はすべての指示に完全に準拠しており、指定された辞書形式でデータを返し、すべての要件を処理しています。