Error Handling Example

This script shows how handle errors occurring during API calls to the Vibration service

The MVG design principle is that the client application using the MVG API is responsible for error handling.

[1]:
import json
import os
import sys
import logging

# import mvg library with python bindings to mvg-API
from mvg import MVG
from mvg.exceptions import MVGAPIError

Note

Each TOKEN is used both for authorization and authentication. Thus, each unique token represents a unique user and each user has their own unique database on the VA-MVG’ service.

You need to insert your token received from Viking Analytics here:

[2]:
TOKEN = os.environ["TEST_TOKEN"]  # replace with your token
ENDPOINT = "https://api.beta.multiviz.com"

This is Viking Analytics default logging setup and can be adapted to suit your needs. Log messages are printed from mvg library, see the source code for details.

[3]:
root_logger = logging.getLogger()
root_logger.setLevel("INFO")
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(name)s - %(message)s")
stream_handler = logging.StreamHandler(stream=sys.stderr)
stream_handler.setFormatter(formatter)
root_logger.addHandler(stream_handler)

As we are interested in error handling we set the logger level to logging.DEBUG. That will trace out the detailed information on exceptions provided by the server.

Set log level to logging.ERROR to just see the results of proper error handling in the code root_logger.setLevel(logging.ERROR)

[4]:
root_logger.setLevel(logging.ERROR)

Instantiate a session object with MVG library. A session object basically catches the endpoint and the token, to simplify the calls to the MVG library.

[5]:
session = MVG(ENDPOINT, TOKEN)

We now check if the server is alive. The hello message contains, amongst others the API version.

[6]:
hello_message = json.dumps(session.say_hello())
print(hello_message)
{"name": "MultiViz Engine API", "version": "v0.3.2", "swagger": "http://api.beta.multiviz.com/docs"}

Invalid Token

Let’s provoke an error by creating a session with a non-valid token.

[7]:
unauth_session = MVG(ENDPOINT, "PASSKEY")

We need to call a method requiring authentication. Check https://api.beta.multiviz.com/docs to see which methods require authentication, they have a lock icon.

[8]:
try:
    print(">>> Provoke Unathorized call")
    sources = unauth_session.list_sources()
except MVGAPIError as exc:
    # As we have rouge token
    # We'll end up here
    print("OUCH")
    print(exc)
>>> Provoke Unathorized call
OUCH
401 - Unauthorized: Unauthorized

We’ll now return to the original session and show how to get details when the server internally rejected a request for other reasons.

Illegal source_id

We provoke the service using an illegal string for the source_id.

[9]:
try:
    print(">>> Provoke illegal source Id name")
    session.create_source("illegal%name", channels=["acc"])
except MVGAPIError as exc:
    # As we have rouge token
    # We'll end up here
    print("OUCH")
    print(exc)
>>> Provoke illegal source Id name
OUCH
422 - Unprocessable Entity: [{'loc': ['body', 'source_id'], 'msg': 'string does not match regex "^[\\w-]+$"', 'type': 'value_error.str.regex', 'ctx': {'pattern': '^[\\w-]+$'}}]

We’ll show a couple of examples what can go wrong when creating a measurement

Non-existing Source

In some cases where there is detailed information provided by the server, we can retrieve it by inspecting the exception object exc, which actually contains all information about the request.

[10]:
try:
    print(">>> Non existing source")
    d = [1, 2, 3]
    session.create_measurement(sid="",
                               duration=-3,
                               timestamp=-5,
                               data=d,
                               meta={})
except MVGAPIError as exc:
    print(exc)
>>> Non existing source
404 - Not Found: Not Found

Parameter Value Out of Range

Sometimes, it is possible to pass a value that it is out of range of the expected, as in this example where the values for the duration and timestamp parameters are negative values.

[11]:
try:
    print(">>> Parameter value out of range")
    d = {"acc": [1, 2, 3]}
    session.create_measurement(sid="u0001",
                               duration=-3,
                               timestamp=-5,
                               data=d,
                               meta={})
except MVGAPIError as exc:
    print(exc)
>>> Parameter value out of range
422 - Unprocessable Entity: [{'loc': ['body', 0, 'duration'], 'msg': 'ensure this value is greater than 0.0', 'type': 'value_error.number.not_gt', 'ctx': {'limit_value': 0.0}}, {'loc': ['body', 0, 'timestamp'], 'msg': 'ensure this value is greater than or equal to 0', 'type': 'value_error.number.not_ge', 'ctx': {'limit_value': 0}}]

Missing Parameter

In this case we have an error on the client side. This means that the data is never sent to the server, so we do not get an MVGAPIError, but a TypeError instead. Only the MVGAPIError contains any details from the server, so to be on the safe side we should catch them separately.

[12]:
try:
    print(">>> Parameter missing in mvg call")
    session.create_measurement(sid="u0001",
                               duration=-3,
                               timestamp=-5,
                               meta={})
except MVGAPIError as exc:
    print(exc)
except Exception as exc:
    print(f"{type(exc).__name__}: {exc}")
    print("No details from server available")

>>> Parameter missing in mvg call
TypeError: create_measurement() missing 1 required positional argument: 'data'
No details from server available