Merge pull request #1929 from influxdata/bugfix/tr-abs-agb

Add nanosecond precision to :interval: calc
pull/1951/merge
Timothy J. Raymond 2017-08-30 16:28:21 -04:00 committed by GitHub
commit 3d2c012e72
11 changed files with 101 additions and 19 deletions

View File

@ -7,6 +7,7 @@
### Features
1. [#1928](https://github.com/influxdata/chronograf/pull/1928): Add prefix, suffix, scale, and other y-axis formatting
1. [#1886](https://github.com/influxdata/chronograf/pull/1886): Fix limit of 100 alert rules on alert rules page
1. [#1934](https://github.com/influxdata/chronograf/pull/1943): Zoom syncronization and enhancement
### UI Improvements
1. [#1933](https://github.com/influxdata/chronograf/pull/1933): Use line-stacked graph type for memory information - thank you, @Joxit!
@ -16,6 +17,30 @@
1. [#1944](https://github.com/influxdata/chronograf/pull/1944): Improve UX of navigation to a sub-nav item in the navbar
## v1.3.7.0 [2017-08-23]
## v1.3.7.0 [unreleased]
### Features
1. [#1928](https://github.com/influxdata/chronograf/pull/1928): Add prefix, suffix, scale, and other y-axis formatting
### UI Improvements
## v1.3.7.0
### Bug Fixes
1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf
1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11.
1. [#1870](https://github.com/influxdata/chronograf/pull/1870): Fix console error for placing prop on div
1. [#1864](https://github.com/influxdata/chronograf/pull/1864): Fix Write Data form upload button and add `onDragExit` handler
1. [#1891](https://github.com/influxdata/chronograf/pull/1891): Fix Kapacitor config for PagerDuty via the UI
1. [#1872](https://github.com/influxdata/chronograf/pull/1872): Prevent stats in the legend from wrapping line
### Features
1. [#1863](https://github.com/influxdata/chronograf/pull/1863): Improve 'new-sources' server flag example by adding 'type' key
### UI Improvements
1. [#1862](https://github.com/influxdata/chronograf/pull/1862): Show "Add Graph" button on cells with no queries
## v1.3.6.1 [2017-08-14]
**Upgrade Note** This release (1.3.6.1) fixes a possibly data corruption issue with dashboard cells' graph types. If you upgraded to 1.3.6.0 and visited any dashboard, once you have then upgraded to this release (1.3.6.1) you will need to manually reset the graph type for every cell via the cell's caret --> Edit --> Display Options. If you upgraded directly to 1.3.6.1, you should not experience this issue.
### Bug Fixes
1. [#1795](https://github.com/influxdata/chronograf/pull/1795): Fix uptime status on Windows hosts running Telegraf
1. [#1715](https://github.com/influxdata/chronograf/pull/1715): Chronograf now renders on IE11.

View File

@ -260,7 +260,7 @@ func (g *GroupByVar) parseRelative(fragment string) (time.Duration, error) {
// example, the fragement "time > '1985-10-25T00:01:21-0800 and time <
// '1985-10-25T00:01:22-0800'" would yield a duration of 1m'
func (g *GroupByVar) parseAbsolute(fragment string) (time.Duration, error) {
timePtn := `time\s[>|<]\s'([0-9\-TZ\:]+)'` // Playground: http://gobular.com/x/41a45095-c384-46ea-b73c-54ef91ab93af
timePtn := `time\s[>|<]\s'([0-9\-T\:\.Z]+)'` // Playground: http://gobular.com/x/208f66bd-1889-4269-ab47-1efdfeeb63f0
re, err := regexp.Compile(timePtn)
if err != nil {
// this is a developer error and should complain loudly

View File

@ -29,6 +29,13 @@ func Test_GroupByVar(t *testing.T) {
1000,
10 * time.Second,
},
{
"absolute time with nano",
"SELECT mean(usage_idle) FROM cpu WHERE time > '2017-07-24T15:33:42.994Z' and time < '2017-08-24T15:33:42.994Z' GROUP BY :interval:",
744 * time.Hour,
1000,
10 * time.Second,
},
}
for _, test := range gbvTests {

View File

@ -7,6 +7,7 @@ import FancyScrollbar from 'shared/components/FancyScrollbar'
const Dashboard = ({
source,
onZoom,
dashboard,
onAddCell,
onEditCell,
@ -71,6 +72,7 @@ const Dashboard = ({
onDeleteCell={onDeleteCell}
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
synchronizer={synchronizer}
onZoom={onZoom}
/>
: <div className="dashboard__empty">
<p>This Dashboard has no Cells</p>
@ -127,6 +129,7 @@ Dashboard.propTypes = {
onSelectTemplate: func.isRequired,
showTemplateControlBar: bool,
onCancelEditCell: func,
onZoom: func,
}
export default Dashboard

View File

@ -11,7 +11,8 @@ const DashboardHeader = ({
buttonText,
dashboard,
headerText,
timeRange,
timeRange: {upper, lower},
zoomedTimeRange: {zoomedLower, zoomedUpper},
autoRefresh,
isHidden,
handleChooseTimeRange,
@ -81,7 +82,10 @@ const DashboardHeader = ({
/>
<TimeRangeDropdown
onChooseTimeRange={handleChooseTimeRange}
selected={timeRange}
selected={{
upper: zoomedUpper || upper,
lower: zoomedLower || lower,
}}
/>
<div
className="btn btn-default btn-sm btn-square"
@ -95,6 +99,13 @@ const DashboardHeader = ({
const {array, bool, func, number, shape, string} = PropTypes
DashboardHeader.defaultProps = {
zoomedTimeRange: {
zoomedLower: null,
zoomedUpper: null,
},
}
DashboardHeader.propTypes = {
sourceID: string,
children: array,
@ -115,6 +126,7 @@ DashboardHeader.propTypes = {
onEditDashboard: func,
onToggleTempVarControls: func,
showTemplateControlBar: bool,
zoomedTimeRange: shape({}),
}
export default DashboardHeader

View File

@ -31,6 +31,7 @@ class DashboardPage extends Component {
isEditMode: false,
selectedCell: null,
isTemplating: false,
zoomedTimeRange: {zoomedLower: null, zoomedUpper: null},
}
}
@ -196,12 +197,19 @@ class DashboardPage extends Component {
)
}
handleZoomedTimeRange = (zoomedLower, zoomedUpper) => {
this.setState({zoomedTimeRange: {zoomedLower, zoomedUpper}})
}
getActiveDashboard() {
const {params: {dashboardID}, dashboards} = this.props
return dashboards.find(d => d.id === +dashboardID)
}
render() {
const {zoomedTimeRange} = this.state
const {zoomedLower, zoomedUpper} = zoomedTimeRange
const {
source,
timeRange,
@ -217,8 +225,11 @@ class DashboardPage extends Component {
params: {sourceID, dashboardID},
} = this.props
const lowerType = lower && lower.includes('Z') ? 'timeStamp' : 'constant'
const upperType = upper && upper.includes('Z') ? 'timeStamp' : 'constant'
const low = zoomedLower ? zoomedLower : lower
const up = zoomedUpper ? zoomedUpper : upper
const lowerType = low && low.includes(':') ? 'timeStamp' : 'constant'
const upperType = up && up.includes(':') ? 'timeStamp' : 'constant'
const dashboardTime = {
id: 'dashtime',
@ -226,7 +237,7 @@ class DashboardPage extends Component {
type: lowerType,
values: [
{
value: lower,
value: low,
type: lowerType,
selected: true,
},
@ -239,7 +250,7 @@ class DashboardPage extends Component {
type: upperType,
values: [
{
value: upper || 'now()',
value: up || 'now()',
type: upperType,
selected: true,
},
@ -310,6 +321,7 @@ class DashboardPage extends Component {
sourceID={sourceID}
dashboard={dashboard}
timeRange={timeRange}
zoomedTimeRange={zoomedTimeRange}
autoRefresh={autoRefresh}
isHidden={inPresentationMode}
onAddCell={this.handleAddCell}
@ -337,6 +349,7 @@ class DashboardPage extends Component {
dashboard={dashboard}
timeRange={timeRange}
autoRefresh={autoRefresh}
onZoom={this.handleZoomedTimeRange}
onAddCell={this.handleAddCell}
synchronizer={this.synchronizer}
inPresentationMode={inPresentationMode}

View File

@ -3,6 +3,7 @@ import React, {Component, PropTypes} from 'react'
import shallowCompare from 'react-addons-shallow-compare'
import _ from 'lodash'
import moment from 'moment'
import Dygraphs from 'src/external/dygraph'
import getRange from 'shared/parsing/getRangeForDygraph'
@ -52,6 +53,7 @@ export default class Dygraph extends Component {
isGraphFilled,
isBarGraph,
options,
onZoom,
} = this.props
const graphRef = this.graphRef
@ -184,6 +186,13 @@ export default class Dygraph extends Component {
}
}
},
zoomCallback: (lower, upper) => {
if (this.dygraph.isZoomed() === false) {
return onZoom(null, null)
}
onZoom(this.formatTimeRange(lower), this.formatTimeRange(upper))
},
}
if (isBarGraph) {
@ -384,6 +393,14 @@ export default class Dygraph extends Component {
this.dygraph.predraw_()
}
formatTimeRange = timeRange => {
if (!timeRange) {
return ''
}
return moment(timeRange).utc().format()
}
render() {
const {
legend,
@ -446,6 +463,7 @@ Dygraph.defaultProps = {
isGraphFilled: true,
overrideLineColors: null,
dygraphRef: () => {},
onZoom: () => {},
}
Dygraph.propTypes = {
@ -477,4 +495,5 @@ Dygraph.propTypes = {
synchronizer: func,
setResolution: func,
dygraphRef: func,
onZoom: func,
}

View File

@ -148,6 +148,7 @@ class LayoutRenderer extends Component {
templates,
synchronizer,
isEditable,
onZoom,
} = this.props
return cells.map(cell => {
@ -176,6 +177,7 @@ class LayoutRenderer extends Component {
queries={this.standardizeQueries(cell, source)}
cellHeight={h}
axes={axes}
onZoom={onZoom}
/>}
</NameableGraph>
</div>
@ -303,6 +305,7 @@ LayoutRenderer.propTypes = {
isStatusPage: bool,
isEditable: bool,
onCancelEditCell: func,
onZoom: func,
}
export default LayoutRenderer

View File

@ -46,6 +46,7 @@ export default React.createClass({
synchronizer: func,
setResolution: func,
cellHeight: number,
onZoom: func,
},
getDefaultProps() {
@ -101,6 +102,7 @@ export default React.createClass({
synchronizer,
timeRange,
cellHeight,
onZoom,
} = this.props
const {labels, timeSeries, dygraphSeries} = this._timeSeries
@ -176,6 +178,7 @@ export default React.createClass({
synchronizer={synchronizer}
timeRange={timeRange}
setResolution={this.props.setResolution}
onZoom={onZoom}
/>
{showSingleStat
? <div className="single-stat single-stat-line">

View File

@ -10,6 +10,7 @@ const RefreshingSingleStat = AutoRefresh(SingleStat)
const RefreshingGraph = ({
axes,
type,
onZoom,
queries,
templates,
timeRange,
@ -46,6 +47,7 @@ const RefreshingGraph = ({
synchronizer={synchronizer}
editQueryStatus={editQueryStatus}
axes={axes}
onZoom={onZoom}
/>
)
}
@ -64,6 +66,7 @@ RefreshingGraph.propTypes = {
axes: shape(),
queries: arrayOf(shape()).isRequired,
editQueryStatus: func,
onZoom: func,
}
export default RefreshingGraph

View File

@ -9,27 +9,21 @@ import CustomTimeRangeOverlay from 'shared/components/CustomTimeRangeOverlay'
import timeRanges from 'hson!shared/data/timeRanges.hson'
import {DROPDOWN_MENU_MAX_HEIGHT} from 'shared/constants/index'
const emptyTime = {lower: '', upper: ''}
class TimeRangeDropdown extends Component {
constructor(props) {
super(props)
const {lower, upper} = props.selected
super(props)
const isTimeValid = moment(upper).isValid() && moment(lower).isValid()
const customTimeRange = isTimeValid ? {lower, upper} : emptyTime
this.state = {
autobind: false,
isOpen: false,
isCustomTimeRangeOpen: false,
customTimeRange:
moment(props.selected.upper).isValid() &&
moment(props.selected.lower).isValid()
? {
lower,
upper,
}
: {
lower: '',
upper: '',
},
customTimeRange,
}
}