Skip to content

Commit

Permalink
Merge pull request #141 from axiomhq/arne/improve-error-handling
Browse files Browse the repository at this point in the history
feat: Add AxiomError for more detailed error messages
  • Loading branch information
darach authored Sep 24, 2024
2 parents 6890a1b + 9e50a91 commit 80e5f2d
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 28 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "axiom-py"
version = "0.7.0"
version = "0.8.0"
description = "Official bindings for the Axiom API"
readme = "README.md"
requires-python = ">=3.8"
Expand Down
4 changes: 2 additions & 2 deletions src/axiom_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from .client import (
Error,
AxiomError,
IngestFailure,
IngestStatus,
IngestOptions,
Expand All @@ -27,7 +27,7 @@
)

_all_ = [
Error,
AxiomError,
IngestFailure,
IngestStatus,
IngestOptions,
Expand Down
40 changes: 29 additions & 11 deletions src/axiom_py/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@
AXIOM_URL = "https://api.axiom.co"


@dataclass
class Error:
status: Optional[int] = field(default=None)
message: Optional[str] = field(default=None)
error: Optional[str] = field(default=None)


@dataclass
class IngestFailure:
"""The ingestion failure of a single event"""
Expand Down Expand Up @@ -118,10 +111,35 @@ class AplOptions:
includeCursor: bool = field(default=False)


def raise_response_error(r):
if r.status_code >= 400:
# TODO: Decode JSON https://github.com/axiomhq/axiom-go/blob/610cfbd235d3df17f96a4bb156c50385cfbd9edd/axiom/error.go#L35-L50
r.raise_for_status()
class AxiomError(Exception):
"""This exception is raised on request errors."""

status: int
message: str

@dataclass
class Response:
message: str
error: Optional[str]

def __init__(self, status: int, res: Response):
message = res.error if res.error is not None else res.message
super().__init__(f"API error {status}: {message}")

self.status = status
self.message = message


def raise_response_error(res):
if res.status_code >= 400:
try:
error_res = from_dict(AxiomError.Response, res.json())
except Exception:
# Response is not in the Axiom JSON format, create generic error
# message
error_res = AxiomError.Response(message=res.reason, error=None)

raise AxiomError(res.status_code, error_res)


class Client: # pylint: disable=R0903
Expand Down
2 changes: 1 addition & 1 deletion src/axiom_py/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""The current version"""

__version__ = "0.7.0"
__version__ = "0.8.0"
6 changes: 3 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from logging import getLogger
from datetime import datetime, timedelta
from .helpers import get_random_name
from requests.exceptions import HTTPError
from axiom_py import (
AxiomError,
Client,
AplOptions,
AplResultFormat,
Expand Down Expand Up @@ -264,7 +264,7 @@ def tearDownClass(cls):
"dataset (%s) was not deleted as part of the test, deleting it now."
% cls.dataset_name
)
except HTTPError as err:
except AxiomError as e:
# nothing to do here, since the dataset doesn't exist
cls.logger.warning(err)
cls.logger.warning(e)
cls.logger.info("finish cleaning up after TestClient")
15 changes: 6 additions & 9 deletions tests/test_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
import unittest
from typing import List, Dict
from logging import getLogger
from requests.exceptions import HTTPError
from datetime import timedelta
from .helpers import get_random_name
from axiom_py import (
Client,
)
from axiom_py import Client, AxiomError


class TestDatasets(unittest.TestCase):
Expand Down Expand Up @@ -78,11 +75,11 @@ def test_step999_delete(self):
dataset,
f"expected test dataset (%{self.dataset_name}) to be deleted",
)
except HTTPError as err:
except AxiomError as e:
# the get method returns 404 error if dataset doesn't exist, so
# that means that our tests passed, otherwise, it should fail.
if err.response.status_code != 404:
self.fail(err)
if e.status != 404:
self.fail(e)

@classmethod
def tearDownClass(cls):
Expand All @@ -97,7 +94,7 @@ def tearDownClass(cls):
"dataset (%s) was not deleted as part of the test, deleting it now."
% cls.dataset_name
)
except HTTPError as err:
except AxiomError as e:
# nothing to do here, since the dataset doesn't exist
cls.logger.warning(err)
cls.logger.warning(e)
cls.logger.info("finish cleaning up after TestDatasets")
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 80e5f2d

Please sign in to comment.