Merge remote-tracking branch 'origin/master' into develop

This commit is contained in:
Torkel Ödegaard
2017-12-07 14:14:50 +01:00
42 changed files with 476 additions and 194 deletions

View File

@@ -10,7 +10,11 @@ import (
)
func RenderToPng(c *middleware.Context) {
queryReader := util.NewUrlQueryReader(c.Req.URL)
queryReader, err := util.NewUrlQueryReader(c.Req.URL)
if err != nil {
c.Handle(400, "Render parameters error", err)
return
}
queryParams := fmt.Sprintf("?%s", c.Req.URL.RawQuery)
renderOpts := &renderer.RenderOpts{

View File

@@ -3,7 +3,9 @@ package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"net"
"os"
"path/filepath"
"strconv"
@@ -96,6 +98,7 @@ func (g *GrafanaServerImpl) Start() {
return
}
SendSystemdNotification("READY=1")
g.startHttpServer()
}
@@ -169,3 +172,28 @@ func (g *GrafanaServerImpl) writePIDFile() {
g.log.Info("Writing PID file", "path", *pidFile, "pid", pid)
}
func SendSystemdNotification(state string) error {
notifySocket := os.Getenv("NOTIFY_SOCKET")
if notifySocket == "" {
return fmt.Errorf("NOTIFY_SOCKET environment variable empty or unset.")
}
socketAddr := &net.UnixAddr{
Name: notifySocket,
Net: "unixgram",
}
conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr)
if err != nil {
return err
}
_, err = conn.Write([]byte(state))
conn.Close()
return err
}

View File

@@ -38,6 +38,7 @@ func TestLogFile(t *testing.T) {
So(fileLogWrite.maxlines_curlines, ShouldEqual, 3)
})
fileLogWrite.Close()
err = os.Remove(fileLogWrite.Filename)
So(err, ShouldBeNil)
})

View File

@@ -366,7 +366,6 @@ func TestAlertRuleExtraction(t *testing.T) {
"steppedLine": false,
"targets": [
{
"dsType": "influxdb",
"groupBy": [
{
"params": [
@@ -411,7 +410,6 @@ func TestAlertRuleExtraction(t *testing.T) {
"tags": []
},
{
"dsType": "influxdb",
"groupBy": [
{
"params": [

View File

@@ -6,6 +6,7 @@ import (
"io"
"mime/multipart"
"os"
"path/filepath"
"time"
"github.com/grafana/grafana/pkg/bus"
@@ -176,7 +177,7 @@ func (this *SlackNotifier) Notify(evalContext *alerting.EvalContext) error {
func SlackFileUpload(evalContext *alerting.EvalContext, log log.Logger, url string, recipient string, token string) error {
if evalContext.ImageOnDiskPath == "" {
evalContext.ImageOnDiskPath = "public/img/mixed_styles.png"
evalContext.ImageOnDiskPath = filepath.Join(setting.HomePath, "public/img/mixed_styles.png")
}
log.Info("Uploading to slack via file.upload API")
headers, uploadBody, err := GenerateSlackBody(evalContext.ImageOnDiskPath, token, recipient)

View File

@@ -401,7 +401,7 @@ func SearchUsers(query *m.SearchUsersQuery) error {
}
if query.Query != "" {
whereConditions = append(whereConditions, "(email LIKE ? OR name LIKE ? OR login like ?)")
whereConditions = append(whereConditions, "(email "+dialect.LikeStr()+" ? OR name "+dialect.LikeStr()+" ? OR login "+dialect.LikeStr()+" ?)")
whereParams = append(whereParams, queryWithWildcards, queryWithWildcards, queryWithWildcards)
}

View File

@@ -17,7 +17,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb"
opentracing "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go"
)
type GraphiteExecutor struct {
@@ -158,7 +158,7 @@ func formatTimeRange(input string) string {
if input == "now" {
return input
}
return strings.Replace(strings.Replace(input, "m", "min", -1), "M", "mon", -1)
return strings.Replace(strings.Replace(strings.Replace(input, "now", "", -1), "m", "min", -1), "M", "mon", -1)
}
func fixIntervalFormat(target string) string {

View File

@@ -18,14 +18,14 @@ func TestGraphiteFunctions(t *testing.T) {
Convey("formatting time range for now-1m", func() {
timeRange := formatTimeRange("now-1m")
So(timeRange, ShouldEqual, "now-1min")
So(timeRange, ShouldEqual, "-1min")
})
Convey("formatting time range for now-1M", func() {
timeRange := formatTimeRange("now-1M")
So(timeRange, ShouldEqual, "now-1mon")
So(timeRange, ShouldEqual, "-1mon")
})

View File

@@ -20,7 +20,6 @@ func TestInfluxdbQueryParser(t *testing.T) {
Convey("can parse influxdb json model", func() {
json := `
{
"dsType": "influxdb",
"groupBy": [
{
"params": [
@@ -123,7 +122,6 @@ func TestInfluxdbQueryParser(t *testing.T) {
Convey("can part raw query json model", func() {
json := `
{
"dsType": "influxdb",
"groupBy": [
{
"params": [

View File

@@ -50,6 +50,7 @@ func (rp *ResponseParser) transformRows(rows []Row, queryResult *tsdb.QueryResul
result = append(result, &tsdb.TimeSeries{
Name: rp.formatSerieName(row, column, query),
Points: points,
Tags: row.Tags,
})
}
}

View File

@@ -78,6 +78,15 @@ func (e PostgresQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Ro
rowLimit := 1000000
rowCount := 0
timeIndex := -1
// check if there is a column named time
for i, col := range columnNames {
switch col {
case "time":
timeIndex = i
}
}
for ; rows.Next(); rowCount++ {
if rowCount > rowLimit {
@@ -89,6 +98,15 @@ func (e PostgresQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Ro
return err
}
// convert column named time to unix timestamp to make
// native datetime postgres types work in annotation queries
if timeIndex != -1 {
switch value := values[timeIndex].(type) {
case time.Time:
values[timeIndex] = float64(value.UnixNano() / 1e9)
}
}
table.Rows = append(table.Rows, values)
}
@@ -142,8 +160,13 @@ func (e PostgresQueryEndpoint) getTypedRowData(rows *core.Rows) (tsdb.RowValues,
func (e PostgresQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *core.Rows, result *tsdb.QueryResult) error {
pointsBySeries := make(map[string]*tsdb.TimeSeries)
seriesByQueryOrder := list.New()
columnNames, err := rows.Columns()
columnNames, err := rows.Columns()
if err != nil {
return err
}
columnTypes, err := rows.ColumnTypes()
if err != nil {
return err
}
@@ -153,13 +176,21 @@ func (e PostgresQueryEndpoint) transformToTimeSeries(query *tsdb.Query, rows *co
timeIndex := -1
metricIndex := -1
// check columns of resultset
// check columns of resultset: a column named time is mandatory
// the first text column is treated as metric name unless a column named metric is present
for i, col := range columnNames {
switch col {
case "time":
timeIndex = i
case "metric":
metricIndex = i
default:
if metricIndex == -1 {
switch columnTypes[i].DatabaseTypeName() {
case "UNKNOWN", "TEXT", "VARCHAR", "CHAR":
metricIndex = i
}
}
}
}

View File

@@ -9,10 +9,15 @@ type UrlQueryReader struct {
values url.Values
}
func NewUrlQueryReader(url *url.URL) *UrlQueryReader {
return &UrlQueryReader{
values: url.Query(),
func NewUrlQueryReader(urlInfo *url.URL) (*UrlQueryReader, error) {
u, err := url.ParseQuery(urlInfo.String())
if err != nil {
return nil, err
}
return &UrlQueryReader{
values: u,
}, nil
}
func (r *UrlQueryReader) Get(name string, def string) string {