Explore: Fix showing of full log context (#37442)

* Fix log context

* Update to auto values insted of unset

* Update comment

* Fix redundant left margin for non-wrapped logs

* Remove unused css styling

* Adjust width and height
This commit is contained in:
Ivana Huckova 2021-08-10 03:01:57 -04:00 committed by GitHub
parent 7e63118ea9
commit a02f9be0c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 20 deletions

View File

@ -4,7 +4,7 @@ import { css, cx } from '@emotion/css';
import { Alert } from '../Alert/Alert';
import { LogRowContextRows, LogRowContextQueryErrors, HasMoreContextRows } from './LogRowContextProvider';
import { useStyles } from '../../themes/ThemeContext';
import { useStyles, useTheme } from '../../themes/ThemeContext';
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
import { List } from '../List/List';
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
@ -13,18 +13,41 @@ import { LogMessageAnsi } from './LogMessageAnsi';
interface LogRowContextProps {
row: LogRowModel;
context: LogRowContextRows;
wrapLogMessage: boolean;
errors?: LogRowContextQueryErrors;
hasMoreContextRows?: HasMoreContextRows;
onOutsideClick: () => void;
onLoadMoreContext: () => void;
}
const getLogRowContextStyles = (theme: GrafanaTheme) => {
const getLogRowContextStyles = (theme: GrafanaTheme, wrapLogMessage?: boolean) => {
/**
* This is workaround for displaying uncropped context when we have unwrapping log messages.
* We are using margins to correctly position context. Because non-wrapped logs have always 1 line of log
* and 1 line of Show/Hide context switch. Therefore correct position can be reliably achieved by margins.
* We also adjust width to 75%.
*/
const afterContext = wrapLogMessage
? css`
top: -250px;
`
: css`
margin-top: -250px;
width: 75%;
`;
const beforeContext = wrapLogMessage
? css`
top: 100%;
`
: css`
margin-top: 40px;
width: 75%;
`;
return {
commonStyles: css`
position: absolute;
width: calc(100% + 20px);
left: -13px;
height: 250px;
z-index: ${theme.zIndex.dropdown};
overflow: hidden;
@ -32,6 +55,7 @@ const getLogRowContextStyles = (theme: GrafanaTheme) => {
box-shadow: 0 0 10px ${theme.colors.dropdownShadow};
border: 1px solid ${theme.colors.bg2};
border-radius: ${theme.border.radius.md};
width: 100%;
`,
header: css`
height: 30px;
@ -44,6 +68,8 @@ const getLogRowContextStyles = (theme: GrafanaTheme) => {
height: 220px;
padding: 10px;
`,
afterContext,
beforeContext,
};
};
@ -56,7 +82,7 @@ interface LogRowContextGroupHeaderProps {
}
interface LogRowContextGroupProps extends LogRowContextGroupHeaderProps {
rows: Array<string | DataQueryError>;
className: string;
className?: string;
error?: string;
}
@ -122,11 +148,11 @@ export const LogRowContextGroup: React.FunctionComponent<LogRowContextGroupProps
};
return (
<div className={cx(className, commonStyles)}>
<div className={cx(commonStyles, className)}>
{/* When displaying "after" context */}
{shouldScrollToBottom && !error && <LogRowContextGroupHeader {...headerProps} />}
<div className={logs}>
<CustomScrollbar autoHide scrollTop={scrollTop}>
<CustomScrollbar autoHide scrollTop={scrollTop} autoHeightMin={'210px'}>
<div ref={listContainerRef}>
{!error && (
<List
@ -161,6 +187,7 @@ export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
onOutsideClick,
onLoadMoreContext,
hasMoreContextRows,
wrapLogMessage,
}) => {
useEffect(() => {
const handleEscKeyDown = (e: KeyboardEvent): void => {
@ -173,6 +200,8 @@ export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
document.removeEventListener('keydown', handleEscKeyDown, false);
};
}, [onOutsideClick]);
const theme = useTheme();
const { afterContext, beforeContext } = getLogRowContextStyles(theme, wrapLogMessage);
return (
<ClickOutsideWrapper onClick={onOutsideClick}>
@ -184,9 +213,7 @@ export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
rows={context.after}
error={errors && errors.after}
row={row}
className={css`
top: -250px;
`}
className={afterContext}
shouldScrollToBottom
canLoadMoreRows={hasMoreContextRows ? hasMoreContextRows.after : false}
onLoadMoreContext={onLoadMoreContext}
@ -200,9 +227,7 @@ export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
row={row}
rows={context.before}
error={errors && errors.before}
className={css`
top: 100%;
`}
className={beforeContext}
/>
)}
</div>

View File

@ -51,6 +51,10 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
label: verticalScroll;
white-space: pre;
`,
contextNewline: css`
display: block;
margin-left: 0px;
`,
};
});
@ -124,12 +128,15 @@ class UnThemedLogRowMessage extends PureComponent<Props> {
return (
<td className={style.logsRowMessage}>
<div className={cx(styles.positionRelative, { [styles.horizontalScroll]: !wrapLogMessage })}>
<div
className={cx({ [styles.positionRelative]: wrapLogMessage }, { [styles.horizontalScroll]: !wrapLogMessage })}
>
{contextIsOpen && context && (
<LogRowContext
row={row}
context={context}
errors={errors}
wrapLogMessage={wrapLogMessage}
hasMoreContextRows={hasMoreContextRows}
onOutsideClick={onToggleContext}
onLoadMoreContext={() => {
@ -143,7 +150,10 @@ class UnThemedLogRowMessage extends PureComponent<Props> {
{renderLogMessage(hasAnsi, restructuredEntry, highlights, highlightClassName)}
</span>
{showContextToggle?.(row) && (
<span onClick={this.onContextToggle} className={cx('log-row-context', style.context)}>
<span
onClick={this.onContextToggle}
className={cx('log-row-context', style.context, { [styles.contextNewline]: !wrapLogMessage })}
>
{contextIsOpen ? 'Hide' : 'Show'} context
</span>
)}

View File

@ -48,13 +48,13 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme, logLevel?: Lo
font-family: ${theme.typography.fontFamily.monospace};
font-size: ${theme.typography.size.sm};
width: 100%;
overflow: hidden;
`,
context: css`
label: context;
visibility: hidden;
white-space: nowrap;
position: relative;
margin-left: 10px;
`,
logsRow: css`
label: logs-row;
@ -66,7 +66,6 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme, logLevel?: Lo
.log-row-context {
visibility: visible;
z-index: 1;
margin-left: 10px;
text-decoration: underline;
&:hover {
color: ${theme.palette.yellow};

View File

@ -283,7 +283,7 @@ export class UnthemedLogs extends PureComponent<Props, State> {
forceEscape,
} = this.state;
const styles = getStyles(theme);
const styles = getStyles(theme, wrapLogMessage);
const hasData = logRows && logRows.length > 0;
const hasUnescapedContent = this.checkUnescapedContent(logRows);
@ -420,7 +420,7 @@ export class UnthemedLogs extends PureComponent<Props, State> {
export const Logs = withTheme2(UnthemedLogs);
const getStyles = (theme: GrafanaTheme2) => {
const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => {
return {
noData: css`
> * {
@ -450,7 +450,8 @@ const getStyles = (theme: GrafanaTheme2) => {
justify-content: space-between;
`,
logRows: css`
overflow-x: scroll;
overflow-x: ${wrapLogMessage ? 'unset' : 'scroll'};
overflow-y: visible;
width: 100%;
`,
infoText: css`