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. [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. [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. [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
|
### Bug Fixes
|
||||||
1. [11819](https://github.com/influxdata/influxdb/pull/11819): Update the inline edit for resource names to guard for empty strings
|
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
|
// Libraries
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent} from 'react'
|
||||||
|
import {withRouter, WithRouterProps} from 'react-router'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {Run} from '@influxdata/influx'
|
import {Run} from '@influxdata/influx'
|
||||||
import {IndexList} from 'src/clockface'
|
|
||||||
import {taskRuns} from '../dummyData'
|
|
||||||
import {Page} from 'src/pageLayout'
|
import {Page} from 'src/pageLayout'
|
||||||
|
import TaskRunsList from 'src/tasks/components/TaskRunsList'
|
||||||
|
|
||||||
|
// DummyData
|
||||||
|
import {taskRuns} from 'src/tasks/dummyData'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
taskID: string
|
params: {id: string}
|
||||||
runs: Run[]
|
runs: Run[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const dummyData = taskRuns
|
const dummyData = taskRuns
|
||||||
|
|
||||||
class TaskRunsPage extends PureComponent<Props> {
|
class TaskRunsPage extends PureComponent<Props & WithRouterProps> {
|
||||||
public render() {
|
public render() {
|
||||||
|
const {params} = this.props
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Page titleTag="Runs">
|
<Page titleTag="Runs">
|
||||||
|
@ -27,47 +31,13 @@ class TaskRunsPage extends PureComponent<Props> {
|
||||||
</Page.Header>
|
</Page.Header>
|
||||||
<Page.Contents fullWidth={false} scrollable={true}>
|
<Page.Contents fullWidth={false} scrollable={true}>
|
||||||
<div className="col-xs-12">
|
<div className="col-xs-12">
|
||||||
<IndexList>
|
<TaskRunsList taskID={params.id} runs={dummyData} />
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</Page.Contents>
|
</Page.Contents>
|
||||||
</Page>
|
</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 {
|
export default withRouter<Props>(TaskRunsPage)
|
||||||
const date = dt.toDateString()
|
|
||||||
const time = dt.toLocaleTimeString()
|
|
||||||
const formatted = `${date} ${time}`
|
|
||||||
|
|
||||||
return formatted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default 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
|
organization: Organization
|
||||||
owner?: User
|
owner?: User
|
||||||
}
|
}
|
||||||
|
|
||||||
import {Sort} from 'src/clockface'
|
import {Sort} from 'src/clockface'
|
||||||
import {addTaskLabelsAsync, removeTaskLabelsAsync} from 'src/tasks/actions/v2'
|
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[] = [
|
export const taskRuns: Run[] = [
|
||||||
{
|
{
|
||||||
|
@ -16,4 +16,32 @@ export const taskRuns: Run[] = [
|
||||||
logs: '/api/v2/tasks/1/runs/1/logs',
|
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