Resolve some PR issues. Improve Logging UX. Switch back to version detection due to poor UX (lag) of feature detection. Split out LogsTableRow to SFC. LogsTable also becomes an SFC.
parent
f2dc4ffb79
commit
8471c829de
|
@ -115,3 +115,17 @@ export const getLogStreamByRuleID = (kapacitor, ruleID) =>
|
|||
headers: {'Content-Type': 'application/json'},
|
||||
}
|
||||
)
|
||||
|
||||
export const pingKapacitorVersion = async kapacitor => {
|
||||
try {
|
||||
const result = await AJAX({
|
||||
method: 'GET',
|
||||
url: `${kapacitor.links.proxy}?path=/kapacitor/v1preview/ping`,
|
||||
})
|
||||
const kapVersion = result.headers['x-kapacitor-version']
|
||||
return kapVersion === '' ? null : kapVersion
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,86 +1,26 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import React, {PropTypes} from 'react'
|
||||
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
import LogItemSession from 'src/kapacitor/components/LogItemSession'
|
||||
import LogItemHTTP from 'src/kapacitor/components/LogItemHTTP'
|
||||
import LogItemHTTPError from 'src/kapacitor/components/LogItemHTTPError'
|
||||
import LogItemKapacitorPoint from 'src/kapacitor/components/LogItemKapacitorPoint'
|
||||
import LogItemKapacitorError from 'src/kapacitor/components/LogItemKapacitorError'
|
||||
import LogItemKapacitorDebug from 'src/kapacitor/components/LogItemKapacitorDebug'
|
||||
import LogItemInfluxDBDebug from 'src/kapacitor/components/LogItemInfluxDBDebug'
|
||||
import LogsTableRow from 'src/kapacitor/components/LogsTableRow'
|
||||
|
||||
class LogsTable extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
renderTableRow = (logItem, index) => {
|
||||
if (logItem.service === 'sessions') {
|
||||
return <LogItemSession logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'http' && logItem.msg === 'http request') {
|
||||
return <LogItemHTTP logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.msg === 'point') {
|
||||
return <LogItemKapacitorPoint logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'httpd_server_errors' && logItem.lvl === 'error') {
|
||||
return <LogItemHTTPError logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.lvl === 'error') {
|
||||
return <LogItemKapacitorError logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.lvl === 'debug') {
|
||||
return <LogItemKapacitorDebug logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'influxdb' && logItem.lvl === 'debug') {
|
||||
return <LogItemInfluxDBDebug logItem={logItem} key={index} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="logs-table--row" key={index}>
|
||||
<div className="logs-table--divider">
|
||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||
<div className="logs-table--timestamp">
|
||||
{logItem.ts}
|
||||
</div>
|
||||
</div>
|
||||
<div className="logs-table--details">
|
||||
<div className="logs-table--service">
|
||||
{logItem.service || '--'}
|
||||
</div>
|
||||
<div className="logs-table--blah">
|
||||
<div className="logs-table--key-values">
|
||||
{logItem.msg || '--'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
const LogsTable = ({logs}) =>
|
||||
<div className="logs-table--container">
|
||||
<div className="logs-table--header">
|
||||
<h2 className="panel-title">Logs</h2>
|
||||
</div>
|
||||
<FancyScrollbar
|
||||
className="logs-table--panel fancy-scroll--kapacitor"
|
||||
autoHide={false}
|
||||
>
|
||||
<div className="logs-table">
|
||||
{logs.length
|
||||
? logs.map((log, i) =>
|
||||
<LogsTableRow key={log.key} logItem={log} index={i} />
|
||||
)
|
||||
: <div className="page-spinner" />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {logs} = this.props
|
||||
|
||||
return (
|
||||
<div className="logs-table--container">
|
||||
<div className="logs-table--header">
|
||||
<h2 className="panel-title">Logs</h2>
|
||||
</div>
|
||||
<FancyScrollbar
|
||||
className="logs-table--panel fancy-scroll--kapacitor"
|
||||
autoHide={false}
|
||||
>
|
||||
<div className="logs-table">
|
||||
{logs.length
|
||||
? logs.map((log, i) => this.renderTableRow(log, i))
|
||||
: <div className="page-spinner" />}
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
|
||||
const {arrayOf, shape, string} = PropTypes
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
import LogItemSession from 'src/kapacitor/components/LogItemSession'
|
||||
import LogItemHTTP from 'src/kapacitor/components/LogItemHTTP'
|
||||
import LogItemHTTPError from 'src/kapacitor/components/LogItemHTTPError'
|
||||
import LogItemKapacitorPoint from 'src/kapacitor/components/LogItemKapacitorPoint'
|
||||
import LogItemKapacitorError from 'src/kapacitor/components/LogItemKapacitorError'
|
||||
import LogItemKapacitorDebug from 'src/kapacitor/components/LogItemKapacitorDebug'
|
||||
import LogItemInfluxDBDebug from 'src/kapacitor/components/LogItemInfluxDBDebug'
|
||||
|
||||
const LogsTableRow = ({logItem, index}) => {
|
||||
if (logItem.service === 'sessions') {
|
||||
return <LogItemSession logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'http' && logItem.msg === 'http request') {
|
||||
return <LogItemHTTP logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.msg === 'point') {
|
||||
return <LogItemKapacitorPoint logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'httpd_server_errors' && logItem.lvl === 'error') {
|
||||
return <LogItemHTTPError logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.lvl === 'error') {
|
||||
return <LogItemKapacitorError logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'kapacitor' && logItem.lvl === 'debug') {
|
||||
return <LogItemKapacitorDebug logItem={logItem} key={index} />
|
||||
}
|
||||
if (logItem.service === 'influxdb' && logItem.lvl === 'debug') {
|
||||
return <LogItemInfluxDBDebug logItem={logItem} key={index} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="logs-table--row" key={index}>
|
||||
<div className="logs-table--divider">
|
||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||
<div className="logs-table--timestamp">
|
||||
{logItem.ts}
|
||||
</div>
|
||||
</div>
|
||||
<div className="logs-table--details">
|
||||
<div className="logs-table--service">
|
||||
{logItem.service || '--'}
|
||||
</div>
|
||||
<div className="logs-table--blah">
|
||||
<div className="logs-table--key-values">
|
||||
{logItem.msg || '--'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {number, shape, string} = PropTypes
|
||||
|
||||
LogsTableRow.propTypes = {
|
||||
logItem: shape({
|
||||
key: string.isRequired,
|
||||
ts: string.isRequired,
|
||||
lvl: string.isRequired,
|
||||
msg: string.isRequired,
|
||||
}).isRequired,
|
||||
index: number,
|
||||
}
|
||||
|
||||
export default LogsTableRow
|
|
@ -1,6 +1,6 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
const LogsToggle = ({areLogsVisible, areLogsEnabled, onToggleLogsVisbility}) =>
|
||||
const LogsToggle = ({areLogsVisible, onToggleLogsVisbility}) =>
|
||||
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite logs-toggle">
|
||||
<li
|
||||
className={areLogsVisible ? null : 'active'}
|
||||
|
@ -8,20 +8,18 @@ const LogsToggle = ({areLogsVisible, areLogsEnabled, onToggleLogsVisbility}) =>
|
|||
>
|
||||
Editor
|
||||
</li>
|
||||
{areLogsEnabled &&
|
||||
<li
|
||||
className={areLogsVisible ? 'active' : null}
|
||||
onClick={onToggleLogsVisbility}
|
||||
>
|
||||
Editor + Logs
|
||||
</li>}
|
||||
<li
|
||||
className={areLogsVisible ? 'active' : null}
|
||||
onClick={onToggleLogsVisbility}
|
||||
>
|
||||
Editor + Logs
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
const {bool, func} = PropTypes
|
||||
|
||||
LogsToggle.propTypes = {
|
||||
areLogsVisible: bool,
|
||||
areLogsEnabled: bool,
|
||||
onToggleLogsVisbility: func.isRequired,
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@ const TickscriptHeader = ({
|
|||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">TICKscript Editor</h1>
|
||||
</div>
|
||||
<LogsToggle
|
||||
areLogsVisible={areLogsVisible}
|
||||
areLogsEnabled={areLogsEnabled}
|
||||
onToggleLogsVisbility={onToggleLogsVisbility}
|
||||
/>
|
||||
{areLogsEnabled &&
|
||||
<LogsToggle
|
||||
areLogsVisible={areLogsVisible}
|
||||
areLogsEnabled={areLogsEnabled}
|
||||
onToggleLogsVisbility={onToggleLogsVisbility}
|
||||
/>}
|
||||
<div className="page-header__right">
|
||||
<SourceIndicator />
|
||||
<button
|
||||
|
|
|
@ -219,5 +219,3 @@ export const ALERT_NODES_ACCESSORS = {
|
|||
)
|
||||
.join('.'),
|
||||
}
|
||||
|
||||
export const KAPACITOR_LOGS_NOT_FOUND = 404
|
||||
|
|
|
@ -7,8 +7,7 @@ import Tickscript from 'src/kapacitor/components/Tickscript'
|
|||
import * as kapactiorActionCreators from 'src/kapacitor/actions/view'
|
||||
import * as errorActionCreators from 'shared/actions/errors'
|
||||
import {getActiveKapacitor} from 'src/shared/apis'
|
||||
import {getLogStreamByRuleID} from 'src/kapacitor/apis'
|
||||
import {KAPACITOR_LOGS_NOT_FOUND} from 'src/kapacitor/constants'
|
||||
import {getLogStreamByRuleID, pingKapacitorVersion} from 'src/kapacitor/apis'
|
||||
import {publishNotification} from 'shared/actions/notifications'
|
||||
|
||||
class TickscriptPage extends Component {
|
||||
|
@ -32,19 +31,16 @@ class TickscriptPage extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
shouldFetch = null
|
||||
|
||||
fetchChunkedLogs = async (kapacitor, ruleID) => {
|
||||
const {notify} = this.props
|
||||
|
||||
try {
|
||||
const response = await getLogStreamByRuleID(kapacitor, ruleID)
|
||||
const version = await pingKapacitorVersion(kapacitor)
|
||||
|
||||
if (response.status === KAPACITOR_LOGS_NOT_FOUND) {
|
||||
if (version && parseInt(version.split('.')[1], 10) < 4) {
|
||||
this.setState({
|
||||
areLogsEnabled: false,
|
||||
})
|
||||
this.shouldFetch = false
|
||||
notify(
|
||||
'warning',
|
||||
'Could not use logging, requires Kapacitor version 1.4'
|
||||
|
@ -54,15 +50,27 @@ class TickscriptPage extends Component {
|
|||
|
||||
this.setState({
|
||||
areLogsEnabled: true,
|
||||
logs: [
|
||||
{
|
||||
id: uuid.v4(),
|
||||
key: uuid.v4(),
|
||||
lvl: 'info',
|
||||
msg: 'created log session',
|
||||
service: 'sessions',
|
||||
tags: 'nil',
|
||||
ts: new Date().toISOString(),
|
||||
},
|
||||
],
|
||||
})
|
||||
this.shouldFetch = true
|
||||
|
||||
const response = await getLogStreamByRuleID(kapacitor, ruleID)
|
||||
|
||||
const reader = await response.body.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
|
||||
let result
|
||||
|
||||
while (this.shouldFetch === true && !(result && result.done)) {
|
||||
while (this.state.areLogsEnabled === true && !(result && result.done)) {
|
||||
result = await reader.read()
|
||||
|
||||
const chunk = decoder.decode(result.value || new Uint8Array(), {
|
||||
|
@ -117,7 +125,9 @@ class TickscriptPage extends Component {
|
|||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.shouldFetch = false
|
||||
this.setState({
|
||||
areLogsEnabled: false,
|
||||
})
|
||||
}
|
||||
|
||||
handleSave = async () => {
|
||||
|
@ -163,7 +173,7 @@ class TickscriptPage extends Component {
|
|||
this.setState({task: {...this.state.task, id: e.target.value}})
|
||||
}
|
||||
|
||||
HandleToggleLogsVisbility = () => {
|
||||
handleToggleLogsVisbility = () => {
|
||||
this.setState({areLogsVisible: !this.state.areLogsVisible})
|
||||
}
|
||||
|
||||
|
@ -185,7 +195,7 @@ class TickscriptPage extends Component {
|
|||
onChangeID={this.handleChangeID}
|
||||
areLogsVisible={areLogsVisible}
|
||||
areLogsEnabled={areLogsEnabled}
|
||||
onToggleLogsVisbility={this.HandleToggleLogsVisbility}
|
||||
onToggleLogsVisbility={this.handleToggleLogsVisbility}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue