时间序列类型格式
所有时间序列格式共有的属性
- 帧应该按时间列/字段的升序排序1
- 时间字段
- 不应有空值
- 字段名称仅用于显示,不应有标签
- 对于每个帧,第一个时间字段之后的所有额外时间字段被视为剩余数据
- 值字段
- 值字段被称为这样,因为它是每个数据点(时间,值)的值所在的位置的字段。
- 它可以是数值或布尔字段。对于数值
- Go: Float64,*Float64,或 Int64 等
- 在 JS 中 'number'
- 系列名称来自值字段的名称属性
无效情况
- 没有至少一个时间字段和一个值字段(除非是单个帧“无数据”情况)
- 存在“无数据”情况(没有字段的帧)与数据并存
- 可能是警告而不是错误
- 重复项(通过名称+维度识别)
- 未排序(时间不是从旧到新排序)
时间序列宽格式(TimeSeriesWide)
版本:0.1
宽格式在单个帧中有多个时间序列,它们共享相同的时间字段。它被称为“宽”,因为随着更多系列的增加,它变得更宽。
示例
类型:时间 名称:T 标签:nil | 类型:数字 名称:cpu 标签:{"host": "a"} | 类型:数字 名称:cpu 标签:{"host": "b"} |
2022-04-27 5:00 | 1 | 6 |
2022-04-27 6:00 | 4 | 8 |
2022-04-27 7:00 | 2 | 5 |
2022-04-27 8:00 | 3 | 9 |
它应该有以下属性:(也请参阅共享属性)
- 类型为时间的第一个字段是所有时间序列的时间索引。
- 应该只有一个带有数据类型声明的帧。
- 应该至少有一个字段是值字段类型
- 如果有多个数值字段,则帧中的时间字段与每个值字段的组合创建每个时间序列(指标)
- 时间字段不应有重复值(重复的时间戳)。
剩余数据
- 任何没有类型声明或不同声明的额外帧
- 帧中的任何字符串字段
注释
- Go 的一个示例可以在这里找到:这里。
时间序列多格式(TimeSeriesMulti)
版本:0.1
TimeSeriesMulti 格式每个帧有一个时间序列。如果响应有多个系列,其中时间值可能不一致,则必须使用此格式而不是 TimeSeriesWide。该格式称为“多”,因为数据存在于多个数据帧中。
示例:
帧 0
类型:时间 名称:T 标签:nil | 类型:数字 名称:cpu 标签: {"host": "a"} |
2022-04-27 5:00 | 1 |
2022-04-27 6:00 | 4 |
2022-04-27 7:00 | 2 |
2022-04-27 8:00 | 3 |
帧 1
类型:时间 名称:T 标签:nil | 类型:数字 名称:cpu 标签: {"host": "b"} |
2022-04-27 5:00 | 6 |
2022-04-27 6:00 | 8 |
2022-04-27 7:00 | 5 |
2022-04-27 8:00 | 9 |
它应该有以下属性:(也请参阅共享属性)
- 每个帧至少应有一个时间和一个数值列。该类型每个字段的首次出现用于系列。
- 不同帧可以有不同的字段长度(但必须在帧内长度相同)
- 每个时间字段应没有重复的值(重复的时间戳)
剩余数据
- 每个帧中的第一个之后的任何数值或时间字段
- 任何没有类型声明或不同声明的额外帧
- 帧中的任何字符串字段
注释
- Go 示例 这里。
- 多格式是唯一可以从中转换而无需数据操作的其他格式的格式。因此,它是一种可以包含其他类型系列信息的类型。
时间序列长格式(TimeSeriesLong)[SQL-like]
版本:0.1
这是SQL-like系统中常见的响应格式2。请参阅Grafana 文档:表格格式中的多个维度以获取一些更简单的(但不是完整的)示例。它目前作为后端某些数据源中查询SQL-like数据的内部数据转换而存在3,请参阅此Go示例以了解该代码的工作原理。
该格式被称为“长”格式,因为与“宽”格式相比,需要更多的行来存储相同的系列,因此它变得更长。
示例
类型:时间 名称:T 标签:nil | 类型:字符串 名称:host 标签:nil | 类型:数字 名称:cpu 标签:nil |
2022-04-27 5:00 | a | 1 |
2022-04-27 5:00 | b | 6 |
2022-04-27 6:00 | a | 4 |
2022-04-27 6:00 | b | 8 |
2022-04-27 7:00 | a | 2 |
2022-04-27 7:00 | b | 5 |
2022-04-27 8:00 | a | 3 |
2022-04-27 8:00 | b | 9 |
它应具有以下属性:(也请参阅共享属性):
- 第一个时间字段用作时间戳
- 时间字段可以有不同的时间戳(但必须按升序排序)
- 可能有字符串字段。对于每个字符串字段
- 列/字段名称是维度(例如,“标签”)名称
- 该字段中对应的字符串值(按行)是标签值
- 通过迭代数据帧表响应的行来构建系列。
- 任何值字段/列的名称成为每个系列名称
- 字段标签属性未使用
剩余数据
- 第一个之后的任何额外时间字段
- 任何没有类型声明或不同声明的额外帧
附加属性或注意事项
- 在此格式中,从字段中的值中提取完整维度(例如,“host”=value),而不是像其他格式一样在字段模式中声明。
- 由于维度表示在为所有派生系列存在的字段中,因此不能持有混合维度键,因此所有系列都将具有相同的维度键集。例如,不能同时有net.bytes{host="a"}和 net.bytes{host="a",int="eth0"}一起 - 第一个必须变为 net.bytes{host="a",int=""}
- 不清楚布尔类型字段是否应被视为值字段(例如,上下度量)或维度(在这种情况下,它将被概念上视为标签)
时间序列格式之间的转换
源 | 目标 | 修改数据 | 属性和 注意 |
宽 | 多 | 无* |
|
多 | 宽 | 是 |
|
宽 | 长† | 是 |
|
长 | 宽 | 是† |
|
长 | 多 | 否 |
|
多 | 长 | 是 |
|
注释
*关于时间序列格式,只有在转换为“多”格式时,底层的时间序列数据才不能被操作
†实际上,我还没有看到将数据转换为长格式的案例,只是读取它。也许将来某天可能会将其作为导出格式请求,但基本上目前这是用于说明的。
‡这是由SQL数据源用于从“长”格式中提取时间序列(通过go sdk/data包)使用的。事后看来,我有点希望我们选择了LongToMany。请参阅“相关”部分此问题评论。
- 这是因为排序通常在资源方面代价高昂,并且在大多数情况下最好由数据源背后的数据库完成。↩
- 我不认为我们当前的SQL数据源严格遵循这一点,但某些Azure数据源确实如此。这可能是由于关于此格式意图的误解以及Grafana 8的升级和/或对破坏性变化的缺乏理解,或者两者兼而有之。↩
- 在查询时选择“格式为时间序列”时发生这种转换。在管道的这个阶段发生转换的问题在于,虽然它确实以表格格式提供了用户的“时间序列”,但它使得数据的“表格视图”与查询的SQL返回值不匹配。待办事项:稍后定义这个通用概念,可能称之为“所见非所得”,“数据误解”,等等。这意味着我们可能需要返回两件事(有点像示例?),或者操作应该移动,或者做其他事情。↩