Data Types

All instrumentation calls should contain JSON payloads and return JSON bodies in the response. Certain fields require particular data formats, these are described in this section; all other data formats are discussed in the sections for each API request that requires it.

For reference, we include an example request body for the PUT /filibuster/create call for the cinema-1 example.

{
  "instrumentation_type": "invocation",
  "source_service_name": "users",
  "module": "requests",
  "method": "get",
  "args": [
    "http://0.0.0.0:5001/movies/267eedb8-0f5d-42d5-8f43-72426b9fb3e6"
  ],
  "kwargs": {},
  "callsite_file": "/Users/c.meiklejohn/Documents/GitHub/nufilibuster/examples/cinema-1/services/users/users/app.py",
  "callsite_line": "113",
  "full_traceback": "436928f8a571d50077e6c6972034959a",
  "metadata": {
    "timeout": 10
  },
  "vclock": {
    "users": 2
  },
  "origin_vclock": {},
  "execution_index": "[[\"68ae4deac392aa61feeeb0634d243d57\", 1]]"
}

Instrumentation Type

The instrumentation_type field in an instrumentation call is an enumeration, provided as a string. The valid values are provided in the table below. Each of these options is described in detail in the following sections where the API is described.

Enumeration for the instrumentation_type field in either a request payload or response body.

Value

Description

invocation

Instrumentation call from a call site where a request to another service is made.

request_received

Instrumentation call from a call site where the request of a remote call is received.

invocation_complete

Instrumentation call from a call site where a request to another service has completed.

Vector Clocks

Vector clocks (and origin vector clocks) should be provided as a JSON object. This JSON object should be structured with a single key for each service and it’s value the associated counter for each action.

We provide an example:

{
  "users": 2
}

Here, the clock shows that the users service has performed two remote requests. Similarly, a if the users service has performed two remote requests and the bookings service had also performed a request, the clock would look like the following:

{
  "users": 2,
  "bookings": 1
}

We refer the reader to our implementation of vector clocks in Python to understand implementation and the algorithm: this is outside of the scope of this documentation.

Execution Index

Execution indexes should be encoded as a string that is JSON-parseable into an array. In our example, the following execution index:

"[[\"68ae4deac392aa61feeeb0634d243d57\", 1]]"

would reflect the following execution index, a list containing a single pair:

[["68ae4deac392aa61feeeb0634d243d57", 1]]

Executions indexes are made up of pairs of unique identifiers for a callsite and a count of how many times that call site was hit before issuing the request. The unique identifier for a callsite need only be a string: any unique hash generated by the service is sufficient and no special encoding is used, as it is specific to that service. As execution indexes are transmitted between machines, these must be serializable and deserializable as strings by all services in the application.

Compared to vector clocks – where the Filibuster test server needs to actually perform clock comparisons for dynamic reduction – execution indexes are only used for direct equality checks and therefore the string representation is used instead of a nested JSON object in the instrumentation call.

We refer the reader to our implementation of execution indexes in Python to understand implementation and the algorithm: this is outside of the scope of this documentation.