Skip to content

Commit

Permalink
Merge pull request #4097 from influxdata/feature/add-logviewer-trunca…
Browse files Browse the repository at this point in the history
…tion

Add log viewer truncation option
  • Loading branch information
OfTheDelmer committed Aug 7, 2018
2 parents 480f24c + 38da28a commit c242699
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 15 deletions.
36 changes: 33 additions & 3 deletions ui/src/logs/components/LogsTable.tsx
Expand Up @@ -13,6 +13,7 @@ import {colorForSeverity} from 'src/logs/utils/colors'
import {
ROW_HEIGHT,
calculateRowCharWidth,
calculateMessageHeight,
getColumnFromData,
getValueFromData,
getValuesFromData,
Expand All @@ -36,12 +37,14 @@ import {
LogsTableColumn,
SeverityFormat,
SeverityLevelColor,
RowHeightHandler,
} from 'src/types/logs'
import {INITIAL_LIMIT} from 'src/logs/actions'

interface Props {
data: TableData
isScrolledToTop: boolean
isTruncated: boolean
onScrollVertical: () => void
onScrolledToTop: () => void
onTagSelection: (selection: {tag: string; key: string}) => void
Expand Down Expand Up @@ -237,7 +240,6 @@ class LogsTable extends Component<Props, State> {
autoHide={false}
>
<Grid
rowHeight={ROW_HEIGHT}
{...this.gridProperties(
width,
height,
Expand Down Expand Up @@ -268,9 +270,17 @@ class LogsTable extends Component<Props, State> {
) => {
const {scrollToRow} = this.props
const {scrollLeft, scrollTop} = this.state

let rowHeight: number | RowHeightHandler = ROW_HEIGHT

if (!this.props.isTruncated) {
rowHeight = this.calculateRowHeight
}

const result: any = {
width,
height,
rowHeight,
rowCount: this.rowCount(),
scrollLeft,
scrollTop,
Expand Down Expand Up @@ -447,7 +457,24 @@ class LogsTable extends Component<Props, State> {
private calculateTotalHeight = (): number => {
const data = getValuesFromData(this.props.data)

return data.length * ROW_HEIGHT
if (this.props.isTruncated) {
return data.length * ROW_HEIGHT
}

return _.reduce(
data,
(acc, __, index) => {
return (
acc +
calculateMessageHeight(index, this.props.data, this.rowCharLimit)
)
},
0
)
}

private calculateRowHeight = ({index}: {index: number}): number => {
return calculateMessageHeight(index, this.props.data, this.rowCharLimit)
}

private headerRenderer = ({key, style, columnIndex}) => {
Expand Down Expand Up @@ -515,7 +542,7 @@ class LogsTable extends Component<Props, State> {
title = formattedValue
}

if (column === 'message') {
if (column === 'message' && this.props.isTruncated) {
formattedValue = (
<ExpandableMessage
formattedValue={formattedValue}
Expand Down Expand Up @@ -578,10 +605,13 @@ class LogsTable extends Component<Props, State> {
)
}

const wrapMessage = column === 'message' && !this.props.isTruncated

return (
<div
className={classnames(`logs-viewer--cell ${column}--cell`, {
highlight: highlightRow,
'message-wrap': wrapMessage,
})}
key={key}
style={style}
Expand Down
82 changes: 74 additions & 8 deletions ui/src/logs/components/OptionsOverlay.tsx
Expand Up @@ -12,23 +12,29 @@ import {
SeverityFormat,
LogsTableColumn,
} from 'src/types/logs'
import SlideToggle from 'src/reusable_ui/components/slide_toggle/SlideToggle'
import {DEFAULT_SEVERITY_LEVELS, SeverityLevelOptions} from 'src/logs/constants'
import {ErrorHandling} from 'src/shared/decorators/errors'

interface Props {
severityLevelColors: SeverityLevelColor[]
onUpdateSeverityLevels: (severityLevelColors: SeverityLevelColor[]) => void
onUpdateSeverityLevels: (
severityLevelColors: SeverityLevelColor[]
) => Promise<void>
onDismissOverlay: () => void
columns: LogsTableColumn[]
onUpdateColumns: (columns: LogsTableColumn[]) => void
onUpdateColumns: (columns: LogsTableColumn[]) => Promise<void>
severityFormat: SeverityFormat
onUpdateSeverityFormat: (format: SeverityFormat) => void
onUpdateSeverityFormat: (format: SeverityFormat) => Promise<void>
onUpdateTruncation: (isTruncated: boolean) => Promise<void>
isTruncated: boolean
}

interface State {
workingLevelColumns: SeverityLevelColor[]
workingColumns: LogsTableColumn[]
workingFormat: SeverityFormat
isWorkingTruncated: boolean
}

@ErrorHandling
Expand All @@ -40,10 +46,14 @@ class OptionsOverlay extends Component<Props, State> {
workingLevelColumns: this.props.severityLevelColors,
workingColumns: this.props.columns,
workingFormat: this.props.severityFormat,
isWorkingTruncated: this.props.isTruncated,
}
}

public shouldComponentUpdate(__, nextState: State) {
const isTruncatedDifferent =
nextState.isWorkingTruncated !== this.state.isWorkingTruncated

const isColorsDifferent = !_.isEqual(
nextState.workingLevelColumns,
this.state.workingLevelColumns
Expand All @@ -56,7 +66,13 @@ class OptionsOverlay extends Component<Props, State> {
nextState.workingColumns,
this.state.workingColumns
)
if (isColorsDifferent || isFormatDifferent || isColumnsDifferent) {

if (
isTruncatedDifferent ||
isColorsDifferent ||
isFormatDifferent ||
isColumnsDifferent
) {
return true
}
return false
Expand All @@ -81,6 +97,7 @@ class OptionsOverlay extends Component<Props, State> {
onChangeSeverityFormat={this.handleChangeSeverityFormat}
/>
</div>
<div className="col-sm-7">{this.renderTruncateOption}</div>
<div className="col-sm-7">
<ColumnsOptions
columns={workingColumns}
Expand Down Expand Up @@ -113,15 +130,57 @@ class OptionsOverlay extends Component<Props, State> {
)
}

private get renderTruncateOption() {
const {isWorkingTruncated} = this.state

let labelMessage = 'Truncate Log Lines'

if (isWorkingTruncated) {
labelMessage = 'Show Log Lines'
}

return (
<>
<label className="form-label">{labelMessage}</label>
<SlideToggle
onChange={this.handleTruncationToggle}
active={isWorkingTruncated}
/>
</>
)
}

private handleTruncationToggle = (): void => {
const {isWorkingTruncated} = this.state

this.setState({isWorkingTruncated: !isWorkingTruncated})
}

private get isSaveDisabled(): boolean {
const {workingLevelColumns, workingColumns, workingFormat} = this.state
const {severityLevelColors, columns, severityFormat} = this.props
const {
workingLevelColumns,
workingColumns,
workingFormat,
isWorkingTruncated,
} = this.state
const {
severityLevelColors,
columns,
severityFormat,
isTruncated,
} = this.props

const severityChanged = !_.isEqual(workingLevelColumns, severityLevelColors)
const columnsChanged = !_.isEqual(workingColumns, columns)
const formatChanged = !_.isEqual(workingFormat, severityFormat)
const isTruncatedChanged = isWorkingTruncated !== isTruncated

if (severityChanged || columnsChanged || formatChanged) {
if (
severityChanged ||
columnsChanged ||
formatChanged ||
isTruncatedChanged
) {
return false
}

Expand All @@ -134,12 +193,19 @@ class OptionsOverlay extends Component<Props, State> {
onDismissOverlay,
onUpdateSeverityFormat,
onUpdateColumns,
onUpdateTruncation,
} = this.props
const {workingLevelColumns, workingFormat, workingColumns} = this.state
const {
workingLevelColumns,
workingFormat,
workingColumns,
isWorkingTruncated,
} = this.state

await onUpdateSeverityFormat(workingFormat)
await onUpdateSeverityLevels(workingLevelColumns)
await onUpdateColumns(workingColumns)
await onUpdateTruncation(isWorkingTruncated)
onDismissOverlay()
}

Expand Down
2 changes: 2 additions & 0 deletions ui/src/logs/constants/index.ts
Expand Up @@ -21,6 +21,8 @@ export enum SeverityColorOptions {
pearl = 'pearl',
}

export const DEFAULT_TRUNCATION = true

export const SeverityColorValues = {
[SeverityColorOptions.ruby]: '#BF3D5E',
[SeverityColorOptions.fire]: '#DC4E58',
Expand Down
18 changes: 18 additions & 0 deletions ui/src/logs/containers/LogsPage.tsx
Expand Up @@ -204,6 +204,7 @@ class LogsPage extends Component<Props, State> {
onScrollVertical={this.handleVerticalScroll}
onScrolledToTop={this.handleScrollToTop}
isScrolledToTop={false}
isTruncated={this.isTruncated}
onTagSelection={this.handleTagSelection}
fetchMore={this.props.fetchOlderLogsAsync}
fetchNewer={this.fetchNewer}
Expand Down Expand Up @@ -606,6 +607,8 @@ class LogsPage extends Component<Props, State> {
onUpdateColumns={this.handleUpdateColumns}
onUpdateSeverityFormat={this.handleUpdateSeverityFormat}
severityFormat={this.severityFormat}
onUpdateTruncation={this.handleUpdateTruncation}
isTruncated={this.isTruncated}
/>
</OverlayTechnology>
)
Expand Down Expand Up @@ -650,6 +653,21 @@ class LogsPage extends Component<Props, State> {
tableColumns,
})
}

private handleUpdateTruncation = async (
isTruncated: boolean
): Promise<void> => {
const {logConfig} = this.props

await this.props.updateConfig(this.logConfigLink, {
...logConfig,
isTruncated,
})
}

private get isTruncated(): boolean {
return this.props.logConfig.isTruncated
}
}

const mapStateToProps = ({
Expand Down
6 changes: 4 additions & 2 deletions ui/src/logs/reducers/index.ts
Expand Up @@ -13,7 +13,7 @@ import {
SetConfigsAction,
} from 'src/logs/actions'

import {SeverityFormatOptions} from 'src/logs/constants'
import {SeverityFormatOptions, DEFAULT_TRUNCATION} from 'src/logs/constants'
import {LogsState, TableData} from 'src/types/logs'

const defaultTableData: TableData = {
Expand Down Expand Up @@ -52,6 +52,7 @@ export const defaultState: LogsState = {
tableColumns: [],
severityFormat: SeverityFormatOptions.dotText,
severityLevelColors: [],
isTruncated: DEFAULT_TRUNCATION,
},
tableTime: {},
tableInfiniteData: {
Expand Down Expand Up @@ -165,13 +166,14 @@ const prependMoreLogs = (
export const setConfigs = (state: LogsState, action: SetConfigsAction) => {
const {logConfig} = state
const {
logConfig: {tableColumns, severityFormat, severityLevelColors},
logConfig: {tableColumns, severityFormat, severityLevelColors, isTruncated},
} = action.payload
const updatedLogConfig = {
...logConfig,
tableColumns,
severityFormat,
severityLevelColors,
isTruncated,
}
return {...state, logConfig: updatedLogConfig}
}
Expand Down
2 changes: 2 additions & 0 deletions ui/src/logs/utils/config.ts
Expand Up @@ -15,6 +15,7 @@ import {
EncodingTypes,
EncodingLabelOptions,
EncodingVisibilityOptions,
DEFAULT_TRUNCATION,
} from 'src/logs/constants'

export const logConfigServerToUI = (
Expand Down Expand Up @@ -42,6 +43,7 @@ export const logConfigServerToUI = (
tableColumns: convertedColumns,
severityFormat,
severityLevelColors,
isTruncated: DEFAULT_TRUNCATION,
}
}

Expand Down
4 changes: 2 additions & 2 deletions ui/src/logs/utils/table.ts
Expand Up @@ -105,9 +105,9 @@ export const calculateMessageHeight = (
return ROW_HEIGHT
}

const lines = Math.ceil(value.length / (rowCharLimit * 0.95))
const lines = Math.ceil(value.length / (rowCharLimit * 1.25))

return Math.max(lines, 1) * ROW_HEIGHT + 4
return Math.max(lines, 1) * ROW_HEIGHT + 2
}

export const getMessageWidth = (
Expand Down
4 changes: 4 additions & 0 deletions ui/src/style/pages/logs-viewer.scss
Expand Up @@ -248,6 +248,10 @@ $logs-viewer-gutter: 60px;
&.highlight {
color: $g20-white;
}

&.message-wrap {
word-break: break-all
}
}
.logs-viewer--cell-header {
font-weight: 600;
Expand Down
5 changes: 5 additions & 0 deletions ui/src/types/logs.ts
@@ -1,3 +1,5 @@
import {Index} from 'react-virtualized'

import {
SeverityFormatOptions,
SeverityColorOptions,
Expand Down Expand Up @@ -48,6 +50,7 @@ export interface LogConfig {
tableColumns: LogsTableColumn[]
severityFormat: SeverityFormat
severityLevelColors: SeverityLevelColor[]
isTruncated: boolean
}

export interface SeverityLevelColor {
Expand Down Expand Up @@ -127,3 +130,5 @@ export interface TimeWindow {
export interface TimeMarker {
timeOption: string
}

export type RowHeightHandler = (index: Index) => number

0 comments on commit c242699

Please sign in to comment.