-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Enhanced pod logs viewer (#11030)
Signed-off-by: Alex Collins <alex_collins@intuit.com>
- Loading branch information
Showing
23 changed files
with
590 additions
and
546 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
ui/src/app/applications/components/pod-logs-viewer/container-selector.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react'; | ||
import {Tooltip} from 'argo-ui'; | ||
|
||
export type ContainerGroup = {offset: number; containers: string[]}; | ||
|
||
// ContainerSelector is a component that renders a dropdown menu of containers | ||
export const ContainerSelector = ({ | ||
containerGroups, | ||
containerName, | ||
onClickContainer | ||
}: { | ||
containerGroups?: ContainerGroup[]; | ||
containerName: string; | ||
onClickContainer: (group: ContainerGroup, index: number, logs: string) => void; | ||
}) => { | ||
if (!containerGroups) { | ||
return <></>; | ||
} | ||
const containers = containerGroups?.reduce((acc, group) => acc.concat(group.containers), []); | ||
const containerNames = containers?.map(container => container.name); | ||
const containerGroup = (n: string) => { | ||
return containerGroups.find(group => group.containers.find(container => container === n)); | ||
}; | ||
const containerIndex = (n: string) => { | ||
return containerGroup(n).containers.findIndex(container => container === n); | ||
}; | ||
if (containerNames.length <= 1) return <></>; | ||
return ( | ||
<Tooltip content='Select a container to view logs'> | ||
<select className='argo-field' onChange={e => onClickContainer(containerGroup(e.target.value), containerIndex(e.target.value), 'logs')}> | ||
{containerNames.map(n => ( | ||
<option key={n} value={n}> | ||
{n} | ||
</option> | ||
))} | ||
</select> | ||
</Tooltip> | ||
); | ||
}; |
30 changes: 30 additions & 0 deletions
30
ui/src/app/applications/components/pod-logs-viewer/copy-logs-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as React from 'react'; | ||
import {useContext} from 'react'; | ||
import {LogLoader} from './log-loader'; | ||
import {Button} from '../../../shared/components/button'; | ||
import {Context} from '../../../shared/context'; | ||
import {NotificationType} from 'argo-ui/src/components/notifications/notifications'; | ||
|
||
// CopyLogsButton is a button that copies the logs to the clipboard | ||
export const CopyLogsButton = ({loader}: {loader: LogLoader}) => { | ||
const ctx = useContext(Context); | ||
return ( | ||
<Button | ||
title='Copy logs to clipboard' | ||
icon='copy' | ||
onClick={async () => { | ||
try { | ||
await navigator.clipboard.writeText( | ||
loader | ||
.getData() | ||
.map(item => item.content) | ||
.join('\n') | ||
); | ||
ctx.notifications.show({type: NotificationType.Success, content: 'Copied'}, 750); | ||
} catch (err) { | ||
ctx.notifications.show({type: NotificationType.Error, content: err.message}); | ||
} | ||
}} | ||
/> | ||
); | ||
}; |
19 changes: 19 additions & 0 deletions
19
ui/src/app/applications/components/pod-logs-viewer/dark-mode-toggle-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import {services, ViewPreferences} from '../../../shared/services'; | ||
import * as React from 'react'; | ||
import {ToggleButton} from '../../../shared/components/toggle-button'; | ||
|
||
// DarkModeToggleButton is a component that renders a toggle button that toggles dark mode. | ||
export const DarkModeToggleButton = ({prefs}: {prefs: ViewPreferences}) => ( | ||
<ToggleButton | ||
title='Dark Mode' | ||
onToggle={() => { | ||
const inverted = prefs.appDetails.darkMode; | ||
services.viewPreferences.updatePreferences({ | ||
...prefs, | ||
appDetails: {...prefs.appDetails, darkMode: !inverted} | ||
}); | ||
}} | ||
toggled={prefs.appDetails.darkMode} | ||
icon='moon' | ||
/> | ||
); |
16 changes: 16 additions & 0 deletions
16
ui/src/app/applications/components/pod-logs-viewer/download-logs-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {services} from '../../../shared/services'; | ||
import * as React from 'react'; | ||
import {PodLogsProps} from './pod-logs-viewer'; | ||
import {Button} from '../../../shared/components/button'; | ||
|
||
// DownloadLogsButton is a button that downloads the logs to a file | ||
export const DownloadLogsButton = ({applicationName, applicationNamespace, containerName, group, kind, name, namespace, podName}: PodLogsProps) => ( | ||
<Button | ||
title='Download logs to file' | ||
icon='download' | ||
onClick={async () => { | ||
const downloadURL = services.applications.getDownloadLogsURL(applicationName, applicationNamespace, namespace, podName, {group, kind, name}, containerName); | ||
window.open(downloadURL, '_blank'); | ||
}} | ||
/> | ||
); |
7 changes: 7 additions & 0 deletions
7
ui/src/app/applications/components/pod-logs-viewer/follow-toggle-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import * as React from 'react'; | ||
import {ToggleButton} from '../../../shared/components/toggle-button'; | ||
|
||
// FollowToggleButton is a component that renders a button to toggle following logs. | ||
export const FollowToggleButton = ({follow, setFollow}: {follow: boolean; setFollow: (value: boolean) => void}) => ( | ||
<ToggleButton title='Follow logs, automatically showing new logs lines' onToggle={() => setFollow(!follow)} toggled={follow} icon='angles-down' /> | ||
); |
26 changes: 26 additions & 0 deletions
26
ui/src/app/applications/components/pod-logs-viewer/fullscreen-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import {Link} from 'react-router-dom'; | ||
import * as React from 'react'; | ||
import {PodLogsProps} from './pod-logs-viewer'; | ||
import {Button} from '../../../shared/components/button'; | ||
|
||
export const FullscreenButton = ({ | ||
applicationName, | ||
applicationNamespace, | ||
containerName, | ||
fullscreen, | ||
group, | ||
kind, | ||
name, | ||
namespace, | ||
podName | ||
}: PodLogsProps & {fullscreen?: boolean}) => { | ||
const fullscreenURL = | ||
`/applications/${applicationNamespace}/${applicationName}/${namespace}/${containerName}/logs?` + `podName=${podName}&group=${group}&kind=${kind}&name=${name}`; | ||
return ( | ||
!fullscreen && ( | ||
<Link to={fullscreenURL} target='_blank'> | ||
<Button title='Show logs in fullscreen in a new window' icon='external-link-alt' /> | ||
</Link> | ||
) | ||
); | ||
}; |
4 changes: 4 additions & 0 deletions
4
ui/src/app/applications/components/pod-logs-viewer/log-loader.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import {DataLoader} from 'argo-ui'; | ||
import * as models from '../../../shared/models'; | ||
|
||
export type LogLoader = DataLoader<models.LogEntry[], string>; |
9 changes: 9 additions & 0 deletions
9
ui/src/app/applications/components/pod-logs-viewer/log-message-filter.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import * as React from 'react'; | ||
import {Tooltip} from 'argo-ui'; | ||
|
||
// Filter is a component that renders a filter input for log lines. | ||
export const LogMessageFilter = ({filterText, setFilterText}: {filterText: string; setFilterText: (value: string) => void}) => ( | ||
<Tooltip content='Filter log lines by text. Prefix with `!` to invert, e.g. `!foo` will find lines without `foo` in them'> | ||
<input className='argo-field' placeholder='containing' value={filterText} onChange={e => setFilterText(e.target.value)} /> | ||
</Tooltip> | ||
); |
Oops, something went wrong.