From 1979c2bd331b5a42d78d562ac41b86953511c3da Mon Sep 17 00:00:00 2001 From: Vinicius Aguiar Date: Wed, 14 Feb 2024 12:21:41 -0300 Subject: [PATCH] feat: add availability as metadata (#564) --- .github/workflows/deploy-dev.yaml | 2 ++ .github/workflows/deploy-prod.yaml | 2 ++ .github/workflows/deploy-staging.yaml | 2 ++ bd_api/apps/core/migrations/0001_initial.py | 31 ++++++++++++++++++ bd_api/apps/core/models.py | 15 +++++++-- bd_api/apps/core/tasks.py | 36 +++++++++++++++++++++ bd_api/custom/client.py | 24 +++++++++++++- bd_api/settings/base.py | 3 ++ 8 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 bd_api/apps/core/migrations/0001_initial.py create mode 100644 bd_api/apps/core/tasks.py diff --git a/.github/workflows/deploy-dev.yaml b/.github/workflows/deploy-dev.yaml index cd5056a8..08eb590f 100644 --- a/.github/workflows/deploy-dev.yaml +++ b/.github/workflows/deploy-dev.yaml @@ -119,6 +119,8 @@ jobs: value: "${{ secrets.STRIPE_TEST_SECRET_KEY }}" - name: "DJSTRIPE_WEBHOOK_SECRET" value: "${{ secrets.DJSTRIPE_WEBHOOK_SECRET }}" + - name: "BETTERSTACK_BEARER_TOKEN" + value: "${{ secrets.BETTERSTACK_BEARER_TOKEN }}" - name: "DISCORD_BACKEND_WEBHOOK_URL" value: "${{ secrets.DISCORD_BACKEND_WEBHOOK_URL }}" envFrom: diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 0857443d..a2e78928 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -88,6 +88,8 @@ jobs: value: "${{ secrets.STRIPE_TEST_SECRET_KEY }}" - name: "DJSTRIPE_WEBHOOK_SECRET" value: "${{ secrets.DJSTRIPE_WEBHOOK_SECRET }}" + - name: "BETTERSTACK_BEARER_TOKEN" + value: "${{ secrets.BETTERSTACK_BEARER_TOKEN }}" - name: "DISCORD_BACKEND_WEBHOOK_URL" value: "${{ secrets.DISCORD_BACKEND_WEBHOOK_URL }}" envFrom: diff --git a/.github/workflows/deploy-staging.yaml b/.github/workflows/deploy-staging.yaml index e1122446..5b778084 100644 --- a/.github/workflows/deploy-staging.yaml +++ b/.github/workflows/deploy-staging.yaml @@ -88,6 +88,8 @@ jobs: value: "${{ secrets.STRIPE_TEST_SECRET_KEY }}" - name: "DJSTRIPE_WEBHOOK_SECRET" value: "${{ secrets.DJSTRIPE_WEBHOOK_SECRET }}" + - name: "BETTERSTACK_BEARER_TOKEN" + value: "${{ secrets.BETTERSTACK_BEARER_TOKEN }}" - name: "DISCORD_BACKEND_WEBHOOK_URL" value: "${{ secrets.DISCORD_BACKEND_WEBHOOK_URL }}" envFrom: diff --git a/bd_api/apps/core/migrations/0001_initial.py b/bd_api/apps/core/migrations/0001_initial.py new file mode 100644 index 00000000..62e0c652 --- /dev/null +++ b/bd_api/apps/core/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 4.2.10 on 2024-02-14 15:01 + +import uuid + +from django.db import migrations, models + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Metadata", + fields=[ + ("created_at", models.DateTimeField(auto_now_add=True)), + ("updated_at", models.DateTimeField(auto_now=True)), + ( + "id", + models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False), + ), + ("key", models.JSONField(default=dict)), + ("value", models.JSONField(default=dict)), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/bd_api/apps/core/models.py b/bd_api/apps/core/models.py index 2967ffa5..6b625a31 100644 --- a/bd_api/apps/core/models.py +++ b/bd_api/apps/core/models.py @@ -1,4 +1,15 @@ # -*- coding: utf-8 -*- -from django.db import models # noqa +from uuid import uuid4 -# Create your models here. +from django.db import models + +from bd_api.custom.model import BaseModel + + +class Metadata(BaseModel): + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + id = models.UUIDField(primary_key=True, default=uuid4) + key = models.JSONField(default=dict, blank=False, null=False) + value = models.JSONField(default=dict, blank=False, null=False) diff --git a/bd_api/apps/core/tasks.py b/bd_api/apps/core/tasks.py new file mode 100644 index 00000000..8ffc84d3 --- /dev/null +++ b/bd_api/apps/core/tasks.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from datetime import datetime, timedelta + +from huey import crontab +from huey.contrib.djhuey import periodic_task + +from bd_api.apps.core.models import Metadata +from bd_api.custom.client import BetterStackClient +from bd_api.utils import production_task + + +@periodic_task(crontab(day="1", hour="3", minute="0")) +@production_task +def get_monitor_availability(): + """Get availability metric and save as metadata""" + + def get_period(): + """Get last month period as tuple of strings""" + + today = datetime.today() + since = datetime(today.year, today.month - 1, 1) + until = datetime(today.year, today.month, 1) - timedelta(days=1) + return since.strftime("%Y-%m-%d"), until.strftime("%Y-%m-%d") + + since, until = get_period() + client = BetterStackClient() + for monitor in client.get_monitors(): + Metadata.objects.create( + key={ + "since": since, + "until": until, + "monitor_id": monitor["id"], + "monitor_url": monitor["attributes"]["url"], + }, + value=client.get_monitor_summary(monitor["id"], since, until), + ) diff --git a/bd_api/custom/client.py b/bd_api/custom/client.py index c15f171d..7a84d5b0 100644 --- a/bd_api/custom/client.py +++ b/bd_api/custom/client.py @@ -8,7 +8,7 @@ from google.cloud.storage import Client as GCSClient from google.oauth2.service_account import Credentials from loguru import logger -from requests import post +from requests import Session, post from bd_api.custom.model import BaseModel @@ -72,3 +72,25 @@ def send(self): """Send message if it has body text""" if self._message.count("\n"): send_discord_message(self._message) + + +class BetterStackClient: + def __init__(self) -> None: + self.session = Session() + self.session.headers.update( + {"Authorization": f"Bearer {settings.BETTERSTACK_BEARER_TOKEN}"} + ) + self.url = "https://uptime.betterstack.com" + + def get_monitors(self): + response = self.session.get(f"{self.url}/api/v2/monitors") + response.raise_for_status() + return response.json() + + def get_monitor_summary(self, monitor_id: str, since: str, until: str): + response = self.session.get( + f"{self.url}/api/v2/{monitor_id}/sla", + params={"from": since, "to": until}, + ) + response.raise_for_status() + return response.json() diff --git a/bd_api/settings/base.py b/bd_api/settings/base.py index c56ccd12..78780d33 100644 --- a/bd_api/settings/base.py +++ b/bd_api/settings/base.py @@ -299,3 +299,6 @@ # Discord DISCORD_BACKEND_WEBHOOK_URL = getenv("DISCORD_BACKEND_WEBHOOK_URL") + +# BetterStack +BETTERSTACK_BEARER_TOKEN = getenv("BETTERSTACK_BEARER_TOKEN")