| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  | import { cx } from '@emotion/css'; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | import memoizeOne from 'memoize-one'; | 
					
						
							|  |  |  | import React, { PureComponent } from 'react'; | 
					
						
							|  |  |  | import Highlighter from 'react-highlight-words'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  | import { LogRowModel, findHighlightChunksInText, CoreApp } from '@grafana/data'; | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  | import { IconButton, Tooltip } from '@grafana/ui'; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import { LogMessageAnsi } from './LogMessageAnsi'; | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  | import { LogRowStyles } from './getLogRowStyles'; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export const MAX_CHARACTERS = 100000; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  | interface Props { | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   row: LogRowModel; | 
					
						
							|  |  |  |   wrapLogMessage: boolean; | 
					
						
							|  |  |  |   prettifyLogMessage: boolean; | 
					
						
							| 
									
										
										
										
											2022-09-29 16:00:01 +08:00
										 |  |  |   app?: CoreApp; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   showContextToggle?: (row?: LogRowModel) => boolean; | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |   onOpenContext: (row: LogRowModel) => void; | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  |   styles: LogRowStyles; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function renderLogMessage( | 
					
						
							|  |  |  |   hasAnsi: boolean, | 
					
						
							|  |  |  |   entry: string, | 
					
						
							|  |  |  |   highlights: string[] | undefined, | 
					
						
							|  |  |  |   highlightClassName: string | 
					
						
							|  |  |  | ) { | 
					
						
							|  |  |  |   const needsHighlighter = | 
					
						
							|  |  |  |     highlights && highlights.length > 0 && highlights[0] && highlights[0].length > 0 && entry.length < MAX_CHARACTERS; | 
					
						
							|  |  |  |   const searchWords = highlights ?? []; | 
					
						
							|  |  |  |   if (hasAnsi) { | 
					
						
							|  |  |  |     const highlight = needsHighlighter ? { searchWords, highlightClassName } : undefined; | 
					
						
							|  |  |  |     return <LogMessageAnsi value={entry} highlight={highlight} />; | 
					
						
							|  |  |  |   } else if (needsHighlighter) { | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |       <Highlighter | 
					
						
							|  |  |  |         textToHighlight={entry} | 
					
						
							|  |  |  |         searchWords={searchWords} | 
					
						
							|  |  |  |         findChunks={findHighlightChunksInText} | 
					
						
							|  |  |  |         highlightClassName={highlightClassName} | 
					
						
							|  |  |  |       /> | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     return entry; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const restructureLog = memoizeOne((line: string, prettifyLogMessage: boolean): string => { | 
					
						
							|  |  |  |   if (prettifyLogMessage) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       return JSON.stringify(JSON.parse(line), undefined, 2); | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |       return line; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return line; | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  | export class LogRowMessage extends PureComponent<Props> { | 
					
						
							| 
									
										
										
										
											2022-09-29 20:51:20 +08:00
										 |  |  |   onShowContextClick = (e: React.SyntheticEvent<HTMLElement, Event>) => { | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |     const { onOpenContext } = this.props; | 
					
						
							|  |  |  |     e.stopPropagation(); | 
					
						
							|  |  |  |     onOpenContext(this.props.row); | 
					
						
							| 
									
										
										
										
											2022-09-29 20:51:20 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |   render() { | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |     const { row, wrapLogMessage, prettifyLogMessage, showContextToggle, styles } = this.props; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |     const { hasAnsi, raw } = row; | 
					
						
							|  |  |  |     const restructuredEntry = restructureLog(raw, prettifyLogMessage); | 
					
						
							| 
									
										
										
										
											2022-09-29 16:00:01 +08:00
										 |  |  |     const shouldShowContextToggle = showContextToggle ? showContextToggle(row) : false; | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return ( | 
					
						
							| 
									
										
										
										
											2022-10-05 22:11:08 +08:00
										 |  |  |       <> | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           // When context is open, the position has to be NOT relative. // Setting the postion as inline-style to
 | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  |           // overwrite the more sepecific style definition from `styles.logsRowMessage`.
 | 
					
						
							| 
									
										
										
										
											2022-10-05 22:11:08 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |         <td className={styles.logsRowMessage}> | 
					
						
							| 
									
										
										
										
											2022-10-05 22:11:08 +08:00
										 |  |  |           <div | 
					
						
							|  |  |  |             className={cx( | 
					
						
							|  |  |  |               { [styles.positionRelative]: wrapLogMessage }, | 
					
						
							|  |  |  |               { [styles.horizontalScroll]: !wrapLogMessage } | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           > | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |             <button className={cx(styles.logLine, styles.positionRelative)}> | 
					
						
							| 
									
										
										
										
											2023-02-01 22:28:10 +08:00
										 |  |  |               {renderLogMessage(hasAnsi, restructuredEntry, row.searchWords, styles.logsRowMatchHighLight)} | 
					
						
							| 
									
										
										
										
											2022-12-21 21:45:47 +08:00
										 |  |  |             </button> | 
					
						
							| 
									
										
										
										
											2022-10-05 22:11:08 +08:00
										 |  |  |           </div> | 
					
						
							|  |  |  |         </td> | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |         <td className={cx('log-row-menu-cell', styles.logRowMenuCell)}> | 
					
						
							|  |  |  |           <span | 
					
						
							|  |  |  |             className={cx('log-row-menu', styles.rowMenu, { | 
					
						
							|  |  |  |               [styles.rowMenuWithContextButton]: shouldShowContextToggle, | 
					
						
							|  |  |  |             })} | 
					
						
							|  |  |  |             onClick={(e) => e.stopPropagation()} | 
					
						
							|  |  |  |           > | 
					
						
							|  |  |  |             {shouldShowContextToggle && ( | 
					
						
							|  |  |  |               <Tooltip placement="top" content={'Show context'}> | 
					
						
							|  |  |  |                 <IconButton size="md" name="gf-show-context" onClick={this.onShowContextClick} /> | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |               </Tooltip> | 
					
						
							| 
									
										
										
										
											2023-04-14 23:05:43 +08:00
										 |  |  |             )} | 
					
						
							|  |  |  |             <Tooltip placement="top" content={'Copy'}> | 
					
						
							|  |  |  |               <IconButton size="md" name="copy" onClick={() => navigator.clipboard.writeText(restructuredEntry)} /> | 
					
						
							|  |  |  |             </Tooltip> | 
					
						
							|  |  |  |           </span> | 
					
						
							|  |  |  |         </td> | 
					
						
							| 
									
										
										
										
											2022-10-05 22:11:08 +08:00
										 |  |  |       </> | 
					
						
							| 
									
										
										
										
											2022-09-19 16:51:46 +08:00
										 |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |