Merge pull request #2756 from influxdata/expandable-kapacitor-logs

Improve TICKscript Editing
pull/10616/head
Alex Paxton 2018-02-09 15:06:47 -08:00 committed by GitHub
commit 60c7332a9f
12 changed files with 103 additions and 69 deletions

View File

@ -19,6 +19,7 @@
### Bug Fixes ### Bug Fixes
1. [#2684](https://github.com/influxdata/chronograf/pull/2684): Fix TICKscript Sensu alerts when no group by tags selected 1. [#2684](https://github.com/influxdata/chronograf/pull/2684): Fix TICKscript Sensu alerts when no group by tags selected
1. [#2735](https://github.com/influxdata/chronograf/pull/2735): Remove cli options from systemd service file 1. [#2735](https://github.com/influxdata/chronograf/pull/2735): Remove cli options from systemd service file
1. [#2756](https://github.com/influxdata/chronograf/pull/2756): Display only 200 most recent TICKscript log messages and prevent overlapping
1. [#2757](https://github.com/influxdata/chronograf/pull/2757): Added "TO" field to kapacitor SMTP config, and improved error messages for config saving and testing 1. [#2757](https://github.com/influxdata/chronograf/pull/2757): Added "TO" field to kapacitor SMTP config, and improved error messages for config saving and testing
1. [#2761](https://github.com/influxdata/chronograf/pull/2761): Remove cli options from sysvinit service file 1. [#2761](https://github.com/influxdata/chronograf/pull/2761): Remove cli options from sysvinit service file
1. [#2780](https://github.com/influxdata/chronograf/pull/2780): Fix routing on alert save 1. [#2780](https://github.com/influxdata/chronograf/pull/2780): Fix routing on alert save

View File

@ -10,7 +10,7 @@ const LogItemHTTPError = ({logItem}) =>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service error">HTTP Server</div> <div className="logs-table--service error">HTTP Server</div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values error"> <div className="logs-table--key-values error">
ERROR: {logItem.msg} ERROR: {logItem.msg}
</div> </div>

View File

@ -10,7 +10,7 @@ const LogItemInfluxDBDebug = ({logItem}) =>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service debug">InfluxDB</div> <div className="logs-table--service debug">InfluxDB</div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values debug"> <div className="logs-table--key-values debug">
DEBUG: {logItem.msg} DEBUG: {logItem.msg}
<br /> <br />

View File

@ -10,7 +10,7 @@ const LogItemKapacitorDebug = ({logItem}) =>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service debug">Kapacitor</div> <div className="logs-table--service debug">Kapacitor</div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values debug"> <div className="logs-table--key-values debug">
DEBUG: {logItem.msg} DEBUG: {logItem.msg}
</div> </div>

View File

@ -10,7 +10,7 @@ const LogItemKapacitorError = ({logItem}) =>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service error">Kapacitor</div> <div className="logs-table--service error">Kapacitor</div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values error"> <div className="logs-table--key-values error">
ERROR: {logItem.msg} ERROR: {logItem.msg}
</div> </div>

View File

@ -1,18 +1,26 @@
import React, {PropTypes} from 'react' import React, {PropTypes} from 'react'
const renderKeysAndValues = object => { const renderKeysAndValues = (object, name) => {
if (!object) { if (!object) {
return <span className="logs-table--empty-cell">--</span> return <span className="logs-table--empty-cell">--</span>
} }
const objKeys = Object.keys(object)
const objValues = Object.values(object)
const objElements = objKeys.map((objKey, i) => const sortedObjKeys = Object.keys(object).sort()
<div key={i} className="logs-table--key-value">
{objKey}: <span>{objValues[i]}</span> return (
<div className="logs-table--column">
<h1>
{`${sortedObjKeys.length} ${name}`}
</h1>
<div className="logs-table--scrollbox">
{sortedObjKeys.map(objKey =>
<div key={objKey} className="logs-table--key-value">
{objKey}: <span>{object[objKey]}</span>
</div>
)}
</div>
</div> </div>
) )
return objElements
} }
const LogItemKapacitorPoint = ({logItem}) => const LogItemKapacitorPoint = ({logItem}) =>
<div className="logs-table--row"> <div className="logs-table--row">
@ -24,15 +32,9 @@ const LogItemKapacitorPoint = ({logItem}) =>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service">Kapacitor Point</div> <div className="logs-table--service">Kapacitor Point</div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values"> {renderKeysAndValues(logItem.tag, 'Tags')}
TAGS<br /> {renderKeysAndValues(logItem.field, 'Fields')}
{renderKeysAndValues(logItem.tag)}
</div>
<div className="logs-table--key-values">
FIELDS<br />
{renderKeysAndValues(logItem.field)}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,24 +1,23 @@
import React, {PropTypes} from 'react' import React, {PropTypes} from 'react'
import InfiniteScroll from 'shared/components/InfiniteScroll'
import LogsTableRow from 'src/kapacitor/components/LogsTableRow' import LogsTableRow from 'src/kapacitor/components/LogsTableRow'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
const numLogsToRender = 200
const LogsTable = ({logs}) => const LogsTable = ({logs}) =>
<div className="logs-table--container"> <div className="logs-table">
<div className="logs-table--header"> <div className="logs-table--header">
<h2 className="panel-title">Logs</h2> {`${numLogsToRender} Most Recent Logs`}
</div>
<div className="logs-table--panel fancy-scroll--kapacitor">
{logs.length
? <InfiniteScroll
className="logs-table"
itemHeight={87}
items={logs.map((log, i) =>
<LogsTableRow key={log.key} logItem={log} index={i} />
)}
/>
: <div className="page-spinner" />}
</div> </div>
<FancyScrollbar
autoHide={false}
className="logs-table--container fancy-scroll--kapacitor"
>
{logs
.slice(0, numLogsToRender)
.map(log => <LogsTableRow key={log.key} logItem={log} />)}
</FancyScrollbar>
</div> </div>
const {arrayOf, shape, string} = PropTypes const {arrayOf, shape, string} = PropTypes

View File

@ -8,31 +8,31 @@ import LogItemKapacitorError from 'src/kapacitor/components/LogItemKapacitorErro
import LogItemKapacitorDebug from 'src/kapacitor/components/LogItemKapacitorDebug' import LogItemKapacitorDebug from 'src/kapacitor/components/LogItemKapacitorDebug'
import LogItemInfluxDBDebug from 'src/kapacitor/components/LogItemInfluxDBDebug' import LogItemInfluxDBDebug from 'src/kapacitor/components/LogItemInfluxDBDebug'
const LogsTableRow = ({logItem, index}) => { const LogsTableRow = ({logItem}) => {
if (logItem.service === 'sessions') { if (logItem.service === 'sessions') {
return <LogItemSession logItem={logItem} key={index} /> return <LogItemSession logItem={logItem} />
} }
if (logItem.service === 'http' && logItem.msg === 'http request') { if (logItem.service === 'http' && logItem.msg === 'http request') {
return <LogItemHTTP logItem={logItem} key={index} /> return <LogItemHTTP logItem={logItem} />
} }
if (logItem.service === 'kapacitor' && logItem.msg === 'point') { if (logItem.service === 'kapacitor' && logItem.msg === 'point') {
return <LogItemKapacitorPoint logItem={logItem} key={index} /> return <LogItemKapacitorPoint logItem={logItem} />
} }
if (logItem.service === 'httpd_server_errors' && logItem.lvl === 'error') { if (logItem.service === 'httpd_server_errors' && logItem.lvl === 'error') {
return <LogItemHTTPError logItem={logItem} key={index} /> return <LogItemHTTPError logItem={logItem} />
} }
if (logItem.service === 'kapacitor' && logItem.lvl === 'error') { if (logItem.service === 'kapacitor' && logItem.lvl === 'error') {
return <LogItemKapacitorError logItem={logItem} key={index} /> return <LogItemKapacitorError logItem={logItem} />
} }
if (logItem.service === 'kapacitor' && logItem.lvl === 'debug') { if (logItem.service === 'kapacitor' && logItem.lvl === 'debug') {
return <LogItemKapacitorDebug logItem={logItem} key={index} /> return <LogItemKapacitorDebug logItem={logItem} />
} }
if (logItem.service === 'influxdb' && logItem.lvl === 'debug') { if (logItem.service === 'influxdb' && logItem.lvl === 'debug') {
return <LogItemInfluxDBDebug logItem={logItem} key={index} /> return <LogItemInfluxDBDebug logItem={logItem} />
} }
return ( return (
<div className="logs-table--row" key={index}> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">
@ -43,7 +43,7 @@ const LogsTableRow = ({logItem, index}) => {
<div className="logs-table--service"> <div className="logs-table--service">
{logItem.service || '--'} {logItem.service || '--'}
</div> </div>
<div className="logs-table--blah"> <div className="logs-table--columns">
<div className="logs-table--key-values"> <div className="logs-table--key-values">
{logItem.msg || '--'} {logItem.msg || '--'}
</div> </div>
@ -53,7 +53,7 @@ const LogsTableRow = ({logItem, index}) => {
) )
} }
const {number, shape, string} = PropTypes const {shape, string} = PropTypes
LogsTableRow.propTypes = { LogsTableRow.propTypes = {
logItem: shape({ logItem: shape({
@ -62,7 +62,6 @@ LogsTableRow.propTypes = {
lvl: string.isRequired, lvl: string.isRequired,
msg: string.isRequired, msg: string.isRequired,
}).isRequired, }).isRequired,
index: number,
} }
export default LogsTableRow export default LogsTableRow

View File

@ -34,7 +34,10 @@ const Tickscript = ({
isNewTickscript={isNewTickscript} isNewTickscript={isNewTickscript}
/> />
<div className="page-contents--split"> <div className="page-contents--split">
<div className="tickscript"> <div
className="tickscript"
style={areLogsVisible ? {maxWidth: '50%'} : null}
>
<TickscriptEditorControls <TickscriptEditorControls
isNewTickscript={isNewTickscript} isNewTickscript={isNewTickscript}
onSelectDbrps={onSelectDbrps} onSelectDbrps={onSelectDbrps}

View File

@ -23,10 +23,17 @@
.CodeMirror-vscrollbar { .CodeMirror-vscrollbar {
@include custom-scrollbar-round($g2-kevlar,$g6-smoke); @include custom-scrollbar-round($g2-kevlar,$g6-smoke);
} }
.CodeMirror-hscrollbar {
@include custom-scrollbar-round($g0-obsidian,$g6-smoke);
}
.cm-s-material .CodeMirror-gutters { .cm-s-material .CodeMirror-gutters {
background-color: fade-out($g4-onyx, 0.7); @include gradient-v($g2-kevlar, $g0-obsidian)
border: none; border: none;
} }
.cm-s-material .CodeMirror-gutters .CodeMirror-gutter {
background-color: fade-out($g4-onyx, 0.75);
height: calc(100% + 30px);
}
.CodeMirror-gutter.CodeMirror-linenumbers { .CodeMirror-gutter.CodeMirror-linenumbers {
width: 60px; width: 60px;
} }

View File

@ -9,11 +9,10 @@ $logs-row-indent: 6px;
$logs-level-dot: 8px; $logs-level-dot: 8px;
$logs-margin: 4px; $logs-margin: 4px;
.logs-table--container { .logs-table {
width: 50%; width: 50%;
position: relative; position: relative;
height: 100%; height: 100%;
@include gradient-v($g3-castle,$g1-raven);
} }
.logs-table--header { .logs-table--header {
display: flex; display: flex;
@ -23,28 +22,28 @@ $logs-margin: 4px;
height: $logs-table-header-height; height: $logs-table-header-height;
padding: 0 $logs-table-padding 0 ($logs-table-padding / 2); padding: 0 $logs-table-padding 0 ($logs-table-padding / 2);
background-color: $g4-onyx; background-color: $g4-onyx;
white-space: nowrap;
font-size: 17px;
@include no-user-select();
letter-spacing: 0.015em;
font-weight: 500;
} }
.logs-table--panel { .logs-table--container {
position: absolute !important; position: absolute !important;
top: $logs-table-header-height; top: $logs-table-header-height;
left: 0; left: 0;
width: 100%; width: 100%;
height: calc(100% - #{$logs-table-header-height}) !important; height: calc(100% - #{$logs-table-header-height}) !important;
@include gradient-v(mix($g3-castle, $g2-kevlar),mix($g1-raven, $g0-obsidian));
} }
.logs-table {
height: 100%;
}
.logs-table--row { .logs-table--row {
height: 87px; // Fixed height, required for Infinite Scroll, allows for 2 tags / fields per line position: relative;
padding: 8px ($logs-table-padding - 16px) 8px ($logs-table-padding / 2); padding: 8px ($logs-table-padding - 16px) 8px ($logs-table-padding / 2);
border-bottom: 2px solid $g3-castle; border-bottom: 2px solid $g3-castle;
transition: background-color 0.25s ease; transition: background-color 0.25s ease;
&:hover { &:last-of-type {
background-color: $g4-onyx;
}
&:first-child {
border-bottom: none; border-bottom: none;
} }
} }
@ -62,21 +61,22 @@ $logs-margin: 4px;
&.debug {background-color: $c-comet;} &.debug {background-color: $c-comet;}
&.info {background-color: $g6-smoke;} &.info {background-color: $g6-smoke;}
&.warn {background-color: $c-pineapple;} &.warn {background-color: $c-pineapple;}
&.ok {background-color: $c-rainforest;} &.ok {background-color: $c-pool;}
&.error {background-color: $c-dreamsicle;} &.error {background-color: $c-dreamsicle;}
} }
.logs-table--timestamp { .logs-table--timestamp {
font-family: $code-font; font-family: $code-font;
font-weight: 500; font-weight: 500;
font-size: 11px; font-size: 13px;
color: $g9-mountain; color: $g9-mountain;
flex: 1 0 0; flex: 1 0 0;
} }
.logs-table--details { .logs-table--details {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap;
font-size: 13px; font-size: 13px;
color: $g13-mist; color: $g11-sidewalk;
font-weight: 600; font-weight: 600;
padding-left: ($logs-level-dot + $logs-row-indent); padding-left: ($logs-level-dot + $logs-row-indent);
@ -85,6 +85,10 @@ $logs-margin: 4px;
} }
/* Logs Table Item Types */ /* Logs Table Item Types */
.logs-table--service,
.logs-table--column h1 {
margin-top: 2px;
}
.logs-table--session { .logs-table--session {
text-transform: capitalize; text-transform: capitalize;
font-style: italic; font-style: italic;
@ -92,16 +96,33 @@ $logs-margin: 4px;
.logs-table--service { .logs-table--service {
width: 140px; width: 140px;
} }
.logs-table--blah { .logs-table--columns {
display: flex; display: flex;
flex: 1 0 0; flex: 1 0 0;
flex-wrap: wrap;
} }
.logs-table--key-values { .logs-table--column {
color: $g11-sidewalk; color: $g11-sidewalk;
flex: 1 0 50%; flex: 1 0 50%;
} }
.logs-table--column h1 {
font-size: 13px;
font-weight: 700;
margin: 0;
letter-spacing: normal;
line-height: 1.42857143em;
text-transform: uppercase;
color: $g16-pearl;
}
.logs-table--key-value { .logs-table--key-value {
white-space: nowrap;
span {
color: $c-rainforest;
}
} }
.logs-table--key-value span { .logs-table--scrollbox {
color: $c-pool; width: 100%;
max-height: 300px;
overflow-y: auto;
@include custom-scrollbar-round($g0-obsidian,$c-rainforest);
} }

View File

@ -71,16 +71,18 @@ $scrollbar-offset: 3px;
width: $scrollbar-width; width: $scrollbar-width;
border-top-right-radius: $radius; border-top-right-radius: $radius;
border-top-left-radius: $radius; border-top-left-radius: $radius;
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius; border-bottom-left-radius: $radius;
border-bottom-right-radius: $radius;
&-button { &-button {
background-color: $trackColor; background-color: $trackColor;
} }
&-track { &-track {
background-color: $trackColor; background-color: $trackColor;
border-top-right-radius: $radius; border-top-right-radius: ($scrollbar-width / 2);
border-bottom-right-radius: $radius; border-top-left-radius: ($scrollbar-width / 2);
border-bottom-left-radius: ($scrollbar-width / 2);
border-bottom-right-radius: ($scrollbar-width / 2);
} }
&-track-piece { &-track-piece {
background-color: $trackColor; background-color: $trackColor;