Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into postgres-query-bu…
Browse files Browse the repository at this point in the history
…ilder
  • Loading branch information
svenklemm committed Jul 11, 2018
2 parents c8a11d5 + 5578097 commit 1d71192
Show file tree
Hide file tree
Showing 24 changed files with 468 additions and 507 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ jobs:
- run:
name: run linters
command: 'gometalinter.v2 --enable-gc --vendor --deadline 10m --disable-all --enable=deadcode --enable=ineffassign --enable=structcheck --enable=unconvert --enable=varcheck ./...'
- run:
name: run go vet
command: 'go vet ./pkg/...'

test-frontend:
docker:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* **Postgres/MySQL/MSSQL**: Use floor rounding in $__timeGroup macro function [#12460](https://github.com/grafana/grafana/issues/12460), thx [@svenklemm](https://github.com/svenklemm)
* **MySQL/MSSQL**: Use datetime format instead of epoch for $__timeFilter, $__timeFrom and $__timeTo macros [#11618](https://github.com/grafana/grafana/issues/11618) [#11619](https://github.com/grafana/grafana/issues/11619), thx [@AustinWinstanley](https://github.com/AustinWinstanley)
* **Github OAuth**: Allow changes of user info at Github to be synched to Grafana when signing in [#11818](https://github.com/grafana/grafana/issues/11818), thx [@rwaweber](https://github.com/rwaweber)
* **Alerting**: Fix diff and percent_diff reducers [#11563](https://github.com/grafana/grafana/issues/11563), thx [@jessetane](https://github.com/jessetane)

# 5.2.2 (unreleased)

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,17 @@
"classnames": "^2.2.5",
"clipboard": "^1.7.1",
"d3": "^4.11.0",
"d3-scale-chromatic": "^1.1.1",
"d3-scale-chromatic": "^1.3.0",
"eventemitter3": "^2.0.3",
"file-saver": "^1.3.3",
"immutable": "^3.8.2",
"jquery": "^3.2.1",
"lodash": "^4.17.4",
"lodash": "^4.17.10",
"mini-css-extract-plugin": "^0.4.0",
"mobx": "^3.4.1",
"mobx-react": "^4.3.5",
"mobx-state-tree": "^1.3.1",
"moment": "^2.18.1",
"moment": "^2.22.2",
"mousetrap": "^1.6.0",
"mousetrap-global-bind": "^1.1.0",
"optimize-css-assets-webpack-plugin": "^4.0.2",
Expand Down
8 changes: 4 additions & 4 deletions pkg/services/alerting/conditions/reducer.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float {
break
}
}
// get other points
// get the oldest point
points = points[0:i]
for i := len(points) - 1; i >= 0; i-- {
for i := 0; i < len(points); i++ {
if points[i][0].Valid {
allNull = false
value = first - points[i][0].Float64
Expand All @@ -131,9 +131,9 @@ func (s *SimpleReducer) Reduce(series *tsdb.TimeSeries) null.Float {
break
}
}
// get other points
// get the oldest point
points = points[0:i]
for i := len(points) - 1; i >= 0; i-- {
for i := 0; i < len(points); i++ {
if points[i][0].Valid {
allNull = false
val := (first - points[i][0].Float64) / points[i][0].Float64 * 100
Expand Down
23 changes: 21 additions & 2 deletions pkg/services/alerting/conditions/reducer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,35 @@ func TestSimpleReducer(t *testing.T) {
So(reducer.Reduce(series).Float64, ShouldEqual, float64(3))
})

Convey("diff", func() {
Convey("diff one point", func() {
result := testReducer("diff", 30)
So(result, ShouldEqual, float64(0))
})

Convey("diff two points", func() {
result := testReducer("diff", 30, 40)
So(result, ShouldEqual, float64(10))
})

Convey("percent_diff", func() {
Convey("diff three points", func() {
result := testReducer("diff", 30, 40, 40)
So(result, ShouldEqual, float64(10))
})

Convey("percent_diff one point", func() {
result := testReducer("percent_diff", 40)
So(result, ShouldEqual, float64(0))
})

Convey("percent_diff two points", func() {
result := testReducer("percent_diff", 30, 40)
So(result, ShouldEqual, float64(33.33333333333333))
})

Convey("percent_diff three points", func() {
result := testReducer("percent_diff", 30, 40, 40)
So(result, ShouldEqual, float64(33.33333333333333))
})
})
}

Expand Down
2 changes: 0 additions & 2 deletions pkg/services/notifications/notifications.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ func (ns *NotificationService) Run(ctx context.Context) error {
return ctx.Err()
}
}

return nil
}

func (ns *NotificationService) SendWebhookSync(ctx context.Context, cmd *m.SendWebhookSync) error {
Expand Down
4 changes: 3 additions & 1 deletion pkg/services/rendering/phantomjs.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ func (rs *RenderingService) renderViaPhantomJS(ctx context.Context, opts Opts) (
cmdArgs = append([]string{fmt.Sprintf("--output-encoding=%s", opts.Encoding)}, cmdArgs...)
}

commandCtx, _ := context.WithTimeout(ctx, opts.Timeout+time.Second*2)
commandCtx, cancel := context.WithTimeout(ctx, opts.Timeout+time.Second*2)
defer cancel()

cmd := exec.CommandContext(commandCtx, binPath, cmdArgs...)
cmd.Stderr = cmd.Stdout

Expand Down
2 changes: 1 addition & 1 deletion pkg/tsdb/elasticsearch/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
elapsed := time.Now().Sub(start)
clientLog.Debug("Decoded multisearch json response", "took", elapsed)

msr.status = res.StatusCode
msr.Status = res.StatusCode

return &msr, nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/tsdb/elasticsearch/client/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type MultiSearchRequest struct {

// MultiSearchResponse represents a multi search response
type MultiSearchResponse struct {
status int `json:"status,omitempty"`
Status int `json:"status,omitempty"`
Responses []*SearchResponse `json:"responses"`
}

Expand Down
98 changes: 64 additions & 34 deletions public/app/containers/Explore/QueryField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import { getNextCharacter, getPreviousCousin } from './utils/dom';
import BracesPlugin from './slate-plugins/braces';
import ClearPlugin from './slate-plugins/clear';
import NewlinePlugin from './slate-plugins/newline';
import PluginPrism, { configurePrismMetricsTokens } from './slate-plugins/prism/index';
import PluginPrism, { setPrismTokens } from './slate-plugins/prism/index';
import RunnerPlugin from './slate-plugins/runner';
import debounce from './utils/debounce';
import { processLabels, RATE_RANGES, cleanText } from './utils/prometheus';

import Typeahead from './Typeahead';

const EMPTY_METRIC = '';
const TYPEAHEAD_DEBOUNCE = 300;
export const TYPEAHEAD_DEBOUNCE = 300;

function flattenSuggestions(s) {
return s ? s.reduce((acc, g) => acc.concat(g.items), []) : [];
}

const getInitialValue = query =>
export const getInitialValue = query =>
Value.fromJSON({
document: {
nodes: [
Expand All @@ -45,12 +45,14 @@ const getInitialValue = query =>
},
});

class Portal extends React.Component {
class Portal extends React.Component<any, any> {
node: any;

constructor(props) {
super(props);
const { index = 0, prefix = 'query' } = props;
this.node = document.createElement('div');
this.node.classList.add('explore-typeahead', `explore-typeahead-${props.index}`);
this.node.classList.add(`slate-typeahead`, `slate-typeahead-${prefix}-${index}`);
document.body.appendChild(this.node);
}

Expand All @@ -71,12 +73,14 @@ class QueryField extends React.Component<any, any> {
constructor(props, context) {
super(props, context);

const { prismDefinition = {}, prismLanguage = 'promql' } = props;

this.plugins = [
BracesPlugin(),
ClearPlugin(),
RunnerPlugin({ handler: props.onPressEnter }),
NewlinePlugin(),
PluginPrism(),
PluginPrism({ definition: prismDefinition, language: prismLanguage }),
];

this.state = {
Expand Down Expand Up @@ -131,7 +135,8 @@ class QueryField extends React.Component<any, any> {
if (!this.state.metrics) {
return;
}
configurePrismMetricsTokens(this.state.metrics);
setPrismTokens(this.props.prismLanguage, 'metrics', this.state.metrics);

// Trigger re-render
window.requestAnimationFrame(() => {
// Bogus edit to trigger highlighting
Expand Down Expand Up @@ -162,7 +167,7 @@ class QueryField extends React.Component<any, any> {
const selection = window.getSelection();
if (selection.anchorNode) {
const wrapperNode = selection.anchorNode.parentElement;
const editorNode = wrapperNode.closest('.query-field');
const editorNode = wrapperNode.closest('.slate-query-field');
if (!editorNode || this.state.value.isBlurred) {
// Not inside this editor
return;
Expand Down Expand Up @@ -330,20 +335,30 @@ class QueryField extends React.Component<any, any> {
}

onKeyDown = (event, change) => {
if (this.menuEl) {
const { typeaheadIndex, suggestions } = this.state;

switch (event.key) {
case 'Escape': {
if (this.menuEl) {
event.preventDefault();
this.resetTypeahead();
return true;
}
break;
const { typeaheadIndex, suggestions } = this.state;

switch (event.key) {
case 'Escape': {
if (this.menuEl) {
event.preventDefault();
event.stopPropagation();
this.resetTypeahead();
return true;
}
break;
}

case 'Tab': {
case ' ': {
if (event.ctrlKey) {
event.preventDefault();
this.handleTypeahead();
return true;
}
break;
}

case 'Tab': {
if (this.menuEl) {
// Dont blur input
event.preventDefault();
if (!suggestions || suggestions.length === 0) {
Expand All @@ -359,25 +374,30 @@ class QueryField extends React.Component<any, any> {
this.applyTypeahead(change, suggestion);
return true;
}
break;
}

case 'ArrowDown': {
case 'ArrowDown': {
if (this.menuEl) {
// Select next suggestion
event.preventDefault();
this.setState({ typeaheadIndex: typeaheadIndex + 1 });
break;
}
break;
}

case 'ArrowUp': {
case 'ArrowUp': {
if (this.menuEl) {
// Select previous suggestion
event.preventDefault();
this.setState({ typeaheadIndex: Math.max(0, typeaheadIndex - 1) });
break;
}
break;
}

default: {
// console.log('default key', event.key, event.which, event.charCode, event.locale, data.key);
break;
}
default: {
// console.log('default key', event.key, event.which, event.charCode, event.locale, data.key);
break;
}
}
return undefined;
Expand Down Expand Up @@ -502,10 +522,17 @@ class QueryField extends React.Component<any, any> {

// Align menu overlay to editor node
if (node) {
// Read from DOM
const rect = node.parentElement.getBoundingClientRect();
menu.style.opacity = 1;
menu.style.top = `${rect.top + window.scrollY + rect.height + 4}px`;
menu.style.left = `${rect.left + window.scrollX - 2}px`;
const scrollX = window.scrollX;
const scrollY = window.scrollY;

// Write DOM
requestAnimationFrame(() => {
menu.style.opacity = 1;
menu.style.top = `${rect.top + scrollY + rect.height + 4}px`;
menu.style.left = `${rect.left + scrollX - 2}px`;
});
}
};

Expand All @@ -514,6 +541,7 @@ class QueryField extends React.Component<any, any> {
};

renderMenu = () => {
const { portalPrefix } = this.props;
const { suggestions } = this.state;
const hasSuggesstions = suggestions && suggestions.length > 0;
if (!hasSuggesstions) {
Expand All @@ -524,11 +552,13 @@ class QueryField extends React.Component<any, any> {
let selectedIndex = Math.max(this.state.typeaheadIndex, 0);
const flattenedSuggestions = flattenSuggestions(suggestions);
selectedIndex = selectedIndex % flattenedSuggestions.length || 0;
const selectedKeys = flattenedSuggestions.length > 0 ? [flattenedSuggestions[selectedIndex]] : [];
const selectedKeys = (flattenedSuggestions.length > 0 ? [flattenedSuggestions[selectedIndex]] : []).map(
i => (typeof i === 'object' ? i.text : i)
);

// Create typeahead in DOM root so we can later position it absolutely
return (
<Portal>
<Portal prefix={portalPrefix}>
<Typeahead
menuRef={this.menuRef}
selectedItems={selectedKeys}
Expand All @@ -541,7 +571,7 @@ class QueryField extends React.Component<any, any> {

render() {
return (
<div className="query-field">
<div className="slate-query-field">
{this.renderMenu()}
<Editor
autoCorrect={false}
Expand Down
6 changes: 5 additions & 1 deletion public/app/containers/Explore/QueryRows.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';

import promql from './slate-plugins/prism/promql';
import QueryField from './QueryField';

class QueryRow extends PureComponent<any, any> {
Expand Down Expand Up @@ -55,12 +56,15 @@ class QueryRow extends PureComponent<any, any> {
<i className="fa fa-minus" />
</button>
</div>
<div className="query-field-wrapper">
<div className="slate-query-field-wrapper">
<QueryField
initialQuery={edited ? null : query}
portalPrefix="explore"
onPressEnter={this.handlePressEnter}
onQueryChange={this.handleChangeQuery}
placeholder="Enter a PromQL query"
prismLanguage="promql"
prismDefinition={promql}
request={request}
/>
</div>
Expand Down
Loading

0 comments on commit 1d71192

Please sign in to comment.