Skip to content

Commit

Permalink
Handle incident client general request errors (#5184)
Browse files Browse the repository at this point in the history
Handle some (unexpected) incident request errors more gracefully.
  • Loading branch information
matiasb authored Oct 16, 2024
1 parent f159a3f commit 00158a5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
23 changes: 19 additions & 4 deletions engine/common/incident_api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import requests
from django.conf import settings
from requests.exceptions import RequestException

from common.constants.plugin_ids import PluginID

Expand Down Expand Up @@ -91,6 +92,18 @@ def __init__(self, api_url: str, api_token: str) -> None:
def _request_headers(self):
return {"User-Agent": settings.GRAFANA_COM_USER_AGENT, "Authorization": f"Bearer {self.api_token}"}

def _make_request(self, url, *args, **kwargs):
try:
response = requests.post(url, *args, **kwargs)
except RequestException as e:
raise IncidentAPIException(
status=e.response.status_code if e.response else 500,
url=e.response.request.url if e.response else url,
msg=e.response.text if e.response else "Unexpected error",
method=e.response.request.method if e.response else "POST",
)
return response

def _check_response(self, response: requests.models.Response):
message = ""

Expand Down Expand Up @@ -119,7 +132,7 @@ def create_incident(
endpoint = "api/v1/IncidentsService.CreateIncident"
url = self.api_url + endpoint
# NOTE: invalid severity will raise a 500 error
response = requests.post(
response = self._make_request(
url,
json={
"title": title,
Expand All @@ -137,7 +150,9 @@ def create_incident(
def get_incident(self, incident_id: str) -> typing.Tuple[IncidentDetails, requests.models.Response]:
endpoint = "api/v1/IncidentsService.GetIncident"
url = self.api_url + endpoint
response = requests.post(url, json={"incidentID": incident_id}, timeout=TIMEOUT, headers=self._request_headers)
response = self._make_request(
url, json={"incidentID": incident_id}, timeout=TIMEOUT, headers=self._request_headers
)
self._check_response(response)
return response.json().get("incident"), response

Expand All @@ -146,7 +161,7 @@ def get_severities(self) -> typing.Tuple[typing.List[SeverityDetails], requests.
endpoint = "api/SeveritiesService.GetOrgSeverities"
url = self.api_url + endpoint
# pass empty json payload otherwise it will return a 500 response
response = requests.post(url, timeout=TIMEOUT, headers=self._request_headers, json={})
response = self._make_request(url, timeout=TIMEOUT, headers=self._request_headers, json={})
self._check_response(response)
return response.json().get("severities"), response

Expand All @@ -155,7 +170,7 @@ def add_activity(
) -> typing.Tuple[ActivityItemDetails, requests.models.Response]:
endpoint = "api/v1/ActivityService.AddActivity"
url = self.api_url + endpoint
response = requests.post(
response = self._make_request(
url,
json={"incidentID": incident_id, "activityKind": kind, "body": body},
timeout=TIMEOUT,
Expand Down
27 changes: 27 additions & 0 deletions engine/common/incident_api/tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import json
from unittest.mock import patch

import httpretty
import pytest
from requests.exceptions import RequestException
from rest_framework import status

from common.incident_api.client import (
Expand Down Expand Up @@ -185,3 +187,28 @@ def test_error_handling(endpoint, client_method_name, args):
assert excinfo.value.msg == response_data["error"]
assert excinfo.value.url == url
assert excinfo.value.method == "POST"


@pytest.mark.parametrize(
"endpoint, client_method_name, args",
[
("api/v1/IncidentsService.CreateIncident", "create_incident", ("title",)),
("api/v1/IncidentsService.GetIncident", "get_incident", ("incident-id",)),
("api/SeveritiesService.GetOrgSeverities", "get_severities", ()),
("api/v1/ActivityService.AddActivity", "add_activity", ("incident-id", "content")),
],
)
@httpretty.activate(verbose=True, allow_net_connect=False)
def test_unexpected_error_handling(endpoint, client_method_name, args):
stack_url = "https://foobar.grafana.net"
api_token = "asdfasdfasdfasdf"
client = IncidentAPIClient(stack_url, api_token)
url = f"{stack_url}{client.INCIDENT_BASE_PATH}{endpoint}"
with patch("common.incident_api.client.requests.post", side_effect=RequestException):
with pytest.raises(IncidentAPIException) as excinfo:
client_method = getattr(client, client_method_name)
client_method(*args)
assert excinfo.value.status == 500
assert excinfo.value.msg == "Unexpected error"
assert excinfo.value.url == url
assert excinfo.value.method == "POST"

0 comments on commit 00158a5

Please sign in to comment.