Pranav Dhiran
final 2 6
a78a875
Raw
History Blame Contribute Delete
4.86 kB
"""Base class for all SRE incident tasks."""
from abc import ABC, abstractmethod
from typing import Dict, Any, Tuple, List
from app.models import Observation, Alert, ServiceStatus, LogEntry, MetricPoint
from datetime import datetime, timezone
BASE_INCIDENT_TIME = "2024-11-15T09:47:00Z"
AVAILABLE_ACTIONS = [
"query_logs",
"check_metrics",
"restart_service",
"rollback_deployment",
"scale_service",
"kill_query",
"acknowledge_alert",
"examine_trace",
"check_config",
"resolve_incident",
]
ACTION_SCHEMA = {
"query_logs": {
"description": "Fetch recent log entries for a service",
"parameters": {
"service": {"type": "string", "required": True, "description": "Service name"},
"lines": {"type": "integer", "required": False, "default": 50},
},
},
"check_metrics": {
"description": "Retrieve current metrics for a service",
"parameters": {
"service": {"type": "string", "required": True},
},
},
"restart_service": {
"description": "Restart a service (rolling restart, brief downtime)",
"parameters": {
"service": {"type": "string", "required": True},
},
},
"rollback_deployment": {
"description": "Roll back a service to its previous deployment version",
"parameters": {
"service": {"type": "string", "required": True},
},
},
"scale_service": {
"description": "Change the number of replicas for a service",
"parameters": {
"service": {"type": "string", "required": True},
"replicas": {"type": "integer", "required": True, "min": 1, "max": 20},
},
},
"kill_query": {
"description": "Kill long-running database queries from a specific source/application",
"parameters": {
"source": {"type": "string", "required": True, "description": "Application or service holding queries"},
},
},
"acknowledge_alert": {
"description": "Acknowledge an alert to stop paging",
"parameters": {
"alert_id": {"type": "string", "required": True},
},
},
"examine_trace": {
"description": "Examine a distributed trace to identify slow spans",
"parameters": {
"trace_id": {"type": "string", "required": True},
},
},
"check_config": {
"description": "Inspect the live runtime configuration of a service",
"parameters": {
"service": {"type": "string", "required": True},
},
},
"resolve_incident": {
"description": "Mark the incident as resolved. Terminal action — ends the episode.",
"parameters": {},
},
}
class BaseTask(ABC):
task_id: str
name: str
description: str
difficulty: str
max_steps: int
passing_score: float = 0.6
@abstractmethod
def initial_state(self, seed: int = 42) -> Dict[str, Any]:
"""Return initial world state dict."""
...
@abstractmethod
def process_action(
self, action_type: str, params: Dict[str, Any], state: Dict[str, Any]
) -> Tuple[Dict[str, Any], float, bool, str]:
"""
Apply action to state.
Returns: (new_state, step_reward, done, message)
"""
...
@abstractmethod
def get_observation(self, state: Dict[str, Any], session_id: str, step: int) -> Observation:
"""Build Observation from state."""
...
@abstractmethod
def grade(self, state: Dict[str, Any], history: List[Dict]) -> Tuple[float, Dict[str, float]]:
"""
Grade the episode.
Returns: (score 0.0–1.0, breakdown dict)
"""
...
@staticmethod
def clamp_score_strict(score: float, eps: float = 0.01) -> float:
"""
Hackathon validator requirement: scores must be strictly within (0, 1).
Use this at the end of task graders to avoid returning exactly 0.0 or 1.0.
"""
try:
s = float(score)
except Exception:
s = 0.0
if s <= 0.0:
return eps
if s >= 1.0:
return 1.0 - eps
return s
def _make_service(self, name: str, status: str, cpu: float, mem: float,
err: float, **kwargs) -> ServiceStatus:
return ServiceStatus(
name=name, status=status,
cpu_percent=cpu, memory_percent=mem, error_rate=err,
**kwargs,
)
def _make_alert(self, alert_id: str, severity: str, service: str,
message: str, ack: bool = False) -> Alert:
return Alert(
alert_id=alert_id, severity=severity, service=service,
message=message, triggered_at=BASE_INCIDENT_TIME, acknowledged=ack,
)