AI API を本番環境に統合する際、最も重要な指標の一つが SLA(Service Level Agreement)達成率です。API が応答不能になると、チーム全員に通知が飛ぶ——そんな体験をしたことがある方は多いのではないでしょうか。本稿では、HolySheep AI を例に、Python を使った SLA 監視システムの実装と、達成率の統計分析方法をお伝えします。

エラースcenario:SLA 監視に出発点あり

私が初めて AI API の監視を設定したのは、ある金曜日の夜でした。モニタリングダッシュボードでエラー率が急上昇し、確認してみると「ConnectionError: timeout after 30 seconds」というログが大量に出ていました。原因を調べると、API キーが環境変数から正しく読み込めていないことに加え、リトライロジックが未実装だったことが判明。この経験から、SLA 監視の重要性を痛感しました。

# api_monitor.py - HolySheheep AI SLA監視システム
import requests
import time
import json
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict
from typing import List, Optional
import statistics

@dataclass
class APIMetrics:
    timestamp: str
    endpoint: str
    status_code: Optional[int]
    response_time_ms: float
    success: bool
    error_type: Optional[str] = None
    error_message: Optional[str] = None

class HolySheepSLAMonitor:
    def __init__(self, api_key: str):
        self.base_url = "https://api.holysheep.ai/v1"
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        self.metrics: List[APIMetrics] = []
        self.sla_targets = {
            "availability": 99.9,  # 目標可用性 %
            "max_latency_ms": 200,  # 最大レイテンシ
            "p95_latency_ms": 100   # P95 レイテンシ
        }

    def check_endpoint(self, endpoint: str, timeout: int = 30) -> APIMetrics:
        """单个エンドポイントの可用性をチェック"""
        start_time = time.time()
        timestamp = datetime.utcnow().isoformat()
        
        try:
            response = requests.get(
                f"{self.base_url}/{endpoint}",
                headers=self.headers,
                timeout=timeout
            )
            response_time_ms = (time.time() - start_time) * 1000
            
            # 401 Unauthorized の處理
            if response.status_code == 401:
                return APIMetrics(
                    timestamp=timestamp,
                    endpoint=endpoint,
                    status_code=response.status_code,
                    response_time_ms=response_time_ms,
                    success=False,
                    error_type="AuthenticationError",
                    error_message="Invalid API key or expired token"
                )
            
            # 429 Too Many Requests (レート制限)
            if response.status_code == 429:
                return APIMetrics(
                    timestamp=timestamp,
                    endpoint=endpoint,
                    status_code=response.status_code,
                    response_time_ms=response_time_ms,
                    success=False,
                    error_type="RateLimitError",
                    error_message=response.json().get("error", {}).get("message", "Rate limit exceeded")
                )
            
            success = 200 <= response.status_code < 300
            return APIMetrics(
                timestamp=timestamp,
                endpoint=endpoint,
                status_code=response.status_code,
                response_time_ms=response_time_ms,
                success=success
            )
            
        except requests.exceptions.Timeout:
            return APIMetrics(
                timestamp=timestamp,
                endpoint=endpoint,
                status_code=None,
                response_time_ms=timeout * 1000,
                success=False,
                error_type="ConnectionTimeout",
                error_message=f"Request timeout after {timeout} seconds"
            )
        except requests.exceptions.ConnectionError as e:
            return APIMetrics(
                timestamp=timestamp,
                endpoint=endpoint,
                status_code=None,
                response_time_ms=0,
                success=False,
                error_type="ConnectionError",
                error_message=str(e)
            )
        except Exception as e:
            return APIMetrics(
                timestamp=timestamp,
                endpoint=endpoint,
                status_code=None,
                response_time_ms=0,
                success=False,
                error_type="UnknownError",
                error_message=str(e)
            )

    def run_health_check(self, interval_seconds: int = 60):
        """定期ヘルスチェックを実行"""
        endpoints = ["models", "health", "usage"]
        
        for endpoint in endpoints:
            metric = self.check_endpoint(endpoint)
            self.metrics.append(metric)
            print(f"[{metric.timestamp}] {endpoint}: {metric.success} ({metric.response_time_ms:.2f}ms)")
        
        time.sleep(interval_seconds)

使用例

monitor = HolySheepSLAMonitor(api_key="YOUR_HOLYSHEEP_API_KEY") print(f"HolySheep AI 監視開始 - ターゲットSLA: {monitor.sla_targets['availability']}%")

SLA 達成率の統計分析方法

監視データを収集するだけではなく、意味のある統計分析に変換することが重要です。特に HolySheep AI の場合、低コストで高可用性なサービスを活用する上で、可用性の可視化が不可欠です。

# sla_statistics.py - SLA達成率の統計分析
import json
from datetime import datetime, timedelta
from typing import Dict, List, Tuple
import statistics

class SLAStatistics:
    def __init__(self, metrics: List[APIMetrics]):
        self.metrics = metrics
    
    def calculate_availability(self) -> Dict[str, float]:
        """可用性率を計算"""
        if not self.metrics:
            return {"availability_percent": 0.0, "total_requests": 0, "failed_requests": 0}
        
        total = len(self.metrics)
        failed = sum(1 for m in self.metrics if not m.success)
        availability = ((total - failed) / total) * 100
        
        return {
            "availability_percent": round(availability, 4),
            "total_requests": total,
            "failed_requests": failed,
            "successful_requests": total - failed
        }
    
    def calculate_latency_stats(self) -> Dict[str, float]:
        """レイテンシ統計を計算"""
        response_times = [m.response_time_ms for m in self.metrics if m.success]
        
        if not response_times:
            return {"p50": 0, "p95": 0, "p99": 0, "avg": 0, "min": 0, "max": 0}
        
        sorted_times = sorted(response_times)
        
        return {
            "p50": round(sorted_times[int(len(sorted_times) * 0.50)], 2),
            "p95": round(sorted_times[int(len(sorted_times) * 0.95)], 2),
            "p99": round(sorted_times[int(len(sorted_times) * 0.99)], 2),
            "avg": round(statistics.mean(response_times), 2),
            "min": round(min(response_times), 2),
            "max": round(max(response_times), 2)
        }
    
    def categorize_errors(self) -> Dict[str, int]:
        """エラーをカテゴリ別に分類"""
        errors = {}
        for metric in self.metrics:
            if not metric.success and metric.error_type:
                errors[metric.error_type] = errors.get(metric.error_type, 0) + 1
        return errors
    
    def generate_sla_report(self, target_availability: float = 99.9) -> Dict:
        """包括的なSLAレポートを生成"""
        availability_data = self.calculate_availability()
        latency_data = self.calculate_latency_stats()
        error_data = self.categorize_errors()
        
        # 目標との比較
        sla_met = availability_data["availability_percent"] >= target_availability
        
        report = {
            "report_generated_at": datetime.utcnow().isoformat(),
            "sla_target_percent": target_availability,
            "sla_met": sla_met,
            "availability": availability_data,
            "latency": latency_data,
            "error_breakdown": error_data,
            "error_rate_percent": round(
                (availability_data["failed_requests"] / availability_data["total_requests"]) * 100 
                if availability_data["total_requests"] > 0 else 0, 4
            )
        }
        
        return report

    def export_json(self, filepath: str):
        """レポートをJSONファイルにエクスポート"""
        report = self.generate_sla_report()
        with open(filepath, "w", encoding="utf-8") as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        print(f"レポートを {filepath} にエクスポートしました")

使用例

stats = SLAStatistics(monitor.metrics) report = stats.generate_sla_report(target_availability=99.9) print(json.dumps(report, ensure_ascii=False, indent=2))

Slack / PagerDuty へのアラート通知

問題が検出されたら、即座にチームに通知する仕組みが本番運用には不可欠です。以下は Slack チャンネルに自動通知を送る実装例です。

# alerting.py - SLA違反時のSlack/PagerDuty通知
import requests
from typing import Optional

class AlertManager:
    def __init__(self, slack_webhook_url: Optional[str] = None):
        self.slack_webhook_url = slack_webhook_url
    
    def send_slack_alert(self, title: str, message: str, severity: str = "warning"):
        """Slack にアラートを送信"""
        if not self.slack_webhook_url:
            print(f"[ALERT] {severity.upper()}: {title} - {message}")
            return
        
        # 重大度に応じた色設定
        color_map = {
            "critical": "#FF0000",  # 赤
            "warning": "#FFA500",   # オレンジ
            "info": "#00FF00"       # 緑
        }
        
        payload = {
            "attachments": [{
                "color": color_map.get(severity, "#808080"),
                "title": f":rotating_light: {title}",
                "text": message,
                "footer": "HolySheep AI SLA Monitor",
                "ts": int(datetime.utcnow().timestamp())
            }]
        }
        
        try:
            response = requests.post(self.slack_webhook_url, json=payload)
            response.raise_for_status()
            print(f"Slack アラート送信成功: {title}")
        except requests.exceptions.RequestException as e:
            print(f"Slack アラート送信失敗: {e}")
    
    def check_and_alert(self, stats: SLAStatistics):
        """SLA統計をチェックして閾値超過時にアラート"""
        report = stats.generate_sla_report()
        
        # 可用性チェック(99.9% 目標)
        if not report["sla_met"]:
            self.send_slack_alert(
                title="SLA違反検出",
                message=f"HolySheep AI API の可用性が {report['availability']['availability_percent']}% まで低下。"
                       f"目標: {report['sla_target_percent']}% | 失敗リクエスト: {report['availability']['failed_requests']}",
                severity="critical"
            )
        
        # レイテンシチェック(P95 > 200ms)
        if report["latency"]["p95"] > 200:
            self.send_slack_alert(
                title="高レイテンシ検出",
                message=f"P95レイテンシが {report['latency']['p95']}ms を記録。閾値: 200ms",
                severity="warning"
            )
        
        # 特定のエラータイプが一定数を超えた場合
        error_breakdown = report["error_breakdown"]
        if error_breakdown.get("ConnectionTimeout", 0) > 5:
            self.send_slack_alert(
                title="タイムアウト多数発生",
                message=f"ConnectionTimeout エラーが {error_breakdown['ConnectionTimeout']} 回発生。ネットワーク確認が必要です。",
                severity="warning"
            )
        
        if error_breakdown.get("RateLimitError", 0) > 3:
            self.send_slack_alert(
                title="レートリミット超過",
                message=f"レートリミットエラーが {error_breakdown['RateLimitError']} 回発生。リクエスト頻度の確認が必要です。",
                severity="info"
            )

使用例

alert_manager = AlertManager(slack_webhook_url="YOUR_SLACK_WEBHOOK_URL") alert_manager.check_and_alert(stats)

よくあるエラーと対処法

実際に SLA 監視を実装・運用していて遭遇する代表的なエラーと、その解決策をまとめます。

1. 401 Unauthorized - API キーが無効

エラー: {"error": {"message": "Invalid API key", "type": "invalid_request_error"}}

原因: API キーが期限切れ、切替わった、または環境変数から正しく読み込めていない。

# 対処法:API キーの有効性をチェック
def validate_api_key(api_key: str) -> bool:
    """API キーの有効性を確認"""
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    try:
        response = requests.get(
            "https://api.holysheep.ai/v1/models",
            headers=headers,
            timeout=10
        )
        if response.status_code == 200:
            print("API キー有効確認 OK")
            return True
        elif response.status_code == 401:
            print("API キーが無効です。ダッシュボードで確認してください: https://www.holysheep.ai/register")
            return False
        else:
            print(f"予期しないステータスコード: {response.status_code}")
            return False
    except Exception as e:
        print(f"API キーチェック失敗: {e}")
        return False

環境変数から読み込む安全な方法

import os api_key = os.environ.get("HOLYSHEEP_API_KEY", "") if not api_key: raise ValueError("HOLYSHEEP_API_KEY 環境変数が設定されていません")

2. ConnectionError: Network is unreachable

エラー: requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.holysheep.ai', port=443): Max retries exceeded

原因: ネットワーク経路の問題、DNS解決失敗、プロキシ設定の誤り。

# 対処法:接続リトライロジックとプロキシ設定
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def create_resilient_session(proxy_config: dict = None):
    """リトライ機能付きセッションを作成"""
    from requests.adapters import HTTPAdapter
    from requests.packages.urllib3.util.retry import Retry
    
    session = requests.Session()
    
    # リトライ戦略:3回リトライ、指数バックオフ
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["HEAD", "GET", "OPTIONS", "POST"]
    )
    
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("https://", adapter)
    session.mount("http://", adapter)
    
    # プロキシ設定(必要な場合)
    if proxy_config:
        session.proxies = {
            "http": proxy_config.get("http"),
            "https": proxy_config.get("https")
        }
    
    session.verify = True  # 本番環境では True を推奨
    return session

使用

session = create_resilient_session() response = session.get( "https://api.holysheep.ai/v1/models", headers={"Authorization": f"Bearer {api_key}"}, timeout=(10, 30) # (connect_timeout, read_timeout) )

3. RateLimitError - 429 Too Many Requests

エラー: {"error": {"message": "Rate limit exceeded. Retry after 60 seconds", "type": "rate_limit_error"}}

原因: 短時間リクエスト過多。HolySheep AI は秒間リクエスト数に制限あり。

# 対処法:レート制限を考慮したリクエスト処理
import time
from threading import Lock

class RateLimitedClient:
    def __init__(self, api_key: str, max_requests_per_minute: int = 60):
        self.api_key = api_key
        self.base_url = "https://api.holysheep.ai/v1"
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        self.max_rpm = max_requests_per_minute
        self.request_times = []
        self.lock = Lock()
    
    def wait_for_capacity(self):
        """レート制限を考慮して待機"""
        with self.lock:
            now = time.time()
            # 過去60秒間のリクエストをクリア
            self.request_times = [t for t in self.request_times if now - t < 60]
            
            if len(self.request_times) >= self.max_rpm:
                # 最も古いリクエストが期限切れになるまで待機
                sleep_time = 60 - (now - self.request_times[0]) + 1
                print(f"レートリミット接近 - {sleep_time:.1f}秒待機")
                time.sleep(sleep_time)
                self.request_times = [t for t in self.request_times if time.time() - t < 60]
            
            self.request_times.append(time.time())
    
    def request_with_rate_limit(self, method: str, endpoint: str, **kwargs):
        """レート制限を考慮したリクエスト"""
        self.wait_for_capacity()
        
        url = f"{self.base_url}/{endpoint}"
        response = requests.request(method, url, headers=self.headers, **kwargs)
        
        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 60))
            print(f"レートリミット到達 - {retry_after}秒後に再試行")
            time.sleep(retry_after)
            return self.request_with_rate_limit(method, endpoint, **kwargs)
        
        return response

使用例:chat completions API で利用

client = RateLimitedClient(api_key="YOUR_HOLYSHEEP_API_KEY", max_requests_per_minute=50) payload = { "model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}], "max_tokens": 100 } response = client.request_with_rate_limit("POST", "chat/completions", json=payload)

Grafana ダッシュボード設定

収集したメトリクスを可視化する際は、Grafana を使用するとリアルタイム監視が容易になります。以下は Prometheus 形式でメトリクスをエクスポートする設定です。

# prometheus_exporter.py - Prometheus 向けメトリクスエクスポート
from prometheus_client import Counter, Histogram, Gauge, generate_latest, start_http_server

Prometheus メトリクス定義

REQUEST_COUNT = Counter( 'holysheep_api_requests_total', 'Total API requests to HolySheep AI', ['endpoint', 'status_code'] ) REQUEST_LATENCY = Histogram( 'holysheep_api_request_duration_seconds', 'API request latency in seconds', ['endpoint'] ) AVAILABILITY_GAUGE = Gauge( 'holysheep_api_availability_percent', 'Current availability percentage' ) ERROR_COUNT = Counter( 'holysheep_api_errors_total', 'Total API errors', ['error_type'] )

監視ループ

def monitoring_loop(monitor: HolySheepSLAMonitor, interval: int = 60): """Prometheus 用メトリクスを定期更新""" stats = SLAStatistics(monitor.metrics) while True: # 新しいメトリクスを収集 for endpoint in ["models", "health", "usage"]: metric = monitor.check_endpoint(endpoint) # カウンター更新 status = str(metric.status_code) if metric.status_code else "error" REQUEST_COUNT.labels(endpoint=endpoint, status_code=status).inc() REQUEST_LATENCY.labels(endpoint=endpoint).observe(metric.response_time_ms / 1000) if not metric.success and metric.error_type: ERROR_COUNT.labels(error_type=metric.error_type).inc() # 可用性Gauge更新 report = stats.calculate_availability() AVAILABILITY_GAUGE.set(report["availability_percent"]) time.sleep(interval) if __name__ == "__main__": # Prometheus サーバー起動(ポート8000) start_http_server(8000) print("Prometheus メトリクスサーバー起動: http://localhost:8000") # 監視開始 monitor = HolySheepSLAMonitor(api_key="YOUR_HOLYSHEEP_API_KEY") monitoring_loop(monitor, interval=60)

まとめ:SLA 監視のベストプラクティス

AI API の SLA 監視を実装する上で、私が学んだ重要なポイントをまとめます。

HolySheep AI は 登録 で無料クレジットがもらえるため、本番導入前に十分なテストが可能です。監視システム構築後は、安心感と共に API 活用の最大化が実現できるでしょう。

50ms 未満の低レイテンシと高可用性を目標に、適切な監視とアラート設計を心がけてください。

👉 HolySheep AI に登録して無料クレジットを獲得