forked from GithubBackups/healthchecks
Second interation of this
This commit is contained in:
parent
4b1b232959
commit
90d4246848
@ -207,7 +207,7 @@ class Check(models.Model):
|
|||||||
code_half = self.code.hex[:16]
|
code_half = self.code.hex[:16]
|
||||||
return hashlib.sha1(code_half.encode()).hexdigest()
|
return hashlib.sha1(code_half.encode()).hexdigest()
|
||||||
|
|
||||||
def to_dict(self, readonly=False, history=None):
|
def to_dict(self, readonly=False):
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
@ -224,24 +224,6 @@ class Check(models.Model):
|
|||||||
if self.last_duration:
|
if self.last_duration:
|
||||||
result["last_duration"] = int(self.last_duration.total_seconds())
|
result["last_duration"] = int(self.last_duration.total_seconds())
|
||||||
|
|
||||||
if history:
|
|
||||||
split = re.split(r'(h|d|w)$',history,maxsplit=0)
|
|
||||||
if len(split) == 3: # re.split should return a list of 3 items if the parameter is set correctly
|
|
||||||
zone = pytz.timezone(self.tz)
|
|
||||||
current_now = datetime.now(tz=zone)
|
|
||||||
|
|
||||||
if split[1] == 'd':
|
|
||||||
cutoff = current_now - td(days=int(split[0]))
|
|
||||||
elif split[1] == 'h':
|
|
||||||
cutoff = current_now - td(hours=int(split[0]))
|
|
||||||
elif split[1] == 'w':
|
|
||||||
cutoff = current_now - td(weeks=int(split[0]))
|
|
||||||
|
|
||||||
flips = Flip.objects.select_related("owner").filter(
|
|
||||||
owner=self, new_status__in=("down","up"), created__gt=cutoff
|
|
||||||
).order_by("created")
|
|
||||||
dictStatus = {"up":1,"down":0}
|
|
||||||
result['history'] = list(map(lambda x: {'timestamp':x.created,'up':dictStatus[x.new_status]}, flips))
|
|
||||||
if readonly:
|
if readonly:
|
||||||
result["unique_key"] = self.unique_key
|
result["unique_key"] = self.unique_key
|
||||||
else:
|
else:
|
||||||
|
@ -38,6 +38,8 @@ urlpatterns = [
|
|||||||
path("api/v1/checks/<uuid:code>/pause", views.pause, name="hc-api-pause"),
|
path("api/v1/checks/<uuid:code>/pause", views.pause, name="hc-api-pause"),
|
||||||
path("api/v1/notifications/<uuid:code>/bounce", views.bounce, name="hc-api-bounce"),
|
path("api/v1/notifications/<uuid:code>/bounce", views.bounce, name="hc-api-bounce"),
|
||||||
path("api/v1/checks/<uuid:code>/pings/", views.pings, name="hc-api-pings"),
|
path("api/v1/checks/<uuid:code>/pings/", views.pings, name="hc-api-pings"),
|
||||||
|
path("api/v1/checks/<uuid:code>/flips/", views.flips, name="hc-api-flips"),
|
||||||
|
path("api/v1/checks/<sha1:unique_key>/flips/", views.get_flips_by_unique_key),
|
||||||
path("api/v1/channels/", views.channels),
|
path("api/v1/channels/", views.channels),
|
||||||
path(
|
path(
|
||||||
"badge/<slug:badge_key>/<slug:signature>/<quoted:tag>.<slug:fmt>",
|
"badge/<slug:badge_key>/<slug:signature>/<quoted:tag>.<slug:fmt>",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from datetime import timedelta as td
|
from datetime import timedelta as td
|
||||||
|
from datetime import datetime
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@ -8,6 +9,7 @@ from django.http import (
|
|||||||
HttpResponse,
|
HttpResponse,
|
||||||
HttpResponseForbidden,
|
HttpResponseForbidden,
|
||||||
HttpResponseNotFound,
|
HttpResponseNotFound,
|
||||||
|
HttpResponseBadRequest,
|
||||||
JsonResponse,
|
JsonResponse,
|
||||||
)
|
)
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
@ -293,6 +295,57 @@ def pings(request, code):
|
|||||||
|
|
||||||
return JsonResponse({"pings": dicts})
|
return JsonResponse({"pings": dicts})
|
||||||
|
|
||||||
|
@cors("GET")
|
||||||
|
@csrf_exempt
|
||||||
|
@validate_json()
|
||||||
|
@authorize_read
|
||||||
|
def flips(request, code):
|
||||||
|
check = get_object_or_404(Check, code=code)
|
||||||
|
if check.project_id != request.project.id:
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
|
if any(x in request.GET for x in ('start','end')) and 'seconds' in request.GET:
|
||||||
|
return HttpResponseBadRequest()
|
||||||
|
|
||||||
|
history_start = None
|
||||||
|
history_end = datetime.now()
|
||||||
|
|
||||||
|
if 'start' in request.GET:
|
||||||
|
history_start = datetime.fromtimestamp(int(request.GET['start']))
|
||||||
|
if 'end' in request.GET:
|
||||||
|
history_end = datetime.fromtimestamp(int(request.GET['end']))
|
||||||
|
|
||||||
|
if 'seconds' in request.GET:
|
||||||
|
history_start = datetime.now()-td(seconds=int(request.GET['seconds']))
|
||||||
|
elif not history_start:
|
||||||
|
history_start = datetime.now()-td(seconds=3600)
|
||||||
|
|
||||||
|
flips = Flip.objects.select_related("owner").filter(
|
||||||
|
owner=check, new_status__in=("down","up"),
|
||||||
|
created__gt=history_start,
|
||||||
|
created__lt=history_end
|
||||||
|
).order_by("created")
|
||||||
|
dictStatus = {"up":1,"down":0}
|
||||||
|
|
||||||
|
return JsonResponse({"flips": list(map(lambda x: {'timestamp':x.created,'up':dictStatus[x.new_status]}, flips))})
|
||||||
|
|
||||||
|
# return JsonResponse(check.to_dict(
|
||||||
|
# readonly=request.readonly,
|
||||||
|
# history=(
|
||||||
|
# history_start,history_end
|
||||||
|
# )
|
||||||
|
# ))
|
||||||
|
|
||||||
|
@cors("GET")
|
||||||
|
@csrf_exempt
|
||||||
|
@validate_json()
|
||||||
|
@authorize_read
|
||||||
|
def get_flips_by_unique_key(request, unique_key):
|
||||||
|
checks = Check.objects.filter(project=request.project.id)
|
||||||
|
for check in checks:
|
||||||
|
if check.unique_key == unique_key:
|
||||||
|
return flips(request,check.code)
|
||||||
|
return HttpResponseNotFound()
|
||||||
|
|
||||||
@never_cache
|
@never_cache
|
||||||
@cors("GET")
|
@cors("GET")
|
||||||
|
@ -746,6 +746,83 @@ curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/pings/ \
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Get a list of check's flips {: #list-flips .rule }
|
||||||
|
|
||||||
|
`GET SITE_ROOT/api/v1/checks/<uuid>/flips/` or `GET SITE_ROOT/api/v1/checks/<unique_key>/flips/`
|
||||||
|
|
||||||
|
Returns a list of flips this check has experienced. A flip is a change of status (up, or down).
|
||||||
|
|
||||||
|
This endpoint returns the status of a check for the period of time passed according to the below parameters. If no parameters are passed, the default is to return flips occuring in the previous 3600 seconds (`/?seconds=3600`), which is the last hour.
|
||||||
|
|
||||||
|
### Query String Parameters
|
||||||
|
|
||||||
|
Either the seconds or the start (and end) parameters can be passed. Passing both the seconds parameter and the start/end parameters will return a 400 error (see below).
|
||||||
|
|
||||||
|
seconds=<value>
|
||||||
|
: Filters the checks, and returns the flip history in the last `n` seconds
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`SITE_ROOT/api/v1/checks/<uuid|unique_key>/flips/?seconds=3600`
|
||||||
|
|
||||||
|
start=<value>&end=<value>
|
||||||
|
: Filters the checks, and returns the flip history between the start and end timestamps.
|
||||||
|
|
||||||
|
If provided, both values must be unix timestamps. The `end` parameter is optional and defaults to the timestamp of the current date and time.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`SITE_ROOT/api/v1/checks/<uuid|unique_key>/flips/?seconds=3600`
|
||||||
|
|
||||||
|
|
||||||
|
### Response Codes
|
||||||
|
|
||||||
|
200 OK
|
||||||
|
: The request succeeded.
|
||||||
|
|
||||||
|
400 Bad Request
|
||||||
|
: Both a seconds and a start or end query string parameter has been passed, which is unsupported.
|
||||||
|
|
||||||
|
401 Unauthorized
|
||||||
|
: The API key is either missing or invalid.
|
||||||
|
|
||||||
|
403 Forbidden
|
||||||
|
: Access denied, wrong API key.
|
||||||
|
|
||||||
|
404 Not Found
|
||||||
|
: The specified check does not exist.
|
||||||
|
|
||||||
|
### Example Request
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl SITE_ROOT/api/v1/checks/f618072a-7bde-4eee-af63-71a77c5723bc/flips/ \
|
||||||
|
--header "X-Api-Key: your-api-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "My First Check",
|
||||||
|
"tags": "",
|
||||||
|
"desc": "",
|
||||||
|
"grace": 3600,
|
||||||
|
"n_pings": 2,
|
||||||
|
"status": "up",
|
||||||
|
"last_ping": "2020-06-12T02:18:46+00:00",
|
||||||
|
"next_ping": "2020-06-13T02:18:46+00:00",
|
||||||
|
"manual_resume": false,
|
||||||
|
"history": [
|
||||||
|
{
|
||||||
|
"timestamp": "2020-03-23T23:30:18.767Z",
|
||||||
|
"up": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unique_key": "e855898bebff1756cde7c571319d877d07a38dab",
|
||||||
|
"timeout": 86400
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Get a List of Existing Integrations {: #list-channels .rule }
|
## Get a List of Existing Integrations {: #list-channels .rule }
|
||||||
|
|
||||||
`GET SITE_ROOT/api/v1/channels/`
|
`GET SITE_ROOT/api/v1/channels/`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user