grafana/public/app/features/logs/legacyLogsFrame.ts
Galen Kistler faa29db241
Logs Panel: Table UI - Pull logs table into dashboard panel (#77757)
* Allows users to add a logs table in explore to a dashboard panel via the includeByName transformation
2023-11-29 10:01:28 -06:00

79 lines
2.7 KiB
TypeScript

import { DataFrame, FieldCache, FieldType, Field, Labels, FieldWithIndex } from '@grafana/data';
import { logFrameLabelsToLabels, LogsFrame } from './logsFrame';
// take the labels from the line-field, and "stretch" it into an array
// with the length of the frame (so there are the same labels for every row)
function makeLabelsArray(lineField: Field, length: number): Labels[] | null {
const lineLabels = lineField.labels;
if (lineLabels !== undefined) {
const result = new Array(length);
result.fill(lineLabels);
return result;
} else {
return null;
}
}
// if the frame has "labels" field with type "other", adjust the behavior.
// we also have to return the labels-field (if we used it),
// to be able to remove it from the unused-fields, later.
function makeLabelsGetter(
cache: FieldCache,
lineField: Field,
frame: DataFrame
): [FieldWithIndex | null, () => Labels[] | null] {
// If we have labels field with type "other", use that
const labelsField = cache.getFieldByName('labels');
if (labelsField !== undefined && labelsField.type === FieldType.other) {
const values = labelsField.values.map(logFrameLabelsToLabels);
return [labelsField, () => values];
} else {
// Otherwise we use the labels on the line-field, and make an array with it
return [null, () => makeLabelsArray(lineField, frame.length)];
}
}
export function parseLegacyLogsFrame(frame: DataFrame): LogsFrame | null {
const cache = new FieldCache(frame);
const timeField = cache.getFirstFieldOfType(FieldType.time);
const bodyField = cache.getFirstFieldOfType(FieldType.string);
// these two are mandatory
if (timeField === undefined || bodyField === undefined) {
return null;
}
const timeNanosecondField = cache.getFieldByName('tsNs') ?? null;
const severityField = cache.getFieldByName('level') ?? null;
const idField = cache.getFieldByName('id') ?? null;
// extracting the labels is done very differently for old-loki-style and simple-style
// dataframes, so it's a little awkward to handle it,
// we both need to on-demand extract the labels, and also get teh labelsField,
// but only if the labelsField is used.
const [labelsField, getL] = makeLabelsGetter(cache, bodyField, frame);
const extraFields = cache.fields.filter(
(_, i) =>
i !== timeField.index &&
i !== bodyField.index &&
i !== timeNanosecondField?.index &&
i !== severityField?.index &&
i !== idField?.index &&
i !== labelsField?.index
);
return {
timeField,
bodyField,
timeNanosecondField,
severityField,
idField,
getLogFrameLabels: getL,
getLogFrameLabelsAsLabels: getL,
getLabelFieldName: () => labelsField?.name ?? null,
extraFields,
};
}