mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 00:25:46 -06:00
Loki: Use fixed bucket size for logs volume (#40873)
* Use fixed bucket size for logs volume * Fix unit tests
This commit is contained in:
parent
fbd68c4e96
commit
877c726246
@ -60,7 +60,7 @@ export function LogsVolumePanel(props: Props) {
|
||||
if (zoomRatio !== undefined && zoomRatio < 1) {
|
||||
zoomLevelInfo = (
|
||||
<>
|
||||
<span className={styles.zoomInfo}>Reload to show higher resolution</span>
|
||||
<span className={styles.zoomInfo}>Reload logs volume</span>
|
||||
<Button size="xs" icon="sync" variant="secondary" onClick={onLoadLogsVolume} />
|
||||
</>
|
||||
);
|
||||
|
@ -40,6 +40,11 @@ describe('LokiLogsVolumeProvider', () => {
|
||||
request = ({
|
||||
targets: [{ expr: '{app="app01"}' }, { expr: '{app="app02"}' }],
|
||||
range: { from: 0, to: 1 },
|
||||
scopedVars: {
|
||||
__interval_ms: {
|
||||
value: 1000,
|
||||
},
|
||||
},
|
||||
} as unknown) as DataQueryRequest<LokiQuery>;
|
||||
volumeProvider = createLokiLogsVolumeProvider((datasource as unknown) as LokiDatasource, request);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
LoadingState,
|
||||
LogLevel,
|
||||
MutableDataFrame,
|
||||
ScopedVars,
|
||||
toDataFrame,
|
||||
} from '@grafana/data';
|
||||
import { LokiQuery } from '../types';
|
||||
@ -20,26 +21,36 @@ import LokiDatasource, { isMetricsQuery } from '../datasource';
|
||||
import { LogLevelColor } from '../../../../core/logs_model';
|
||||
import { BarAlignment, GraphDrawStyle, StackingMode } from '@grafana/schema';
|
||||
|
||||
const SECOND = 1000;
|
||||
const MINUTE = 60 * SECOND;
|
||||
const HOUR = 60 * MINUTE;
|
||||
const DAY = 24 * HOUR;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
const TIMEOUT = 10 * SECOND;
|
||||
|
||||
export function createLokiLogsVolumeProvider(
|
||||
datasource: LokiDatasource,
|
||||
dataQueryRequest: DataQueryRequest<LokiQuery>
|
||||
): Observable<DataQueryResponse> {
|
||||
const logsVolumeRequest = cloneDeep(dataQueryRequest);
|
||||
const intervalInfo = getIntervalInfo(dataQueryRequest.scopedVars);
|
||||
logsVolumeRequest.targets = logsVolumeRequest.targets
|
||||
.filter((target) => target.expr && !isMetricsQuery(target.expr))
|
||||
.map((target) => {
|
||||
return {
|
||||
...target,
|
||||
instant: false,
|
||||
expr: `sum by (level) (count_over_time(${target.expr}[$__interval]))`,
|
||||
expr: `sum by (level) (count_over_time(${target.expr}[${intervalInfo.interval}]))`,
|
||||
};
|
||||
});
|
||||
logsVolumeRequest.interval = intervalInfo.interval;
|
||||
if (intervalInfo.intervalMs !== undefined) {
|
||||
logsVolumeRequest.intervalMs = intervalInfo.intervalMs;
|
||||
}
|
||||
|
||||
return new Observable((observer) => {
|
||||
let rawLogsVolume: DataFrame[] = [];
|
||||
@ -54,7 +65,12 @@ export function createLokiLogsVolumeProvider(
|
||||
.pipe(
|
||||
timeout({
|
||||
each: TIMEOUT,
|
||||
with: () => throwError(new Error('Request timed-out. Please make your query more specific and try again.')),
|
||||
with: () =>
|
||||
throwError(
|
||||
new Error(
|
||||
'Request timed-out. Please try making your query more specific or narrow selected time range and try again.'
|
||||
)
|
||||
),
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
@ -133,8 +149,6 @@ function getFieldConfig(level: LogLevel, levels: number) {
|
||||
custom: {
|
||||
drawStyle: GraphDrawStyle.Bars,
|
||||
barAlignment: BarAlignment.Center,
|
||||
barWidthFactor: 0.9,
|
||||
barMaxWidth: 5,
|
||||
lineColor: color,
|
||||
pointColor: color,
|
||||
fillColor: color,
|
||||
@ -196,3 +210,27 @@ function getLogLevelFromLabels(labels: Labels): LogLevel {
|
||||
}
|
||||
return levelLabel ? getLogLevelFromKey(labels[levelLabel]) : LogLevel.unknown;
|
||||
}
|
||||
|
||||
function getIntervalInfo(scopedVars: ScopedVars): { interval: string; intervalMs?: number } {
|
||||
if (scopedVars.__interval) {
|
||||
let intervalMs: number = scopedVars.__interval_ms.value;
|
||||
let interval = '';
|
||||
if (intervalMs > HOUR) {
|
||||
intervalMs = DAY;
|
||||
interval = '1d';
|
||||
} else if (intervalMs > MINUTE) {
|
||||
intervalMs = HOUR;
|
||||
interval = '1h';
|
||||
} else if (intervalMs > SECOND) {
|
||||
intervalMs = MINUTE;
|
||||
interval = '1m';
|
||||
} else {
|
||||
intervalMs = SECOND;
|
||||
interval = '1s';
|
||||
}
|
||||
|
||||
return { interval, intervalMs };
|
||||
} else {
|
||||
return { interval: '$__interval' };
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user