configFromQuery.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { map } from 'rxjs/operators';
  2. import {
  3. ArrayVector,
  4. DataFrame,
  5. DataTransformerID,
  6. DataTransformerInfo,
  7. FieldMatcherID,
  8. getFieldDisplayName,
  9. getFieldMatcher,
  10. MatcherConfig,
  11. reduceField,
  12. } from '@grafana/data';
  13. import {
  14. getFieldConfigFromFrame,
  15. FieldToConfigMapping,
  16. evaluteFieldMappings,
  17. } from '../fieldToConfigMapping/fieldToConfigMapping';
  18. export interface ConfigFromQueryTransformOptions {
  19. configRefId?: string;
  20. mappings: FieldToConfigMapping[];
  21. applyTo?: MatcherConfig;
  22. }
  23. export function extractConfigFromQuery(options: ConfigFromQueryTransformOptions, data: DataFrame[]) {
  24. let configFrame: DataFrame | null = null;
  25. for (const frame of data) {
  26. if (frame.refId === options.configRefId) {
  27. configFrame = frame;
  28. break;
  29. }
  30. }
  31. if (!configFrame) {
  32. return data;
  33. }
  34. const reducedConfigFrame: DataFrame = {
  35. fields: [],
  36. length: 1,
  37. };
  38. const mappingResult = evaluteFieldMappings(configFrame, options.mappings ?? [], false);
  39. // reduce config frame
  40. for (const field of configFrame.fields) {
  41. const newField = { ...field };
  42. const fieldName = getFieldDisplayName(field, configFrame);
  43. const fieldMapping = mappingResult.index[fieldName];
  44. const result = reduceField({ field, reducers: [fieldMapping.reducerId] });
  45. newField.values = new ArrayVector([result[fieldMapping.reducerId]]);
  46. reducedConfigFrame.fields.push(newField);
  47. }
  48. const output: DataFrame[] = [];
  49. const matcher = getFieldMatcher(options.applyTo || { id: FieldMatcherID.numeric });
  50. for (const frame of data) {
  51. // Skip config frame in output
  52. if (frame === configFrame && data.length > 1) {
  53. continue;
  54. }
  55. const outputFrame: DataFrame = {
  56. fields: [],
  57. length: frame.length,
  58. };
  59. for (const field of frame.fields) {
  60. if (matcher(field, frame, data)) {
  61. const dataConfig = getFieldConfigFromFrame(reducedConfigFrame, 0, mappingResult);
  62. outputFrame.fields.push({
  63. ...field,
  64. config: {
  65. ...field.config,
  66. ...dataConfig,
  67. },
  68. });
  69. } else {
  70. outputFrame.fields.push(field);
  71. }
  72. }
  73. output.push(outputFrame);
  74. }
  75. return output;
  76. }
  77. export const configFromDataTransformer: DataTransformerInfo<ConfigFromQueryTransformOptions> = {
  78. id: DataTransformerID.configFromData,
  79. name: 'Config from query results',
  80. description: 'Set unit, min, max and more from data',
  81. defaultOptions: {
  82. configRefId: 'config',
  83. mappings: [],
  84. },
  85. /**
  86. * Return a modified copy of the series. If the transform is not or should not
  87. * be applied, just return the input series
  88. */
  89. operator: (options) => (source) => source.pipe(map((data) => extractConfigFromQuery(options, data))),
  90. };