Skip to main content
Annotate recordings with timestamped events — errors, state changes, anomalies, and custom markers. Events appear as colored markers on the MCAP viewer timeline and can be queried across your entire fleet for trend analysis and incident investigation.
Fleet Management is in preview. APIs and features described on this page may change.

Event Types

Every event has a type that determines how it renders on the timeline and how it appears in search results.
TypeDescriptionTimeline IconDefault Severity
errorSystem errors, hardware faults, crash reportsRed circlecritical
warningDegraded performance, threshold breaches, near-missesYellow trianglewarning
infoInformational markers, milestones, mode changesBlue circleinfo
state_changeRobot state transitions (idle, active, charging, etc.)Purple diamondinfo
anomalyML-detected anomalies, outlier sensor readingsOrange starwarning
customUser-defined event types with custom labelsGray squareinfo
Use custom events for domain-specific markers that don’t fit the built-in types. Custom events support the same metadata, querying, and visualization features as built-in types.

Creating Events

Single Event

Attach an event to a specific timestamp within a recording. The timestamp field must fall within the recording’s time range.
from avala import Client

client = Client()

event = client.fleet.events.create(
    recording_id="rec_abc123",
    timestamp="2026-01-15T10:30:00Z",
    type="anomaly",
    label="Gripper force spike",
    description="Gripper force exceeded expected maximum during pick operation",
    metadata={"force_n": 45.2, "expected_max": 30.0, "joint": "gripper_left"}
)

print(f"Event created: {event.uid} at {event.timestamp}")

Event Properties

PropertyTypeRequiredDescription
recording_idstringYesRecording to attach the event to
timestampdatetimeYesISO 8601 timestamp within the recording’s time range
typestringYesOne of: error, warning, info, state_change, anomaly, custom
labelstringYesShort label displayed on the timeline (max 120 characters)
descriptionstringNoLonger description shown in the event detail panel
metadataobjectNoArbitrary key-value pairs for structured data
severitystringNoOverride default severity: critical, warning, info
duration_msintegerNoEvent duration in milliseconds (for range events)
tagsstring[]NoTags for filtering and categorization

Batch Create

When processing recordings offline, create events in bulk to avoid per-event API overhead.
events = client.fleet.events.create_batch(
    recording_id="rec_abc123",
    events=[
        {
            "timestamp": "2026-01-15T10:30:00Z",
            "type": "error",
            "label": "Motor overtemp",
            "metadata": {"motor_id": "joint_3", "temp_c": 85.2}
        },
        {
            "timestamp": "2026-01-15T10:30:05Z",
            "type": "state_change",
            "label": "Emergency stop activated",
            "metadata": {"trigger": "thermal_protection"}
        },
        {
            "timestamp": "2026-01-15T10:32:00Z",
            "type": "info",
            "label": "Cooldown complete",
            "metadata": {"motor_id": "joint_3", "temp_c": 55.0}
        }
    ]
)

print(f"Created {len(events)} events")
Batch creation accepts up to 1,000 events per request. For larger volumes, split into multiple batch calls. Events within a batch are created atomically — if any event fails validation, none are created.

Querying Events

Filter by Device and Type

Search events across recordings and devices to identify patterns and recurring issues.
# All errors from a specific device in January
events = client.fleet.events.list(
    device_id="dev_abc123",
    type="error",
    since="2026-01-01T00:00:00Z",
    until="2026-02-01T00:00:00Z"
)

for event in events:
    print(f"[{event.timestamp}] {event.label}")
    if event.metadata:
        print(f"  metadata: {event.metadata}")

Filter by Recording

List all events within a single recording, ordered by timestamp.
events = client.fleet.events.list(
    recording_id="rec_abc123",
    order_by="timestamp"
)

for event in events:
    print(f"[{event.type}] {event.timestamp} - {event.label}")

Aggregate Event Counts

Get event counts grouped by type, device, or time interval for trend analysis.
# Error count by device over the last 7 days
summary = client.fleet.events.aggregate(
    type="error",
    group_by="device",
    since="2026-01-20T00:00:00Z",
    until="2026-01-27T00:00:00Z"
)

for entry in summary:
    print(f"{entry.device_name}: {entry.count} errors")

# Event count by type per day
daily = client.fleet.events.aggregate(
    group_by="type",
    interval="day",
    since="2026-01-01T00:00:00Z",
    until="2026-02-01T00:00:00Z"
)

for entry in daily:
    print(f"{entry.date} | {entry.type}: {entry.count}")

Search by Metadata

Query events using metadata field values to find specific incidents.
# Find all events related to a specific motor
events = client.fleet.events.list(
    metadata_filter={"motor_id": "joint_3"}
)

# Find force spikes above a threshold
events = client.fleet.events.list(
    type="anomaly",
    metadata_filter={"force_n": {"$gt": 40.0}}
)

Timeline Visualization

Events render as colored markers on the MCAP viewer timeline. Each event type has a distinct icon and color that matches the table in Event Types.

Interaction

  • Hover over a marker to see the event label and timestamp in a tooltip
  • Click a marker to jump the playback position to that timestamp and open the event detail panel
  • Right-click a marker to edit, delete, or copy the event
  • Drag across the timeline to select a range and filter the event list to that window

Multi-Panel Sync

When you click an event marker, all viewer panels jump to the event’s timestamp simultaneously. Camera panels show the frame at that moment, point cloud panels show the scan at that moment, and plot panels highlight the corresponding data point.
Use keyboard shortcuts to step between events: press E to jump to the next event and Shift+E to jump to the previous event. Press F to filter the timeline to show only events of the currently selected type.

Range Events

Events with a duration_ms field render as colored spans on the timeline instead of point markers. This is useful for representing conditions that persist over time, such as a period of degraded sensor quality or an extended error state.
# Create a range event spanning 30 seconds
event = client.fleet.events.create(
    recording_id="rec_abc123",
    timestamp="2026-01-15T10:30:00Z",
    type="warning",
    label="LiDAR degraded mode",
    description="Point cloud density dropped below 50% of nominal",
    duration_ms=30000,
    metadata={"density_pct": 42.0, "nominal_density_pct": 100.0}
)

Event Rules

Instead of creating events manually, use recording rules to automatically generate events when data patterns match defined conditions. For example, a rule can create an anomaly event whenever motor temperature exceeds a threshold, or a state_change event whenever the robot transitions between operating modes. Automatically generated events are tagged with source: rule and include the rule ID in their metadata so you can trace them back to the rule that created them.
# Events created by rules have source metadata
events = client.fleet.events.list(
    recording_id="rec_abc123",
    tags=["source:rule"]
)

for event in events:
    rule_id = event.metadata.get("rule_id")
    print(f"[{event.type}] {event.label} (created by rule {rule_id})")

Updating and Deleting Events

Update an Event

client.fleet.events.update(
    event_id="evt_abc123",
    label="Gripper force spike (confirmed)",
    severity="critical",
    tags=["reviewed", "confirmed"]
)

Delete an Event

client.fleet.events.delete(event_id="evt_abc123")
Deleting an event removes it permanently from the recording timeline. Events generated by recording rules will not be re-created unless the rule is re-evaluated against the recording.

Export Events

Export events to CSV or JSON for offline analysis, reporting, or integration with external tools.
# Export all error events from a device group
export = client.fleet.events.export(
    group_id="grp_abc123",
    type="error",
    since="2026-01-01T00:00:00Z",
    format="csv"
)

with open("errors_jan_2026.csv", "wb") as f:
    f.write(export.content)

Next Steps