Merge pull request #11836 from influxdata/feat/view-logs-tasks
Add the ability to view logs for a specific task runpull/11852/head
commit
2fca416bf3
|
@ -5,6 +5,7 @@
|
|||
1. [11821](https://github.com/influxdata/influxdb/pull/11821): Display scraper name as the first and only updatable column in scrapers list
|
||||
1. [11804](https://github.com/influxdata/influxdb/pull/11804): Add the ability to view runs for a task
|
||||
1. [11824](https://github.com/influxdata/influxdb/pull/11824): Display last completed run for tasks list
|
||||
1. [11836](https://github.com/influxdata/influxdb/pull/11836): Add the ability to view the logs for a specific task run
|
||||
|
||||
### Bug Fixes
|
||||
1. [11819](https://github.com/influxdata/influxdb/pull/11819): Update the inline edit for resource names to guard for empty strings
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import _ from 'lodash'
|
||||
|
||||
import Container from 'src/clockface/components/overlays/OverlayContainer'
|
||||
import Heading from 'src/clockface/components/overlays/OverlayHeading'
|
||||
import Body from 'src/clockface/components/overlays/OverlayBody'
|
||||
|
||||
// DummyData
|
||||
import {runLogs} from 'src/tasks/dummyData'
|
||||
import {IndexList} from 'src/clockface'
|
||||
|
||||
interface Props {
|
||||
onDismissOverlay: () => void
|
||||
taskID: string
|
||||
runID: string
|
||||
}
|
||||
|
||||
class RunLogsOverlay extends PureComponent<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {onDismissOverlay} = this.props
|
||||
|
||||
return (
|
||||
<Container maxWidth={800}>
|
||||
<Heading title="Run Logs" onDismiss={onDismissOverlay} />
|
||||
<Body>
|
||||
<IndexList>
|
||||
<IndexList.Header>
|
||||
<IndexList.HeaderCell columnName="Time" width="50%" />
|
||||
<IndexList.HeaderCell columnName="Message" width="50%" />
|
||||
</IndexList.Header>
|
||||
<IndexList.Body emptyState={<></>} columnCount={2}>
|
||||
{this.listLogs}
|
||||
</IndexList.Body>
|
||||
</IndexList>
|
||||
</Body>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
public get listLogs(): JSX.Element[] {
|
||||
const logs = runLogs.events.map(rl => (
|
||||
<IndexList.Row key={rl.message}>
|
||||
<IndexList.Cell>{this.dateTimeString(rl.time)}</IndexList.Cell>
|
||||
<IndexList.Cell>{rl.message}</IndexList.Cell>
|
||||
</IndexList.Row>
|
||||
))
|
||||
|
||||
return logs
|
||||
}
|
||||
|
||||
private dateTimeString(dt: Date): string {
|
||||
const date = dt.toDateString()
|
||||
const time = dt.toLocaleTimeString()
|
||||
const formatted = `${date} ${time}`
|
||||
|
||||
return formatted
|
||||
}
|
||||
}
|
||||
|
||||
export default RunLogsOverlay
|
|
@ -0,0 +1,41 @@
|
|||
// Libraries
|
||||
import React, {PureComponent} from 'react'
|
||||
|
||||
// Components
|
||||
import {Run} from '@influxdata/influx'
|
||||
import {IndexList} from 'src/clockface'
|
||||
import TaskRunsRow from './TaskRunsRow'
|
||||
|
||||
interface Props {
|
||||
taskID: string
|
||||
runs: Run[]
|
||||
}
|
||||
|
||||
export default class TaskRunsList extends PureComponent<Props> {
|
||||
public render() {
|
||||
return (
|
||||
<IndexList>
|
||||
<IndexList.Header>
|
||||
<IndexList.HeaderCell columnName="Requested At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Started At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Finished At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Status" width="10%" />
|
||||
<IndexList.HeaderCell columnName="Schedule For" width="20%" />
|
||||
<IndexList.HeaderCell columnName="" width="10%" />
|
||||
</IndexList.Header>
|
||||
<IndexList.Body emptyState={<></>} columnCount={6}>
|
||||
{this.listRuns}
|
||||
</IndexList.Body>
|
||||
</IndexList>
|
||||
)
|
||||
}
|
||||
|
||||
public get listRuns(): JSX.Element[] {
|
||||
const {runs, taskID} = this.props
|
||||
const taskRuns = runs.map(t => (
|
||||
<TaskRunsRow key={t.id} taskID={taskID} run={t} />
|
||||
))
|
||||
|
||||
return taskRuns
|
||||
}
|
||||
}
|
|
@ -1,21 +1,25 @@
|
|||
// Libraries
|
||||
import React, {PureComponent} from 'react'
|
||||
import {withRouter, WithRouterProps} from 'react-router'
|
||||
|
||||
// Types
|
||||
import {Run} from '@influxdata/influx'
|
||||
import {IndexList} from 'src/clockface'
|
||||
import {taskRuns} from '../dummyData'
|
||||
import {Page} from 'src/pageLayout'
|
||||
import TaskRunsList from 'src/tasks/components/TaskRunsList'
|
||||
|
||||
// DummyData
|
||||
import {taskRuns} from 'src/tasks/dummyData'
|
||||
|
||||
interface Props {
|
||||
taskID: string
|
||||
params: {id: string}
|
||||
runs: Run[]
|
||||
}
|
||||
|
||||
const dummyData = taskRuns
|
||||
|
||||
class TaskRunsPage extends PureComponent<Props> {
|
||||
class TaskRunsPage extends PureComponent<Props & WithRouterProps> {
|
||||
public render() {
|
||||
const {params} = this.props
|
||||
return (
|
||||
<>
|
||||
<Page titleTag="Runs">
|
||||
|
@ -27,47 +31,13 @@ class TaskRunsPage extends PureComponent<Props> {
|
|||
</Page.Header>
|
||||
<Page.Contents fullWidth={false} scrollable={true}>
|
||||
<div className="col-xs-12">
|
||||
<IndexList>
|
||||
<IndexList.Header>
|
||||
<IndexList.HeaderCell columnName="Requested At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Started At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Finished At" width="20%" />
|
||||
<IndexList.HeaderCell columnName="Status" width="10%" />
|
||||
<IndexList.HeaderCell columnName="Schedule For" width="20%" />
|
||||
<IndexList.HeaderCell columnName="" width="10%" />
|
||||
</IndexList.Header>
|
||||
<IndexList.Body emptyState={<></>} columnCount={6}>
|
||||
{this.listRuns}
|
||||
</IndexList.Body>
|
||||
</IndexList>
|
||||
<TaskRunsList taskID={params.id} runs={dummyData} />
|
||||
</div>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
public get listRuns(): JSX.Element[] {
|
||||
const taskRuns = dummyData.map(t => (
|
||||
<IndexList.Row key={`task-id--${t.id}`}>
|
||||
<IndexList.Cell>{this.dateTimeString(t.requestedAt)}</IndexList.Cell>
|
||||
<IndexList.Cell>{this.dateTimeString(t.startedAt)}</IndexList.Cell>
|
||||
<IndexList.Cell>{this.dateTimeString(t.finishedAt)}</IndexList.Cell>
|
||||
<IndexList.Cell>{t.status}</IndexList.Cell>
|
||||
<IndexList.Cell>{this.dateTimeString(t.scheduledFor)}</IndexList.Cell>
|
||||
<IndexList.Cell />
|
||||
</IndexList.Row>
|
||||
))
|
||||
|
||||
return taskRuns
|
||||
}
|
||||
|
||||
private dateTimeString(dt: Date): string {
|
||||
const date = dt.toDateString()
|
||||
const time = dt.toLocaleTimeString()
|
||||
const formatted = `${date} ${time}`
|
||||
|
||||
return formatted
|
||||
}
|
||||
}
|
||||
export default TaskRunsPage
|
||||
|
||||
export default withRouter<Props>(TaskRunsPage)
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
// Libraries
|
||||
import React, {PureComponent} from 'react'
|
||||
|
||||
// Components
|
||||
import {Run} from '@influxdata/influx'
|
||||
import {
|
||||
IndexList,
|
||||
ComponentSize,
|
||||
ComponentColor,
|
||||
OverlayTechnology,
|
||||
} from 'src/clockface'
|
||||
import {Button} from '@influxdata/clockface'
|
||||
import RunLogsOverlay from './RunLogsOverlay'
|
||||
|
||||
interface Props {
|
||||
taskID: string
|
||||
run: Run
|
||||
}
|
||||
|
||||
interface State {
|
||||
isImportOverlayVisible: boolean
|
||||
}
|
||||
|
||||
export default class TaskRunsRow extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
isImportOverlayVisible: false,
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {run} = this.props
|
||||
return (
|
||||
<>
|
||||
<IndexList.Row>
|
||||
<IndexList.Cell>
|
||||
{this.dateTimeString(run.requestedAt)}
|
||||
</IndexList.Cell>
|
||||
<IndexList.Cell>{this.dateTimeString(run.startedAt)}</IndexList.Cell>
|
||||
<IndexList.Cell>{this.dateTimeString(run.finishedAt)}</IndexList.Cell>
|
||||
<IndexList.Cell>{run.status}</IndexList.Cell>
|
||||
<IndexList.Cell>
|
||||
{this.dateTimeString(run.scheduledFor)}
|
||||
</IndexList.Cell>
|
||||
<IndexList.Cell>
|
||||
<Button
|
||||
key={run.id}
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Default}
|
||||
text="View Logs"
|
||||
onClick={this.handleToggleOverlay}
|
||||
/>
|
||||
</IndexList.Cell>
|
||||
</IndexList.Row>
|
||||
|
||||
{this.renderLogOverlay}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
private dateTimeString(dt: Date): string {
|
||||
const date = dt.toDateString()
|
||||
const time = dt.toLocaleTimeString()
|
||||
const formatted = `${date} ${time}`
|
||||
|
||||
return formatted
|
||||
}
|
||||
|
||||
private handleToggleOverlay = () => {
|
||||
this.setState({isImportOverlayVisible: !this.state.isImportOverlayVisible})
|
||||
}
|
||||
|
||||
private get renderLogOverlay(): JSX.Element {
|
||||
const {isImportOverlayVisible} = this.state
|
||||
const {taskID, run} = this.props
|
||||
|
||||
return (
|
||||
<OverlayTechnology visible={isImportOverlayVisible}>
|
||||
<RunLogsOverlay
|
||||
onDismissOverlay={this.handleToggleOverlay}
|
||||
taskID={taskID}
|
||||
runID={run.id}
|
||||
/>
|
||||
</OverlayTechnology>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ interface Task extends TaskAPI {
|
|||
organization: Organization
|
||||
owner?: User
|
||||
}
|
||||
|
||||
import {Sort} from 'src/clockface'
|
||||
import {addTaskLabelsAsync, removeTaskLabelsAsync} from 'src/tasks/actions/v2'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {Run} from '@influxdata/influx'
|
||||
import {Run, Logs} from '@influxdata/influx'
|
||||
|
||||
export const taskRuns: Run[] = [
|
||||
{
|
||||
|
@ -16,4 +16,32 @@ export const taskRuns: Run[] = [
|
|||
logs: '/api/v2/tasks/1/runs/1/logs',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '40002342',
|
||||
taskID: 'string',
|
||||
status: Run.StatusEnum.Scheduled,
|
||||
scheduledFor: new Date('2019-02-11T22:37:25.985Z'),
|
||||
startedAt: new Date('2019-02-11T22:37:25.985Z'),
|
||||
finishedAt: new Date('2019-02-11T22:37:25.985Z'),
|
||||
requestedAt: new Date('2019-02-11T22:37:25.985Z'),
|
||||
links: {
|
||||
self: '/api/v2/tasks/1/runs/1',
|
||||
task: '/arequei/v2/tasks/1',
|
||||
retry: '/api/v2/tasks/1/runs/1/retry',
|
||||
logs: '/api/v2/tasks/1/runs/1/logs',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export const runLogs: Logs = {
|
||||
events: [
|
||||
{
|
||||
time: new Date('2019-02-12T22:00:09.572Z'),
|
||||
message: 'Halt and catch fire',
|
||||
},
|
||||
{
|
||||
time: new Date('2019-02-12T22:00:09.572Z'),
|
||||
message: 'Catch fire and Halt',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue