makeTableFrames.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { groupBy } from 'lodash';
  2. import { DataFrame, Field, FieldType, ArrayVector } from '@grafana/data';
  3. export function makeTableFrames(instantMetricFrames: DataFrame[]): DataFrame[] {
  4. // first we remove frames that have no refId
  5. // (we will group them by refId, so we need it to be set)
  6. const framesWithRefId = instantMetricFrames.filter((f) => f.refId !== undefined);
  7. const framesByRefId = groupBy(framesWithRefId, (frame) => frame.refId);
  8. return Object.entries(framesByRefId).map(([refId, frames]) => makeTableFrame(frames, refId));
  9. }
  10. type NumberField = Field<number, ArrayVector<number>>;
  11. type StringField = Field<string, ArrayVector<string>>;
  12. function makeTableFrame(instantMetricFrames: DataFrame[], refId: string): DataFrame {
  13. const tableTimeField: NumberField = { name: 'Time', config: {}, values: new ArrayVector(), type: FieldType.time };
  14. const tableValueField: NumberField = {
  15. name: `Value #${refId}`,
  16. config: {},
  17. values: new ArrayVector(),
  18. type: FieldType.number,
  19. };
  20. // Sort metric labels, create columns for them and record their index
  21. const allLabelNames = new Set(
  22. instantMetricFrames.map((frame) => frame.fields.map((field) => Object.keys(field.labels ?? {})).flat()).flat()
  23. );
  24. const sortedLabelNames = Array.from(allLabelNames).sort();
  25. const labelFields: StringField[] = sortedLabelNames.map((labelName) => ({
  26. name: labelName,
  27. config: { filterable: true },
  28. values: new ArrayVector(),
  29. type: FieldType.string,
  30. }));
  31. instantMetricFrames.forEach((frame) => {
  32. const timeField = frame.fields.find((field) => field.type === FieldType.time);
  33. const valueField = frame.fields.find((field) => field.type === FieldType.number);
  34. if (timeField == null || valueField == null) {
  35. return;
  36. }
  37. const timeArray = timeField.values.toArray();
  38. const valueArray = valueField.values.toArray();
  39. for (let x of timeArray) {
  40. tableTimeField.values.add(x);
  41. }
  42. for (let x of valueArray) {
  43. tableValueField.values.add(x);
  44. }
  45. const labels = valueField.labels ?? {};
  46. for (let f of labelFields) {
  47. const text = labels[f.name] ?? '';
  48. // we insert the labels as many times as we have values
  49. for (let i = 0; i < valueArray.length; i++) {
  50. f.values.add(text);
  51. }
  52. }
  53. });
  54. return {
  55. fields: [tableTimeField, ...labelFields, tableValueField],
  56. refId,
  57. meta: { preferredVisualisationType: 'table' },
  58. length: tableTimeField.values.length,
  59. };
  60. }