Instrumentation SDK Reference

# Summary

This reference provides details on Modality's Instrumentation SDK, with an emphasis on Modality's C API.

# Tracing Macros

The following macros are used to provide functionality while exposing additional metadata to the CLI tooling, like description and tag strings. The extra metadata is detected by the CLI for generating manifest information and will never be included in your binary.

# MODALITY_PROBE_INIT

Initialize a new Modality probe instance with metadata for the CLI tooling. Probes are not thread-safe, so you cannot record events on different threads with the same probe. The recommended approach is to log all events from a single thread to the same probe since there is generally no advantage to having multiple probes on the same thread.

Parameters

dest
uint8_t*
User-allocated backing storage for the probe, used for events, mutations, and internal tracking. Probes use this storage as a ring buffer, overwriting the oldest data if it gets full. Creating a report with the modality_probe_report command will flush the buffer.
dest_size
size_t
Size of the user-provided backing storage for the probe in bytes.
probe_id
uint32_t
Unique ID for the probe. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the probe's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
time_res
uint32_t
The wall-clock time resolution in nanoseconds. If the probe does not use wall-clock time or the resolution is unknown, use MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED.
wc_id
uint16_t
User-assigned identifier for the probe's wall-clock time domain. Probes which share the same clock should be assigned the same wc_id, which enables time-based queries between events on those probes. If the probe does not use wall-clock time or belongs to no other time domains, use MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY.
next_sid_fn
Function pointer to a user defined persistent sequence number retrieval function. If null, next_sid_state is unused and the probe will not do any restart handling (any events logged after a restart will be seen as duplicates). If non-null, the probe will call this function to retrieve a new sequence number when it initializes and when its logical clock overflows.
next_sid_state
void*
User state provided to the next_sid_fn function (if one was provided).
probe
modality_probe**
Pointer to the newly-initialized probe instance.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the probe. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the probe when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

err = MODALITY_PROBE_INIT(
  &g_producer_probe_buffer[0],                 // probe storage buffer
  sizeof(g_producer_probe_buffer),             // size of probe buffer
  PRODUCER_PROBE,                              // probe name
  MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED,  // clock resolution
  MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY,     // wall clock ID
  NULL,                                        // next_sid_fn
  NULL,                                        // next_sid_state
  &g_producer_probe,                           // output parameter, points to initialized probe
  MODALITY_TAGS("measurement", "producer"),    // optional tags associated with this probe
  "Measurement producer probe");               // optional probe description

# MODALITY_PROBE_RECORD

Record an event with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

err = MODALITY_PROBE_RECORD(
  g_producer_probe,                   // pointer to probe
  PRODUCER_STARTED,                   // event name
  MODALITY_TAGS("producer", "init"),  // optional event tags
  "Measurement producer started");    // optional event description

# MODALITY_PROBE_RECORD_W_TIME

Record an event with time, with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();

MODALITY_PROBE_RECORD_W_TIME(
  g_producer_probe,                      // pointer to probe
  PRODUCER_STARTED,                      // event name
  time_ns,                               // timestamp
  MODALITY_TAGS("producer"),             // optional event tags
  "Measurement producer started");       // optional event description

# MODALITY_PROBE_RECORD_W_I8

Record an event with an i8 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int8_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

int8_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I8(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_I8_W_TIME

Record an event with an i8 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int8_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
int8_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I8_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U8

Record an event with a u8 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint8_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint8_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U8(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U8_W_TIME

Record an event with a u8 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint8_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
uint8_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U8_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_I16

Record an event with an i16 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int16_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

int16_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I16(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_I16_W_TIME

Record an event with an i16 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int16_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
int16_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I16_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U16

Record an event with a u16 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint16_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint16_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U16(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U16_W_TIME

Record an event with a u16 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint16_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
uint16_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U16_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_I32

Record an event with an i32 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int32_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

int32_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I8_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_I32_W_TIME

Record an event with an i32 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
int32_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
int32_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_I32_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U32

Record an event with a u32 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint32_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint32_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U32(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_U32_W_TIME

Record an event with a u32 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
uint32_t
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
uint32_t measurement = take_measurement();

MODALITY_PROBE_RECORD_W_U32_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_BOOL

Record an event with a bool payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
bool
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

bool success = get_operation_succeeded();

MODALITY_PROBE_RECORD_W_BOOL(
  g_producer_probe,                       // pointer to probe
  OPERATION_SUCCEEDED,                    // event name
  success,                                // payload
  MODALITY_TAGS("producer, operation"),   // optional event tags
  "Producer operation success");          // optional event description

# MODALITY_PROBE_RECORD_W_BOOL_W_TIME

Record an event with a bool payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
bool
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
bool success = get_operation_succeeded();

MODALITY_PROBE_RECORD_W_BOOL_W_TIME(
  g_producer_probe,                       // pointer to probe
  OPERATION_SUCCEEDED,                    // event name
  success,                                // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, operation"),   // optional event tags
  "Producer operation success");          // optional event description

# MODALITY_PROBE_RECORD_W_F32

Record an event with an f32 payload along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
float
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

float measurement = take_measurement();

MODALITY_PROBE_RECORD_W_F32(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_RECORD_W_F32_W_TIME

Record an event with an f32 payload and wall-clock time, along with metadata for the CLI tooling.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
payload
float
User-defined payload for this event. Can be used in event predicates as part of queries and specifications.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();
float measurement = take_measurement();

MODALITY_PROBE_RECORD_W_F32_W_TIME(
  g_producer_probe,                       // pointer to probe
  MEASUREMENT,                            // event name
  measurement,                            // payload
  time_ns,                                // timestamp
  MODALITY_TAGS("producer, measurement"), // optional event tags
  "Producer took measurement");           // optional event description

# MODALITY_PROBE_EXPECT

Record an expectation event with metadata for the CLI tooling. Expectations aid analysis by highlighting potential problems, impact certain metrics, and can influence the mutation planner.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this expectation event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the expectation event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
expr
boolean expression
Boolean expression for expectation success, true is passing.
MODALITY_SEVERITY(<level>)
Optional
macro
No-op macro. Use MODALITY_SEVERITY to specify the severity of a failure. Accepts an integer value between 1 and 10. Modality's manifest generation tool scans for this value—it will never be included in your binary.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the expectation event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the expectation event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

MODALITY_PROBE_EXPECT(
  g_producer_probe,                         // pointer to probe
  PRODUCER_SAMPLE_DELTA_OK,                 // expectation name
  (sample - g_producer_measurement.m) <= 2, // failure condition
  MODALITY_SEVERITY(6),                     // optional expectation severity
  MODALITY_TAGS("producer", "measurement"), // optional expectation tags
  "Measurement delta within ok range");     // optional expectation description

# MODALITY_PROBE_EXPECT_W_TIME

Record an expectation with time, with metadata for the CLI tooling. Expectations aid analysis by highlighting potential problems, impact certain metrics, and can influence the mutation planner.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this expectation event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the expectation event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
expr
boolean expression
Boolean expression for expectation success, true is passing.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_SEVERITY(<level>)
Optional
macro
No-op macro. Use MODALITY_SEVERITY to specify the severity of a failure. Accepts an integer value between 1 and 10. Modality's manifest generation tool scans for this value—it will never be included in your binary.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the expectation event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the expectation event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();

MODALITY_PROBE_EXPECT_W_TIME(
  g_producer_probe,                         // pointer to probe
  PRODUCER_SAMPLE_DELTA_OK,                 // expectation name
  (sample - g_producer_measurement.m) <= 2, // failure condition
  time_ns,                                  // timestamp
  MODALITY_SEVERITY(6),                     // optional expectation severity
  MODALITY_TAGS("producer", "measurement"), // optional expectation tags
  "Measurement delta within ok range");     // optional expectation description

# MODALITY_PROBE_FAILURE

Record a failure event with metadata for the CLI tooling. Failures aid analysis by highlighting problems, impact certain metrics, and can influence the mutation planner.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this failure event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the failure event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
MODALITY_SEVERITY(<level>)
Optional
macro
No-op macro. Use MODALITY_SEVERITY to specify the severity of a failure. Accepts an integer value between 1 and 10. Modality's manifest generation tool scans for this value—it will never be included in your binary.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the failure event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the failure event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

MODALITY_PROBE_FAILURE(
  g_producer_probe,                         // pointer to probe
  SENSOR_OFFLINE,                           // failure name
  MODALITY_SEVERITY(6),                     // optional expectation severity
  MODALITY_TAGS("producer", "sensor"),      // optional expectation tags
  "Detected sensor offline");               // optional expectation description

# MODALITY_PROBE_FAILURE_W_TIME

Record a failure event with time, with metadata for the CLI tooling. Failures aid analysis by highlighting problems, impact certain metrics, and can influence the mutation planner.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this failure event will be recorded—multiple threads cannot record events to a single probe.
event
uint32_t
Unique ID for the failure event. We strongly recommend putting the name you would use with #define in this field and using modality-probe manifest-gen and modality-probe header-gen, or the corresponding CMake functions for manifests and headers, to generate a unique ID for you. This then provides a token that identifies the event's unique name, which is listed in command line descriptions of your system and used in many user-written queries.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
MODALITY_SEVERITY(<level>)
Optional
macro
No-op macro. Use MODALITY_SEVERITY to specify the severity of a failure. Accepts an integer value between 1 and 10. Modality's manifest generation tool scans for this value—it will never be included in your binary.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the failure event. Modality's manifest generation tool scans for this value—it will never be included in your binary.
description
Optional
string literal
String to help identify the failure event when inspecting it from the CLI. Modality's manifest generation tool scans for this value—it will never be included in your binary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

uint64_t time_ns = get_wall_clock_time();

MODALITY_PROBE_FAILURE(
  g_producer_probe,                         // pointer to probe
  SENSOR_OFFLINE,                           // failure name
  time_ns,                                  // timestamp
  MODALITY_SEVERITY(6),                     // optional expectation severity
  MODALITY_TAGS("producer", "sensor"),      // optional expectation tags
  "Detected sensor offline");               // optional expectation description

# MODALITY_TAGS

#define MODALITY_TAGS(...)

No-op macro used from other macros to expose tags to the CLI tooling. Accepts a comma-separated list of string literals. Note that tag strings must not contain any ( or ) characters.

Tags are arbitrary user-defined strings which can be attached to probes, events, expectations, failures, and mutators to help organize your system in Modality. They can be used in queries, specifications, and objectives.

Modality's manifest generation tool scans for MODALITY_TAGS and saves them as metadata—they will never be included in your binary.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

err = MODALITY_PROBE_RECORD(
  g_producer_probe,                   // pointer to probe
  PRODUCER_STARTED,                   // event name
  MODALITY_TAGS("producer", "init"),  // optional event tags
  "Measurement producer started");    // optional event description

# MODALITY_SEVERITY

#define MODALITY_SEVERITY(level)

No-op macro used from other macros to specify the severity of an expectation or failure event for the CLI tooling. The levels are aligned with FMEA (opens new window) severity ratings, integers going from one to ten, with one indicating negligible or nonexistent harm and ten indicating a safety or regulatory hazard.

Modality's manifest generation tool scans for MODALITY_SEVERITY and saves it as metadata—it will never be included in your binary.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

err = MODALITY_PROBE_EXPECT(
  g_producer_probe,                         // pointer to probe
  PRODUCER_SAMPLE_DELTA_OK,                 // expectation name
  (sample - g_producer_measurement.m) <= 2, // failure condition
  MODALITY_SEVERITY(6));                    // optional expectation severity

# MODALITY_PROBE_MACROS_ENABLED

Value used to enable or disable Modality macros. When MODALITY_PROBE_MACROS_ENABLED = 1 macros are enabled. They can be disabled by setting MODALITY_PROBE_MACROS_ENABLED to 0. This effectively makes the invocations a no-op, returning MODALITY_PROBE_ERROR_OK where a return code is expected. Defaults to 1, meaning macros are enabled.

// Enable Modality macros (the default)
#define MODALITY_PROBE_MACROS_ENABLED 1

// Disable Modality macros
#define MODALITY_PROBE_MACROS_ENABLED 0

# MODALITY_PROBE_NULL_INITIALIZER

#define MODALITY_PROBE_NULL_INITIALIZER (NULL)

A default NULL initializer value for a modality_probe pointer.

#include <modality/probe.h>

modality_probe *probe = MODALITY_PROBE_NULL_INITIALIZER;

# MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY

#define MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY (0)

Convenience wall-clock ID value for a probe which does not share a wall clock with any other probes. Time-based queries (i.e. queries using WITHIN or AFTER) are only allowed between probes that use the same wall clock. This value lets you specify that a probe does not share a wall clock with any other probes without having to assign it a unique wall-clock ID.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

/* MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY in a probe */
err = MODALITY_PROBE_INIT(
  &g_producer_probe_buffer[0],                 // probe storage buffer
  sizeof(g_producer_probe_buffer),             // size of probe buffer
  PRODUCER_PROBE,                              // probe name
  MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED,  // clock resolution
  MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY,     // wall clock ID
  NULL,                                        // next_sid_fn
  NULL,                                        // next_sid_state
  &g_producer_probe);                           // output parameter

# MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED

#define MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED (0)

Convenience value for time resolution of a probe which does not use wall-clock time or whose clock resolution is unknown.

#include <modality/probe.h>
/* Generated header file for this component */
#include "generated_component_definitions.h"

/* MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED in a probe */
err = MODALITY_PROBE_INIT(
  &g_producer_probe_buffer[0],                 // probe storage buffer
  sizeof(g_producer_probe_buffer),             // size of probe buffer
  PRODUCER_PROBE,                              // probe name
  MODALITY_PROBE_TIME_RESOLUTION_UNSPECIFIED,  // clock resolution
  MODALITY_PROBE_WALL_CLOCK_ID_LOCAL_ONLY,     // wall clock ID
  NULL,                                        // next_sid_fn
  NULL,                                        // next_sid_state
  &g_producer_probe);                           // output parameter

# MODALITY_PROBE_ID_BROADCAST

#define MODALITY_PROBE_ID_BROADCAST (0)

Return value used by modality_probe_get_control_message_destination to indicate that a control message is intended to be processed by all probes.

# Tracing Functions

# modality_probe_report

size_t modality_probe_report(
    modality_probe *probe,
    uint8_t *log_report_destination,
    size_t log_report_destination_bytes,
    size_t *out_written_bytes);

Write a report of recorded events and logical clock data to a supplied destination buffer. The user is responsible for sending this report to the Modality daemon through its collector connections. If out_written_bytes is zero there were no new events, so the report does not need to be sent to Modality.

This function flushes the probe's internal storage buffer, clearing space to record more information. It should therefore be called repeatedly, at a frequency determined by the rate at which events are recorded to the probe.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
log_report_destination
uint8_t*
The destination buffer to be written to. This function will attempt to flush the entire probe storage buffer. If the report buffer is too small this function will flush as much of the probe storage buffer as possible.
log_report_destination_bytes
size_t
Size of the destination buffer in bytes.
out_written_bytes
size_t*
Number of bytes written to the destination buffer.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

static void send_report(modality_probe * const probe)
{
  size_t report_size;
  const size_t err = modality_probe_report(
    probe,                      // probe to generate report from
    &g_report_buffer[0],        // report buffer
    sizeof(g_report_buffer),    // size of report buffer
    &report_size);              // size of created report
  assert(err == MODALITY_PROBE_ERROR_OK);

  if(report_size != 0)
  {
    const ssize_t status = sendto(
      g_report_socket,
      &g_report_buffer[0],
      report_size,
      0,
      (const struct sockaddr*) &g_collector_addr,
      sizeof(g_collector_addr));
    assert(status != -1);
  }
}

# modality_probe_produce_snapshot

size_t modality_probe_produce_snapshot(
    modality_probe *probe,
    modality_probe_causal_snapshot *snapshot);

Produce a transmittable summary of this probe's history for use by another probe elsewhere in the system. This snapshot should be merged by the receiving probe with modality_probe_merge_snapshot, or with modality_probe_merge_snapshot_with_time if that probe uses wall-clock time.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
snapshot
The destination snapshot to receive this probe’s causal history summary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_produce_snapshot(
  g_producer_probe,        // pointer to probe (sender)
  &measurement.snapshot);  // pointer to produced snapshot
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_produce_snapshot_with_time

size_t modality_probe_produce_snapshot_with_time(
    modality_probe *probe,
    uint64_t time_ns,
    modality_probe_causal_snapshot *snapshot);

Produce a transmittable summary of this probe's history for use by another probe elsewhere in the system. This snapshot should be merged by the receiving probe with modality_probe_merge_snapshot, or with modality_probe_merge_snapshot_with_time if that probe uses wall-clock time. This variant will record the current time in the log, along with the regular snapshot information. A future version of modality will use this information to determine the relationship between the wall-clock time on different probes, even if they do not share a clock.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
snapshot
The destination snapshot to receive this probe’s causal history summary.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

uint64_t time_ns = get_wall_clock_time();

err = modality_probe_produce_snapshot(
  g_producer_probe,        // pointer to probe (sender)
  time_ns,                 // timestamp
  &measurement.snapshot);  // pointer to produced snapshot
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_produce_snapshot_bytes

size_t modality_probe_produce_snapshot_bytes(
    modality_probe *probe,
    uint8_t *history_destination,
    size_t history_destination_bytes,
    size_t *out_written_bytes);

Produce a transmittable opaque blob of this probe's history for use by another probe elsewhere in the system. This function allows you to avoid parsing the snapshot data into the modality_probe_causal_snapshot type, instead encoding it in a system-architecture independent way. This snapshot should be merged by the receiving probe with modality_probe_merge_snapshot_bytes, or with modality_probe_merge_snapshot_bytes_with_time if that probe uses wall-clock time.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
history_destination
uint8_t*
The destination buffer to be written to.
history_destination_bytes
size_t
Size of the destination buffer in bytes.
out_written_bytes
size_t*
Number of bytes written to the destination buffer.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_produce_snapshot_bytes(
    g_producer_probe,      // pointer to probe (sender)
    snapshot_bytes,        // snapshot buffer
    snapshot_bytes_length, // size of snapshot buffer
    &snapshot_size);       // number of bytes written
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_produce_snapshot_bytes_with_time

size_t modality_probe_produce_snapshot_bytes_with_time(
    modality_probe *probe,
    uint64_t time_ns,
    uint8_t *history_destination,
    size_t history_destination_bytes,
    size_t *out_written_bytes);

Produce a transmittable opaque blob of this probe's history for use by another probe elsewhere in the system. This function allows you to avoid parsing the snapshot data into the modality_probe_causal_snapshot type, instead encoding it in a system-architecture independent way. This snapshot should be merged by the receiving probe with modality_probe_merge_snapshot_bytes, or with modality_probe_merge_snapshot_bytes_with_time if that probe uses wall-clock time. This variant will record the current time in the log, along with the regular snapshot information. A future version of modality will use this information to determine the relationship between the wall-clock time on different probes, even if they do not share a clock.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
history_destination
uint8_t*
The destination buffer to be written to.
history_destination_bytes
size_t
Size of the destination buffer in bytes.
out_written_bytes
size_t*
Number of bytes written to the destination buffer.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

uint64_t time_ns = get_wall_clock_time();

err = modality_probe_produce_snapshot_bytes(
    g_producer_probe,      // pointer to probe (sender)
    time_ns,               // timestamp
    snapshot_bytes,        // snapshot buffer
    snapshot_bytes_length, // size of snapshot buffer
    &snapshot_size);       // number of bytes written
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_merge_snapshot

size_t modality_probe_merge_snapshot(
    modality_probe *probe,
    const modality_probe_causal_snapshot *snapshot);

Consume a causal history summary structure provided by some other probe. Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
snapshot
The snapshot to merge.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_merge_snapshot(
  g_consumer_probe,        // pointer to probe (receiver)
  &measurement.snapshot);  // pointer to received snapshot
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_merge_snapshot_with_time

size_t modality_probe_merge_snapshot_with_time(
    modality_probe *probe,
    const modality_probe_causal_snapshot *snapshot,
    uint64_t time_ns);

Consume a causal history summary structure provided by some other probe. This variant will record the current time in the log, along with the regular snapshot information. A future version of modality will use this information to determine the relationship between the wall-clock time on different probes, even if they do not share a clock.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
snapshot
The snapshot to merge.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

uint64_t time_ns = get_wall_clock_time();

err = modality_probe_merge_snapshot_with_time(
  g_consumer_probe,        // pointer to probe (receiver)
  &measurement.snapshot,   // pointer to received snapshot
  time_ns);                // timestamp
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_merge_snapshot_bytes

size_t modality_probe_merge_snapshot_bytes(
    modality_probe *probe,
    const uint8_t *history_source,
    size_t history_source_bytes);

Consume an opaque causal history blob provided by some other probe. Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
history_source
const uint8_t*
The snapshot buffer to merge.
history_source_bytes
size_t
Size of the snapshot buffer in bytes.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_merge_snapshot_bytes(
  g_consumer_probe,     // pointer to probe (receiver)
  snapshot_bytes,       // received snapshot buffer
  snapshot_bytes_size); // size of received snapshot buffer
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_merge_snapshot_bytes_with_time

size_t modality_probe_merge_snapshot_bytes_with_time(
    modality_probe *probe,
    const uint8_t *history_source,
    size_t history_source_bytes,
    uint64_t time_ns);

Consume an opaque causal history blob provided by some other probe. This variant will record the current time in the log, along with the regular snapshot information. A future version of modality will use this information to determine the relationship between the wall-clock time on different probes, even if they do not share a clock.

Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
history_source
const uint8_t*
The snapshot buffer to merge.
history_source_bytes
size_t
Size of the snapshot buffer in bytes.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

uint64_t time_ns = get_wall_clock_time();

err = modality_probe_merge_snapshot_bytes_with_time(
  g_consumer_probe,    // pointer to probe (receiver)
  snapshot_bytes,      // received snapshot buffer
  snapshot_bytes_size, // size of received snapshot buffer
  time_ns);            // timestamp
assert(err == MODALITY_PROBE_ERROR_OK);

# modality_probe_get_control_message_destination

size_t modality_probe_get_control_message_destination(
    const uint8_t *message_source,
    size_t message_source_bytes,
    uint32_t *target_probe_id);

Retrieve the target probe id from a control-message-containing buffer. The target probe id may be a specific probe id or MODALITY_PROBE_ID_BROADCAST for broadcast. Processing control messages is required for mutation functionality and for correlating your stimulus with events recorded in the System Under Test (SUT) using scopes. The SUT should listen on the control connections listed in the Modality Configuration File to receive and process messages.

Parameters

message_source
const uint8_t*
The buffer containing a control message.
message_source_bytes
size_t
Size of the buffer in bytes.
target_probe_id
uint32_t*
The destination probe id to be written to.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_get_control_message_destination(
    control_message_bytes,  // control message buffer
    control_message_length, // buffer size
    &target_probe_id);      // destination probe ID
assert(err == MODALITY_PROBE_ERROR_OK);

// route according to destination

# modality_probe_process_control_message

size_t modality_probe_process_control_message(
    modality_probe *probe,
    const uint8_t *message_source,
    size_t message_source_bytes,
    size_t *should_forward);

Process a control message. If the message is meant for the probe passed as the first parameter it will be processed, otherwise it will be ignored. Processing control messages is required for mutation functionality and for correlating your stimulus with events recorded in the System Under Test (SUT) using scopes. The SUT should listen on the control connections listed in the Modality Configuration File to receive and process messages.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
message_source
const uint8_t*
The control message buffer to process.
message_source_bytes
size_t
Size of the control message buffer in bytes.
should_forward
size_t*
If the control message is targeting this probe, should_forward will be set to zero. Otherwise if this control message is broadcast (see MODALITY_PROBE_ID_BROADCAST) or targeting another probe, should_forward will be set to one.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_process_control_message(
    g_producer_probe,       // pointer to probe
    control_message_bytes,  // control message buffer
    control_message_length, // buffer size
    &should_forward);       // should forward
assert(err == MODALITY_PROBE_ERROR_OK);

// forward if necessary

# modality_probe_process_control_message_with_time

size_t modality_probe_process_control_message_with_time(
    modality_probe *probe,
    const uint8_t *message_source,
    size_t message_source_bytes,
    uint64_t time_ns,
    size_t *should_forward);

Process a control message. This variant will record the current time in the log along with processing the message. If the message is meant for the probe passed as the first parameter it will be processed, otherwise it will be ignored. Processing control messages is required for mutation functionality and for correlating your stimulus with events recorded in the System Under Test (SUT) using scopes. The SUT should listen on the control connections listed in the Modality Configuration File to receive and process messages.

Parameters

probe
modality_probe*
The probe instance to use. This function must be called on the thread that is recording events to this probe.
message_source
const uint8_t*
The control message buffer to process.
message_source_bytes
size_t
Size of the control message buffer in bytes.
time_ns
uint64_t
The wall-clock time, limited to 61 bits of nanoseconds.
should_forward
size_t*
If the control message is targeting this probe, should_forward will be set to zero. Otherwise if this control message is broadcast (see MODALITY_PROBE_ID_BROADCAST) or targeting another probe, should_forward will be set to one.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

uint64_t time_ns = get_wall_clock_time();

err = modality_probe_process_control_message_with_time(
    g_producer_probe,       // pointer to probe
    control_message_bytes,  // control message buffer
    control_message_length, // buffer size
    time_ns,                // timestamp
    &should_forward);       // should forward
assert(err == MODALITY_PROBE_ERROR_OK);

// forward if necessary

# modality_probe_announce_mutators Pro

size_t modality_probe_announce_mutators(
    modality_probe *probe,
    uint8_t *announcement_destination,
    size_t announcement_destination_size_bytes,
    size_t *out_written_bytes);

Write mutator announcement data to a supplied destination buffer. The mutator announcement data produced by this function must be sent to one of modalityd’s collector connections at least once per session before any mutations are injected. modalityd will gracefully handle receiving mutator announcement data multiple times. This function must be called on the thread that is recording events to this probe.

Parameters

probe
modality_probe*
The probe instance to use.
announcement_destination
uint8_t*
The destination buffer to be written to.
announcement_destination_size_bytes
size_t
Size of the destination buffer in bytes.
out_written_bytes
size_t*
Number of bytes written to the destination buffer.

Returns

One of the modality_probe_error error values.

#include <modality/probe.h>

err = modality_probe_announce_mutators(
    g_producer_probe,    // pointer to probe
    announcement_bytes,  // announcement buffer
    announcement_length, // size of announcement buffer
    &announcement_size); // number of bytes written
assert(err == MODALITY_PROBE_ERROR_OK);

# Typedefs

# modality_probe_error

typedef enum {} modality_probe_error;

Modality probe error values.

Possible Values

MODALITY_PROBE_ERROR_OK
Everything is okay.
MODALITY_PROBE_ERROR_NULL_POINTER
A null pointer was provided to the function.
MODALITY_PROBE_ERROR_INVALID_EVENT_ID
An event id outside of the allowed range was provided.
MODALITY_PROBE_ERROR_INVALID_PROBE_ID
A probe id outside of the allowed range was provided.
MODALITY_PROBE_ERROR_INSUFFICIENT_DESTINATION_BYTES
The size available for output bytes was insufficient to store a valid representation.
MODALITY_PROBE_ERROR_EXCEEDED_MAXIMUM_ADDRESSABLE_SIZE
Bumped into a pointer size limitation.
MODALITY_PROBE_ERROR_EXCEEDED_AVAILABLE_CLOCKS
The local probe does not have enough space to track all of direct neighbors attempting to communicate with it. Detected during merging.
MODALITY_PROBE_ERROR_INSUFFICIENT_SOURCE_BYTES
The external history source buffer we attempted to merge was insufficiently sized for a valid causal snapshot. Detected during merging.
MODALITY_PROBE_ERROR_INVALID_EXTERNAL_HISTORY_SEMANTICS
The provided external history violated a semantic rule of the protocol, such as by having a probe id outside of the allowed value range. Detected during merging.
MODALITY_PROBE_ERROR_RESTART_PERSISTENCE_SEQUENCE_ID_UNAVAILABLE
The user-supplied restart persistence counter failed to produce the next sequence id.
MODALITY_PROBE_ERROR_INVALID_WALL_CLOCK_TIME
A wall-clock time outside of the allowed range was provided.
MODALITY_PROBE_ERROR_INTERNAL_ENCODING_ERROR
An unexpected error in internal data encoding occurred.
MODALITY_PROBE_ERROR_EXCEEDED_AVAILABLE_MUTATOR_SLOTS
The local probe does not have enough space to track the mutator that was just attempted to be registered.
MODALITY_PROBE_ERROR_MALFORMED_ANNOUNCEMENT
The announcement data was malformed. The local probe does not have enough space to track the mutator that was just attempted to be registered.

# modality_probe modality_probe

typedef struct modality_probe modality_probe;

The opaque type of a probe instance. Probes are not thread-safe, so only one thread should record events to a given modality_probe.

# modality_probe_logical_clock

typedef struct modality_probe_logical_clock {
    uint32_t id;
    uint16_t epoch;
    uint16_t ticks;
} modality_probe_logical_clock;

A single logical clock, usable as an entry in a vector clock.

Fields

id
uint32_t
The Modality probe that this clock is tracking.
epoch
uint16_t
Clock epoch.
ticks
uint16_t
Clock tick count.

# modality_probe_causal_snapshot

typedef struct modality_probe_causal_snapshot {
    modality_probe_logical_clock clock;
    uint8_t reserved_0[2];
    uint8_t reserved_1[2];
} modality_probe_causal_snapshot;

Snapshot of a probe's causal history for transmission around the system. Snapshots should be sent and merged between the corresponding probes along with all communication between different parts of the SUT. This allows Modality to create causal links between probes when they communicate, letting you trace execution between different parts of your system.

Fields

clock
Probe id and tick-count at the probe which this history snapshot was created from.
reserved_0
uint8_t[2]
Reserved field.
reserved_1
uint8_t[2]
Reserved field.

# modality_probe_next_sequence_id_fn

typedef size_t (*modality_probe_next_sequence_id_fn)(
    uint32_t probe_id,
    void *user_state,
    uint16_t *out_sequence_id);

Function type for retrieving the next persistent sequence number.

This method is called when a probe initializes to get the initial epoch portion of the clock, and each time the ticks portion of the clock overflows during the probe's lifetime.

The function should return MODALITY_PROBE_ERROR_OK when the next sequence value could be retrieved and was used to populate the value at out_sequence_id.

The sequence number starts at zero, and should be monotonically increased by a step size of one after each retrieval.

When the sequence number reaches its maximum value (0xFFFF), it should wrap around to the value 0.

If no sequence number could be retrieved, the function should return MODALITY_PROBE_ERROR_RESTART_PERSISTENCE_SEQUENCE_ID_UNAVAILABLE.

Parameters

probe_id
uint32_t
The probe identifier for the probe calling this function.
user_state
void*
The user’s state passed from MODALITY_PROBE_INIT.
out_sequence_id
uint16_t*
The next user provided sequence identifier for the probe to use.

Returns

One of the modality_probe_error error values.

# Mutator Macros Pro

The following macros are used to register mutators along with additional metadata for the CLI tooling, specifically mutator parameter definitional content and tag strings. The extra metadata is detected by the CLI for generating manifest information and mutator definitions—it will never be included in your binary.

Pro Mutation is a feature of the full version of Modality.

# MODALITY_MUTATOR Pro

This macro exposes arbitrary user data as a parameter for mutation. You can invoke this macro multiple times with the same mutator_token to associate multiple data parameters under a single mutator, up to 6 parameters per mutator.

When a mutation is injected using this mutator the behavior is as follows: every time the flow of execution passes through the invocation of the MODALITY_MUTATOR macro, the parameter value for the active mutation will be copied into the data_ptr location. User code otherwise runs normally and can change the value at data_ptr, meaning that access to the data before the call to MODALITY_MUTATOR will not see the mutation's effects, and changes to the data after the call can undo the mutation. It is therefore important to consider where in code to invoke MODALITY_MUTATOR, since this will change the effect of mutations using this mutator. For example, to create a mutator that changes the value reported by a sensor, you could add MODALITY_MUTATOR immediately after getting the sensor value. Then, even if the value is read in a loop, the mutator will reset it to the mutation value every time it is read.

The modality-probe mutator-gen command or corresponding CMake function will generate a mutator manifest, header, and source code based on the information exposed in the macro invocation. The probe that this mutator is associated with must process control messages for mutation functionality to work.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this mutator will be used—whichever probe that thread is recording events to must also trigger mutations on that thread.
mutator_token
identifier
The mutator identifier token. This will be used to name the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to the mutator throughout Modality, including in queries and specifications, the CLI, and objectives.
param_token
identifier
An identifier token that uniquely identifies this parameter within the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to this parameter in the CLI. Multiple invocations may be used for a given mutator_token to associate multiple data parameters under a single mutator, up to 6 parameters per mutator.
param_def
macro
The mutator parameter definition, giving parameter type and relevant metadata. Specified using the MODALITY_PARAM_DEF macro.
data_ptr
void*
Pointer to the actual user data that this mutator will modify.
data_size
size_t
The size of the user’s data to be exposed for mutation, in bytes.
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the mutator. Modality's mutator manifest generation tool scans for this value—it will never be included in your binary.

Returns

Void

MODALITY_MUTATOR Example

#include <modality/probe.h>
#include <modality/mutator.h>

/* The header file you generated with 'modality-probe mutator-gen' */
#include "battery_mutator.h"

/* Generates a mutator over the filtered voltage parameter */
MODALITY_MUTATOR(
  _probe,                       // pointer to probe
  BATTERY_MUTATOR,              // mutator token
  voltage,                      // parameter token
  MODALITY_PARAM_DEF(           // parameter definition
    F32,                        // parameter type
    12.15f,                     // minimum effect value
    NOMINAL(11.5f, 12.3f),      // nominal range
    SAFETY(6.0f, 12.3f),        // safety range
    HARD(2.1f, 12.3f)),         // hard range
  &_voltage_filtered_v,         // system variable to mutate
  sizeof(_voltage_filtered_v),  // size of system variable
  MODALITY_TAGS("px4", "battery", "power")); // optional mutator tags

# MODALITY_MUTATOR_DELAY_MS Pro

This macro creates a mutator to introduce delays. The amount of time to delay in milliseconds is exposed as a parameter for mutation. The user is responsible for implementing a delay function in whichever way makes sense for the SUT. This function will receive the delay period as a uint32_t parameter.

When a mutation is injected using this mutator the behavior is as follows: every time the flow of execution passes through the invocation of the MODALITY_MUTATOR_DELAY_MS macro, the user-provided delay function will be called with the mutation's delay period. It is therefore important to consider where in code to invoke MODALITY_MUTATOR_DELAY_MS, since this will change the effect of mutations using this mutator—if code flow passes through the invocation multiple times while a mutation is active a delay will be introduced each time.

The modality-probe mutator-gen command or corresponding CMake function will generate a mutator manifest, header, and source code based on the information exposed in the macro invocation. The probe that this mutator is associated with must process control messages for mutation functionality to work.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this mutator will be used—whichever probe that thread is recording events to must also trigger mutations on that thread.
mutator_token
identifier
The mutator identifier token. This will be used to name the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to the mutator throughout Modality, including in queries and specifications, the CLI, and objectives.
param_token
identifier
An identifier token that uniquely identifies this parameter within the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to this parameter in the CLI.
delay_def
macro
The mutator delay-milliseconds parameter definition. Specified using the MODALITY_DELAY_MS_DEF macro.
delay_fn_ptr
void(*)(const uint32_t)
A pointer to the user’s delay-milliseconds function. The function prototype is void my_delay_ms(const uint32_t ms).
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the mutator. Modality's mutator manifest generation tool scans for this value—it will never be included in your binary.

Returns

Void

MODALITY_MUTATOR_DELAY_MS Example

#include <modality/probe.h>
#include <modality/mutator.h>

/* The header file you generated with 'modality-probe mutator-gen' */
#include "sensor_delay_mutator.h"

static void sensor_delay_fn(const uint32_t ms)
{
    /* ... delay implementation here ... */
}

/* Generates a delay mutator to create sensor lag */
MODALITY_MUTATOR_DELAY_MS(
  _probe,                 // pointer to probe
  SENSOR_DELAY_MUTATOR,   // mutator token
  sensor_delay,           // parameter token
  MODALITY_DELAY_MS_DEF(  // parameter definition
    0,                    // minimum effect value
    NOMINAL(0, 100),      // nominal range
    SAFETY(0, 2500) ,     // safety range
    HARD(0, 10000)),      // hard range
  sensor_delay_fn,        // delay function pointer
  MODALITY_TAGS("px4", "sensor", "delay")); // optional mutator tags

# MODALITY_MUTATOR_FN_CALL Pro

This macro creates a mutator that calls an arbitrary user defined function as a mutation.

The modality-probe mutator-gen command or corresponding CMake function will generate a mutator manifest, header, and source code based on the information exposed in the macro invocation. The probe that this mutator is associated with must process control messages for mutation functionality to work.

Parameters

probe
modality_probe*
The probe instance to use. This should be determined according to the thread on which this mutator will be used—whichever probe that thread is recording events to must also trigger mutations on that thread.
mutator_token
identifier
The mutator identifier token. This will be used to name the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to the mutator throughout Modality, including in queries and specifications, the CLI, and objectives.
param_token
identifier
An identifier token that uniquely identifies this parameter within the mutator, where the name is converted to a lower case hyphenated string. This name is used to refer to this parameter in the CLI.
fn_ptr
void(*)(void)
A pointer to the user’s function to be called when a mutation is injected. The function prototype is void my_fn(void).
MODALITY_TAGS(“<tag>”[,”<tag>”])
Optional
macro
No-op macro. Use MODALITY_TAGS to add any number of strings you want to associate with the mutator. Modality's mutator manifest generation tool scans for this value—it will never be included in your binary.

Returns

Void

MODALITY_MUTATOR_FN_CALL Example

#include <modality/probe.h>
#include <modality/mutator.h>

/* The header file you generated with 'modality-probe mutator-gen' */
#include "randomizer_fn_mutator.h"

static void randomize(void)
{
    /* ... randomize implementation here ... */
}

/* Generates a mutator to call a randomizer function */
MODALITY_MUTATOR_FN_CALL(
  _probe,                 // pointer to probe
  RANDOMIZER_FN_MUTATOR,  // mutator token
  randomizer_function,    // parameter token
  randomize,              // mutation function pointer
  MODALITY_TAGS("px4", "randomize")); // optional mutator tags

# MODALITY_PARAM_DEF Pro

#define MODALITY_PARAM_DEF(...)

No-op macro used to provide Modality with metadata about a mutation parameter for the MODALITY_MUTATOR data mutator macro. This metadata consists of guidance about the parameter type, the value for this parameter which is expected to impact the system the least, and information about what values can be used for generated mutations.

Parameters for primitive types:

  • Parameter type
    • I8 - signed 8-bit integer
    • I16 - signed 16-bit integer
    • I32 - signed 32-bit integer
    • I64 - signed 64-bit integer
    • U8 - unsigned 8-bit integer
    • U16 - unsigned 16-bit integer
    • U32 - unsigned 32-bit integer
    • U64 - unsigned 64-bit integer
    • F32 - 32-bit float
    • F64 - 64-bit float
  • Minimum effect value
    • Value for the parameter which is expected to have the least impact on the system under test.
  • Nominal range
    • Specified using the NOMINAL(inclusive_start, inclusive_end) no-op macro.
  • Safety range
    • Specified using the SAFETY(inclusive_start, inclusive_end) no-op macro.
  • Hard range
    • Specified using the HARD(inclusive_start, inclusive_end) no-op macro.

Parameters for boolean types:

  • Parameter type, must be BOOLEAN
  • Minimum effect value
    • Must be true or false.
    • Value for the parameter which is expected to have the least impact on the system under test.

Parameters for enum types:

  • Parameter type, must be ENUM
  • Minimum effect value
    • Must be one of the supplied enum variant values.
    • Value for the parameter which is expected to have the least impact on the system under test.
  • One or more enum value and name pairs
    • Specified using the ENUM_VALUE_NAME(value, "ENUM_VALUE_NAME") no-op macro.
    • Note that enum values are limited to the range of an i32.

Parameters for byte blob types:

  • Parameter type, must be BYTE_BLOB
  • Minimum effect value
    • Value for the parameter which is expected to have the least impact on the system under test.
  • Nominal range
    • Specified using the NOMINAL(inclusive_start, inclusive_end) no-op macro.
  • Safety range
    • Specified using the SAFETY(inclusive_start, inclusive_end) no-op macro.
  • Hard range
    • Specified using the HARD(inclusive_start, inclusive_end) no-op macro.

Note that byte blob range constraints specify the number of bytes to generate, limited to the range of a u32.

MODALITY_PARAM_DEF Primitive Type Example

#include <modality/mutator.h>

MODALITY_PARAM_DEF(
  I8,                          // parameter type
  0,                           // minimum effect value
  NOMINAL(-10, 10),            // nominal range
  SAFETY(-100, 100),           // safety range
  HARD(INT8_MIN, INT8_MAX))    // hard range

MODALITY_PARAM_DEF Boolean Example

#include <modality/mutator.h>

MODALITY_PARAM_DEF(
  BOOLEAN,     // parameter type
  false)       // minimum effect value

MODALITY_PARAM_DEF Enum Example

#include <modality/mutator.h>

enum
{
    ENUM_VAL_A = -10,
    ENUM_VAL_B = 0,
    ENUM_VAL_C = 10,
};

MODALITY_PARAM_DEF(
  ENUM,                                // parameter type
  -10,                                 // minimum effect value
  ENUM_VALUE_NAME(-10, "ENUM_VAL_A"),  // value and name pairs
  ENUM_VALUE_NAME(0, "ENUM_VAL_B"),
  ENUM_VALUE_NAME(10, "ENUM_VAL_c"))

MODALITY_PARAM_DEF Byte Blob Example

#include <modality/mutator.h>

MODALITY_PARAM_DEF(
  BYTE_BLOB,       // Parameter type
  0,               // Minimum effect value
  NOMINAL(0, 4),   // Nominal range
  SAFETY(0, 5),    // Safety range
  HARD(0, 6))      // Hard range

# MODALITY_DELAY_MS_DEF Pro

A no-op macro used to define a Modality delay-milliseconds mutator parameter definition parsed by the Modality probe CLI.

Parameters

Minimum effect value
Value for the parameter which is expected to have the least impact on the system under test.
Nominal range
Specified using the NOMINAL(inclusive_start, inclusive_end) format.
Safety range
Specified using the SAFETY(inclusive_start, inclusive_end) format.
Hard range
Specified using the HARD(inclusive_start, inclusive_end) format.

Note that the minimum effect value and range constraints are limited to the range of a u32.

MODALITY_DELAY_MS_DEF Example

MODALITY_DELAY_MS_DEF(
  0,                 // minimum effect value
  NOMINAL(0, 100),   // nominal range
  SAFETY(0, 2500) ,  // safety range
  HARD(0, 10000))    // hard range

# MODALITY_MUTATOR_MACROS_ENABLED Pro

Value used to enable or disable Modality mutator macros. When MODALITY_MUTATOR_MACROS_ENABLED = 1 macros are enabled. They can be disabled by setting MODALITY_MUTATOR_MACROS_ENABLED to 0. This effectively makes the invocations a no-op. Defaults to 1, meaning mutator macros are enabled.

// Enable Modality mutator macros (the default)
#define MODALITY_MUTATOR_MACROS_ENABLED 1

// Disable Modality mutator macros
#define MODALITY_MUTATOR_MACROS_ENABLED 0

# Build Tools

# CMake Integrations

The Modality installer includes CMake functions to make it easier to run the instrumentation-based manifest and code generation tools as part of your build process. These functions come in the ModalityProbe config package, so to use them you must include the line find_package(ModalityProbe REQUIRED) in your CMakeLists.txt file. For step by step instructions on integrating Modality with your build see the guide to instrumenting your system.

Example: Find ModalityProbe package
cmake_minimum_required(VERSION 3.5)
project(cmake-example)

# 1. Load ModalityProbe config package
find_package(ModalityProbe REQUIRED)

...

# ModalityProbe config package

The ModalityProbe config package includes the following potentially useful target and variables along with the functions below:

  • When found, this config-file defines the ModalityProbe::LibModalityProbe target.
  • ModalityProbe_FOUND
    • True if modality-probe is found.
  • MODALITY_PROBE_INCLUDE_DIRS
    • Include directories, where to find modality/probe.h, etc...
  • MODALITY_PROBE_LIBRARIES
    • List of libraries to link when using modality-probe.
  • MODALITY_PROBE_LIBRARY_DIRS
    • Library directories.
  • MODALITY_PROBE_BINARY_DIRS
    • Binary directories.
  • MODALITY_PROBE_CLI
    • Absolute path to modality-probe CLI.
  • MODALITY_CLI
    • Absolute path to Modality CLI.
  • MODALITY_PROBE_MAJOR_VERSION
    • The major version number.
  • MODALITY_PROBE_MINOR_VERSION
    • The minor version number.
  • MODALITY_PROBE_PATCH_VERSION
    • The patch version number.

# modality_probe_generate_manifest

CMake function to call the modality-probe manifest-gen command as part of your build process. This function generates Modality component definition files from instrumentation macro invocations. It monitors changes to relevant files and/or targets to generate new component manifests or update existing ones as needed.

Parameters

TARGET
CMake build target.
OUTPUT_PATH
Output path for generated component files. Defaults to component.
SOURCE_PATH
Path to a directory under which the modality-probe manifest-gen command will search for instrumentation in your code to generate component manifest files.
REGEN_COMPONENT_ID
Regenerate the component IDs instead of using existing IDs (if present).
LANG
Language, either C or RUST. Defaults to C.
DEPENDS
Files or targets this function depends on.
COMPONENT_NAME
Component name used when generating a component manifest. Defaults to component.
FILE_EXTENSIONS
Limit the source code searching to files with matching extensions.
EXCLUDES
Exclude files/paths that match the given pattern.
WORKING_DIRECTORY
Working directory for this command. Defaults to CMAKE_CURRENT_SOURCE_DIR.

modality_probe_generate_manifest Example

modality_probe_generate_manifest(
    TARGET cmake-example
    DEPENDS main.c
    COMPONENT_NAME "my-component"
    OUTPUT_PATH "my-component"
    EXCLUDES "build"
    FILE_EXTENSIONS "c"
    SOURCE_PATH ".")

# modality_probe_generate_header

CMake function to call the modality-probe header-gen command as part of your build process. This function generates C or Rust header files with event/probe ID constants from component definition files. It monitors changes to relevant files and/or targets to generate new headers or update existing ones as needed.

Parameters

TARGET
CMake build target.
COMPONENT_PATH
Path to component definition directory.
OUTPUT_FILE
Output file path for generated headers.
LANG
Language, either C or RUST. Defaults to C.
WORKING_DIRECTORY
Working directory for this command. Defaults to CMAKE_CURRENT_SOURCE_DIR.

modality_probe_generate_header Example

modality_probe_generate_header(
    TARGET cmake-example
    OUTPUT_FILE "generated_component_definitions.h"
    COMPONENT_PATH "my-component")

# modality_probe_generate_mutators Pro

CMake function to call the modality-probe mutator-gen command as part of your build process. This function generates mutator implementations and definition files from instrumentation macro invocations. It monitors changes to relevant files to generate new mutator implementations and definitions or update existing ones as needed.

Parameters

TARGET
CMake build target.
COMPONENT_PATH
Path to component definition directory that mutator manifests should be output to.
OUTPUT_PATH
Output path for generated source and header files. Defaults to ..
SOURCE_PATH
Source path where the modality-probe mutator-gen command will search for instrumentation in your code to generate mutator implementations and definition files.
EXCLUDES
Exclude files/paths that match the given pattern.
DEPENDS
Files or targets this function depends on.
FILE_EXTENSIONS
Limit the source code searching to files with matching extensions.
WORKING_DIRECTORY
Working directory for this command. Defaults to CMAKE_CURRENT_SOURCE_DIR.

modality_probe_generate_mutators Example

modality_probe_generate_mutators(
    TARGET cmake-example
    DEPENDS main.c
    FILE_EXTENSIONS "c"
    COMPONENT_PATH "my-component"
    OUTPUT_PATH "generated_mutators"
    EXCLUDES "build"
    SOURCE_PATH ".")