Commit a5ed86ed by David Kaltschmidt

Graph log entries by log level

parent e39e8294
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 {
......
......@@ -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',
......
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),
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment