使用带有 BIGINT 列作为时间的 Postgres 数据源在 Grafana 中绘制图形

Graph in Grafana using Postgres Datasource with BIGINT column as time

我正在尝试构建一个非常简单的图表来显示我在一段时间内的访问量(例如每 5 分钟)。 我将 v.5.4.0 的 Grafana 与充满数据的 Postgres v.9.6 配对得很好。 我的 table 下面:

CREATE TABLE visit (
    id                    serial CONSTRAINT visit_primary_key PRIMARY KEY,
    user_credit_id        INTEGER NOT NULL REFERENCES user_credit(id),
    visit_date            bigint NOT NULL,
    visit_path            varchar(128),
    method                varchar(8) NOT NULL DEFAULT 'GET'
);

其中有一些数据:

 id | user_credit_id |  visit_date   |                 visit_path                  | method 
----+----------------+---------------+---------------------------------------------+--------
  1 |              1 | 1550094818029 | /                                           | GET
  2 |              1 | 1550094949537 | /mortgage/restapi/credit/{userId}/decrement | POST
  3 |              1 | 1550094968651 | /mortgage/restapi/credit/{userId}/decrement | POST
  4 |              1 | 1550094988557 | /mortgage/restapi/credit/{userId}/decrement | POST
  5 |              1 | 1550094990820 | /index/UGiBGp0V                             | GET
  6 |              1 | 1550094990929 | /                                           | GET
  7 |              2 | 1550095986310 | /                                           | GET
...

所以我尝试了这 3 个变体(实际上,还有几十个其他变体都没有成功)但没有成功:

  1. 方案一:
SELECT
  visit_date as "time",
  count(user_credit_id) AS "user_credit_id"
FROM visit
WHERE $__timeFilter(visit_date)
ORDER BY visit_date ASC

图表上没有数据。错误:pq:整数的输入语法无效:“2019-02-14T13:16:50Z”

  1. 方案B
SELECT
  $__unixEpochFrom(visit_date),
  count(user_credit_id) AS "user_credit_id"
FROM visit
GROUP BY time
ORDER BY user_credit_id

Series ASELECT
  $__time(visit_date/1000,10m,previous),
  count(user_credit_id) AS "user_credit_id A"
FROM
  visit
WHERE
 visit_date >= $__unixEpochFrom()::bigint*1000 and
 visit_date <= $__unixEpochTo()::bigint*1000
GROUP BY 1
ORDER BY 1

图表上没有数据。没有错误..

  1. 解决方案 C:
SELECT
  $__timeGroup(visit_date, '1h'),
  count(user_credit_id) AS "user_credit_id"
FROM visit
GROUP BY time
ORDER BY time

图表上没有数据。错误:pq: 函数 pg_catalog.date_part(unknown, bigint) 不存在

有人能帮我解决这个简单的问题吗,因为我认为查询应该紧凑、天真和简单。但是 Grafana 演示其语法和功能的文档让我有点困惑。提前致谢!

使用这个查询,如果 visit_datetimestamptz:

SELECT
  $__timeGroupAlias(visit_date,5m,0),
  count(*) AS "count"
FROM visit
WHERE
  $__timeFilter(visit_date)
GROUP BY 1
ORDER BY 1

但是你的visit_datebigint所以你需要把它转换成timestamp(可能用TO_TIMESTAMP())或者你需要找到其他的使用方法bigint。使用查询检查器进行调试,您将看到 Grafana 生成的 SQL。

Jan Garaj,非常感谢!我应该承认,您的代码片段以及您建议切换到 SQL 调试的其他评论更有价值,这极大地帮助了我 "breakthrough"。 因此,生成的查询解决了我的问题:

SELECT
  $__unixEpochGroup(visit_date/1000, '5m') AS "time",
  count(user_credit_id) AS "Total Visits"
FROM visit
WHERE
  '1970-01-01 00:00:00 GMT'::timestamp + ((visit_date/1000)::text)::interval BETWEEN
  $__timeFrom()::timestamp
  AND
  $__timeTo()::timestamp
GROUP BY 1
ORDER BY 1

破解所有这些Grafana魔法的几条评论:

  1. Grafana 有其有限的 DSL 来制作可配置的图表,这组函数转换成一些有意义的 SQL (这是看到 "compiled" SQL对我帮助很大,再次感谢)。
  2. 为了使我的 BIGINT 列适用于预定义的 Grafana 函数,我们需要简单地将其转换为从 UNIX 纪元开始的秒数,因此,在数学语言中 - 只需除以 1000。
  3. 现在,WHERE 语句似乎不那么简单和可预测,Grafana DSL 的工作方式不同,简单的除法并没有成功,我通过使用另一个 Grafana 函数来解决它 FROMTO 个时间点(应呈现图表的时间段),但这些函数生成时间戳类型,而我们的专栏中确实有 BIGINT。所以,多亏了 Postgres 我们有一堆转换器可以让它成为时间戳 ('1970-01-01 00:00:00 GMT'::timestamp + ((visit_date/1000::text) ::interval - 生成一个 BIGINT 值转换为 Postgres TIMESTAMPGrafana 处理得很好)。

P.S。如果您不介意,我已经将我的问题文本更改为更精确和详细。