def handle(self, *args, **options): threshold = min(month_boundaries(months=3)) q = Flip.objects.filter(created__lt=threshold) n_pruned, _ = q.delete() return "Done! Pruned %d flips." % n_pruned
def send_report(self, nag=False): checks = self.checks_from_all_projects() # Has there been a ping in last 6 months? result = checks.aggregate(models.Max("last_ping")) last_ping = result["last_ping__max"] six_months_ago = now() - timedelta(days=180) if last_ping is None or last_ping < six_months_ago: return False # Is there at least one check that is down? num_down = checks.filter(status="down").count() if nag and num_down == 0: return False # Sort checks by project. Need this because will group by project in # template. checks = checks.select_related("project") checks = checks.order_by("project_id") # list() executes the query, to avoid DB access while # rendering the template checks = list(checks) unsub_url = self.reports_unsub_url() headers = { "List-Unsubscribe": "<%s>" % unsub_url, "X-Bounce-Url": unsub_url, "List-Unsubscribe-Post": "List-Unsubscribe=One-Click", } boundaries = month_boundaries(months=3) # throw away the current month, keep two previous months boundaries.pop() ctx = { "checks": checks, "sort": self.sort, "now": now(), "unsub_link": unsub_url, "notifications_url": self.notifications_url(), "nag": nag, "nag_period": self.nag_period.total_seconds(), "num_down": num_down, "month_boundaries": boundaries, "monthly_or_weekly": self.reports, } emails.report(self.user.email, ctx, headers) return True
def downtimes(self, months=2): """ Calculate the number of downtimes and downtime minutes per month. Returns a list of (datetime, downtime_in_secs, number_of_outages) tuples. """ def monthkey(dt): return dt.year, dt.month # Datetimes of the first days of months we're interested in. Ascending order. boundaries = month_boundaries(months=months) # Will accumulate totals here. # (year, month) -> [datetime, total_downtime, number_of_outages] totals = {monthkey(b): [b, td(), 0] for b in boundaries} # A list of flips and month boundaries events = [(b, "---") for b in boundaries] q = self.flip_set.filter(created__gt=min(boundaries)) for pair in q.values_list("created", "old_status"): events.append(pair) # Iterate through flips and month boundaries in reverse order, # and for each "down" event increase the counters in `totals`. dt, status = timezone.now(), self.status for prev_dt, prev_status in sorted(events, reverse=True): if status == "down": delta = dt - prev_dt totals[monthkey(prev_dt)][1] += delta totals[monthkey(prev_dt)][2] += 1 dt = prev_dt if prev_status != "---": status = prev_status # Set counters to None for months when the check didn't exist yet for ym in totals: if ym < monthkey(self.created): totals[ym][1] = None totals[ym][2] = None return sorted(totals.values())