From 2e6690428f821ab0af72dedce97b5c079b422298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 6 Dec 2018 12:12:43 +0100 Subject: [PATCH] fixed logs to time series calculation issue, increased bucket size, fixes #14248 --- public/app/core/logs_model.ts | 15 ++++++++++++--- public/app/core/utils/explore.ts | 22 ++++++++++------------ public/app/features/explore/Logs.tsx | 1 + public/app/types/index.ts | 2 ++ public/app/types/series.ts | 18 ++++++++++++++++++ 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index 1efe26d28ef..1527f18e4b6 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -170,16 +170,25 @@ export function filterLogLevels(logs: LogsModel, hiddenLogLevels: Set) } export function makeSeriesForLogs(rows: LogRow[], intervalMs: number): TimeSeries[] { + // currently interval is rangeMs / resolution, which is too low for showing series as bars. + // need at least 10px per bucket, so we multiply interval by 10. Should be solved higher up the chain + // when executing queries & interval calculated and not here but this is a temporary fix. + // intervalMs = intervalMs * 10; + // Graph time series by log level const seriesByLevel = {}; - rows.forEach(row => { + const bucketSize = intervalMs * 10; + + for (const row of rows) { if (!seriesByLevel[row.logLevel]) { seriesByLevel[row.logLevel] = { lastTs: null, datapoints: [], alias: row.logLevel }; } + const levelSeries = seriesByLevel[row.logLevel]; // Bucket to nearest minute - const time = Math.round(row.timeEpochMs / intervalMs / 10) * intervalMs * 10; + const time = Math.round(row.timeEpochMs / bucketSize) * bucketSize; + // Entry for time if (time === levelSeries.lastTs) { levelSeries.datapoints[levelSeries.datapoints.length - 1][0]++; @@ -187,7 +196,7 @@ export function makeSeriesForLogs(rows: LogRow[], intervalMs: number): TimeSerie levelSeries.datapoints.push([1, time]); levelSeries.lastTs = time; } - }); + } return Object.keys(seriesByLevel).reduce((acc, level) => { if (seriesByLevel[level]) { diff --git a/public/app/core/utils/explore.ts b/public/app/core/utils/explore.ts index e268508b833..26b6a527d95 100644 --- a/public/app/core/utils/explore.ts +++ b/public/app/core/utils/explore.ts @@ -1,15 +1,15 @@ import _ from 'lodash'; import { renderUrl } from 'app/core/utils/url'; -import { ExploreState, ExploreUrlState, HistoryItem, QueryTransaction } from 'app/types/explore'; -import { DataQuery, RawTimeRange } from 'app/types/series'; - -import TableModel, { mergeTablesIntoModel } from 'app/core/table_model'; import kbn from 'app/core/utils/kbn'; -import colors from 'app/core/utils/colors'; -import TimeSeries from 'app/core/time_series2'; -import { parse as parseDate } from 'app/core/utils/datemath'; import store from 'app/core/store'; +import colors from 'app/core/utils/colors'; +import { parse as parseDate } from 'app/core/utils/datemath'; + +import TimeSeries from 'app/core/time_series2'; +import TableModel, { mergeTablesIntoModel } from 'app/core/table_model'; +import { ExploreState, ExploreUrlState, HistoryItem, QueryTransaction } from 'app/types/explore'; +import { DataQuery, RawTimeRange, IntervalValues, DataSourceApi } from 'app/types/series'; export const DEFAULT_RANGE = { from: 'now-6h', @@ -170,18 +170,16 @@ export function calculateResultsFromQueryTransactions( }; } -export function getIntervals( - range: RawTimeRange, - datasource, - resolution: number -): { interval: string; intervalMs: number } { +export function getIntervals(range: RawTimeRange, datasource: DataSourceApi, resolution: number): IntervalValues { if (!datasource || !resolution) { return { interval: '1s', intervalMs: 1000 }; } + const absoluteRange: RawTimeRange = { from: parseDate(range.from, false), to: parseDate(range.to, true), }; + return kbn.calculateInterval(absoluteRange, resolution, datasource.interval); } diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index 3a584cd5664..43233dce6f5 100644 --- a/public/app/features/explore/Logs.tsx +++ b/public/app/features/explore/Logs.tsx @@ -24,6 +24,7 @@ const PREVIEW_LIMIT = 100; const graphOptions = { series: { + stack: true, bars: { show: true, lineWidth: 5, diff --git a/public/app/types/index.ts b/public/app/types/index.ts index 3bf6b4c9803..30af6549097 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -19,6 +19,7 @@ import { DataQuery, DataQueryResponse, DataQueryOptions, + IntervalValues, } from './series'; import { PanelProps, PanelOptionsProps } from './panel'; import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins'; @@ -87,6 +88,7 @@ export { AppNotificationTimeout, DashboardSearchHit, UserState, + IntervalValues, }; export interface StoreState { diff --git a/public/app/types/series.ts b/public/app/types/series.ts index 18ebbc5f648..7d7d00b1a60 100644 --- a/public/app/types/series.ts +++ b/public/app/types/series.ts @@ -19,6 +19,11 @@ export interface TimeRange { raw: RawTimeRange; } +export interface IntervalValues { + interval: string; // 10s,5m + intervalMs: number; +} + export type TimeSeriesValue = string | number | null; export type TimeSeriesPoints = TimeSeriesValue[][]; @@ -89,6 +94,11 @@ export interface DataQueryOptions { } export interface DataSourceApi { + /** + * min interval range + */ + interval?: string; + /** * Imports queries from a different datasource */ @@ -97,6 +107,14 @@ export interface DataSourceApi { * Initializes a datasource after instantiation */ init?: () => void; + + /** + * Main data query method + */ query(options: DataQueryOptions): Promise; + + /** + * test data source + */ testDatasource?: () => Promise; }