0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-24 18:07:17 +01:00
posthog/ee/tasks/auto_rollback_feature_flag.py
Luke Harries 7abbbbea30
fix: feature flag autorollback (#13115)
prevent current day from being cut off
2022-12-05 23:13:41 +00:00

85 lines
2.9 KiB
Python

from datetime import datetime, timedelta
from typing import Dict
import pytz
from celery import shared_task
from ee.api.sentry_stats import get_stats_for_timerange
from posthog.models.feature_flag import FeatureFlag
from posthog.models.filters.filter import Filter
from posthog.models.team import Team
from posthog.queries.trends.trends import Trends
def check_flags_to_rollback():
flags_with_threshold = FeatureFlag.objects.exclude(rollback_conditions__isnull=True).exclude(
rollback_conditions__exact=[]
)
for feature_flag in flags_with_threshold:
check_feature_flag_rollback_conditions(feature_flag_id=feature_flag.pk)
@shared_task(ignore_result=True, max_retries=2)
def check_feature_flag_rollback_conditions(feature_flag_id: int) -> None:
flag: FeatureFlag = FeatureFlag.objects.get(pk=feature_flag_id)
if any(check_condition(condition, flag) for condition in flag.rollback_conditions):
flag.performed_rollback = True
flag.active = False
flag.save()
def calculate_rolling_average(threshold_metric: Dict, team: Team, timezone: str) -> float:
curr = datetime.now(tz=pytz.timezone(timezone))
rolling_average_days = 7
filter = Filter(
data={
**threshold_metric,
"date_from": (curr - timedelta(days=rolling_average_days)).strftime("%Y-%m-%d %H:%M:%S.%f"),
"date_to": curr.strftime("%Y-%m-%d %H:%M:%S.%f"),
},
team=team,
)
trends_query = Trends()
result = trends_query.run(filter, team)
if not len(result):
return False
data = result[0]["data"]
return sum(data) / rolling_average_days
def check_condition(rollback_condition: Dict, feature_flag: FeatureFlag) -> bool:
if rollback_condition["threshold_type"] == "sentry":
created_date = feature_flag.created_at
base_start_date = created_date.strftime("%Y-%m-%dT%H:%M:%S")
base_end_date = (created_date + timedelta(days=1)).strftime("%Y-%m-%dT%H:%M:%S")
current_time = datetime.utcnow()
target_end_date = current_time.strftime("%Y-%m-%dT%H:%M:%S")
target_start_date = (current_time - timedelta(days=1)).strftime("%Y-%m-%dT%H:%M:%S")
base, target = get_stats_for_timerange(base_start_date, base_end_date, target_start_date, target_end_date)
if rollback_condition["operator"] == "lt":
return target < float(rollback_condition["threshold"]) * base
else:
return target > float(rollback_condition["threshold"]) * base
elif rollback_condition["threshold_type"] == "insight":
rolling_average = calculate_rolling_average(
rollback_condition["threshold_metric"], feature_flag.team, feature_flag.team.timezone
)
if rollback_condition["operator"] == "lt":
return rolling_average < rollback_condition["threshold"]
else:
return rolling_average > rollback_condition["threshold"]
return False