Logs Volume: Do not throw when fields are missing (#99318)
* Logs Volume: Do not throw when fields are missing * Add removed line back * Prevent permanent mutations * Decrease nesting * Move conditional up * Update public/app/features/logs/utils.ts Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com> * Use dataframe length and remove from function * Use getFieldDisplayName * Keep original dependency array * Keep original dependency array --------- Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com>
This commit is contained in:
co-authored by
Galen Kistler
parent
ad30ca2ccd
commit
dccca0729f
@@ -266,7 +266,7 @@ const UnthemedLogs: React.FunctionComponent<Props> = (props: Props) => {
|
|||||||
// check if we have dataFrames that return the same level
|
// check if we have dataFrames that return the same level
|
||||||
const logLevelsArray: Array<{ levelStr: string; logLevel: LogLevel }> = [];
|
const logLevelsArray: Array<{ levelStr: string; logLevel: LogLevel }> = [];
|
||||||
logVolumeDataFrames.forEach((dataFrame) => {
|
logVolumeDataFrames.forEach((dataFrame) => {
|
||||||
const { level } = getLogLevelInfo(dataFrame);
|
const { level } = getLogLevelInfo(dataFrame, logsVolumeData?.data ?? []);
|
||||||
logLevelsArray.push({ levelStr: level, logLevel: getLogLevel(level) });
|
logLevelsArray.push({ levelStr: level, logLevel: getLogLevel(level) });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
QueryResultMeta,
|
QueryResultMeta,
|
||||||
LogsVolumeType,
|
LogsVolumeType,
|
||||||
NumericLogLevel,
|
NumericLogLevel,
|
||||||
|
getFieldDisplayName,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import { getDataframeFields } from './components/logParser';
|
import { getDataframeFields } from './components/logParser';
|
||||||
@@ -216,22 +217,28 @@ export const mergeLogsVolumeDataFrames = (dataFrames: DataFrame[]): { dataFrames
|
|||||||
|
|
||||||
// collect and aggregate into aggregated object
|
// collect and aggregate into aggregated object
|
||||||
dataFrames.forEach((dataFrame) => {
|
dataFrames.forEach((dataFrame) => {
|
||||||
const { level, valueField, timeField, length } = getLogLevelInfo(dataFrame);
|
const { level, valueField, timeField } = getLogLevelInfo(dataFrame, dataFrames);
|
||||||
|
|
||||||
|
if (!timeField || !valueField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
configs[level] = {
|
configs[level] = {
|
||||||
meta: dataFrame.meta,
|
meta: dataFrame.meta,
|
||||||
valueFieldConfig: valueField.config,
|
valueFieldConfig: valueField?.config ?? {},
|
||||||
timeFieldConfig: timeField.config,
|
timeFieldConfig: timeField?.config ?? {},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let pointIndex = 0; pointIndex < length; pointIndex++) {
|
for (let pointIndex = 0; pointIndex < dataFrame.length; pointIndex++) {
|
||||||
const time: number = timeField.values[pointIndex];
|
const time: number = timeField.values[pointIndex];
|
||||||
const value: number = valueField.values[pointIndex];
|
const value: number = valueField.values[pointIndex];
|
||||||
aggregated[level] ??= {};
|
aggregated[level] ??= {};
|
||||||
aggregated[level][time] = (aggregated[level][time] || 0) + value;
|
aggregated[level][time] = (aggregated[level][time] || 0) + value;
|
||||||
|
|
||||||
totals[time] = (totals[time] || 0) + value;
|
totals[time] = (totals[time] || 0) + value;
|
||||||
maximumValue = Math.max(totals[time], maximumValue);
|
if (totals[time] > maximumValue) {
|
||||||
|
maximumValue = totals[time];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -296,21 +303,20 @@ export const copyText = async (text: string, buttonRef: React.MutableRefObject<E
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getLogLevelInfo(dataFrame: DataFrame) {
|
export function getLogLevelInfo(dataFrame: DataFrame, allDataFrames: DataFrame[]) {
|
||||||
const fieldCache = new FieldCache(dataFrame);
|
const fieldCache = new FieldCache(dataFrame);
|
||||||
const timeField = fieldCache.getFirstFieldOfType(FieldType.time);
|
const timeField = fieldCache.getFirstFieldOfType(FieldType.time);
|
||||||
const valueField = fieldCache.getFirstFieldOfType(FieldType.number);
|
const valueField = fieldCache.getFirstFieldOfType(FieldType.number);
|
||||||
|
|
||||||
if (!timeField) {
|
if (!timeField) {
|
||||||
throw new Error('Missing time field');
|
console.error('Time field missing in data frame');
|
||||||
}
|
}
|
||||||
if (!valueField) {
|
if (!valueField) {
|
||||||
throw new Error('Missing value field');
|
console.error('Value field missing in data frame');
|
||||||
}
|
}
|
||||||
|
|
||||||
const level = valueField.config.displayNameFromDS || dataFrame.name || 'logs';
|
const level = valueField ? getFieldDisplayName(valueField, dataFrame, allDataFrames) : 'logs';
|
||||||
const length = valueField.values.length;
|
return { level, valueField, timeField };
|
||||||
return { level, valueField, timeField, length };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function targetIsElement(target: EventTarget | null): target is Element {
|
export function targetIsElement(target: EventTarget | null): target is Element {
|
||||||
|
|||||||
Reference in New Issue
Block a user