目录
-
- 摘要
- 一、实时监控概述
-
- [1.1 监控大屏架构](#1.1 监控大屏架构)
- [1.2 Grafana优势](#1.2 Grafana优势)
- [1.3 适用场景](#1.3 适用场景)
- 二、Grafana安装配置
-
- [2.1 安装Grafana](#2.1 安装Grafana)
- [2.2 安装DolphinDB数据源插件](#2.2 安装DolphinDB数据源插件)
- [2.3 配置数据源](#2.3 配置数据源)
- 三、DolphinDB数据准备
-
- [3.1 创建监控数据表](#3.1 创建监控数据表)
- [3.2 创建聚合视图](#3.2 创建聚合视图)
- [3.3 创建API接口](#3.3 创建API接口)
- 四、Grafana仪表盘配置
-
- [4.1 创建仪表盘](#4.1 创建仪表盘)
- [4.2 配置面板](#4.2 配置面板)
- [4.3 模板变量](#4.3 模板变量)
- 五、实时数据展示
-
- [5.1 实时曲线图](#5.1 实时曲线图)
- [5.2 实时统计卡片](#5.2 实时统计卡片)
- [5.3 设备状态面板](#5.3 设备状态面板)
- 六、告警配置
-
- [6.1 Grafana告警规则](#6.1 Grafana告警规则)
- [6.2 DolphinDB告警表](#6.2 DolphinDB告警表)
- 七、大屏设计最佳实践
-
- [7.1 布局设计](#7.1 布局设计)
- [7.2 颜色规范](#7.2 颜色规范)
- [7.3 刷新策略](#7.3 刷新策略)
- 八、实战案例
-
- [8.1 完整监控大屏系统](#8.1 完整监控大屏系统)
- 九、总结
- 参考资料
摘要
本文深入讲解DolphinDB与Grafana集成的实时监控大屏技术。从Grafana安装配置到数据源连接,从实时数据展示到告警配置,从大屏设计到性能优化,全面介绍实时监控大屏的核心方法。通过丰富的代码示例,帮助读者掌握DolphinDB + Grafana实时监控的核心技能。
一、实时监控概述
1.1 监控大屏架构
#mermaid-svg-uAkbAhDToiF96zTA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uAkbAhDToiF96zTA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uAkbAhDToiF96zTA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uAkbAhDToiF96zTA .error-icon{fill:#552222;}#mermaid-svg-uAkbAhDToiF96zTA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uAkbAhDToiF96zTA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uAkbAhDToiF96zTA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uAkbAhDToiF96zTA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uAkbAhDToiF96zTA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uAkbAhDToiF96zTA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uAkbAhDToiF96zTA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uAkbAhDToiF96zTA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uAkbAhDToiF96zTA .marker.cross{stroke:#333333;}#mermaid-svg-uAkbAhDToiF96zTA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uAkbAhDToiF96zTA p{margin:0;}#mermaid-svg-uAkbAhDToiF96zTA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uAkbAhDToiF96zTA .cluster-label text{fill:#333;}#mermaid-svg-uAkbAhDToiF96zTA .cluster-label span{color:#333;}#mermaid-svg-uAkbAhDToiF96zTA .cluster-label span p{background-color:transparent;}#mermaid-svg-uAkbAhDToiF96zTA .label text,#mermaid-svg-uAkbAhDToiF96zTA span{fill:#333;color:#333;}#mermaid-svg-uAkbAhDToiF96zTA .node rect,#mermaid-svg-uAkbAhDToiF96zTA .node circle,#mermaid-svg-uAkbAhDToiF96zTA .node ellipse,#mermaid-svg-uAkbAhDToiF96zTA .node polygon,#mermaid-svg-uAkbAhDToiF96zTA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uAkbAhDToiF96zTA .rough-node .label text,#mermaid-svg-uAkbAhDToiF96zTA .node .label text,#mermaid-svg-uAkbAhDToiF96zTA .image-shape .label,#mermaid-svg-uAkbAhDToiF96zTA .icon-shape .label{text-anchor:middle;}#mermaid-svg-uAkbAhDToiF96zTA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uAkbAhDToiF96zTA .rough-node .label,#mermaid-svg-uAkbAhDToiF96zTA .node .label,#mermaid-svg-uAkbAhDToiF96zTA .image-shape .label,#mermaid-svg-uAkbAhDToiF96zTA .icon-shape .label{text-align:center;}#mermaid-svg-uAkbAhDToiF96zTA .node.clickable{cursor:pointer;}#mermaid-svg-uAkbAhDToiF96zTA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uAkbAhDToiF96zTA .arrowheadPath{fill:#333333;}#mermaid-svg-uAkbAhDToiF96zTA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uAkbAhDToiF96zTA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uAkbAhDToiF96zTA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uAkbAhDToiF96zTA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uAkbAhDToiF96zTA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uAkbAhDToiF96zTA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uAkbAhDToiF96zTA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uAkbAhDToiF96zTA .cluster text{fill:#333;}#mermaid-svg-uAkbAhDToiF96zTA .cluster span{color:#333;}#mermaid-svg-uAkbAhDToiF96zTA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uAkbAhDToiF96zTA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uAkbAhDToiF96zTA rect.text{fill:none;stroke-width:0;}#mermaid-svg-uAkbAhDToiF96zTA .icon-shape,#mermaid-svg-uAkbAhDToiF96zTA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uAkbAhDToiF96zTA .icon-shape p,#mermaid-svg-uAkbAhDToiF96zTA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uAkbAhDToiF96zTA .icon-shape .label rect,#mermaid-svg-uAkbAhDToiF96zTA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uAkbAhDToiF96zTA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uAkbAhDToiF96zTA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uAkbAhDToiF96zTA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 实时监控架构
设备数据
DolphinDB
Grafana
监控大屏
流计算
1.2 Grafana优势
| 优势 | 说明 |
|---|---|
| 开源免费 | 社区版免费使用 |
| 多数据源 | 支持多种数据库 |
| 丰富图表 | 多种可视化组件 |
| 告警功能 | 内置告警系统 |
| 模板变量 | 动态仪表盘 |
1.3 适用场景
| 场景 | 说明 |
|---|---|
| 生产监控 | 实时生产数据展示 |
| 设备监控 | 设备状态实时追踪 |
| 能耗监控 | 能耗数据可视化 |
| 质量监控 | 质量指标实时展示 |
二、Grafana安装配置
2.1 安装Grafana
bash
# Ubuntu/Debian
sudo apt-get install -y software-properties-common
sudo add-apt-repository "deb https://packages.grafana.com/oss/deb stable main"
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install grafana
# 启动服务
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
# 访问
# http://localhost:3000
# 默认账号: admin/admin
2.2 安装DolphinDB数据源插件
bash
# 下载插件
git clone https://github.com/dolphindb/grafana-datasource.git
# 复制到Grafana插件目录
sudo cp -r grafana-datasource /var/lib/grafana/plugins/
# 重启Grafana
sudo systemctl restart grafana-server
2.3 配置数据源
yaml
# Grafana数据源配置
apiVersion: 1
datasources:
- name: DolphinDB
type: dolphindb-datasource
access: proxy
url: http://localhost:8848
isDefault: true
editable: true
三、DolphinDB数据准备
3.1 创建监控数据表
python
// 创建实时监控数据表
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity`pressure`status,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, INT]) as monitor_stream
// 启用持久化
enableTablePersistence(monitor_stream, true, true, 1000000)
// 创建分布式存储表
db = database("dfs://monitor_db", VALUE, 1..100)
schema = table(1:0,
`device_id`timestamp`temperature`humidity`pressure`status,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, INT])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// 订阅写入
subscribeTable(, "monitor_stream", "persist", -1,
def(msg) {
loadTable("dfs://monitor_db", "sensor_data").append!(msg)
}, 10000, 5000)
3.2 创建聚合视图
python
// 创建实时聚合表
share table(1:0,
`device_id`time_window`avg_temp`max_temp`min_temp`cnt,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG]) as monitor_agg
// 时间序列聚合引擎
aggEngine = createTimeSeriesEngine("monitor_agg_engine", 60000,
<[avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as cnt]>,
monitor_agg, `timestamp, `device_id)
// 订阅聚合
subscribeTable(, "monitor_stream", "agg", -1, aggEngine, true)
3.3 创建API接口
python
// Grafana查询接口
def grafanaQuery(fromTime, toTime, deviceIds) {
t = loadTable("dfs://monitor_db", "sensor_data")
return select device_id, timestamp, temperature, humidity, pressure
from t
where timestamp between fromTime and toTime
and device_id in deviceIds
}
// 注册函数
addFunctionView(grafanaQuery)
四、Grafana仪表盘配置
4.1 创建仪表盘
json
{
"dashboard": {
"title": "工业设备实时监控",
"tags": ["industrial", "monitor"],
"timezone": "browser",
"panels": [],
"refresh": "5s",
"time": {
"from": "now-1h",
"to": "now"
}
}
}
4.2 配置面板
json
// 温度曲线面板
{
"type": "graph",
"title": "设备温度实时曲线",
"targets": [
{
"datasource": "DolphinDB",
"query": "select timestamp, temperature from monitor_stream where device_id = '$device'",
"refId": "A"
}
],
"xaxis": {
"mode": "time"
},
"yaxes": [
{
"label": "温度(°C)",
"min": 0,
"max": 100
}
]
}
4.3 模板变量
json
// 设备选择变量
{
"name": "device",
"type": "query",
"datasource": "DolphinDB",
"query": "select distinct device_id from sensor_data",
"refresh": 1,
"multi": true,
"includeAll": true
}
五、实时数据展示
5.1 实时曲线图
python
// DolphinDB查询函数
def getTemperatureCurve(deviceId, startTime, endTime) {
t = loadTable("dfs://monitor_db", "sensor_data")
return select timestamp as time, temperature as value
from t
where device_id = deviceId
and timestamp between startTime and endTime
order by timestamp
}
// 注册
addFunctionView(getTemperatureCurve)
5.2 实时统计卡片
python
// 实时统计
def getRealtimeStats() {
t = loadTable("dfs://monitor_db", "sensor_data")
return select count(*) as total_records,
avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(distinct device_id) as device_count
from t
where timestamp > now() - 3600000
}
addFunctionView(getRealtimeStats)
5.3 设备状态面板
python
// 设备状态统计
def getDeviceStatus() {
t = loadTable("dfs://monitor_db", "sensor_data")
return select device_id,
last(temperature) as current_temp,
last(status) as status,
count(*) as record_count
from t
where timestamp > now() - 300000
group by device_id
}
addFunctionView(getDeviceStatus)
六、告警配置
6.1 Grafana告警规则
json
{
"name": "温度过高告警",
"conditions": [
{
"evaluator": {
"type": "gt",
"params": [80]
},
"operator": {
"type": "and"
},
"query": {
"params": ["A", "5m", "now"]
},
"reducer": {
"type": "avg"
}
}
],
"notifications": [
{
"type": "email",
"settings": {
"addresses": "admin@company.com"
}
}
]
}
6.2 DolphinDB告警表
python
// 告警记录表
share table(1:0,
`alert_time`device_id`alert_type`alert_level`value`message,
[TIMESTAMP, SYMBOL, STRING, INT, DOUBLE, STRING]) as alert_log
// 告警触发
def checkAlert(data) {
for (row in data) {
if (row.temperature > 80) {
insert into alert_log values (
now(), row.device_id, "temperature_high", 2,
row.temperature, "温度超过阈值: " + string(row.temperature)
)
}
}
}
// 订阅告警检测
subscribeTable(, "monitor_stream", "alert", -1,
def(msg) { checkAlert(msg) }, true)
七、大屏设计最佳实践
7.1 布局设计
#mermaid-svg-nwKGfmiNTE8twzcB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nwKGfmiNTE8twzcB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nwKGfmiNTE8twzcB .error-icon{fill:#552222;}#mermaid-svg-nwKGfmiNTE8twzcB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nwKGfmiNTE8twzcB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nwKGfmiNTE8twzcB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nwKGfmiNTE8twzcB .marker.cross{stroke:#333333;}#mermaid-svg-nwKGfmiNTE8twzcB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nwKGfmiNTE8twzcB p{margin:0;}#mermaid-svg-nwKGfmiNTE8twzcB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nwKGfmiNTE8twzcB .cluster-label text{fill:#333;}#mermaid-svg-nwKGfmiNTE8twzcB .cluster-label span{color:#333;}#mermaid-svg-nwKGfmiNTE8twzcB .cluster-label span p{background-color:transparent;}#mermaid-svg-nwKGfmiNTE8twzcB .label text,#mermaid-svg-nwKGfmiNTE8twzcB span{fill:#333;color:#333;}#mermaid-svg-nwKGfmiNTE8twzcB .node rect,#mermaid-svg-nwKGfmiNTE8twzcB .node circle,#mermaid-svg-nwKGfmiNTE8twzcB .node ellipse,#mermaid-svg-nwKGfmiNTE8twzcB .node polygon,#mermaid-svg-nwKGfmiNTE8twzcB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nwKGfmiNTE8twzcB .rough-node .label text,#mermaid-svg-nwKGfmiNTE8twzcB .node .label text,#mermaid-svg-nwKGfmiNTE8twzcB .image-shape .label,#mermaid-svg-nwKGfmiNTE8twzcB .icon-shape .label{text-anchor:middle;}#mermaid-svg-nwKGfmiNTE8twzcB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nwKGfmiNTE8twzcB .rough-node .label,#mermaid-svg-nwKGfmiNTE8twzcB .node .label,#mermaid-svg-nwKGfmiNTE8twzcB .image-shape .label,#mermaid-svg-nwKGfmiNTE8twzcB .icon-shape .label{text-align:center;}#mermaid-svg-nwKGfmiNTE8twzcB .node.clickable{cursor:pointer;}#mermaid-svg-nwKGfmiNTE8twzcB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nwKGfmiNTE8twzcB .arrowheadPath{fill:#333333;}#mermaid-svg-nwKGfmiNTE8twzcB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nwKGfmiNTE8twzcB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nwKGfmiNTE8twzcB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nwKGfmiNTE8twzcB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nwKGfmiNTE8twzcB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nwKGfmiNTE8twzcB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nwKGfmiNTE8twzcB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nwKGfmiNTE8twzcB .cluster text{fill:#333;}#mermaid-svg-nwKGfmiNTE8twzcB .cluster span{color:#333;}#mermaid-svg-nwKGfmiNTE8twzcB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nwKGfmiNTE8twzcB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nwKGfmiNTE8twzcB rect.text{fill:none;stroke-width:0;}#mermaid-svg-nwKGfmiNTE8twzcB .icon-shape,#mermaid-svg-nwKGfmiNTE8twzcB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nwKGfmiNTE8twzcB .icon-shape p,#mermaid-svg-nwKGfmiNTE8twzcB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nwKGfmiNTE8twzcB .icon-shape .label rect,#mermaid-svg-nwKGfmiNTE8twzcB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nwKGfmiNTE8twzcB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nwKGfmiNTE8twzcB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nwKGfmiNTE8twzcB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 监控大屏布局
顶部: 标题 + 时间
左侧: 设备列表
中间: 实时曲线
右侧: 统计卡片
底部: 告警列表
7.2 颜色规范
| 状态 | 颜色 | 说明 |
|---|---|---|
| 正常 | 绿色 | 设备运行正常 |
| 警告 | 黄色 | 指标接近阈值 |
| 异常 | 红色 | 指标超限 |
| 离线 | 灰色 | 设备离线 |
7.3 刷新策略
| 数据类型 | 刷新间隔 |
|---|---|
| 实时曲线 | 5秒 |
| 统计卡片 | 10秒 |
| 设备状态 | 30秒 |
| 历史数据 | 1分钟 |
八、实战案例
8.1 完整监控大屏系统
python
// ========== 工业设备实时监控大屏 ==========
// 1. 创建数据表
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity`pressure`status,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, INT]) as monitor_stream
enableTablePersistence(monitor_stream, true, true, 1000000)
// 2. 创建分布式表
db = database("dfs://monitor_db", VALUE, 1..100)
schema = table(1:0,
`device_id`timestamp`temperature`humidity`pressure`status,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, INT])
db.createPartitionedTable(schema, `sensor_data, `device_id)
// 3. 订阅写入
subscribeTable(, "monitor_stream", "persist", -1,
def(msg) {
loadTable("dfs://monitor_db", "sensor_data").append!(msg)
}, 10000, 5000)
// 4. 创建聚合引擎
share table(1:0,
`device_id`time_window`avg_temp`max_temp`min_temp`cnt,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE, LONG]) as monitor_agg
aggEngine = createTimeSeriesEngine("monitor_agg_engine", 60000,
<[avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp,
count(*) as cnt]>,
monitor_agg, `timestamp, `device_id)
subscribeTable(, "monitor_stream", "agg", -1, aggEngine, true)
// 5. 创建告警表
share table(1:0,
`alert_time`device_id`alert_type`alert_level`value`message,
[TIMESTAMP, SYMBOL, STRING, INT, DOUBLE, STRING]) as alert_log
// 6. Grafana查询接口
def getTemperatureCurve(deviceId, startTime, endTime) {
t = loadTable("dfs://monitor_db", "sensor_data")
return select timestamp as time, temperature as value
from t
where device_id = deviceId
and timestamp between startTime and endTime
order by timestamp
}
def getRealtimeStats() {
t = loadTable("dfs://monitor_db", "sensor_data")
return select count(*) as total_records,
avg(temperature) as avg_temp,
max(temperature) as max_temp,
min(temperature) as min_temp
from t
where timestamp > now() - 3600000
}
def getDeviceStatus() {
t = loadTable("dfs://monitor_db", "sensor_data")
return select device_id,
last(temperature) as current_temp,
last(status) as status
from t
where timestamp > now() - 300000
group by device_id
}
addFunctionView(getTemperatureCurve)
addFunctionView(getRealtimeStats)
addFunctionView(getDeviceStatus)
// 7. 模拟数据生成
def generateMockData() {
while (true) {
data = table(
take(1..10, 10) as device_id,
take(now(), 10) as timestamp,
rand(20.0..30.0, 10) as temperature,
rand(40.0..60.0, 10) as humidity,
rand(1000.0..1020.0, 10) as pressure,
take(1, 10) as status
)
monitor_stream.append!(data)
sleep(5000)
}
}
submitJob("mock_data", "模拟数据", generateMockData)
print("实时监控大屏系统启动完成")
print("Grafana访问: http://localhost:3000")
九、总结
本文详细介绍了DolphinDB + Grafana实时监控大屏:
- Grafana安装:安装配置、插件安装
- 数据准备:监控表、聚合引擎、API接口
- 仪表盘配置:面板配置、模板变量
- 实时展示:曲线图、统计卡片、状态面板
- 告警配置:告警规则、告警记录
- 大屏设计:布局设计、颜色规范、刷新策略
思考题:
- 如何设计高性能的实时监控大屏?
- 如何优化Grafana查询性能?
- 如何实现多租户监控大屏?