跳转到主要内容

变换

注意

开始之前:在继续本指南之前,您必须已经了解 在场景应用程序中连接数据

变换是在场景渲染可视化之前操作由 SceneQueryRunner 对象返回的数据的强大方式。使用变换,您可以

  • 重命名字段
  • 连接时间序列数据
  • 在查询间执行数学运算
  • 将一个变换的输出用作另一个变换的输入

使用变换,您可以查询一次数据,对其进行操作,并在场景中显示它。

有关Grafana变换的更多信息,请参阅 官方Grafana文档

在场景中变换查询结果

步骤 1. 创建场景

使用单个表格面板和Prometheus查询创建场景。示例查询返回Prometheus API端点的HTTP请求的平均持续时间。结果表包含三个列: 时间处理程序

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. 配置数据变换

上一步骤生成的表格将类似于以下表格

时间处理程序
2023-05-09 14:00:00.000/metrics1.10
2023-05-09 14:00:00.000/api/v1/label/:name/values0.361
2023-05-09 14:00:00.000/api/v1/metadata0.113
2023-05-09 14:00:00.000/api/v1/query_range0.0847
2023-05-09 14:00:00.000/api/v1/query0.14
2023-05-09 14:00:00.000/api/v1/labels0.0194
2023-05-09 14:00:00.000/api/v1/series0
2023-05-09 14:00:00.000/api/v1/status/buildinfo0

添加组织字段转换以隐藏时间字段

创建一个SceneDataTransformer对象

const transformedData = new SceneDataTransformer({
$data: queryRunner,
transformations: [
{
id: 'organize',
options: {
excludeByName: {
Time: true,
},
indexByName: {},
renameByName: {},
},
},
],
});
注意

转换中使用的对象与在典型的仪表板面板中查看面板检查器中的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(),
}),
],
}),
});

生成的表格将类似于以下表格

处理程序
/metrics1.10
/api/v1/label/:name/values0.361
/api/v1/metadata0.113
/api/v1/query_range0.0847
/api/v1/query0.14
/api/v1/labels0.0194
/api/v1/series0
/api/v1/status/buildinfo0

步骤 3. 配置多个转换

SceneDataTransformer允许您配置多个转换。转换的执行顺序与它们添加到转换数组中的顺序相同。

修改transformedData对象并添加按正则表达式重命名转换以更改字段名称:将handler更改为Handler,将Value更改为平均持续时间

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',
},
},
],
});

生成的表格将类似于以下表格

处理程序平均持续时间
/metrics1.10
/api/v1/label/:name/values0.361
/api/v1/metadata0.113
/api/v1/query_range0.0847
/api/v1/query0.14
/api/v1/labels0.0194
/api/v1/series0
/api/v1/status/buildinfo0

添加自定义转换

除了Grafana中提供的所有转换外,场景还允许您创建自定义转换。

SceneDataTransformer接受CustomTransformOperator作为转换数组的一项

  transformations: Array<DataTransformerConfig | CustomTransformOperator>;

CustomTransformOperator是一个返回RxJS操作符的函数,它转换数据

type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;
注意

有关RxJS操作符的更多信息,请参阅RxJS官方文档

步骤 1. 创建自定义转换

创建一个应用于handler字段的自定义转换,并给所有值添加URL前缀

注意

自定义转换严重依赖于操作名为数据帧的内部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',
},
},
],
});
注意

由于在以下转换中将handler字段重命名为Handler,因此将prefixHandlerTransformation自定义转换添加为第一个转换。您可以根据需要修改自定义转换实现,使其不一定要在其他转换之前使用。

生成的表格将类似于以下表格

处理程序平均持续时间
http://www.my-api.com/metrics1.10
http://www.my-api.com/api/v1/label/:name/values0.361
http://www.my-api.com/api/v1/metadata0.113
http://www.my-api.com/api/v1/query_range0.0847
http://www.my-api.com/api/v1/query0.14
http://www.my-api.com/api/v1/labels0.0194
http://www.my-api.com/api/v1/series0
http://www.my-api.com/api/v1/status/buildinfo0

合并和过滤

使用转换(自定义和内置)的一个强大功能是能够在不同面板之间以有趣的方式共享查询结果。这允许您将大部分查询放在场景顶部的单个查询运行器中。然后,您可以在 VizPanel 层上使用 SceneDataTransformer 对象以不同方式连接和过滤结果数据。某些面板可能需要两个查询的结果,而另一个可能需要所有查询的结果。

通过在 DataFrame 上使用 refId 属性,可以轻松根据来源查询过滤结果 DataFrame 数组。

源代码

查看示例源代码