Loki: Logs volume improvements (#40327)

* Skip logfmt errors

* Run volume queries as range queries

* Remove auto-skipping parsing errors

* Remove auto-skipping parsing errors

* Cache logs volume results

* Remove auto-loading

* Fix tests

* Clean up

* Disable logs volume in live streaming

* Clean up

* Add logs volume timeout

* Switch tooltip mode

* Increase timeout to 15s

* Fix test

* Change timeout to 10 seconds

* Remove unused code

* Extract styles

* Remove info about zoom level
This commit is contained in:
Piotr Jamróz
2021-10-18 12:22:41 +02:00
committed by GitHub
parent 52b69a9a80
commit 8939636492
17 changed files with 199 additions and 257 deletions

View File

@@ -39,6 +39,7 @@ describe('LokiLogsVolumeProvider', () => {
datasourceSetup();
request = ({
targets: [{ expr: '{app="app01"}' }, { expr: '{app="app02"}' }],
range: { from: 0, to: 1 },
} as unknown) as DataQueryRequest<LokiQuery>;
volumeProvider = createLokiLogsVolumeProvider((datasource as unknown) as LokiDatasource, request);
}

View File

@@ -14,12 +14,18 @@ import {
toDataFrame,
} from '@grafana/data';
import { LokiQuery } from '../types';
import { Observable } from 'rxjs';
import { Observable, throwError, timeout } from 'rxjs';
import { cloneDeep } from 'lodash';
import LokiDatasource, { isMetricsQuery } from '../datasource';
import { LogLevelColor } from '../../../../core/logs_model';
import { BarAlignment, GraphDrawStyle, StackingMode } from '@grafana/schema';
/**
* Logs volume query may be expensive as it requires counting all logs in the selected range. If such query
* takes too much time it may need be made more specific to limit number of logs processed under the hood.
*/
const TIMEOUT = 10000;
export function createLokiLogsVolumeProvider(
datasource: LokiDatasource,
dataQueryRequest: DataQueryRequest<LokiQuery>
@@ -30,6 +36,7 @@ export function createLokiLogsVolumeProvider(
.map((target) => {
return {
...target,
instant: false,
expr: `sum by (level) (count_over_time(${target.expr}[$__interval]))`,
};
});
@@ -42,28 +49,44 @@ export function createLokiLogsVolumeProvider(
data: [],
});
const subscription = datasource.query(logsVolumeRequest).subscribe({
complete: () => {
const aggregatedLogsVolume = aggregateRawLogsVolume(rawLogsVolume);
observer.next({
state: LoadingState.Done,
error: undefined,
data: aggregatedLogsVolume,
});
observer.complete();
},
next: (dataQueryResponse: DataQueryResponse) => {
rawLogsVolume = rawLogsVolume.concat(dataQueryResponse.data.map(toDataFrame));
},
error: (error) => {
observer.next({
state: LoadingState.Error,
error: error,
data: [],
});
observer.error(error);
},
});
const subscription = datasource
.query(logsVolumeRequest)
.pipe(
timeout({
each: TIMEOUT,
with: () => throwError(new Error('Request timed-out. Please make your query more specific and try again.')),
})
)
.subscribe({
complete: () => {
const aggregatedLogsVolume = aggregateRawLogsVolume(rawLogsVolume);
if (aggregatedLogsVolume[0]) {
aggregatedLogsVolume[0].meta = {
custom: {
targets: dataQueryRequest.targets,
absoluteRange: { from: dataQueryRequest.range.from.valueOf(), to: dataQueryRequest.range.to.valueOf() },
},
};
}
observer.next({
state: LoadingState.Done,
error: undefined,
data: aggregatedLogsVolume,
});
observer.complete();
},
next: (dataQueryResponse: DataQueryResponse) => {
rawLogsVolume = rawLogsVolume.concat(dataQueryResponse.data.map(toDataFrame));
},
error: (error) => {
observer.next({
state: LoadingState.Error,
error: error,
data: [],
});
observer.error(error);
},
});
return () => {
subscription?.unsubscribe();
};