数据平面契约 - 技术规范
状态:草案 版本:0.1
文档目标
详细定义数据源返回数据的通用查询响应模式。这改善了功能开发人员和数据源开发人员的体验。通过提高可靠性和质量,这也将改善用户体验,从而将更多的开发时间用于改善体验。
种类和格式
存在逻辑上的种类(例如时间序列数据、数值型、直方图等),并且存在特定种类可以采用的格式。
在此框架中,数据类型定义或声明包括种类和格式。例如,“TimeSeriesWide”是:种类:“时间序列”,格式:“Wide”。
基于维度的集合种类
在数据类型(种类+格式)中,可能存在多个通过唯一标识的数据项。这构成了数据项的集合。例如,在数值型种类中可能存在一个数字集合,或者在时间序列种类中可能存在一组时间序列。
集合中的每个数据项通过其名称和维度唯一标识。
维度是数据的方面(例如“location”或“host”)及其对应的值。例如,{"host"="a", "location"="new york"}。
在 dataframe 中,维度要么存在于字段的 Labels 属性中,要么存在于字符串字段中。
所有基于维度的集合种类共享的属性
- 当存在多个具有相同名称的数据项时,它们应该具有不同的维度(例如标签),以唯一标识每个数据项1。
- 数据项名称应出现在每个值(数值型或布尔型)Field 的 Name 属性中,任何 Labels 也应如此2
- 一个响应中可以有不同的数据项名称(注意:SSE 目前不支持此功能)
剩余数据
数据被编码为 dataframe(s),因此所有类型都实现为一个 data.Frames 数组。
dataframe(s) 中可能存在不属于数据类型的数据。这些额外的数据是剩余数据。读取器如何处理这些数据是开放的。但是,基于此契约的库必须明确区分剩余数据和属于类型的数据。
哪些数据成为剩余数据取决于数据类型并在数据类型中指定。通常,它可以是附加的 frame 和/或特定字段类型的附加字段。
无效数据
尽管存在剩余数据,但在某些情况下读取器仍然应该报错。这种情况发生时,frame(s) 上存在数据类型指定符,但未遵循该类型的规则。
“无数据”和空值
当响应缺少数据且没有错误时,有两种命名情况。
“无数据”用于我们从数据源检索到响应但响应没有数据项的情况。类型的形式编码是一个单独的 frame,包含数据类型声明,并且字段长度为零(null 或 [])。这种情况适用于整个集合没有数据项。无数据也可以是没有 frame(且没有错误)的响应。但是,在这种情况下,Type 和其他元数据无法返回——因此通常首选单 frame 的形式。
我们从数据源检索到一个或多个数据项,但某个数据项没有值,该数据项被称为“空值”。在这种情况下,必需的 dataframe 字段仍应存在(但字段本身都没有值)。
错误响应
使用 DataResponse 上的 Error
和 Status
属性在 dataframe 外部返回错误。
当 DataResponse 返回错误时,也可能包含一个没有字段的单独 frame。如果存在错误,则不会将其视为“无数据”。包含此 frame 是为了在发生错误时将元数据(特别是 Frame 的 ExecutedQueryString
)返回给调用者。
注意:在后端插件中,可以通过 DataQueryHandler
调用返回错误。这仅应用于整个请求(所有查询)都将失败的情况。
多数据类型响应
在单个结果中存在多种数据类型(在 RefID 内)的情况是存在的,但目前超出此版本规范的范围。
但是,需要有可能增加对此情况的支持。目前,建议采用以下逻辑
- 在响应中,每种数据类型应仅使用一种格式。例如:可能有 TimeSeriesWide 和 NumericLong,但不应有 TimeSeriesWide 和 TimeSeriesLong。
- 类型之间的边界源自共享相同数据类型的相邻 frame(在 frame 数组中)。
- 如果读取器未选择启用多类型响应,则应能够获取与读取器正在查找的内容匹配的第一种数据类型。
版本控制
此契约的目标是尽可能保持稳定。达到 1.0
版本后,更改应仅限于增强功能,直到达到 2.0
版本,这在数据类型版本中通常应避免。
契约版本控制
契约版本仅适用于影响契约总体概念的概念,例如错误处理或多数据类型响应。
新增或更改数据类型不影响契约版本。
数据类型版本
每种独立的数据类型都采用主/次要版本形式(x.x)。版本位于 Frame.Meta.TypeVersion
属性中。
- 版本
0.0
表示数据类型是契约之前的,或者处于非常早期的开发阶段。 - 版本
0.x
表示数据类型在契约中有明确定义,但可能会根据更广泛使用中学到的知识进行更改。 - 版本
1.0
应该是稳定的数据类型,并且不应与之前版本有任何更改 1.0
之后的小版本更改必须向后兼容数据读取器实现。它们还必须向前兼容其他1.x
版本(但不提供增强功能支持)。
需要添加的考量 / 待办事项
- 元数据(Frame 和 Field)
- 如果声明了类型/模式,我们是否需要支持在某种原因下,类型可以同时被视为多种种类的情况?
- 目前忽略了顺序(例如,TimeSeriesWide 中 Value Fields 的顺序或 TimeSeriesMulti 中 Frames 的顺序)。需要决定顺序是否有任何语义含义,如果有,是什么,并将其视为在格式之间转换的属性
- 注意:关于顺序的问题 https://github.com/grafana/grafana-plugin-sdk-go/issues/366 ,目前不确定是否是显示问题