D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
self
/
root
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
panel
/
logs
/
Filename :
LogsPanel.tsx
back
Copy
import { css, cx } from '@emotion/css'; import React, { useCallback, useMemo, useRef, useLayoutEffect, useState } from 'react'; import { PanelProps, Field, Labels, GrafanaTheme2, LogsSortOrder, LogRowModel, DataHoverClearEvent, DataHoverEvent, CoreApp, } from '@grafana/data'; import { CustomScrollbar, useStyles2, usePanelContext } from '@grafana/ui'; import { getFieldLinksForExplore } from 'app/features/explore/utils/links'; import { PanelDataErrorView } from 'app/features/panel/components/PanelDataErrorView'; import { LogLabels } from '../../../features/logs/components/LogLabels'; import { LogRows } from '../../../features/logs/components/LogRows'; import { dataFrameToLogsModel, dedupLogRows, COMMON_LABELS } from '../../../features/logs/logsModel'; import { Options } from './types'; interface LogsPanelProps extends PanelProps<Options> {} export const LogsPanel = ({ data, timeZone, fieldConfig, options: { showLabels, showTime, wrapLogMessage, showCommonLabels, prettifyLogMessage, sortOrder, dedupStrategy, enableLogDetails, }, title, id, }: LogsPanelProps) => { const isAscending = sortOrder === LogsSortOrder.Ascending; const style = useStyles2(getStyles); const [scrollTop, setScrollTop] = useState(0); const logsContainerRef = useRef<HTMLDivElement>(null); const { eventBus } = usePanelContext(); const onLogRowHover = useCallback( (row?: LogRowModel) => { if (!row) { eventBus.publish(new DataHoverClearEvent()); } else { eventBus.publish( new DataHoverEvent({ point: { time: row.timeEpochMs, }, }) ); } }, [eventBus] ); // Important to memoize stuff here, as panel rerenders a lot for example when resizing. const [logRows, deduplicatedRows, commonLabels] = useMemo(() => { const logs = data ? dataFrameToLogsModel(data.series, data.request?.intervalMs, undefined, data.request?.targets) : null; const logRows = logs?.rows || []; const commonLabels = logs?.meta?.find((m) => m.label === COMMON_LABELS); const deduplicatedRows = dedupLogRows(logRows, dedupStrategy); return [logRows, deduplicatedRows, commonLabels]; }, [data, dedupStrategy]); useLayoutEffect(() => { if (isAscending && logsContainerRef.current) { setScrollTop(logsContainerRef.current.offsetHeight); } else { setScrollTop(0); } }, [isAscending, logRows]); const getFieldLinks = useCallback( (field: Field, rowIndex: number) => { return getFieldLinksForExplore({ field, rowIndex, range: data.timeRange }); }, [data] ); if (!data || logRows.length === 0) { return <PanelDataErrorView fieldConfig={fieldConfig} panelId={id} data={data} needsStringField />; } const renderCommonLabels = () => ( <div className={cx(style.labelContainer, isAscending && style.labelContainerAscending)}> <span className={style.label}>Common labels:</span> <LogLabels labels={commonLabels ? (commonLabels.value as Labels) : { labels: '(no common labels)' }} /> </div> ); return ( <CustomScrollbar autoHide scrollTop={scrollTop}> <div className={style.container} ref={logsContainerRef}> {showCommonLabels && !isAscending && renderCommonLabels()} <LogRows logRows={logRows} deduplicatedRows={deduplicatedRows} dedupStrategy={dedupStrategy} showLabels={showLabels} showTime={showTime} wrapLogMessage={wrapLogMessage} prettifyLogMessage={prettifyLogMessage} timeZone={timeZone} getFieldLinks={getFieldLinks} logsSortOrder={sortOrder} enableLogDetails={enableLogDetails} previewLimit={isAscending ? logRows.length : undefined} onLogRowHover={onLogRowHover} app={CoreApp.Dashboard} /> {showCommonLabels && isAscending && renderCommonLabels()} </div> </CustomScrollbar> ); }; const getStyles = (theme: GrafanaTheme2) => ({ container: css({ marginBottom: theme.spacing(1.5), }), labelContainer: css({ margin: theme.spacing(0, 0, 0.5, 0.5), display: 'flex', alignItems: 'center', }), labelContainerAscending: css({ margin: theme.spacing(0.5, 0, 0.5, 0), }), label: css({ marginRight: theme.spacing(0.5), fontSize: theme.typography.bodySmall.fontSize, fontWeight: theme.typography.fontWeightMedium, }), });