Grafana 是一个非常流行的开源数据可视化和监控平台,它与 TimescaleDB 集成得非常好,因为 TimescaleDB 是基于 PostgreSQL 的,而 Grafana 对 PostgreSQL 有原生的数据源支持。

下面我将介绍如何在 Grafana 中配置 TimescaleDB 数据源,并演示如何创建一个简单的 Panel 来可视化你的 FactPowerReadings 表中的数据。

1. Grafana 与 TimescaleDB (PostgreSQL) 集成步骤

Grafana 通过其 PostgreSQL 数据源插件与 TimescaleDB 通信。由于 TimescaleDB 是 PostgreSQL 的扩展,Grafana 的 PostgreSQL 数据源可以直接连接到 TimescaleDB 数据库。

步骤如下:

  1. 安装 Grafana: 如果你还没有安装 Grafana,可以访问 Grafana 官方网站 (https://grafana.com/get/) 下载适合你操作系统的版本或使用 Docker 镜像进行安装。安装过程通常很简单,按照官方文档指引即可。默认情况下,Grafana 运行在 http://localhost:3000
  2. 登录 Grafana: 打开浏览器访问 Grafana 地址,使用默认用户名 admin 和密码 admin 登录。首次登录会提示修改密码。
  3. 添加数据源 (Data Source):
    • 在 Grafana 左侧菜单中,将鼠标悬停在齿轮图标 (Settings) 上,然后点击 Data sources
    • 点击右上角的 Add data source 按钮。
    • 在数据源列表中找到并选择 PostgreSQL
  4. 配置 PostgreSQL 数据源:
    • Name: 给你的数据源起一个名字,例如 TimescaleDB-Telemetry
    • Host: 填写你的 TimescaleDB 服务器地址和端口,例如 localhost:5432 (使用你在 Perl 脚本中配置的 $db_host:$db_port)。
    • Database: 填写你的数据库名,例如 telemetry (使用你在 Perl 脚本中配置的 $db_name)。
    • User: 填写数据库用户名,例如 ops (使用你在 Perl 脚本中配置的 $db_user)。
    • Password: 填写数据库密码 (使用你在 Perl 脚本中配置的 $db_pass)。
    • SSL Mode: 根据你的数据库配置选择合适的 SSL 模式。如果数据库和 Grafana 在同一台机器上且没有配置 SSL,可以选择 disable
    • TimescaleDB: 勾选 TimescaleDB 选项。这会启用 TimescaleDB 特有的一些优化,比如 time_bucket 函数的自动补全和支持。
    • 其他设置通常保持默认即可。
  5. 保存并测试: 点击页面底部的 Save & test 按钮。如果连接成功,会显示 “Database Connection OK”。如果失败,请检查数据库地址、端口、用户名、密码、数据库名以及防火墙设置。

2. 创建一个 Panel 演示

现在我们来创建一个 Panel,例如展示一段时间内所有 FTU 的总平均有功功率 (ActivePower_Total) 随时间变化的折线图。

  1. 创建新的 Dashboard (可选但推荐):

    • 在左侧菜单中,将鼠标悬停在加号图标 (+) 上,点击 New dashboard
    • 点击 Add a new panel
  2. 配置 Panel:

    • Visualization: 选择 Graph (图表)。
    • Data source: 选择你刚刚配置好的 TimescaleDB 数据源 (例如 TimescaleDB-Telemetry)。
    • Query Editor: 这是核心部分,你需要在这里编写 SQL 查询来获取数据。确保选择的模式是 TimescaleDB

    SQL 查询:

    SQL

    SELECT
      time_bucket('$__interval', "ReadingTimestamp") AS time,
      AVG("ActivePower_Total") AS value
    FROM
      FactPowerReadings
    WHERE
      $__timeFilter("ReadingTimestamp")
    GROUP BY
      1 -- Group by the first selected column (time)
    ORDER BY
      time
    
    

    解释一下这个查询:

    • SELECT time_bucket('$__interval', "ReadingTimestamp") AS time:
      • time_bucket 是 TimescaleDB 提供的一个函数,用于将时间戳按指定的时间间隔进行分组。
      • '$__interval' 是 Grafana 提供的一个内置变量,它会根据你在 Dashboard 右上角选择的时间范围和图表的宽度,自动计算出一个合适的时间间隔(例如 1分钟、5分钟、1小时等),用于数据的聚合。这使得图表在不同时间范围下显示的数据密度是合理的。
      • "ReadingTimestamp" 是你的事实表中的时间列。
      • AS time 是必须的!Grafana 的 Graph Panel 要求时间序列查询的结果集包含一个名为 time 的列(通常是时间戳或时间桶的起始时间),一个名为 value 的列(表示在该时间点或时间桶内的度量值)。
    • AVG("ActivePower_Total") AS value: 计算每个时间桶内的 ActivePower_Total 的平均值,并将其命名为 value,符合 Grafana 的要求。你也可以使用 SUM, MAX, MIN, COUNT 等聚合函数。
    • FROM FactPowerReadings: 从你的事实表中获取数据。
    • WHERE $__timeFilter("ReadingTimestamp"):
      • $__timeFilter("ReadingTimestamp") 是 Grafana 提供的另一个非常重要的内置变量。它会根据你在 Dashboard 右上角选择的全局时间范围,自动生成一个 WHERE "ReadingTimestamp" BETWEEN '...' AND '...' 这样的 SQL 子句,从而只查询指定时间范围内的数据。所有时序相关的查询都应该包含这个条件。
    • GROUP BY 1: 根据 SELECT 语句中的第一列进行分组,这里就是按 time_bucket 生成的时间桶进行分组。
    • ORDER BY time: 按照时间顺序排序结果,这对于绘制时间序列图是必要的。
  3. 预览和调整: 在你输入查询后,Grafana 会自动执行并显示预览图。如果数据插入成功并且时间范围选对了,你应该能看到一条折线图。

  4. 配置可视化选项: 在 Panel 编辑器的右侧,你可以调整各种可视化选项,例如:

    • Axes (坐标轴): 配置 Y 轴的单位、刻度、标签等。
    • Legend (图例): 配置图例的显示方式。
    • Tooltip (悬停提示): 配置鼠标悬停在图表上时显示的信息。
    • Graph styles (图表样式): 配置线条粗细、填充等。
  5. 保存 Panel 和 Dashboard: 点击右上角的 Apply 按钮保存 Panel。然后点击 Dashboard 顶部的保存图标保存整个 Dashboard。

添加按 FTU 分组或过滤

如果你想看每个 FTU 的功率曲线,或者只看某个特定 FTU 的数据,可以修改查询并使用 Grafana 变量。

示例:按 FTU 分组并显示多条曲线

SQL

SELECT
  time_bucket('$__interval', "ReadingTimestamp") AS time,
  AVG("ActivePower_Total") AS value,
  "FTUKey" AS metric -- 将 FTUKey 作为 metric,Grafana 会为每个 FTUKey 绘制一条曲线
FROM
  FactPowerReadings
WHERE
  $__timeFilter("ReadingTimestamp")
GROUP BY
  1, "FTUKey" -- 同时按时间桶和 FTUKey 分组
ORDER BY
  time

在这个查询中,我们将 FTUKey 选出来并命名为 metric。Grafana 的 Graph Panel 会识别 metric 列,并为 metric 列的每一个不同的值绘制一条单独的折线。

示例:使用 Grafana 变量过滤特定 FTU

  1. 创建变量: 在 Dashboard 设置中 (齿轮图标),点击 Variables。添加一个新变量,例如命名为 ftu_key

    • Type: Query
    • Data source: 选择你的 TimescaleDB 数据源。
    • Query: 编写一个查询来获取所有有效的 FTUKey 列表,例如 SELECT "FTUKey" FROM DimFTU WHERE "IsCurrent" = TRUE ORDER BY "FTUKey";
    • 这样你就可以在 Dashboard 顶部看到一个下拉菜单,用于选择 FTUKey。
  2. 修改 Panel 查询: 在你的 Graph Panel 查询中,使用 $ftu_key 变量:

    SQL

    SELECT
      time_bucket('$__interval', "ReadingTimestamp") AS time,
      AVG("ActivePower_Total") AS value
    FROM
      FactPowerReadings
    WHERE
      $__timeFilter("ReadingTimestamp") AND "FTUKey" = $ftu_key -- 使用变量过滤
    GROUP BY
      1
    ORDER BY
      time
    
    

    现在,图表将只显示你在变量下拉菜单中选择的那个 FTU 的数据。

使用维度表信息 (例如 FTU_ID 或 Substation)

如果你想在图例中显示 FTU 的 ID (DimFTU.FTU_ID) 而不是数字的 Key,或者想按变电站 (DimXTU.Substation) 过滤,你需要使用 SQL JOIN。

示例:按 Substation 过滤,显示 FTU_ID 作为图例

假设你已经创建了一个名为 $substation 的 Grafana 变量来选择变电站。

SQL

SELECT
  time_bucket('$__interval', fr.ReadingTimestamp) AS time,
  AVG(fr."ActivePower_Total") AS value,
  df.ftu_id AS metric -- 使用 FTU_ID 作为图例
FROM
  FactPowerReadings fr
JOIN DimFTU df ON fr.FTUKey = df.FTUKey -- 连接 DimFTU
JOIN DimXTU dx ON df.XTUKey = dx.XTUKey -- 连接 DimXTU
WHERE
  $__timeFilter(fr.ReadingTimestamp) AND dx.substation = $substation -- 按变电站过滤
GROUP BY
  1, df.ftu_id -- 按时间桶和 FTU_ID 分组
ORDER BY
  time

这个查询稍微复杂一些,通过 JOIN 获取维度信息,并用于过滤和作为多条曲线的标识 (metric)。

总结:

Grafana 与 TimescaleDB 的集成非常顺畅,主要依赖于 Grafana 的 PostgreSQL 数据源和 TimescaleDB 的时序函数 (如 time_bucket)。核心是编写正确的 SQL 查询,利用 Grafana 的内置变量 ($__timeFilter, $__interval) 来实现动态时间范围和自动聚合,并根据需要使用 SQL JOIN 和 Grafana 变量来结合维度信息进行过滤和分组可视化。