Open app

Send logs and events

Plexus stores two kinds of data: metrics (numbers) and events (everything else — faults, state changes, log lines). There is no log file upload and no drop-in Python logging handler. To get logs into Plexus, send the lines that matter as events.

Send a log line as an event

Send a dict with the fields you want to see later. A level and a msg are enough to start:

from plexus import Plexus

px = Plexus(source_id="robot-01")   # reads PLEXUS_API_KEY from the environment

px.event("log", {"level": "error", "msg": "IMU read timed out", "code": 42})
px.event("log", {"level": "warning", "msg": "Battery below 20%"})

The first argument is the event name. Use one name for all your log lines (log), or split them by subsystem (nav.log, motor.log) so you can filter them apart when you read them back.

Over plain HTTP, send the same thing as a point with "class": "event":

curl -X POST https://gateway.plexus.company/ingest \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "source_id": "robot-01",
    "points": [
      {
        "metric": "log",
        "value": { "level": "error", "msg": "IMU read timed out" },
        "class": "event"
      }
    ]
  }'

Forward only what matters

Plexus is not a place to ship every debug line. Forward errors, warnings, and the state changes you'd want to see next to your metrics. If you use Python's logging module, a few lines of your own code can forward warnings and above:

import logging

class PlexusForwarder(logging.Handler):
    def __init__(self, px):
        super().__init__(level=logging.WARNING)
        self.px = px

    def emit(self, record):
        if record.name.startswith("plexus"):
            return  # don't forward the SDK's own log lines
        self.px.event("log", {
            "level": record.levelname.lower(),
            "logger": record.name,
            "msg": record.getMessage()[:1000],
        })

logging.getLogger().addHandler(PlexusForwarder(px))

Every px.event() call is one message, and events share the same rate limit as metrics. If you forward bursts of lines, queue them with px.batch() instead: b.send("log", {...}, data_class="event").

Limits

Maximum
Event value as a plain string256 characters
Event value as a dict or list4,096 bytes of JSON
Event name256 characters
Tags per event16
Points per batch10,000
HTTP request body5 MB
WebSocket message1 MB

A value over the limit is rejected. Over HTTP, one bad point fails the whole request with 400, so trim long messages before you send them. Stack traces and long lines should be cut down to the part you need.

Don't upload raw log files. There is no endpoint for them, and a whole file won't fit in an event. Parse the file on the device and send the lines that matter.

Events are kept for 7 days on Free; on Pro, for 3 years. See Plans and limits.

Read them back

  • In a dashboard — add a Device Events panel, pick the device, and optionally filter by event name.

  • Over the API — GET /v1/sources/{source_id}/events, filtered by name:

    curl "https://api.plexus.company/v1/sources/robot-01/events?name=log&last=1h" \
      -H "x-api-key: YOUR_API_KEY"

    value comes back as a string. Dicts arrive JSON-encoded, so parse them. See Events.

  • Live — subscribe to wss://api.plexus.company/v1/sources/{source_id}/events/stream. See Live streams.