数据帧
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>>;
}
让我们来看一个例子。下表演示了一个包含两个字段的数据帧,time 和 temperature
时间 | 温度 |
---|---|
2020-01-02 03:04:00 | 45.0 |
2020-01-02 03:05:00 | 47.0 |
2020-01-02 03:06:00 | 48.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
包。
Go
有关数据帧的 Go 实现的文档,请参阅 github.com/grafana/grafana-plugin-sdk-go/data 包。
了解更多
有关使用数据帧进行插件开发的指南,请参阅以下主题