ResultProcessor.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import { DataQueryResponse, DataQueryResponseData } from '@grafana/ui';
  2. import {
  3. TableData,
  4. isTableData,
  5. LogsModel,
  6. toDataFrame,
  7. guessFieldTypes,
  8. TimeSeries,
  9. GraphSeriesXY,
  10. LoadingState,
  11. } from '@grafana/data';
  12. import { ExploreItemState, ExploreMode } from 'app/types/explore';
  13. import { getProcessedDataFrames } from 'app/features/dashboard/state/PanelQueryState';
  14. import TableModel, { mergeTablesIntoModel } from 'app/core/table_model';
  15. import { sortLogsResult, refreshIntervalToSortOrder } from 'app/core/utils/explore';
  16. import { dataFrameToLogsModel } from 'app/core/logs_model';
  17. import { getGraphSeriesModel } from 'app/plugins/panel/graph2/getGraphSeriesModel';
  18. export class ResultProcessor {
  19. private rawData: DataQueryResponseData[] = [];
  20. private metrics: TimeSeries[] = [];
  21. private tables: TableData[] = [];
  22. constructor(
  23. private state: ExploreItemState,
  24. private replacePreviousResults: boolean,
  25. result?: DataQueryResponse | DataQueryResponseData[]
  26. ) {
  27. if (result && result.hasOwnProperty('data')) {
  28. this.rawData = (result as DataQueryResponse).data;
  29. } else {
  30. this.rawData = (result as DataQueryResponseData[]) || [];
  31. }
  32. if (this.state.mode !== ExploreMode.Metrics) {
  33. return;
  34. }
  35. for (let index = 0; index < this.rawData.length; index++) {
  36. const res: any = this.rawData[index];
  37. const isTable = isTableData(res);
  38. if (isTable) {
  39. this.tables.push(res);
  40. } else {
  41. this.metrics.push(res);
  42. }
  43. }
  44. }
  45. getRawData = (): any[] => {
  46. return this.rawData;
  47. };
  48. getGraphResult = (): GraphSeriesXY[] => {
  49. if (this.state.mode !== ExploreMode.Metrics) {
  50. return [];
  51. }
  52. const newResults = this.createGraphSeries(this.metrics);
  53. return this.mergeGraphResults(newResults, this.state.graphResult);
  54. };
  55. getTableResult = (): TableModel => {
  56. if (this.state.mode !== ExploreMode.Metrics) {
  57. return new TableModel();
  58. }
  59. const prevTableResults: any[] | TableModel = this.state.tableResult || [];
  60. const tablesToMerge = this.replacePreviousResults ? this.tables : [].concat(prevTableResults, this.tables);
  61. return mergeTablesIntoModel(new TableModel(), ...tablesToMerge);
  62. };
  63. getLogsResult = (): LogsModel => {
  64. if (this.state.mode !== ExploreMode.Logs) {
  65. return null;
  66. }
  67. const graphInterval = this.state.queryIntervals.intervalMs;
  68. const dataFrame = this.rawData.map(result => guessFieldTypes(toDataFrame(result)));
  69. const newResults = this.rawData ? dataFrameToLogsModel(dataFrame, graphInterval) : null;
  70. const sortOrder = refreshIntervalToSortOrder(this.state.refreshInterval);
  71. const sortedNewResults = sortLogsResult(newResults, sortOrder);
  72. if (this.replacePreviousResults) {
  73. const slice = 1000;
  74. const rows = sortedNewResults.rows.slice(0, slice);
  75. const series = sortedNewResults.series;
  76. return { ...sortedNewResults, rows, series };
  77. }
  78. const prevLogsResult: LogsModel = this.state.logsResult || { hasUniqueLabels: false, rows: [] };
  79. const sortedLogResult = sortLogsResult(prevLogsResult, sortOrder);
  80. const rowsInState = sortedLogResult.rows;
  81. const seriesInState = sortedLogResult.series || [];
  82. const processedRows = [];
  83. for (const row of rowsInState) {
  84. processedRows.push({ ...row, fresh: false });
  85. }
  86. for (const row of sortedNewResults.rows) {
  87. processedRows.push({ ...row, fresh: true });
  88. }
  89. const processedSeries = this.mergeGraphResults(sortedNewResults.series, seriesInState);
  90. const slice = -1000;
  91. const rows = processedRows.slice(slice);
  92. const series = processedSeries.slice(slice);
  93. return { ...sortedNewResults, rows, series };
  94. };
  95. private createGraphSeries = (rawData: any[]) => {
  96. const dataFrames = getProcessedDataFrames(rawData);
  97. const graphSeries = getGraphSeriesModel(
  98. { series: dataFrames, state: LoadingState.Done },
  99. {},
  100. { showBars: false, showLines: true, showPoints: false },
  101. {
  102. asTable: false,
  103. isVisible: true,
  104. placement: 'under',
  105. }
  106. );
  107. return graphSeries;
  108. };
  109. private isSameGraphSeries = (a: GraphSeriesXY, b: GraphSeriesXY) => {
  110. if (a.hasOwnProperty('label') && b.hasOwnProperty('label')) {
  111. const aValue = a.label;
  112. const bValue = b.label;
  113. if (aValue !== undefined && bValue !== undefined && aValue === bValue) {
  114. return true;
  115. }
  116. }
  117. return false;
  118. };
  119. private mergeGraphResults = (newResults: GraphSeriesXY[], prevResults: GraphSeriesXY[]): GraphSeriesXY[] => {
  120. if (!prevResults || prevResults.length === 0 || this.replacePreviousResults) {
  121. return newResults; // Hack before we use GraphSeriesXY instead
  122. }
  123. const results: GraphSeriesXY[] = prevResults.slice() as GraphSeriesXY[];
  124. // update existing results
  125. for (let index = 0; index < results.length; index++) {
  126. const prevResult = results[index];
  127. for (const newResult of newResults) {
  128. const isSame = this.isSameGraphSeries(prevResult, newResult);
  129. if (isSame) {
  130. prevResult.data = prevResult.data.concat(newResult.data);
  131. break;
  132. }
  133. }
  134. }
  135. // add new results
  136. for (const newResult of newResults) {
  137. let isNew = true;
  138. for (const prevResult of results) {
  139. const isSame = this.isSameGraphSeries(prevResult, newResult);
  140. if (isSame) {
  141. isNew = false;
  142. break;
  143. }
  144. }
  145. if (isNew) {
  146. results.push(newResult);
  147. }
  148. }
  149. return results;
  150. };
  151. }