From a5ed86edba52db8500234e9f8de2a62669473ebf Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Tue, 6 Nov 2018 12:00:05 +0100 Subject: [PATCH] Graph log entries by log level --- public/app/core/logs_model.ts | 15 ++++- public/app/core/utils/colors.ts | 20 +++--- .../datasource/logging/result_transformer.ts | 66 +++++++++++-------- 3 files changed, 62 insertions(+), 39 deletions(-) diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index ca7899db7d8..42c2e1ae453 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -1,5 +1,6 @@ import _ from 'lodash'; import { TimeSeries } from 'app/core/core'; +import colors from 'app/core/utils/colors'; export enum LogLevel { crit = 'crit', @@ -9,8 +10,20 @@ export enum LogLevel { info = 'info', debug = 'debug', trace = 'trace', + none = 'none', } +export const LogLevelColor = { + [LogLevel.crit]: colors[7], + [LogLevel.warn]: colors[1], + [LogLevel.err]: colors[4], + [LogLevel.error]: colors[4], + [LogLevel.info]: colors[0], + [LogLevel.debug]: colors[3], + [LogLevel.trace]: colors[3], + [LogLevel.none]: '#eee', +}; + export interface LogSearchMatch { start: number; length: number; @@ -44,7 +57,7 @@ export interface LogsStream { labels: string; entries: LogsStreamEntry[]; parsedLabels: { [key: string]: string }; - graphSeries: TimeSeries; + intervalMs?: number; } export interface LogsStreamEntry { diff --git a/public/app/core/utils/colors.ts b/public/app/core/utils/colors.ts index e8a7366beb5..16214679996 100644 --- a/public/app/core/utils/colors.ts +++ b/public/app/core/utils/colors.ts @@ -10,16 +10,16 @@ export const NO_DATA_COLOR = 'rgba(150, 150, 150, 1)'; export const REGION_FILL_ALPHA = 0.09; const colors = [ - '#7EB26D', - '#EAB839', - '#6ED0E0', - '#EF843C', - '#E24D42', - '#1F78C1', - '#BA43A9', - '#705DA0', - '#508642', - '#CCA300', + '#7EB26D', // 0: pale green + '#EAB839', // 1: mustard + '#6ED0E0', // 2: light blue + '#EF843C', // 3: orange + '#E24D42', // 4: red + '#1F78C1', // 5: ocean + '#BA43A9', // 6: purple + '#705DA0', // 7: violet + '#508642', // 8: dark green + '#CCA300', // 9: dark sand '#447EBC', '#C15C17', '#890F02', diff --git a/public/app/plugins/datasource/logging/result_transformer.ts b/public/app/plugins/datasource/logging/result_transformer.ts index e1e622aeb59..61c0feb493c 100644 --- a/public/app/plugins/datasource/logging/result_transformer.ts +++ b/public/app/plugins/datasource/logging/result_transformer.ts @@ -1,13 +1,12 @@ import _ from 'lodash'; import moment from 'moment'; -import { LogLevel, LogsMetaItem, LogsModel, LogRow, LogsStream } from 'app/core/logs_model'; +import { LogLevel, LogLevelColor, LogsMetaItem, LogsModel, LogRow, LogsStream } from 'app/core/logs_model'; import { TimeSeries } from 'app/core/core'; -import colors from 'app/core/utils/colors'; export function getLogLevel(line: string): LogLevel { if (!line) { - return undefined; + return LogLevel.none; } let level: LogLevel; Object.keys(LogLevel).forEach(key => { @@ -18,6 +17,9 @@ export function getLogLevel(line: string): LogLevel { } } }); + if (!level) { + level = LogLevel.none; + } return level; } @@ -107,8 +109,13 @@ export function mergeStreams(streams: LogsStream[], limit?: number): LogsModel { }, ]; + let intervalMs; + // Flatten entries of streams - const combinedEntries = streams.reduce((acc, stream) => { + const combinedEntries: LogRow[] = streams.reduce((acc, stream) => { + // Set interval for graphs + intervalMs = stream.intervalMs; + // Overwrite labels to be only the non-common ones const labels = formatLabels(findUncommonLabels(stream.parsedLabels, commonLabels)); return [ @@ -120,15 +127,34 @@ export function mergeStreams(streams: LogsStream[], limit?: number): LogsModel { ]; }, []); - const commonLabelsAlias = - streams.length === 1 ? formatLabels(commonLabels) : `Stream with common labels ${formatLabels(commonLabels)}`; - const series = streams.map((stream, index) => { - const colorIndex = index % colors.length; - stream.graphSeries.setColor(colors[colorIndex]); - stream.graphSeries.alias = formatLabels(findUncommonLabels(stream.parsedLabels, commonLabels), commonLabelsAlias); - return stream.graphSeries; + // Graph time series by log level + const seriesByLevel = {}; + combinedEntries.forEach(entry => { + if (!seriesByLevel[entry.logLevel]) { + seriesByLevel[entry.logLevel] = { lastTs: null, datapoints: [], alias: entry.logLevel }; + } + const levelSeries = seriesByLevel[entry.logLevel]; + + // Bucket to nearest minute + const time = Math.round(entry.timeJs / intervalMs / 10) * intervalMs * 10; + // Entry for time + if (time === levelSeries.lastTs) { + levelSeries.datapoints[levelSeries.datapoints.length - 1][0]++; + } else { + levelSeries.datapoints.push([1, time]); + levelSeries.lastTs = time; + } }); + const series = Object.keys(seriesByLevel).reduce((acc, level, index) => { + if (seriesByLevel[level]) { + const gs = new TimeSeries(seriesByLevel[level]); + gs.setColor(LogLevelColor[level]); + acc.push(gs); + } + return acc; + }, []); + const sortedEntries = _.chain(combinedEntries) .sortBy('timestamp') .reverse() @@ -151,25 +177,9 @@ export function processStream(stream: LogsStream, limit?: number, intervalMs?: n .slice(0, limit || stream.entries.length) .value(); - // Build graph data - let previousTime; - const datapoints = sortedEntries.reduce((acc, entry, index) => { - // Bucket to nearest minute - const time = Math.round(entry.timeJs / intervalMs / 10) * intervalMs * 10; - // Entry for time - if (time === previousTime) { - acc[acc.length - 1][0]++; - } else { - acc.push([1, time]); - previousTime = time; - } - return acc; - }, []); - const graphSeries = new TimeSeries({ datapoints, alias: stream.labels }); - return { ...stream, - graphSeries, + intervalMs, entries: sortedEntries, parsedLabels: parseLabels(stream.labels), };