Datasets
Logical buckets for your events. Each dataset gets its own retention window, default severity, alerts, and dashboards.
Datasets
A dataset is a named bucket that your server uses to tag events. Setting dataset: "player-actions" on an event puts it in that bucket. Setting dataset: "anti-cheat" puts it in a different one.
You choose the dataset names. Most ServerOps customers organise theirs by area of concern: player-actions, economy, anti-cheat, system, database, staff-actions. There is no fixed list.
The Datasets page (Logs ▸ Datasets) is where you see what your project has accumulated, edit retention and default severity, and archive buckets you no longer need.
Why datasets
Datasets are first-class in three ways your alternative (one big stream + payload metadata) is not:
- Per-bucket retention. Chatty
debugat 7 days, audit-gradestaff-actionsat 365 days. Each dataset has its own retention window. - Per-bucket alerts and dashboards. "Alert when errors per minute in
staff-actionsexceeds 10" is scoped at the dataset level. Same for dashboards. - Faster searches. Queries that include a
dataset:<name>filter prune partitions at the storage layer; queries that key off payload fields scan more.
You can technically put everything in one dataset and discriminate inside the event payload. It works, but you lose per-bucket retention and alerts and your searches get slower as your volume grows.
The index page
Click Datasets in the Logs sub-nav. You land on a table with one row per non-archived dataset:
| Column | What it shows |
|---|---|
| NAME | The dataset name (e.g., player-actions), prefixed with a small orange ● dot. The default bucket carries a SYSTEM badge. |
| EVENTS (LAST 24H) | How many events landed in this dataset in the last 24 hours |
| RETENTION | Number of days events are kept before being aged out. 0d means "use the project default." |
| DEFAULT SEVERITY | The severity assigned to events that come in without one. Often INFO. |
| CREATED | The date the dataset first received an event |
Above the table, a DATASETS · N / M chip shows how many user datasets you have versus your plan cap. It turns orange when you are at or over the cap.
Click any row to drill into the schema or settings.
Plan caps and the default bucket
Your plan limits how many datasets you can have:
| Plan | Datasets |
|---|---|
| Hobby | 5 |
| Pro | 50 |
| Scale | Unlimited |
If you POST an event under a new dataset name when you are already at the cap, the event is not rejected. Instead it lands in a system-managed bucket called default, with the name you asked for stamped onto the event payload as _intended_dataset. The API response includes a warning so your SDK can surface it:
{
"accepted": 1,
"event_ids": ["evt_..."],
"warnings": [{
"code": "dataset_capped",
"requested": "dataset-f",
"routed_to": "default"
}]
}You can search overflowed events with:
dataset:default payload._intended_dataset:dataset-fThe default bucket does not count against your cap. It cannot be renamed, archived, or have its retention edited separately - it is system-managed. Hobby gives you 5 user-named buckets plus default as a no-cap catch-all.
To stop overflowing, archive a bucket you no longer need (see below) or upgrade your plan.
The schema tab
Click a dataset and you land on the SCHEMA tab.
CANONICAL FIELDS. The 10 baseline fields every event has, with their types. Same set for every dataset:
ts(datetime)severity(severity enum)event(string)actor(string)source(string)message(string)dataset(string)event_id(uuid)ingested_at(datetime)org_id,project_id(uuid, structurally injected, never queryable directly)
PAYLOAD FIELDS. Auto-discovered list of payload.* keys this dataset has carried in the last 24 hours, with approximate cardinality (how many distinct values were seen) and up to 5 sample values per key.
Payload discovery is cached for 5 minutes. If you push new payload shapes through, give it a few minutes to show up here.
The ↗ OPEN IN SEARCH button at the top right jumps to the search page with dataset:<name> pre-applied.
The settings tab
Click SETTINGS on the dataset detail page to edit it.
RENAME. Change the dataset name. ServerOps writes a 30-day alias for the old name so any game-server code still posting to the previous name keeps working without changes. After 30 days the alias expires.
RETENTION. Set the retention window in days. 0 means "use the plan default." The maximum you can set is capped by your plan:
| Plan | Max retention |
|---|---|
| Hobby | 15 days |
| Pro | 90 days |
| Scale | 365 days |
DEFAULT SEVERITY. Assign a severity for events that arrive with none set. One of trace, debug, info, warn, error, fatal, or NONE to leave events without a severity.
ARCHIVE. Hides the dataset from your dashboard and from the dataset picker. Indexed events stay searchable until they age out via retention. Type the dataset name to confirm.
Archive is reversible
Archive is not a hard wall. If new events arrive under an archived name later, the dataset auto-restores: the existing row is unarchived with its retention, default severity, and history intact. You do not need to touch your game-server code.
The customer mental model is: "archive hides this from my dashboard for now; if a server keeps sending, it comes back." If you actually want to stop a misbehaving server, the right tool is to revoke or rate-limit its token, not archive its dataset.
Common error responses
The settings tab surfaces these inline; if you call the API directly, you will see the codes:
| Code | Meaning |
|---|---|
dataset_name_taken | Another dataset (active or archived) already uses the new name |
invalid_retention_days | Retention is negative or exceeds your plan cap |
invalid_severity | Default severity is not one of the allowed values |
dataset_reserved | You tried to rename, archive, or edit the system-managed default bucket |
dataset_not_found | The dataset does not exist or is already archived |
What this page does NOT do
- It does not show the historical schema (which payload keys existed last week but not today). Discovery is always over the most recent 24 hours.
- It does not surface event-level data; for that, use the search page with a
dataset:<name>filter. - It does not currently expose explicit "unarchive" - sending an event to the archived name is how you restore it. A dedicated unarchive button is a planned follow-up.
- It does not let you set per-dataset colour overrides yet. The
color_overridescolumn exists in storage; the UI surface lands in a later release.