| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | import memoizeOne from 'memoize-one'; | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  | import React, { PureComponent } from 'react'; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 22:33:17 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   TimeZone, | 
					
						
							|  |  |  |   LogsDedupStrategy, | 
					
						
							|  |  |  |   LogRowModel, | 
					
						
							|  |  |  |   Field, | 
					
						
							|  |  |  |   LinkModel, | 
					
						
							|  |  |  |   LogsSortOrder, | 
					
						
							|  |  |  |   CoreApp, | 
					
						
							|  |  |  |   DataFrame, | 
					
						
							|  |  |  | } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | import { withTheme2, Themeable2 } from '@grafana/ui'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 14:01:55 +08:00
										 |  |  | import { UniqueKeyMaker } from '../UniqueKeyMaker'; | 
					
						
							| 
									
										
										
										
											2022-09-30 18:16:47 +08:00
										 |  |  | import { sortLogRows } from '../utils'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | //Components
 | 
					
						
							|  |  |  | import { LogRow } from './LogRow'; | 
					
						
							|  |  |  | import { getLogRowStyles } from './getLogRowStyles'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const PREVIEW_LIMIT = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface Props extends Themeable2 { | 
					
						
							|  |  |  |   logRows?: LogRowModel[]; | 
					
						
							|  |  |  |   deduplicatedRows?: LogRowModel[]; | 
					
						
							|  |  |  |   dedupStrategy: LogsDedupStrategy; | 
					
						
							|  |  |  |   showLabels: boolean; | 
					
						
							|  |  |  |   showTime: boolean; | 
					
						
							|  |  |  |   wrapLogMessage: boolean; | 
					
						
							|  |  |  |   prettifyLogMessage: boolean; | 
					
						
							|  |  |  |   timeZone: TimeZone; | 
					
						
							|  |  |  |   enableLogDetails: boolean; | 
					
						
							|  |  |  |   logsSortOrder?: LogsSortOrder | null; | 
					
						
							|  |  |  |   previewLimit?: number; | 
					
						
							|  |  |  |   forceEscape?: boolean; | 
					
						
							| 
									
										
										
										
											2023-01-12 02:20:11 +08:00
										 |  |  |   displayedFields?: string[]; | 
					
						
							| 
									
										
										
										
											2022-09-29 16:00:01 +08:00
										 |  |  |   app?: CoreApp; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   showContextToggle?: (row?: LogRowModel) => boolean; | 
					
						
							|  |  |  |   onClickFilterLabel?: (key: string, value: string) => void; | 
					
						
							|  |  |  |   onClickFilterOutLabel?: (key: string, value: string) => void; | 
					
						
							| 
									
										
										
										
											2022-11-10 22:33:17 +08:00
										 |  |  |   getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>; | 
					
						
							| 
									
										
										
										
											2023-01-12 02:20:11 +08:00
										 |  |  |   onClickShowField?: (key: string) => void; | 
					
						
							|  |  |  |   onClickHideField?: (key: string) => void; | 
					
						
							| 
									
										
										
										
											2023-06-28 21:22:54 +08:00
										 |  |  |   onPinLine?: (row: LogRowModel) => void; | 
					
						
							|  |  |  |   onUnpinLine?: (row: LogRowModel) => void; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   onLogRowHover?: (row?: LogRowModel) => void; | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |   onOpenContext?: (row: LogRowModel, onClose: () => void) => void; | 
					
						
							| 
									
										
										
										
											2023-06-16 20:07:51 +08:00
										 |  |  |   onPermalinkClick?: (row: LogRowModel) => Promise<void>; | 
					
						
							|  |  |  |   permalinkedRowId?: string; | 
					
						
							|  |  |  |   scrollIntoView?: (element: HTMLElement) => void; | 
					
						
							| 
									
										
										
										
											2023-07-24 16:22:47 +08:00
										 |  |  |   isFilterLabelActive?: (key: string, value: string) => Promise<boolean>; | 
					
						
							| 
									
										
										
										
											2023-06-28 21:22:54 +08:00
										 |  |  |   pinnedRowId?: string; | 
					
						
							| 
									
										
										
										
											2023-08-18 18:54:08 +08:00
										 |  |  |   containerRendered?: boolean; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | interface State { | 
					
						
							|  |  |  |   renderAll: boolean; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UnThemedLogRows extends PureComponent<Props, State> { | 
					
						
							|  |  |  |   renderAllTimer: number | null = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static defaultProps = { | 
					
						
							|  |  |  |     previewLimit: PREVIEW_LIMIT, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   state: State = { | 
					
						
							|  |  |  |     renderAll: false, | 
					
						
							| 
									
										
										
										
											2022-09-29 16:00:01 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** | 
					
						
							|  |  |  |    * Toggle the `contextIsOpen` state when a context of one LogRow is opened in order to not show the menu of the other log rows. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |   openContext = (row: LogRowModel, onClose: () => void): void => { | 
					
						
							|  |  |  |     if (this.props.onOpenContext) { | 
					
						
							|  |  |  |       this.props.onOpenContext(row, onClose); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   componentDidMount() { | 
					
						
							|  |  |  |     // Staged rendering
 | 
					
						
							|  |  |  |     const { logRows, previewLimit } = this.props; | 
					
						
							|  |  |  |     const rowCount = logRows ? logRows.length : 0; | 
					
						
							|  |  |  |     // Render all right away if not too far over the limit
 | 
					
						
							|  |  |  |     const renderAll = rowCount <= previewLimit! * 2; | 
					
						
							|  |  |  |     if (renderAll) { | 
					
						
							|  |  |  |       this.setState({ renderAll }); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       this.renderAllTimer = window.setTimeout(() => this.setState({ renderAll: true }), 2000); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   componentWillUnmount() { | 
					
						
							|  |  |  |     if (this.renderAllTimer) { | 
					
						
							|  |  |  |       clearTimeout(this.renderAllTimer); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   makeGetRows = memoizeOne((orderedRows: LogRowModel[]) => { | 
					
						
							|  |  |  |     return () => orderedRows; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sortLogs = memoizeOne((logRows: LogRowModel[], logsSortOrder: LogsSortOrder): LogRowModel[] => | 
					
						
							|  |  |  |     sortLogRows(logRows, logsSortOrder) | 
					
						
							|  |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   render() { | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |     const { deduplicatedRows, logRows, dedupStrategy, theme, logsSortOrder, previewLimit, ...rest } = this.props; | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |     const { renderAll } = this.state; | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  |     const styles = getLogRowStyles(theme); | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |     const dedupedRows = deduplicatedRows ? deduplicatedRows : logRows; | 
					
						
							|  |  |  |     const hasData = logRows && logRows.length > 0; | 
					
						
							|  |  |  |     const dedupCount = dedupedRows | 
					
						
							|  |  |  |       ? dedupedRows.reduce((sum, row) => (row.duplicates ? sum + row.duplicates : sum), 0) | 
					
						
							|  |  |  |       : 0; | 
					
						
							|  |  |  |     const showDuplicates = dedupStrategy !== LogsDedupStrategy.none && dedupCount > 0; | 
					
						
							|  |  |  |     // Staged rendering
 | 
					
						
							|  |  |  |     const processedRows = dedupedRows ? dedupedRows : []; | 
					
						
							|  |  |  |     const orderedRows = logsSortOrder ? this.sortLogs(processedRows, logsSortOrder) : processedRows; | 
					
						
							|  |  |  |     const firstRows = orderedRows.slice(0, previewLimit!); | 
					
						
							|  |  |  |     const lastRows = orderedRows.slice(previewLimit!, orderedRows.length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // React profiler becomes unusable if we pass all rows to all rows and their labels, using getter instead
 | 
					
						
							|  |  |  |     const getRows = this.makeGetRows(orderedRows); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-13 14:01:55 +08:00
										 |  |  |     const keyMaker = new UniqueKeyMaker(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  |       <table className={styles.logsRowsTable}> | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |         <tbody> | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |           {hasData && | 
					
						
							|  |  |  |             firstRows.map((row) => ( | 
					
						
							|  |  |  |               <LogRow | 
					
						
							| 
									
										
										
										
											2023-07-13 14:01:55 +08:00
										 |  |  |                 key={keyMaker.getKey(row.uid)} | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |                 getRows={getRows} | 
					
						
							|  |  |  |                 row={row} | 
					
						
							|  |  |  |                 showDuplicates={showDuplicates} | 
					
						
							|  |  |  |                 logsSortOrder={logsSortOrder} | 
					
						
							|  |  |  |                 onOpenContext={this.openContext} | 
					
						
							|  |  |  |                 styles={styles} | 
					
						
							|  |  |  |                 onPermalinkClick={this.props.onPermalinkClick} | 
					
						
							|  |  |  |                 scrollIntoView={this.props.scrollIntoView} | 
					
						
							|  |  |  |                 permalinkedRowId={this.props.permalinkedRowId} | 
					
						
							|  |  |  |                 onPinLine={this.props.onPinLine} | 
					
						
							|  |  |  |                 onUnpinLine={this.props.onUnpinLine} | 
					
						
							|  |  |  |                 pinned={this.props.pinnedRowId === row.uid} | 
					
						
							| 
									
										
										
										
											2023-07-24 16:22:47 +08:00
										 |  |  |                 isFilterLabelActive={this.props.isFilterLabelActive} | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |                 {...rest} | 
					
						
							|  |  |  |               /> | 
					
						
							|  |  |  |             ))} | 
					
						
							|  |  |  |           {hasData && | 
					
						
							|  |  |  |             renderAll && | 
					
						
							|  |  |  |             lastRows.map((row) => ( | 
					
						
							|  |  |  |               <LogRow | 
					
						
							| 
									
										
										
										
											2023-07-13 14:01:55 +08:00
										 |  |  |                 key={keyMaker.getKey(row.uid)} | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |                 getRows={getRows} | 
					
						
							|  |  |  |                 row={row} | 
					
						
							|  |  |  |                 showDuplicates={showDuplicates} | 
					
						
							|  |  |  |                 logsSortOrder={logsSortOrder} | 
					
						
							|  |  |  |                 onOpenContext={this.openContext} | 
					
						
							|  |  |  |                 styles={styles} | 
					
						
							|  |  |  |                 onPermalinkClick={this.props.onPermalinkClick} | 
					
						
							|  |  |  |                 scrollIntoView={this.props.scrollIntoView} | 
					
						
							|  |  |  |                 permalinkedRowId={this.props.permalinkedRowId} | 
					
						
							|  |  |  |                 onPinLine={this.props.onPinLine} | 
					
						
							|  |  |  |                 onUnpinLine={this.props.onUnpinLine} | 
					
						
							|  |  |  |                 pinned={this.props.pinnedRowId === row.uid} | 
					
						
							| 
									
										
										
										
											2023-07-24 16:22:47 +08:00
										 |  |  |                 isFilterLabelActive={this.props.isFilterLabelActive} | 
					
						
							| 
									
										
										
										
											2023-06-28 21:45:22 +08:00
										 |  |  |                 {...rest} | 
					
						
							|  |  |  |               /> | 
					
						
							|  |  |  |             ))} | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |           {hasData && !renderAll && ( | 
					
						
							|  |  |  |             <tr> | 
					
						
							|  |  |  |               <td colSpan={5}>Rendering {orderedRows.length - previewLimit!} rows...</td> | 
					
						
							|  |  |  |             </tr> | 
					
						
							|  |  |  |           )} | 
					
						
							|  |  |  |         </tbody> | 
					
						
							|  |  |  |       </table> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export const LogRows = withTheme2(UnThemedLogRows); | 
					
						
							|  |  |  | LogRows.displayName = 'LogsRows'; |