Custom Dashboards
Custom dashboards let you assemble your own view of an environment: log volume next to trace latency, uptime next to Sigma detections, a world map of where traffic is coming from. Panels are arranged on a 12-column grid, each one queries LogTide directly, and the whole board can be exported as YAML and version-controlled alongside the rest of your infrastructure.
Overview
A dashboard belongs to an organization and holds a list of panels. Each panel carries its own layout (position and size on the grid) and its own configuration (what it queries and how it renders). Editing is inline: click Edit, drag panels to rearrange them, drag the bottom-right corner to resize, use the gear icon to configure, then Save. Nothing is written until you save, so Cancel always restores the board.
Shared or personal
A dashboard is visible to the whole organization by default. Mark it personal and only its creator sees it, which keeps scratch boards out of everyone else's switcher.
One default board
The dashboard marked as default is what opens when someone lands on the Dashboard page. Promoting another one demotes the previous default automatically.
Org-wide or per project
Most panels take an optional project. Leave it empty and the panel aggregates every project in the organization; set it and the panel is scoped to that one.
The number of custom dashboards per organization is governed by the
dashboards.max_custom capability, which is unlimited on self-hosted installs
unless you configure an entitlement. See Usage & Metering.
Panel Catalog
Fifteen panel types are available, covering every LogTide vertical. Panels that scope their query to a lookback window are marked windowed; those are the ones the time range controls in the next section apply to.
Logs
| Panel | Shows | Key options |
|---|---|---|
time_serieswindowed | Log volume over time, one line per level. | Levels to plot, service filter, custom per-level series labels. |
single_stat | A headline number with a trend arrow. | Metric: total logs, error rate, active services or throughput. |
top_n_tablewindowed | Ranked list with counts and share of total. | Dimension: service, error message, or any flat metadata key. Row limit 3-50, optional Last seen column. |
log_tablewindowed | Individual log rows, one per line. | Snapshot or live mode, up to 10 metadata columns, toggleable built-in columns, 10-100 rows. |
live_log_stream | A scrolling feed of the most recent logs. | Level and service filters, up to 100 rows. |
geo_mapwindowed | World map of log volume from GeoIP metadata. | Country bubbles or precise locations, level/service/hostname filters. See Geo Map Setup. |
Traces and metrics
| Panel | Shows | Key options |
|---|---|---|
trace_latencywindowed | Span latency percentiles over time. | Any combination of p50, p95, p99; optional service filter. |
trace_volumewindowed | Span count over time, with an optional errors line. | Service filter, show errors on or off. |
metric_chartwindowed | An OTLP metric over time. | Metric name, aggregation (avg, sum, min, max, count, last, p50, p95, p99), bucket interval. |
metric_statwindowed | A single OTLP metric value. | Same aggregations, plus an optional unit label. |
Percentiles are computed from raw spans on every storage engine, not from approximations, so the numbers match what the Traces view reports. Metric panels read OTLP metrics ingested through the OpenTelemetry endpoint.
Security, uptime and overview
| Panel | Shows | Key options |
|---|---|---|
detection_eventswindowed | Sigma detection events over time, plus a severity breakdown. | Severities to include. |
alert_status | State of your alert rules and recent triggers. | Specific rules or all of them, show history on or off. |
monitor_status | Current status and last check of your monitors. | Specific monitors or all, row limit 3-20. |
system_status | One banner: operational, degraded, or outage. | Show per-state counts or just the banner. |
activity_overviewwindowed | Logs, log errors, spans, span errors, detections and alerts on one timeline. | Which of the six series to plot. |
Span panels and storage engines
The span series of activity_overview are populated on TimescaleDB. On
ClickHouse and MongoDB the log series still render and the dedicated
trace_latency and trace_volume panels work on all three
engines. See Storage Engines.
Time Ranges
Every windowed panel picks its lookback from the same list, so a board never mixes incompatible sets of options:
15m 1h 6h 12h 24h 48h 3d 7d 14d 30d In the panel editor the control is labelled Time range and spells the values out ("Last 48 hours"). The stored configuration keeps the short form, which is what you see in a YAML export.
Retiming a whole board
The clock control in the dashboard toolbar overrides the time range of every windowed panel at once, which is what you usually want during an incident review: same board, different window. It is a view-level control:
- Panel configurations and the saved dashboard are never modified.
- Panels without a window (single stat, live stream, alert and monitor status) are left alone, and so are log tables in live mode.
- Choosing Panel defaults hands every panel back its own configured range.
- The override is not persisted, so a shared dashboard always opens the way its author set it up.
Bucket sizes
Time-based charts choose a bucket size to match the window, so a one-hour view is not drawn with the same granularity as a month:
| Window | Bucket |
|---|---|
| up to 1 hour | 1 minute |
| up to 6 hours | 5 minutes |
| up to 12 hours | 15 minutes |
| up to 14 days | 1 hour |
| 30 days | 1 day |
Empty buckets are filled with zeros rather than skipped, so a quiet period reads as quiet instead of disappearing from the line, and axis labels switch to dates once the window spans more than a couple of days.
Working With Panels
Pause a panel
Freeze a single panel while you read it: paused panels are skipped by auto-refresh and left out of the batch fetch entirely. A paused live log table stops applying updates but keeps its connection, so resuming is instant. Pause is ephemeral and resets when you switch dashboards.
Refresh
The toolbar sets a board-wide auto-refresh interval (off, 30s, 1m, 5m); auto-refresh pauses while you are editing so it cannot clobber unsaved layout changes. Each panel header also has a manual refresh that works even when the panel is paused.
Clock and timezone
Settings > Display sets a 12-hour or 24-hour clock and an explicit IANA timezone for every dashboard panel timestamp. Defaults are your browser timezone and a 24-hour clock, so nothing changes unless you ask.
Layout
Panels sit on a 12-column grid. Each panel type declares a minimum width and height so it stays readable, and the grid collapses to a single column on narrow screens.
Metadata columns and dimensions
The log table's extra columns and the Top N table's metadata dimension both address a metadata
field by path, using the same rules as Log Search: an exact key wins over a dotted path, so a
field literally named user.id is matched before the nested
user → id lookup is attempted.
status_code # flat key
user.id # exact key "user.id", else nested user -> id
geo_country # flat key written by the GeoIP pipeline step A log table accepts up to ten metadata columns alongside the built-in time, level, service and message columns. In the Top N table, percentages are computed against all logs matching the panel's filters, so on a project where only some logs carry the key, the share reflects reality instead of being inflated.
Geo Map Setup
The geo map plots log volume on a world map. It reads geographic metadata that a GeoIP pipeline step writes onto your logs, so the panel needs that step configured before it has anything to draw.
Add a GeoIP step to a parsing pipeline for the project, pointing it at the metadata field that
holds the client IP and choosing an output target (geo by default). The step
writes a nested object plus flat keys derived from the target name:
{
"client_ip": "203.0.113.10",
"geo": { "country": "Italy", "countryCode": "IT", "city": "Milan" },
"geo_country": "Italy",
"geo_country_code": "IT",
"geo_city": "Milan",
"geo_place": "45.46,9.19|Milan, Italy"
}
In the panel configuration, Geo field prefix must match the step's target
(geo unless you changed it). Two modes are available:
- By country reads
{prefix}_country_codeand places one bubble per country, sized by volume. - By location reads
{prefix}_placeand places bubbles at rounded coordinates, which is more precise but produces more points; the row limit caps how many are drawn.
The map needs no tile server and makes no external requests: the world outline ships with the frontend, so the panel works on air-gapped installs and follows your light or dark theme. Values without usable coordinates are counted and reported under the map rather than silently dropped.
Your framing is preserved
The map fits itself to the data on first paint and whenever you change what the panel queries. After that it stays where you put it: background refreshes never move the viewport, so a board left open on a wall display does not drift. Use the Fit data control to re-frame on demand. The mouse wheel scrolls the page rather than zooming the map; zoom with the +/- controls, a double click, or pinch.
Sharing Dashboards
Any dashboard can be exported to YAML and imported into another organization or another LogTide install, which makes boards reviewable in a pull request and reproducible across environments. The export contains the board's name, description, schema version and panels:
name: Edge Traffic
description: Public traffic overview
schema_version: 1
panels:
- id: panel-1
layout: { x: 0, y: 0, w: 8, h: 4 }
config:
type: geo_map
title: Traffic Map
source: logs
projectId: null
interval: 24h
mode: country
limit: 100
fieldPrefix: geo
levels: []
service: null
hostname: null
- id: panel-2
layout: { x: 8, y: 0, w: 4, h: 4 }
config:
type: top_n_table
title: Top Countries
source: logs
dimension: metadata
metadataField: geo_country
limit: 10
projectId: null
interval: 24h
showLastSeen: true Import validates every panel against the same rules the editor enforces, so a malformed board is rejected with an explanation instead of being half-created. Project references are checked against the importing organization: a panel pointing at a project id from somewhere else is refused rather than silently returning another tenant's data.
Project ids are environment-specific
When moving a board between installs, either set projectId: null to make
panels organization-wide, or update the ids to match the target environment before
importing.
API
Dashboards are managed through the authenticated API under
/api/v1/custom-dashboards. All endpoints require a session and take the
organization id.
| Endpoint | Purpose |
|---|---|
GET / | List the dashboards visible to the caller. |
GET /default | Fetch the default dashboard. |
POST / | Create a dashboard, optionally with its panels. |
GET /:id · PUT /:id · DELETE /:id | Read, update (name, description, panels) or delete one. |
POST /:id/set-default | Promote a dashboard to default. |
GET /:id/export-yaml | Export as YAML. |
POST /import-yaml | Create a dashboard from YAML. |
POST /:id/panels/data | Fetch data for the board's panels in one request. |
The batch data endpoint is what the UI calls on every refresh. Restrict it to specific panels
with panelIds, and apply the board-wide time override with
timeRange:
POST /api/v1/custom-dashboards/{dashboardId}/panels/data
Content-Type: application/json
{
"organizationId": "…",
"panelIds": ["panel-1", "panel-2"],
"timeRange": "48h"
}
Panels are fetched independently, so one failing panel returns an error in its own entry while
the rest still return data. Omit panelIds to fetch the whole board, and omit
timeRange to use each panel's configured window.