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.

pull/2188/head
Hunter Trujillo 2017-11-28 10:47:14 -07:00
parent f2dc4ffb79
commit 8471c829de
7 changed files with 136 additions and 107 deletions

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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,
}

View File

@ -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

View File

@ -219,5 +219,3 @@ export const ALERT_NODES_ACCESSORS = {
)
.join('.'),
}
export const KAPACITOR_LOGS_NOT_FOUND = 404

View File

@ -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}
/>
)
}