GraphSeriesModel.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {
  2. getFlotPairs,
  3. getDisplayProcessor,
  4. NullValueMode,
  5. reduceField,
  6. FieldType,
  7. DisplayValue,
  8. GraphSeriesXY,
  9. getTimeField,
  10. DataFrame,
  11. getSeriesTimeStep,
  12. TimeZone,
  13. hasMsResolution,
  14. systemDateFormats,
  15. FieldColor,
  16. FieldColorModeId,
  17. FieldConfigSource,
  18. getFieldDisplayName,
  19. } from '@grafana/data';
  20. import { config } from '@grafana/runtime';
  21. import { colors } from '@grafana/ui';
  22. import { GraphLegendEditorLegendOptions, GraphOptions, SeriesOptions } from '../types/flotgraph';
  23. export const getGraphSeriesModel = (
  24. dataFrames: DataFrame[],
  25. timeZone: TimeZone,
  26. seriesOptions: SeriesOptions,
  27. graphOptions: GraphOptions,
  28. legendOptions: GraphLegendEditorLegendOptions,
  29. fieldOptions?: FieldConfigSource
  30. ) => {
  31. const graphs: GraphSeriesXY[] = [];
  32. const displayProcessor = getDisplayProcessor({
  33. field: {
  34. config: {
  35. unit: fieldOptions?.defaults?.unit,
  36. decimals: legendOptions.decimals,
  37. },
  38. },
  39. theme: config.theme2,
  40. timeZone,
  41. });
  42. let fieldColumnIndex = -1;
  43. for (const series of dataFrames) {
  44. const { timeField } = getTimeField(series);
  45. if (!timeField) {
  46. continue;
  47. }
  48. for (const field of series.fields) {
  49. if (field.type !== FieldType.number) {
  50. continue;
  51. }
  52. // Storing index of series field for future inspection
  53. fieldColumnIndex++;
  54. // Use external calculator just to make sure it works :)
  55. const points = getFlotPairs({
  56. xField: timeField,
  57. yField: field,
  58. nullValueMode: NullValueMode.Null,
  59. });
  60. if (points.length > 0) {
  61. const seriesStats = reduceField({ field, reducers: legendOptions.stats || [] });
  62. let statsDisplayValues: DisplayValue[] = [];
  63. if (legendOptions.stats) {
  64. statsDisplayValues = legendOptions.stats.map<DisplayValue>((stat) => {
  65. const statDisplayValue = displayProcessor(seriesStats[stat]);
  66. return {
  67. ...statDisplayValue,
  68. title: stat,
  69. };
  70. });
  71. }
  72. let color: FieldColor;
  73. if (seriesOptions[field.name] && seriesOptions[field.name].color) {
  74. // Case when panel has settings provided via SeriesOptions, i.e. graph panel
  75. color = {
  76. mode: FieldColorModeId.Fixed,
  77. fixedColor: seriesOptions[field.name].color,
  78. };
  79. } else if (field.config && field.config.color) {
  80. // Case when color settings are set on field, i.e. Explore logs histogram (see makeSeriesForLogs)
  81. color = field.config.color;
  82. } else {
  83. color = {
  84. mode: FieldColorModeId.Fixed,
  85. fixedColor: colors[graphs.length % colors.length],
  86. };
  87. }
  88. field.config = fieldOptions
  89. ? {
  90. ...field.config,
  91. unit: fieldOptions.defaults.unit,
  92. decimals: fieldOptions.defaults.decimals,
  93. color,
  94. }
  95. : { ...field.config, color };
  96. field.display = getDisplayProcessor({ field, timeZone, theme: config.theme2 });
  97. // Time step is used to determine bars width when graph is rendered as bar chart
  98. const timeStep = getSeriesTimeStep(timeField);
  99. const useMsDateFormat = hasMsResolution(timeField);
  100. timeField.display = getDisplayProcessor({
  101. timeZone,
  102. field: {
  103. ...timeField,
  104. type: timeField.type,
  105. config: {
  106. unit: systemDateFormats.getTimeFieldUnit(useMsDateFormat),
  107. },
  108. },
  109. theme: config.theme2,
  110. });
  111. graphs.push({
  112. label: getFieldDisplayName(field, series, dataFrames),
  113. data: points,
  114. color: field.config.color?.fixedColor,
  115. info: statsDisplayValues,
  116. isVisible: true,
  117. yAxis: {
  118. index: (seriesOptions[field.name] && seriesOptions[field.name].yAxis) || 1,
  119. },
  120. // This index is used later on to retrieve appropriate series/time for X and Y axes
  121. seriesIndex: fieldColumnIndex,
  122. timeField: { ...timeField },
  123. valueField: { ...field },
  124. timeStep,
  125. });
  126. }
  127. }
  128. }
  129. return graphs;
  130. };