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:
Matias Chomicki
2025-01-21 20:02:07 +01:00
committed by GitHub
co-authored by Galen Kistler
parent ad30ca2ccd
commit dccca0729f
2 changed files with 18 additions and 12 deletions
+1 -1
View File
@@ -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) });
}); });
+17 -11
View File
@@ -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 {