Commit 7cac7435 by Hugo Häggmark Committed by GitHub

Explore: Displays only one Time column as configured in TimeZone settings (#17775)

* Refactor: Removes switches for TimeStamp and LocalTime and displays time as configured for user

* Styles: Updates classname used to display timeUtc

* Refactor: Adds switch for Time column
parent 8541214c
......@@ -46,6 +46,7 @@ export interface LogRowModel {
timeFromNow: string;
timeEpochMs: number;
timeLocal: string;
timeUtc: string;
uniqueLabels?: Labels;
}
......
......@@ -24,7 +24,7 @@ import {
} from '@grafana/ui';
import { getThemeColor } from 'app/core/utils/colors';
import { hasAnsiCodes } from 'app/core/utils/text';
import { dateTime } from '@grafana/ui/src/utils/moment_wrapper';
import { dateTime, toUtc } from '@grafana/ui/src/utils/moment_wrapper';
export const LogLevelColor = {
[LogLevel.critical]: colors[7],
......@@ -369,6 +369,7 @@ export function processLogSeriesRow(
const timeEpochMs = time.valueOf();
const timeFromNow = time.fromNow();
const timeLocal = time.format('YYYY-MM-DD HH:mm:ss');
const timeUtc = toUtc(ts).format('YYYY-MM-DD HH:mm:ss');
let logLevel = LogLevel.unknown;
const logLevelField = fieldCache.getFieldByName('level');
......@@ -388,6 +389,7 @@ export function processLogSeriesRow(
timeFromNow,
timeEpochMs,
timeLocal,
timeUtc,
uniqueLabels,
hasAnsi,
searchWords,
......
......@@ -8,6 +8,7 @@ import {
LinkButton,
LogsModel,
LogRowModel,
TimeZone,
} from '@grafana/ui';
import ElapsedTime from './ElapsedTime';
......@@ -42,6 +43,7 @@ const getStyles = (theme: GrafanaTheme) => ({
export interface Props extends Themeable {
logsResult?: LogsModel;
timeZone: TimeZone;
stopLive: () => void;
}
......@@ -73,10 +75,11 @@ class LiveLogs extends PureComponent<Props, State> {
}
render() {
const { theme } = this.props;
const { theme, timeZone } = this.props;
const { renderCount } = this.state;
const styles = getStyles(theme);
const rowsToRender: LogRowModel[] = this.props.logsResult ? this.props.logsResult.rows : [];
const showUtc = timeZone === 'utc';
return (
<>
......@@ -87,9 +90,16 @@ class LiveLogs extends PureComponent<Props, State> {
className={row.fresh ? cx(['logs-row', styles.logsRowFresh]) : cx(['logs-row', styles.logsRowOld])}
key={`${row.timeEpochMs}-${index}`}
>
<div className="logs-row__localtime" title={`${row.timestamp} (${row.timeFromNow})`}>
{row.timeLocal}
</div>
{showUtc && (
<div className="logs-row__localtime" title={`Local: ${row.timeLocal} (${row.timeFromNow})`}>
{row.timeUtc}
</div>
)}
{!showUtc && (
<div className="logs-row__localtime" title={`${row.timeUtc} (${row.timeFromNow})`}>
{row.timeLocal}
</div>
)}
<div className="logs-row__message">{row.entry}</div>
</div>
);
......
......@@ -23,6 +23,7 @@ import {
LogRowModel,
LogLabelStatsModel,
LogsParser,
TimeZone,
} from '@grafana/ui';
import { LogRowContext } from './LogRowContext';
import tinycolor from 'tinycolor2';
......@@ -32,8 +33,8 @@ interface Props {
row: LogRowModel;
showDuplicates: boolean;
showLabels: boolean;
showLocalTime: boolean;
showUtc: boolean;
showTime: boolean;
timeZone: TimeZone;
getRows: () => LogRowModel[];
onClickLabel?: (label: string, value: string) => void;
onContextClick?: () => void;
......@@ -209,8 +210,8 @@ export class LogRow extends PureComponent<Props, State> {
row,
showDuplicates,
showLabels,
showLocalTime,
showUtc,
timeZone,
showTime,
} = this.props;
const {
fieldCount,
......@@ -229,6 +230,7 @@ export class LogRow extends PureComponent<Props, State> {
const highlightClassName = classnames('logs-row__match-highlight', {
'logs-row__match-highlight--preview': previewHighlights,
});
const showUtc = timeZone === 'utc';
return (
<ThemeContext.Consumer>
......@@ -242,13 +244,13 @@ export class LogRow extends PureComponent<Props, State> {
<div className="logs-row__duplicates">{row.duplicates > 0 ? `${row.duplicates + 1}x` : null}</div>
)}
<div className={row.logLevel ? `logs-row__level logs-row__level--${row.logLevel}` : ''} />
{showUtc && (
<div className="logs-row__time" title={`Local: ${row.timeLocal} (${row.timeFromNow})`}>
{row.timestamp}
{showTime && showUtc && (
<div className="logs-row__localtime" title={`Local: ${row.timeLocal} (${row.timeFromNow})`}>
{row.timeUtc}
</div>
)}
{showLocalTime && (
<div className="logs-row__localtime" title={`${row.timestamp} (${row.timeFromNow})`}>
{showTime && !showUtc && (
<div className="logs-row__localtime" title={`${row.timeUtc} (${row.timeFromNow})`}>
{row.timeLocal}
</div>
)}
......
......@@ -76,8 +76,7 @@ interface State {
deferLogs: boolean;
renderAll: boolean;
showLabels: boolean;
showLocalTime: boolean;
showUtc: boolean;
showTime: boolean;
}
export default class Logs extends PureComponent<Props, State> {
......@@ -88,8 +87,7 @@ export default class Logs extends PureComponent<Props, State> {
deferLogs: true,
renderAll: false,
showLabels: false,
showLocalTime: true,
showUtc: false,
showTime: true,
};
componentDidMount() {
......@@ -130,17 +128,10 @@ export default class Logs extends PureComponent<Props, State> {
});
};
onChangeLocalTime = (event: React.SyntheticEvent) => {
onChangeTime = (event: React.SyntheticEvent) => {
const target = event.target as HTMLInputElement;
this.setState({
showLocalTime: target.checked,
});
};
onChangeUtc = (event: React.SyntheticEvent) => {
const target = event.target as HTMLInputElement;
this.setState({
showUtc: target.checked,
showTime: target.checked,
});
};
......@@ -178,7 +169,7 @@ export default class Logs extends PureComponent<Props, State> {
return null;
}
const { deferLogs, renderAll, showLabels, showLocalTime, showUtc } = this.state;
const { deferLogs, renderAll, showLabels, showTime } = this.state;
const { dedupStrategy } = this.props;
const hasData = data && data.rows && data.rows.length > 0;
const hasLabel = hasData && dedupedData.hasUniqueLabels;
......@@ -223,8 +214,7 @@ export default class Logs extends PureComponent<Props, State> {
</div>
<div className="logs-panel-options">
<div className="logs-panel-controls">
<Switch label="Timestamp" checked={showUtc} onChange={this.onChangeUtc} transparent />
<Switch label="Local time" checked={showLocalTime} onChange={this.onChangeLocalTime} transparent />
<Switch label="Time" checked={showTime} onChange={this.onChangeTime} transparent />
<Switch label="Labels" checked={showLabels} onChange={this.onChangeLabels} transparent />
<ToggleButtonGroup label="Dedup" transparent={true}>
{Object.keys(LogsDedupStrategy).map((dedupType, i) => (
......@@ -265,8 +255,8 @@ export default class Logs extends PureComponent<Props, State> {
row={row}
showDuplicates={showDuplicates}
showLabels={showLabels && hasLabel}
showLocalTime={showLocalTime}
showUtc={showUtc}
showTime={showTime}
timeZone={timeZone}
onClickLabel={onClickLabel}
/>
))}
......@@ -281,8 +271,8 @@ export default class Logs extends PureComponent<Props, State> {
row={row}
showDuplicates={showDuplicates}
showLabels={showLabels && hasLabel}
showLocalTime={showLocalTime}
showUtc={showUtc}
showTime={showTime}
timeZone={timeZone}
onClickLabel={onClickLabel}
/>
))}
......
......@@ -116,7 +116,7 @@ export class LogsContainer extends Component<LogsContainerProps> {
if (isLive) {
return (
<Panel label="Logs" loading={false} isOpen>
<LiveLogsWithTheme logsResult={logsResult} stopLive={this.onStopLive} />
<LiveLogsWithTheme logsResult={logsResult} timeZone={timeZone} stopLive={this.onStopLive} />
</Panel>
);
}
......
......@@ -6,6 +6,11 @@ jest.mock('@grafana/ui/src/utils/moment_wrapper', () => ({
format: (fmt: string) => 'format() jest mocked',
};
},
toUtc: (ts: any) => {
return {
format: (fmt: string) => 'format() jest mocked',
};
},
}));
import { ResultProcessor } from './ResultProcessor';
......@@ -178,6 +183,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1559038519831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1559038519831,
uniqueLabels: {},
},
......@@ -191,6 +197,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1559038518831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1559038518831,
uniqueLabels: {},
},
......@@ -321,6 +328,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1558038519831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1558038519831,
uniqueLabels: {},
},
......@@ -335,6 +343,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1558038518831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1558038518831,
uniqueLabels: {},
},
......@@ -375,6 +384,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1558038519831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1558038519831,
uniqueLabels: {},
},
......@@ -389,6 +399,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1558038518831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1558038518831,
uniqueLabels: {},
},
......@@ -403,6 +414,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1559038519831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1559038519831,
uniqueLabels: {},
},
......@@ -417,6 +429,7 @@ describe('ResultProcessor', () => {
timeEpochMs: 1559038518831,
timeFromNow: 'fromNow() jest mocked',
timeLocal: 'format() jest mocked',
timeUtc: 'format() jest mocked',
timestamp: 1559038518831,
uniqueLabels: {},
},
......
......@@ -81,11 +81,6 @@ $column-horizontal-spacing: 10px;
}
}
.logs-row__time {
white-space: nowrap;
width: 19em;
}
.logs-row__localtime {
white-space: nowrap;
width: 12.5em;
......
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