mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Unification of logs/metrics/traces user interface (#25890)
Removes "Metrics"/"Logs" mode switcher from Explore, allowing for both metrics and logs queries at the same time. Co-authored-by: kay delaney <kay@grafana.com>
This commit is contained in:
@@ -32,7 +32,6 @@ import {
|
||||
import { getThemeColor } from 'app/core/utils/colors';
|
||||
|
||||
import { sortInAscendingOrder, deduplicateLogRowsById } from 'app/core/utils/explore';
|
||||
import { getGraphSeriesModel } from 'app/plugins/panel/graph2/getGraphSeriesModel';
|
||||
import { decimalSIPrefix } from '@grafana/data/src/valueFormats/symbolFormatters';
|
||||
|
||||
export const LogLevelColor = {
|
||||
@@ -143,19 +142,23 @@ export function makeSeriesForLogs(sortedRows: LogRowModel[], bucketSize: number,
|
||||
const fieldCache = new FieldCache(data);
|
||||
|
||||
const timeField = fieldCache.getFirstFieldOfType(FieldType.time);
|
||||
timeField.display = getDisplayProcessor({
|
||||
field: timeField,
|
||||
timeZone,
|
||||
});
|
||||
if (timeField) {
|
||||
timeField.display = getDisplayProcessor({
|
||||
field: timeField,
|
||||
timeZone,
|
||||
});
|
||||
}
|
||||
|
||||
const valueField = fieldCache.getFirstFieldOfType(FieldType.number);
|
||||
valueField.config = {
|
||||
...valueField.config,
|
||||
color: series.color,
|
||||
};
|
||||
valueField.name = series.alias;
|
||||
const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone });
|
||||
valueField.display = (value: any) => ({ ...fieldDisplayProcessor(value), color: series.color });
|
||||
if (valueField) {
|
||||
valueField.config = {
|
||||
...valueField.config,
|
||||
color: series.color,
|
||||
};
|
||||
valueField.name = series.alias;
|
||||
const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone });
|
||||
valueField.display = (value: any) => ({ ...fieldDisplayProcessor(value), color: series.color });
|
||||
}
|
||||
|
||||
const points = getFlotPairs({
|
||||
xField: timeField,
|
||||
@@ -201,35 +204,21 @@ export function dataFrameToLogsModel(
|
||||
timeZone: TimeZone,
|
||||
absoluteRange?: AbsoluteTimeRange
|
||||
): LogsModel {
|
||||
const { logSeries, metricSeries } = separateLogsAndMetrics(dataFrame);
|
||||
const { logSeries } = separateLogsAndMetrics(dataFrame);
|
||||
const logsModel = logSeriesToLogsModel(logSeries);
|
||||
|
||||
// unification: Removed logic for using metrics data in LogsModel as with the unification changes this would result
|
||||
// in the incorrect data being used. Instead logs series are always derived from logs.
|
||||
if (logsModel) {
|
||||
if (metricSeries.length === 0) {
|
||||
// Create histogram metrics from logs using the interval as bucket size for the line count
|
||||
if (intervalMs && logsModel.rows.length > 0) {
|
||||
const sortedRows = logsModel.rows.sort(sortInAscendingOrder);
|
||||
const { visibleRange, bucketSize } = getSeriesProperties(sortedRows, intervalMs, absoluteRange);
|
||||
logsModel.visibleRange = visibleRange;
|
||||
logsModel.series = makeSeriesForLogs(sortedRows, bucketSize, timeZone);
|
||||
} else {
|
||||
logsModel.series = [];
|
||||
}
|
||||
// Create histogram metrics from logs using the interval as bucket size for the line count
|
||||
if (intervalMs && logsModel.rows.length > 0) {
|
||||
const sortedRows = logsModel.rows.sort(sortInAscendingOrder);
|
||||
const { visibleRange, bucketSize } = getSeriesProperties(sortedRows, intervalMs, absoluteRange);
|
||||
logsModel.visibleRange = visibleRange;
|
||||
logsModel.series = makeSeriesForLogs(sortedRows, bucketSize, timeZone);
|
||||
} else {
|
||||
// We got metrics in the dataFrame so process those
|
||||
logsModel.series = getGraphSeriesModel(
|
||||
metricSeries,
|
||||
timeZone,
|
||||
{},
|
||||
{ showBars: true, showLines: false, showPoints: false },
|
||||
{
|
||||
asTable: false,
|
||||
isVisible: true,
|
||||
placement: 'under',
|
||||
}
|
||||
);
|
||||
logsModel.series = [];
|
||||
}
|
||||
|
||||
return logsModel;
|
||||
}
|
||||
|
||||
@@ -431,8 +420,8 @@ export function logSeriesToLogsModel(logSeries: DataFrame[]): LogsModel | undefi
|
||||
// Stats are per query, keeping track by refId
|
||||
const { refId } = series;
|
||||
if (refId && !queriesVisited[refId]) {
|
||||
if (totalBytesKey && series.meta.stats) {
|
||||
const byteStat = series.meta.stats.find(stat => stat.displayName === totalBytesKey);
|
||||
if (totalBytesKey && series.meta?.stats) {
|
||||
const byteStat = series.meta?.stats.find(stat => stat.displayName === totalBytesKey);
|
||||
if (byteStat) {
|
||||
totalBytes += byteStat.value;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import store from 'app/core/store';
|
||||
import {
|
||||
DataQueryError,
|
||||
dateTime,
|
||||
ExploreMode,
|
||||
LogLevel,
|
||||
LogRowModel,
|
||||
LogsDedupStrategy,
|
||||
@@ -33,7 +32,6 @@ const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
|
||||
datasource: '',
|
||||
queries: [],
|
||||
range: DEFAULT_RANGE,
|
||||
mode: ExploreMode.Metrics,
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingTable: true,
|
||||
@@ -101,7 +99,6 @@ describe('state functions', () => {
|
||||
expect(serializeStateToUrlParam(state)).toBe(
|
||||
'{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
|
||||
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"},' +
|
||||
'"mode":"Metrics",' +
|
||||
'"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true,"dedupStrategy":"none"}}'
|
||||
);
|
||||
});
|
||||
@@ -124,7 +121,7 @@ describe('state functions', () => {
|
||||
},
|
||||
};
|
||||
expect(serializeStateToUrlParam(state, true)).toBe(
|
||||
'["now-5h","now","foo",{"expr":"metric{test=\\"a/b\\"}"},{"expr":"super{foo=\\"x/z\\"}"},{"mode":"Metrics"},{"ui":[true,true,true,"none"]}]'
|
||||
'["now-5h","now","foo",{"expr":"metric{test=\\"a/b\\"}"},{"expr":"super{foo=\\"x/z\\"}"},{"ui":[true,true,true,"none"]}]'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
DataSourceApi,
|
||||
dateMath,
|
||||
DefaultTimeZone,
|
||||
ExploreMode,
|
||||
HistoryItem,
|
||||
IntervalValues,
|
||||
LogRowModel,
|
||||
@@ -249,9 +248,6 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
const metricProperties = ['expr', 'expression', 'target', 'datasource', 'query'];
|
||||
const queries = parsedSegments.filter(segment => isSegment(segment, ...metricProperties));
|
||||
|
||||
const modeObj = parsedSegments.filter(segment => isSegment(segment, 'mode'))[0];
|
||||
const mode = modeObj ? modeObj.mode : ExploreMode.Metrics;
|
||||
|
||||
const uiState = parsedSegments.filter(segment => isSegment(segment, 'ui'))[0];
|
||||
const ui = uiState
|
||||
? {
|
||||
@@ -263,7 +259,7 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
: DEFAULT_UI_STATE;
|
||||
|
||||
const originPanelId = parsedSegments.filter(segment => isSegment(segment, 'originPanelId'))[0];
|
||||
return { datasource, queries, range, ui, mode, originPanelId };
|
||||
return { datasource, queries, range, ui, originPanelId };
|
||||
}
|
||||
|
||||
export function generateKey(index = 0): string {
|
||||
|
||||
@@ -2,15 +2,7 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
// Services & Utils
|
||||
import {
|
||||
DataQuery,
|
||||
DataSourceApi,
|
||||
ExploreMode,
|
||||
dateTimeFormat,
|
||||
AppEvents,
|
||||
urlUtil,
|
||||
ExploreUrlState,
|
||||
} from '@grafana/data';
|
||||
import { DataQuery, DataSourceApi, dateTimeFormat, AppEvents, urlUtil, ExploreUrlState } from '@grafana/data';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import store from 'app/core/store';
|
||||
import { SortOrder } from './explore';
|
||||
@@ -187,15 +179,6 @@ export const createUrlFromRichHistory = (query: RichHistoryQuery) => {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
datasource: query.datasourceName,
|
||||
queries: query.queries,
|
||||
/* Default mode is metrics. Exceptions are Loki (logs) and Jaeger (tracing) data sources.
|
||||
* In the future, we can remove this as we are working on metrics & logs logic.
|
||||
**/
|
||||
mode:
|
||||
query.datasourceId === 'loki'
|
||||
? ExploreMode.Logs
|
||||
: query.datasourceId === 'jaeger'
|
||||
? ExploreMode.Tracing
|
||||
: ExploreMode.Metrics,
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingLogs: true,
|
||||
|
||||
Reference in New Issue
Block a user