跳转到主要内容

数据帧

Grafana 支持各种不同的数据源,每个数据源都有自己的数据模型。为了实现这一点,Grafana 将每个数据源的查询结果合并到一个统一的数据结构中,称为 数据帧

数据帧结构是从数据分析工具如 R 编程语言Pandas 中借鉴的概念。

注意

数据帧在 Grafana 7.0+ 中可用,并替换了时间序列和表格结构,以支持更广泛的数据类型。

本文档概述了数据帧结构和 Grafana 中数据处理的方式。

数据帧字段

数据帧是一组 字段 的集合,其中每个字段对应于一列。每个字段本身又由值的集合和元数据组成,例如这些值的类型。

export interface Field<T = any, V = Vector<T>> {
/**
* Name of the field (column)
*/
name: string;
/**
* Field value type (string, number, and so on)
*/
type: FieldType;
/**
* Meta info about how field and how to display it
*/
config: FieldConfig;

/**
* The raw field values
* In Grafana 10, this accepts both simple arrays and the Vector interface
* In Grafana 11, the Vector interface will be removed
*/
values: V | T[];

/**
* When type === FieldType.Time, this can optionally store
* the nanosecond-precison fractions as integers between
* 0 and 999999.
*/
nanos?: number[];

labels?: Labels;

/**
* Cached values with appropriate display and id values
*/
state?: FieldState | null;

/**
* Convert a value for display
*/
display?: DisplayProcessor;

/**
* Get value data links with variables interpolated
*/
getLinks?: (config: ValueLinkConfig) => Array<LinkModel<Field>>;
}

让我们看看一个例子。以下表格演示了一个具有两个字段的数据帧,即 timetemperature

timetemperature
2020-01-02 03:04:0045.0
2020-01-02 03:05:0047.0
2020-01-02 03:06:0048.0

每个字段有三个值,字段中的每个值必须具有相同的类型。在这种情况下,time字段的全部值都是时间戳,而temperature字段的全部值都是数字。

虽然时间字段表示时间戳,但值的类型应该是Number(TypeScript)或time.Time(Golang)。

日期框架中时间字段的一个限制是数字转换。在插件前端代码中,可以使用来自@grafana/data包的函数ensureTimeField将其他格式转换为Number。此函数将遵循ISO 8601格式的字符串(例如,2017-07-19 00:00:00.000)、JavaScript DateTime和具有相对时间的字符串(例如,now-10s)转换为Numbers

数据框架的一个限制是,框架中的所有字段都必须具有相同的长度才能被认为是有效数据框架。

字段配置

数据框架中的每个字段包含有关字段值的可选信息,例如单位、缩放等。

通过将字段配置添加到数据框架中,Grafana可以自动配置可视化。例如,您可以配置Grafana自动设置数据源提供的单位。

数据转换

我们已经看到字段配置包含类型信息;此外,数据框架字段在Grafana中启用数据转换

数据转换是指接受数据框架作为输入并返回另一个数据框架的任何函数。通过在插件中使用数据框架,您可以免费获得一系列转换。

要了解更多有关Grafana中的数据转换的信息,请参阅转换数据

数据框架作为时间序列

具有至少一个时间字段的数据框架被认为是时间序列

有关时间序列的更多信息,请参阅我们的时间序列简介

宽格式

当一系列时间序列共享相同的时间索引——每个时间序列中的时间字段都是相同的——它们可以一起存储,在格式中。通过重用时间字段,浏览器发送的数据更少。

在这个例子中,每个主机的cpu使用情况共享时间索引,因此我们可以将它们存储在同一个数据框架中

Name: Wide
Dimensions: 3 fields by 2 rows
+---------------------+-----------------+-----------------+
| Name: time | Name: cpu | Name: cpu |
| Labels: | Labels: host=a | Labels: host=b |
| Type: []time.Time | Type: []float64 | Type: []float64 |
+---------------------+-----------------+-----------------+
| 2020-01-02 03:04:00 | 3 | 4 |
| 2020-01-02 03:05:00 | 6 | 7 |
+---------------------+-----------------+-----------------+

然而,如果两个时间序列不共享相同的时间值,它们将作为两个不同的数据框架表示

Name: cpu
Dimensions: 2 fields by 2 rows
+---------------------+-----------------+
| Name: time | Name: cpu |
| Labels: | Labels: host=a |
| Type: []time.Time | Type: []float64 |
+---------------------+-----------------+
| 2020-01-02 03:04:00 | 3 |
| 2020-01-02 03:05:00 | 6 |
+---------------------+-----------------+

Name: cpu
Dimensions: 2 fields by 2 rows
+---------------------+-----------------+
| Name: time | Name: cpu |
| Labels: | Labels: host=b |
| Type: []time.Time | Type: []float64 |
+---------------------+-----------------+
| 2020-01-02 03:04:01 | 4 |
| 2020-01-02 03:05:01 | 7 |
+---------------------+-----------------+

宽格式的典型用途是在多个时间序列由同一进程收集时。在这种情况下,每个测量都在相同的间隔进行,因此共享相同的时间值。

长格式

一些数据源返回的数据采用长格式(也称为窄格式)。例如,SQL数据库通常会返回这种格式。

在长格式中,字符串值以单独的字段表示,而不是作为标签。因此,长格式的数据表可能会有重复的时间值。

Grafana可以检测并将长格式数据帧转换为宽格式。

例如,以下数据帧以长格式显示

Name: Long
Dimensions: 4 fields by 4 rows
+---------------------+-----------------+-----------------+----------------+
| Name: time | Name: aMetric | Name: bMetric | Name: host |
| Labels: | Labels: | Labels: | Labels: |
| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []string |
+---------------------+-----------------+-----------------+----------------+
| 2020-01-02 03:04:00 | 2 | 10 | foo |
| 2020-01-02 03:04:00 | 5 | 15 | bar |
| 2020-01-02 03:05:00 | 3 | 11 | foo |
| 2020-01-02 03:05:00 | 6 | 16 | bar |
+---------------------+-----------------+-----------------+----------------+

上述表格可以转换为如下宽格式的数据帧

Name: Wide
Dimensions: 5 fields by 2 rows
+---------------------+------------------+------------------+------------------+------------------+
| Name: time | Name: aMetric | Name: bMetric | Name: aMetric | Name: bMetric |
| Labels: | Labels: host=foo | Labels: host=foo | Labels: host=bar | Labels: host=bar |
| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 |
+---------------------+------------------+------------------+------------------+------------------+
| 2020-01-02 03:04:00 | 2 | 10 | 5 | 15 |
| 2020-01-02 03:05:00 | 3 | 11 | 6 | 16 |
+---------------------+------------------+------------------+------------------+------------------+
注意

并非所有面板都支持宽时间序列数据帧格式。为了保持与旧版本的完全向后兼容,Grafana引入了一种转换功能,可以将宽格式转换为长格式。有关使用信息,请参阅准备时间序列转换

技术参考

Grafana中的数据帧概念借鉴了如R编程语言Pandas这样的数据分析工具。以下提供其他技术参考。

Apache Arrow

数据帧结构受Apache Arrow项目的启发,并使用该项目。JavaScript数据帧使用Arrow表作为底层结构,后端Go代码将其帧序列化为Arrow表以进行传输。

JavaScript

JavaScript数据帧的实现位于/src/dataframe文件夹和/src/types/dataframe.ts文件中,这些文件在@grafana/data/src/dataframe目录/src/types/dataframe.ts目录中。

Go

有关数据帧Go实现的文档,请参阅github.com/grafana/grafana-plugin-sdk-go/data包

了解更多

有关使用数据帧进行插件开发的指南,请参阅以下主题