Skip to main content

Grafana Integration

Connect Arc to Grafana for real-time monitoring, alerting, and beautiful visualizations using the Arc datasource plugin.

Overview

The Arc datasource plugin for Grafana provides:

  • Apache Arrow Protocol: High-performance columnar data transfer
  • Native SQL Support: Full DuckDB SQL with syntax highlighting
  • Template Variables: Dynamic dashboards with filters
  • Alerting: Built-in alert rule support
  • Multi-database: Query across different Arc databases
  • Real-time Dashboards: Sub-second query performance

Installation

From Grafana Plugin Catalog

  1. In Grafana, go to ConfigurationPlugins
  2. Search for Arc
  3. Click Install
  4. Restart Grafana if prompted

From Release

# Download latest release
wget https://github.com/basekick-labs/grafana-arc-datasource/releases/download/v1.0.0/grafana-arc-datasource-1.0.0.zip

# Extract to Grafana plugins directory
unzip grafana-arc-datasource-1.0.0.zip -d /var/lib/grafana/plugins/

# Restart Grafana
systemctl restart grafana-server

From Source

# Clone repository
git clone https://github.com/basekick-labs/grafana-arc-datasource
cd grafana-arc-datasource

# Install dependencies
npm install

# Build plugin
npm run build

# Build backend
mage -v

# Install to Grafana
cp -r dist /var/lib/grafana/plugins/grafana-arc-datasource
systemctl restart grafana-server

Configuration

1. Add Data Source

  1. In Grafana, go to ConfigurationData sources
  2. Click Add data source
  3. Search for and select Arc
  4. Configure connection settings

2. Connection Settings

SettingDescriptionRequiredDefault
URLArc API endpointYeshttp://localhost:8000
API KeyAuthentication tokenYes-
DatabaseDefault database nameNodefault
TimeoutQuery timeout in secondsNo30
Use ArrowEnable Apache Arrow protocolNotrue

3. Example Configuration

URL:      http://localhost:8000
API Key: arc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Database: prod
Timeout: 30

Click Save & Test to verify the connection.

4. Get Your API Token

# Docker - check logs for admin token
docker logs <container-id> 2>&1 | grep "Admin token"

# Or create a new token specifically for Grafana
curl -X POST http://localhost:8000/api/v1/auth/tokens \
-H "Authorization: Bearer $ARC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "grafana-datasource",
"description": "Grafana datasource access"
}'

Creating Queries

Query Editor

The Arc datasource provides a SQL query editor with:

  • Syntax highlighting
  • Auto-completion
  • Time range macros
  • Multi-database support

Basic Query Example

CPU Usage:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(usage_idle) * -1 + 100 AS cpu_usage,
host
FROM prod.cpu
WHERE cpu = 'cpu-total'
AND $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC

Time Macros

Grafana provides powerful time macros for dynamic queries:

MacroDescriptionExample
$__timeFilter(columnName)Complete time range filterWHERE $__timeFilter(time)
$__timeFrom()Start of time rangetime >= $__timeFrom()
$__timeTo()End of time rangetime < $__timeTo()
$__intervalAuto-calculated intervaltime_bucket(INTERVAL '$__interval', time)

How macros expand:

-- Your query
WHERE $__timeFilter(time)

-- Expands to
WHERE time >= '2025-01-17 10:00:00' AND time < '2025-01-17 11:00:00'

Example Queries

Memory Usage:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(used_percent) AS memory_used,
host
FROM prod.mem
WHERE $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC

Network Traffic (bytes to bits):

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(bytes_recv) * 8 AS bits_in,
AVG(bytes_sent) * 8 AS bits_out,
host,
interface
FROM prod.net
WHERE $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host, interface
ORDER BY time ASC

Disk I/O:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(read_bytes) AS disk_read,
AVG(write_bytes) AS disk_write,
host
FROM prod.diskio
WHERE $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC

Template Variables

Create dynamic dashboards with variables that filter your data.

Creating Variables

  1. Go to Dashboard settingsVariables
  2. Click Add variable
  3. Configure variable settings

Variable Examples

Host Variable:

SELECT DISTINCT host FROM prod.cpu ORDER BY host

Interface Variable:

SELECT DISTINCT interface FROM prod.net ORDER BY interface

Database Variable:

SELECT DISTINCT schema_name FROM information_schema.schemata
WHERE schema_name NOT IN ('information_schema', 'pg_catalog')
ORDER BY schema_name

Using Variables in Queries

Reference variables with $variable syntax:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(usage_idle) * -1 + 100 AS cpu_usage
FROM $database.cpu
WHERE host = '$server'
AND cpu = 'cpu-total'
AND $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time)
ORDER BY time ASC

Multi-Select Variables

Enable Multi-value in variable settings, then use IN:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(usage_idle) * -1 + 100 AS cpu_usage,
host
FROM prod.cpu
WHERE host IN ($hosts) -- Multi-select variable
AND cpu = 'cpu-total'
AND $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC

Alerting

The Arc datasource fully supports Grafana alerting.

Creating Alert Rules

  1. Open a panel with an Arc query
  2. Go to Alert tab
  3. Click Create alert rule from this panel
  4. Configure alert conditions

Example Alert Query

High CPU Usage (> 80%):

SELECT
time,
100 - usage_idle AS cpu_usage,
host
FROM prod.cpu
WHERE cpu = 'cpu-total'
AND time >= NOW() - INTERVAL '5 minutes'
ORDER BY time ASC

Alert Condition:

  • WHEN avg() OF query(A, 5m, now) IS ABOVE 80

Example Alert: Memory Usage

Query:

SELECT
time,
used_percent AS memory_used,
host
FROM prod.mem
WHERE time >= NOW() - INTERVAL '5 minutes'
ORDER BY time ASC

Alert Condition:

  • WHEN avg() OF query(A, 5m, now) IS ABOVE 90

Alert Notifications

Configure notification channels:

  1. Go to AlertingContact points
  2. Add notification channel (Email, Slack, PagerDuty, etc.)
  3. Link alert rules to notification channels

Dashboard Examples

System Monitoring Dashboard

Create a comprehensive system monitoring dashboard:

Panels:

  1. CPU Usage by Host (Time series)
SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(100 - usage_idle) AS cpu_usage,
host
FROM prod.cpu
WHERE cpu = 'cpu-total' AND $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC
  1. Memory Usage (Time series)
SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(used_percent) AS memory_used,
host
FROM prod.mem
WHERE $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC
  1. Disk Usage (Gauge)
SELECT
host,
AVG(used_percent) AS disk_used
FROM prod.disk
WHERE $__timeFilter(time)
GROUP BY host
  1. Network Traffic (Graph)
SELECT
time_bucket(INTERVAL '$__interval', time) as time,
SUM(bytes_recv) * 8 / 1000000 AS mbps_in,
SUM(bytes_sent) * 8 / 1000000 AS mbps_out,
host
FROM prod.net
WHERE $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC
  1. Top Hosts by CPU (Bar gauge)
SELECT
host,
AVG(100 - usage_idle) AS avg_cpu
FROM prod.cpu
WHERE cpu = 'cpu-total'
AND time >= NOW() - INTERVAL '1 hour'
GROUP BY host
ORDER BY avg_cpu DESC
LIMIT 10

Dashboard Layout

┌─────────────────────────────────────────────────┐
│ System Overview - Last 24 Hours │
│ [Host: All ▼] [Refresh: 30s ▼] │
├───────────────────────┬─────────────────────────┤
│ │ │
│ CPU Usage │ Memory Usage │
│ (Time Series) │ (Time Series) │
│ │ │
├───────────────────────┼─────────────────────────┤
│ │ │
│ Network Traffic │ Disk I/O │
│ (Graph) │ (Graph) │
│ │ │
├───────────────────────┴─────────────────────────┤
│ Top 10 Hosts by CPU Usage (Bar Gauge) │
└─────────────────────────────────────────────────┘

Advanced Queries

Window Functions

Moving Average:

SELECT
time,
usage_idle,
host,
AVG(usage_idle) OVER (
PARTITION BY host
ORDER BY time
ROWS BETWEEN 5 PRECEDING AND CURRENT ROW
) as moving_avg
FROM prod.cpu
WHERE cpu = 'cpu-total' AND $__timeFilter(time)
ORDER BY time ASC

Percentiles

CPU Usage Percentiles:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
host,
PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY usage_idle) as p50,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY usage_idle) as p95,
PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY usage_idle) as p99
FROM prod.cpu
WHERE cpu = 'cpu-total' AND $__timeFilter(time)
GROUP BY time_bucket(INTERVAL '$__interval', time), host
ORDER BY time ASC

Cross-Database Queries

Production vs Staging Comparison:

SELECT
time_bucket(INTERVAL '$__interval', time) as time,
AVG(p.usage_idle) as prod_cpu_idle,
AVG(s.usage_idle) as staging_cpu_idle
FROM prod.cpu p
JOIN staging.cpu s ON p.time = s.time AND p.host = s.host
WHERE p.cpu = 'cpu-total'
AND s.cpu = 'cpu-total'
AND $__timeFilter(p.time)
GROUP BY time_bucket(INTERVAL '$__interval', time)
ORDER BY time ASC

Performance Optimization

1. Use Apache Arrow

Arrow protocol is enabled by default and provides significantly faster data transfer:

  • 7.36x faster than JSON for large result sets
  • Zero-copy deserialization
  • Columnar format perfect for time-series

2. Optimize Time Ranges

  • Use Grafana's time picker to limit data scanned
  • Add time filters with $__timeFilter()
  • Avoid querying months of data for real-time dashboards

3. Leverage time_bucket()

Grafana automatically adjusts $__interval based on dashboard width:

-- Good: Automatic interval adjustment
time_bucket(INTERVAL '$__interval', time)

-- Bad: Fixed interval (too many points)
time_bucket(INTERVAL '1 second', time)

4. Use LIMIT for Exploration

SELECT * FROM prod.cpu
WHERE $__timeFilter(time)
LIMIT 1000 -- Limit result size

5. Enable Query Caching

In Grafana's data source settings:

  • Enable Cache timeout: 60 seconds
  • Repeated queries return instantly from cache

Troubleshooting

Plugin Not Appearing

# Check plugin directory permissions
ls -la /var/lib/grafana/plugins/grafana-arc-datasource

# Verify plugin.json exists
cat /var/lib/grafana/plugins/grafana-arc-datasource/plugin.json

# Check Grafana logs
tail -f /var/log/grafana/grafana.log

# Restart Grafana
systemctl restart grafana-server

Connection Failed

# Verify Arc is running
curl http://localhost:8000/health

# Test API token
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://localhost:8000/api/v1/auth/verify

# Check network connectivity
ping localhost

Query Errors

"Table not found":

-- List available tables
SHOW TABLES FROM prod;

-- Verify database exists
SHOW DATABASES;

"Column not found":

-- Describe table schema
DESCRIBE prod.cpu;

Slow Queries

# Check Arc query performance
curl -X POST http://localhost:8000/api/v1/query \
-H "Authorization: Bearer $ARC_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sql": "EXPLAIN SELECT * FROM prod.cpu WHERE time > NOW() - INTERVAL '\''1 hour'\''",
"format": "json"
}'

# Trigger compaction
curl -X POST http://localhost:8000/api/v1/compaction/trigger \
-H "Authorization: Bearer $ARC_TOKEN"

Backend Plugin Issues

# Ensure backend binary is compiled
cd /path/to/grafana-arc-datasource
mage -v

# Check binary permissions
chmod +x dist/gpx_arc-datasource_*

# Verify Go version
go version # Should be 1.21+

Performance Tips

  1. Use Arrow Protocol: Enabled by default, provides 7x faster data transfer
  2. Optimize Time Ranges: Smaller ranges = faster queries
  3. Leverage time_bucket(): Use $__interval for automatic aggregation
  4. Add Indexes: Arc automatically indexes time columns
  5. Enable Caching: Configure query caching in datasource settings
  6. Limit Result Size: Use LIMIT for exploratory queries
  7. Use Variables: Filter data with template variables instead of loading everything

Resources

Next Steps