Как определить общую оценку надёжности программы?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Метрики надёжности программы (Reliability Metrics)
Надёжность программы — это способность работать без сбоев в течение длительного времени. Есть несколько метрик для её оценки.
1. Mean Time Between Failures (MTBF)
Определение: среднее время между отказами.
МТВF = Общее время наблюдения / Количество отказов
Пример:
Время наблюдения: 30 дней = 43200 часов
Отказы произошли в часы: 5, 108, 284, 1032
Количество отказов: 4
МТВF = 43200 / 4 = 10800 часов (~1.2 года)
from datetime import datetime, timedelta
class ReliabilityMetrics:
def __init__(self):
self.failures = [] # время в формате timestamp
self.start_time = datetime.now()
def log_failure(self):
self.failures.append(datetime.now())
def calculate_mtbf(self) -> float:
"""Возвращает MTBF в часах"""
if not self.failures:
return float('inf')
observation_time = (datetime.now() - self.start_time).total_seconds() / 3600
return observation_time / len(self.failures)
def get_mtbf_report(self):
mtbf = self.calculate_mtbf()
if mtbf == float('inf'):
return "Ещё не было отказов"
elif mtbf > 8760: # > года
return f"MTBF > 1 года (очень надёжная)"
elif mtbf > 720: # > месяца
return f"MTBF = {mtbf:.0f} часов (~{mtbf/24:.0f} дней)"
else:
return f"MTBF = {mtbf:.1f} часов (не надёжная)"
# Использование
metrics = ReliabilityMetrics()
metrics.log_failure() # пробой прошёл
metrics.log_failure() # ещё пробой
print(metrics.get_mtbf_report())
2. Mean Time To Recovery (MTTR)
Определение: среднее время восстановления после отказа.
МТТR = Сумма времени на восстановление / Количество отказов
Пример:
Отказ 1: восстанавливался 15 минут
Отказ 2: восстанавливался 8 минут
Отказ 3: восстанавливался 22 минуты
МТТR = (15 + 8 + 22) / 3 = 15 минут
from datetime import datetime
class FailureRecovery:
def __init__(self):
self.failure_start = None
self.recovery_times = []
def failure_detected(self):
self.failure_start = datetime.now()
def recovered(self):
if self.failure_start:
recovery_time = (datetime.now() - self.failure_start).total_seconds() / 60
self.recovery_times.append(recovery_time)
self.failure_start = None
def get_mttr(self) -> float:
"""Возвращает MTTR в минутах"""
if not self.recovery_times:
return 0
return sum(self.recovery_times) / len(self.recovery_times)
# Использование
recovery = FailureRecovery()
recovery.failure_detected()
# ... приложение упало
recovery.recovered()
print(f"MTTR: {recovery.get_mttr():.1f} минут")
3. Availability (Доступность)
Определение: процент времени когда система доступна и работает.
Availability = MTBF / (MTBF + MTTR) * 100%
Или:
Availability = (Uptime / (Uptime + Downtime)) * 100%
Примеры доступности:
99% = 52 минуты downtime в год (2 нуля после запятой)
99.9% = 8.7 часа downtime в год (три нуля) — "three nines"
99.99% = 52 минуты downtime в год (four nines) — SLA для критичных систем
99.999% = 26 секунд downtime в год (five nines) — Financial systems
class SystemAvailability:
def __init__(self):
self.uptime_seconds = 0
self.downtime_seconds = 0
def calculate_availability(self) -> float:
"""Возвращает доступность в процентах"""
total_time = self.uptime_seconds + self.downtime_seconds
if total_time == 0:
return 100.0
return (self.uptime_seconds / total_time) * 100
def get_availability_nines(self) -> str:
"""Определяет 'nines' """
avail = self.calculate_availability()
if avail >= 99.999:
return "Five nines (99.999%) — Enterprise level"
elif avail >= 99.99:
return "Four nines (99.99%) — High availability"
elif avail >= 99.9:
return "Three nines (99.9%) — Standard for SaaS"
elif avail >= 99:
return "Two nines (99%) — Acceptable"
else:
return "Below 99% — Unacceptable"
def estimate_downtime_per_year(self) -> dict:
"""Расчёт downtime в год"""
avail = self.calculate_availability()
downtime_percent = 100 - avail
seconds_per_year = 365 * 24 * 3600
downtime_seconds = (downtime_percent / 100) * seconds_per_year
hours = downtime_seconds // 3600
minutes = (downtime_seconds % 3600) // 60
seconds = int(downtime_seconds % 60)
return {
"availability": f"{avail:.3f}%",
"downtime_per_year": f"{hours:.0f}h {minutes:.0f}m {seconds}s"
}
# Использование
availability = SystemAvailability()
availability.uptime_seconds = 31536000 - 3600 # год минус час
availability.downtime_seconds = 3600
print(availability.calculate_availability()) # 99.997%
print(availability.get_availability_nines()) # Four nines
print(availability.estimate_downtime_per_year())
4. Reliability at Time t — R(t)
Определение: вероятность что система будет работать без отказов до времени t.
R(t) = e^(-λt)
где λ (lambda) — failure rate
import math
def reliability_at_time(failure_rate: float, time_hours: float) -> float:
"""Рассчитывает надёжность в момент времени t"""
return math.exp(-failure_rate * time_hours)
# Пример: failure rate = 0.001 отказа в час
failure_rate = 0.001
# Надёжность через 100 часов
reliability_100h = reliability_at_time(failure_rate, 100)
print(f"R(100h) = {reliability_100h:.3f} = {reliability_100h*100:.1f}%")
# Вывод: есть 90.5% шанс что система будет работать 100 часов без отказов
# Надёжность через 1000 часов
reliability_1000h = reliability_at_time(failure_rate, 1000)
print(f"R(1000h) = {reliability_1000h:.3f} = {reliability_1000h*100:.1f}%")
# Вывод: есть 36.8% шанс что система будет работать 1000 часов без отказов
5. Failure Rate (λ — Lambda)
Определение: количество отказов в единицу времени
λ = Количество отказов / Общее время (часы, дни)
class FailureRateTracker:
def __init__(self):
self.failures_per_hour = {}
self.current_hour = None
def log_failure(self):
from datetime import datetime
now = datetime.now()
hour_key = now.strftime("%Y-%m-%d %H:00")
if hour_key not in self.failures_per_hour:
self.failures_per_hour[hour_key] = 0
self.failures_per_hour[hour_key] += 1
def get_failure_rate(self) -> float:
"""Возвращает λ (отказы в час)"""
if not self.failures_per_hour:
return 0
total_failures = sum(self.failures_per_hour.values())
total_hours = len(self.failures_per_hour)
return total_failures / total_hours
tracker = FailureRateTracker()
tracker.log_failure()
tracker.log_failure()
print(f"Failure rate: {tracker.get_failure_rate():.4f} failures/hour")
6. Error Budget
Концепция: если SLA = 99.9%, сколько downtime нам "позволено"?
Error Budget = (1 - SLA%) × Время периода
Пример:
SLA = 99.9% (three nines)
Период = 30 дней
Allowed downtime = (1 - 0.999) × 30 дней × 24 часа
= 0.001 × 720 часов
= 0.72 часа
= 43.2 минуты downtime в месяц
def calculate_error_budget(sla_percentage: float, days_in_period: int) -> dict:
"""Рассчитывает error budget"""
minutes_per_period = days_in_period * 24 * 60
allowed_downtime_minutes = minutes_per_period * (100 - sla_percentage) / 100
hours = int(allowed_downtime_minutes // 60)
minutes = int(allowed_downtime_minutes % 60)
return {
"sla": f"{sla_percentage}%",
"period": f"{days_in_period} дней",
"allowed_downtime": f"{hours}h {minutes}m",
"used_minutes": 0
}
budget = calculate_error_budget(99.9, 30) # Three nines за месяц
print(budget)
# {'sla': '99.9%', 'period': '30 дней', 'allowed_downtime': '0h 43m'}
7. Резервный расчёт: Series vs Parallel Systems
Series (компоненты последовательно) — отказ одного = отказ всей системы:
R_system = R1 × R2 × R3
Parallel (компоненты параллельно) — отказ одного ok:
R_system = 1 - (1-R1) × (1-R2) × (1-R3)
def reliability_series(*component_reliabilities) -> float:
"""Надёжность системы с компонентами в series"""
result = 1.0
for r in component_reliabilities:
result *= r
return result
def reliability_parallel(*component_reliabilities) -> float:
"""Надёжность системы с компонентами в parallel"""
result = 1.0
for r in component_reliabilities:
result *= (1 - r)
return 1 - result
# Пример: 3 компонента, каждый R = 0.95
print(f"Series: {reliability_series(0.95, 0.95, 0.95):.3f}") # 0.857
print(f"Parallel: {reliability_parallel(0.95, 0.95, 0.95):.3f}") # 0.9988
# Series: каждый компонент должен работать
# Parallel: нужен хотя бы один рабочий
Практический пример: комплексная метрика
class ComprehensiveReliabilityReport:
def __init__(self, mtbf: float, mttr: float, sla_target: float):
self.mtbf = mtbf # часы
self.mttr = mttr # часы
self.sla_target = sla_target # процент
def calculate_metrics(self) -> dict:
availability = self.mtbf / (self.mtbf + self.mttr) * 100
failure_rate = 1 / self.mtbf
# Error budget в год
minutes_per_year = 365 * 24 * 60
downtime_budget = minutes_per_year * (100 - self.sla_target) / 100
return {
"MTBF": f"{self.mtbf:.0f} часов ({self.mtbf/24:.0f} дней)",
"MTTR": f"{self.mttr:.2f} часов ({self.mttr*60:.0f} минут)",
"Availability": f"{availability:.2f}%",
"Failure Rate": f"{failure_rate:.6f} отказов/час",
"SLA Target": f"{self.sla_target}%",
"Error Budget/Year": f"{downtime_budget:.0f} минут ({downtime_budget/60:.1f} часов)",
"Status": "✓ OK" if availability >= self.sla_target else "✗ FAIL"
}
# Использование
report = ComprehensiveReliabilityReport(
mtbf=8760, # 1 год между отказами
mttr=0.5, # 30 минут на восстановление
sla_target=99.95 # Four nines
)
for key, value in report.calculate_metrics().items():
print(f"{key}: {value}")
Лучшие практики
Отслеживай MTBF и MTTR — основные метрики надёжности. Задавай SLA целевые — communicate expectations. Мониторь error budget — знай сколько downtime осталось. Тестируй failover — убедись что восстановление работает. Анализируй root cause отказов. Улучшай непрерывно — каждый incident — урок.