转换
开始之前: 在继续本指南之前,您必须已经了解 如何在 Scenes 应用中连接数据。
转换是一种强大的方法,可以在 Scenes 渲染可视化之前,处理由 SceneQueryRunner
对象返回的数据。使用转换,您可以
- 重命名字段
- 合并时间序列数据
- 跨查询执行数学运算
- 将一个转换的输出用作另一个转换的输入
通过转换,您可以只查询一次数据,然后对其进行处理,并在场景中显示。
在官方 Grafana 文档中了解有关 Grafana 转换的更多信息。
在场景中转换查询结果
步骤 1. 创建一个场景
创建一个包含单个 Table 面板和 Prometheus 查询的场景。示例查询返回 Prometheus API 端点的 HTTP 请求的平均持续时间。结果表包含三列:Time
、handler
和 Value
。
const queryRunner = new SceneQueryRunner({
$timeRange: new SceneTimeRange(),
datasource: {
type: 'prometheus',
uid: '<PROVIDE_GRAFANA_DS_UID>',
},
queries: [
{
refId: 'A',
expr: 'sort_desc(avg by(handler) (rate(prometheus_http_request_duration_seconds_sum {}[5m]) * 1e3))',
format: 'table',
instant: true,
},
],
});
const scene = new EmbeddedScene({
$data: queryRunner,
body: new SceneFlexLayout({
direction: 'column',
children: [
new SceneFlexItem({
body: PanelBuilders.table().setTitle('Average duration of HTTP request').build(),
}),
],
}),
});
步骤 2. 配置数据转换
上一步的结果表将类似于下面的表格
时间 | handler | 值 |
---|---|---|
2023-05-09 14:00:00.000 | /metrics | 1.10 |
2023-05-09 14:00:00.000 | /api/v1/label/:name/values | 0.361 |
2023-05-09 14:00:00.000 | /api/v1/metadata | 0.113 |
2023-05-09 14:00:00.000 | /api/v1/query_range | 0.0847 |
2023-05-09 14:00:00.000 | /api/v1/query | 0.14 |
2023-05-09 14:00:00.000 | /api/v1/labels | 0.0194 |
2023-05-09 14:00:00.000 | /api/v1/series | 0 |
2023-05-09 14:00:00.000 | /api/v1/status/buildinfo | 0 |
添加组织字段(Organize fields)转换来隐藏 Time
字段
创建一个 SceneDataTransformer
对象
const transformedData = new SceneDataTransformer({
$data: queryRunner,
transformations: [
{
id: 'organize',
options: {
excludeByName: {
Time: true,
},
indexByName: {},
renameByName: {},
},
},
],
});
transformations
中使用的对象与您在查看面板检查抽屉中的 JSON 选项卡时,在典型仪表盘面板中看到的转换配置对象相同。要访问此选项卡,请在面板编辑菜单中点击 检查 > 面板 JSON。
使用新创建的 transformedData
对象替换之前使用的 SceneQueryRunner
const scene = new EmbeddedScene({
$data: transformedData,
body: new SceneFlexLayout({
direction: 'column',
children: [
new SceneFlexItem({
body: PanelBuilders.table().setTitle('Average duration of HTTP request').build(),
}),
],
}),
});
结果表将类似于下面的表格
handler | 值 |
---|---|
/metrics | 1.10 |
/api/v1/label/:name/values | 0.361 |
/api/v1/metadata | 0.113 |
/api/v1/query_range | 0.0847 |
/api/v1/query | 0.14 |
/api/v1/labels | 0.0194 |
/api/v1/series | 0 |
/api/v1/status/buildinfo | 0 |
步骤 3. 配置多个转换
SceneDataTransformer
允许您配置多个转换。转换按照它们添加到 transformations
数组中的顺序执行。
修改 transformedData
对象并添加按正则表达式重命名(Rename by regex)转换来更改字段名称:将 handler
改为 Handler
,将 Value
改为 Average duration
const transformedData = new SceneDataTransformer({
$data: queryRunner,
transformations: [
{
id: 'organize',
options: {
excludeByName: {
Time: true,
},
indexByName: {},
renameByName: {},
},
},
{
id: 'renameByRegex',
options: {
regex: 'handler',
renamePattern: 'Handler',
},
},
{
id: 'renameByRegex',
options: {
regex: 'Value',
renamePattern: 'Average duration',
},
},
],
});
结果表将类似于下面的表格
处理程序 | 平均持续时间 |
---|---|
/metrics | 1.10 |
/api/v1/label/:name/values | 0.361 |
/api/v1/metadata | 0.113 |
/api/v1/query_range | 0.0847 |
/api/v1/query | 0.14 |
/api/v1/labels | 0.0194 |
/api/v1/series | 0 |
/api/v1/status/buildinfo | 0 |
添加自定义转换
除了 Grafana 中所有可用的转换之外,Scenes 还允许您创建自定义转换。
SceneDataTransformer
接受 CustomTransformOperator
作为 transformations
数组的一个项
transformations: Array<DataTransformerConfig | CustomTransformOperator>;
CustomTransformOperator
是一个返回 RxJS Operator 的函数,该 Operator 用于转换数据
type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;
在RxJS 官方文档中阅读更多关于 RxJS operator 的信息。
步骤 1. 创建自定义转换
创建一个自定义转换,该转换将应用于 handler
字段,并为所有值添加 URL 前缀
自定义转换在很大程度上依赖于操纵称为 数据帧(data frames) 的内部 Grafana 数据对象。在官方 Grafana 文档中了解有关数据帧的更多信息。
import { DataFrame } from '@grafana/data';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
const prefixHandlerTransformation: CustomTransformOperator = () => (source: Observable<DataFrame[]>) => {
return source.pipe(
map((data: DataFrame[]) => {
return data.map((frame: DataFrame) => {
return {
...frame,
fields: frame.fields.map((field) => {
if (field.name === 'handler') {
return {
...field,
values: field.values.map((v) => 'http://www.my-api.com' + v),
};
}
return field;
}),
};
});
})
);
};
步骤 2. 使用自定义转换
将自定义转换添加到之前创建的 transformedData
对象
const transformedData = new SceneDataTransformer({
$data: queryRunner,
transformations: [
prefixHandlerTransformation,
{
id: 'organize',
options: {
excludeByName: {
Time: true,
},
indexByName: {},
renameByName: {},
},
},
{
id: 'renameByRegex',
options: {
regex: 'handler',
renamePattern: 'Handler',
},
},
{
id: 'renameByRegex',
options: {
regex: 'Value',
renamePattern: 'Average duration',
},
},
],
});
prefixHandlerTransformation
自定义转换被添加为第一个,因为它应用于在后续转换中被重命名为 Handler
的 handler
字段。您可以修改自定义转换的实现,使其不必在其他转换之前使用。
结果表将类似于下面的表格
处理程序 | 平均持续时间 |
---|---|
http://www.my-api.com/metrics | 1.10 |
http://www.my-api.com/api/v1/label/:name/values | 0.361 |
http://www.my-api.com/api/v1/metadata | 0.113 |
http://www.my-api.com/api/v1/query_range | 0.0847 |
http://www.my-api.com/api/v1/query | 0.14 |
http://www.my-api.com/api/v1/labels | 0.0194 |
http://www.my-api.com/api/v1/series | 0 |
http://www.my-api.com/api/v1/status/buildinfo | 0 |
组合和过滤
转换(自定义和内置)的一项强大功能是以有趣的方式在面板之间共享查询结果。这允许您将大多数查询放在场景顶部的单个查询运行器中。然后,您可以在 VizPanel
级别使用 SceneDataTransformer
对象以不同的方式合并和过滤结果数据。某些面板可能需要其中两个查询的结果,而另一些面板可能需要所有查询的结果。
使用 DataFrame
上的 refId
属性,可以轻松地根据它们来自哪个查询来过滤结果 DataFrame
数组。