mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Allows users to add a logs table in explore to a dashboard panel via the includeByName transformation
79 lines
2.7 KiB
TypeScript
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,
|
|
};
|
|
}
|