Merge branch 'master' of github.com:grafana/grafana into develop

This commit is contained in:
Torkel Ödegaard
2017-09-28 10:37:57 +02:00
145 changed files with 676 additions and 42551 deletions
+5 -2
View File
@@ -17,8 +17,11 @@ import (
)
var pluginProxyTransport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Renegotiation: tls.RenegotiateFreelyAsClient,
},
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
+4 -3
View File
@@ -43,7 +43,7 @@ func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response {
})
}
resp, err := tsdb.HandleRequest(context.Background(), request)
resp, err := tsdb.HandleRequest(context.Background(), dsQuery.Result, request)
if err != nil {
return ApiError(500, "Metric request error", err)
}
@@ -100,16 +100,17 @@ func GetTestDataRandomWalk(c *middleware.Context) Response {
timeRange := tsdb.NewTimeRange(from, to)
request := &tsdb.TsdbQuery{TimeRange: timeRange}
dsInfo := &models.DataSource{Type: "grafana-testdata-datasource"}
request.Queries = append(request.Queries, &tsdb.Query{
RefId: "A",
IntervalMs: intervalMs,
Model: simplejson.NewFromAny(&util.DynMap{
"scenario": "random_walk",
}),
DataSource: &models.DataSource{Type: "grafana-testdata-datasource"},
DataSource: dsInfo,
})
resp, err := tsdb.HandleRequest(context.Background(), request)
resp, err := tsdb.HandleRequest(context.Background(), dsInfo, request)
if err != nil {
return ApiError(500, "Metric request error", err)
}
@@ -19,6 +19,7 @@ type CommandLine interface {
PluginDirectory() string
RepoDirectory() string
PluginURL() string
}
type contextCommandLine struct {
@@ -44,3 +45,7 @@ func (c *contextCommandLine) PluginDirectory() string {
func (c *contextCommandLine) RepoDirectory() string {
return c.GlobalString("repo")
}
func (c *contextCommandLine) PluginURL() string {
return c.GlobalString("pluginUrl")
}
@@ -101,3 +101,7 @@ func (fcli *FakeCommandLine) RepoDirectory() string {
func (fcli *FakeCommandLine) PluginDirectory() string {
return fcli.GlobalString("pluginsDir")
}
func (fcli *FakeCommandLine) PluginURL() string {
return fcli.GlobalString("pluginUrl")
}
+22 -20
View File
@@ -58,37 +58,39 @@ func installCommand(c CommandLine) error {
}
func InstallPlugin(pluginName, version string, c CommandLine) error {
plugin, err := s.GetPlugin(pluginName, c.RepoDirectory())
pluginFolder := c.PluginDirectory()
if err != nil {
return err
downloadURL := c.PluginURL()
if downloadURL == "" {
plugin, err := s.GetPlugin(pluginName, c.RepoDirectory())
if err != nil {
return err
}
v, err := SelectVersion(plugin, version)
if err != nil {
return err
}
if version == "" {
version = v.Version
}
downloadURL = fmt.Sprintf("%s/%s/versions/%s/download",
c.GlobalString("repo"),
pluginName,
version)
}
v, err := SelectVersion(plugin, version)
if err != nil {
return err
}
if version == "" {
version = v.Version
}
downloadURL := fmt.Sprintf("%s/%s/versions/%s/download",
c.GlobalString("repo"),
pluginName,
version)
logger.Infof("installing %v @ %v\n", plugin.Id, version)
logger.Infof("installing %v @ %v\n", pluginName, version)
logger.Infof("from url: %v\n", downloadURL)
logger.Infof("into: %v\n", pluginFolder)
logger.Info("\n")
err = downloadFile(plugin.Id, pluginFolder, downloadURL)
err := downloadFile(pluginName, pluginFolder, downloadURL)
if err != nil {
return err
}
logger.Infof("%s Installed %s successfully \n", color.GreenString("✔"), plugin.Id)
logger.Infof("%s Installed %s successfully \n", color.GreenString("✔"), pluginName)
res, _ := s.ReadPlugin(pluginFolder, pluginName)
for _, v := range res.Dependencies.Plugins {
+6
View File
@@ -38,6 +38,12 @@ func main() {
Value: "https://grafana.com/api/plugins",
EnvVar: "GF_PLUGIN_REPO",
},
cli.StringFlag{
Name: "pluginUrl",
Usage: "Full url to the plugin zip file instead of downloading the plugin from grafana.com/api",
Value: "",
EnvVar: "GF_PLUGIN_URL",
},
cli.BoolFlag{
Name: "debug, d",
Usage: "enable debug logging",
+4 -1
View File
@@ -14,6 +14,7 @@ import (
"net/http"
_ "net/http/pprof"
"github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
@@ -29,7 +30,7 @@ import (
_ "github.com/grafana/grafana/pkg/tsdb/testdata"
)
var version = "4.1.0"
var version = "4.6.0"
var commit = "NA"
var buildstamp string
var build_date string
@@ -80,6 +81,8 @@ func main() {
setting.BuildCommit = commit
setting.BuildStamp = buildstampInt64
metrics.M_Grafana_Version.WithLabelValues(version).Set(1)
server := NewGrafanaServer()
server.Start()
}
+10 -4
View File
@@ -28,15 +28,21 @@ func NewImageUploader() (ImageUploader, error) {
return nil, err
}
bucket := s3sec.Key("bucket").MustString("")
region := s3sec.Key("region").MustString("")
bucketUrl := s3sec.Key("bucket_url").MustString("")
accessKey := s3sec.Key("access_key").MustString("")
secretKey := s3sec.Key("secret_key").MustString("")
info, err := getRegionAndBucketFromUrl(bucketUrl)
if err != nil {
return nil, err
if bucket == "" || region == "" {
info, err := getRegionAndBucketFromUrl(bucketUrl)
if err != nil {
return nil, err
}
bucket = info.bucket
region = info.region
}
return NewS3Uploader(info.region, info.bucket, "public-read", accessKey, secretKey), nil
return NewS3Uploader(region, bucket, "public-read", accessKey, secretKey), nil
case "webdav":
webdavSec, err := setting.Cfg.GetSection("external_image_storage.webdav")
if err != nil {
+5 -7
View File
@@ -9,6 +9,7 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/grafana/grafana/pkg/log"
@@ -54,8 +55,10 @@ func (u *S3Uploader) Upload(ctx context.Context, imageDiskPath string) (string,
Credentials: creds,
}
s3_endpoint, _ := endpoints.DefaultResolver().EndpointFor("s3", u.region)
key := util.GetRandomString(20) + ".png"
log.Debug("Uploading image to s3", "bucket = ", u.bucket, ", key = ", key)
image_url := s3_endpoint.URL + "/" + u.bucket + "/" + key
log.Debug("Uploading image to s3", "url = ", image_url)
file, err := os.Open(imageDiskPath)
if err != nil {
@@ -78,10 +81,5 @@ func (u *S3Uploader) Upload(ctx context.Context, imageDiskPath string) (string,
if err != nil {
return "", err
}
if u.region == "us-east-1" {
return "https://" + u.bucket + ".s3.amazonaws.com/" + key, nil
} else {
return "https://" + u.bucket + ".s3-" + u.region + ".amazonaws.com/" + key, nil
}
return image_url, nil
}
+10 -1
View File
@@ -56,6 +56,7 @@ var (
M_StatTotal_Users prometheus.Gauge
M_StatTotal_Orgs prometheus.Gauge
M_StatTotal_Playlists prometheus.Gauge
M_Grafana_Version *prometheus.GaugeVec
)
func init() {
@@ -263,6 +264,13 @@ func init() {
Help: "total amount of playlists",
Namespace: exporterName,
})
M_Grafana_Version = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "info",
Help: "Information about the Grafana",
Namespace: exporterName,
}, []string{"version"})
}
func initMetricVars(settings *MetricSettings) {
@@ -298,7 +306,8 @@ func initMetricVars(settings *MetricSettings) {
M_StatTotal_Dashboards,
M_StatTotal_Users,
M_StatTotal_Orgs,
M_StatTotal_Playlists)
M_StatTotal_Playlists,
M_Grafana_Version)
go instrumentationLoop(settings)
}
+1
View File
@@ -48,6 +48,7 @@ func (ds *DataSource) GetHttpTransport() (*http.Transport, error) {
transport := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
Renegotiation: tls.RenegotiateFreelyAsClient,
},
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
+1 -1
View File
@@ -112,7 +112,7 @@ func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange *
req := c.getRequestForAlertRule(getDsInfo.Result, timeRange)
result := make(tsdb.TimeSeriesSlice, 0)
resp, err := c.HandleRequest(context.Ctx, req)
resp, err := c.HandleRequest(context.Ctx, getDsInfo.Result, req)
if err != nil {
if err == gocontext.DeadlineExceeded {
return nil, fmt.Errorf("Alert execution exceeded the timeout")
@@ -168,7 +168,7 @@ func (ctx *queryConditionTestContext) exec() (*alerting.ConditionResult, error)
ctx.condition = condition
condition.HandleRequest = func(context context.Context, req *tsdb.TsdbQuery) (*tsdb.Response, error) {
condition.HandleRequest = func(context context.Context, dsInfo *m.DataSource, req *tsdb.TsdbQuery) (*tsdb.Response, error) {
return &tsdb.Response{
Results: map[string]*tsdb.QueryResult{
"A": {Series: ctx.series},
+5 -1
View File
@@ -101,7 +101,11 @@ func createDialer() (*gomail.Dialer, error) {
d := gomail.NewDialer(host, iPort, setting.Smtp.User, setting.Smtp.Password)
d.TLSConfig = tlsconfig
d.LocalName = setting.InstanceName
if setting.Smtp.EhloIdentity != "" {
d.LocalName = setting.Smtp.EhloIdentity
} else {
d.LocalName = setting.InstanceName
}
return d, nil
}
+11 -9
View File
@@ -1,15 +1,16 @@
package setting
type SmtpSettings struct {
Enabled bool
Host string
User string
Password string
CertFile string
KeyFile string
FromAddress string
FromName string
SkipVerify bool
Enabled bool
Host string
User string
Password string
CertFile string
KeyFile string
FromAddress string
FromName string
EhloIdentity string
SkipVerify bool
SendWelcomeEmailOnSignUp bool
TemplatesPattern string
@@ -25,6 +26,7 @@ func readSmtpSettings() {
Smtp.KeyFile = sec.Key("key_file").String()
Smtp.FromAddress = sec.Key("from_address").String()
Smtp.FromName = sec.Key("from_name").String()
Smtp.EhloIdentity = sec.Key("ehlo_identity").String()
Smtp.SkipVerify = sec.Key("skip_verify").MustBool(false)
emails := Cfg.Section("emails")
+5 -5
View File
@@ -20,18 +20,18 @@ func NewFakeExecutor(dsInfo *models.DataSource) (*FakeExecutor, error) {
}, nil
}
func (e *FakeExecutor) Query(ctx context.Context, dsInfo *models.DataSource, context *TsdbQuery) *BatchResult {
result := &BatchResult{QueryResults: make(map[string]*QueryResult)}
func (e *FakeExecutor) Query(ctx context.Context, dsInfo *models.DataSource, context *TsdbQuery) (*Response, error) {
result := &Response{Results: make(map[string]*QueryResult)}
for _, query := range context.Queries {
if results, has := e.results[query.RefId]; has {
result.QueryResults[query.RefId] = results
result.Results[query.RefId] = results
}
if testFunc, has := e.resultsFn[query.RefId]; has {
result.QueryResults[query.RefId] = testFunc(context)
result.Results[query.RefId] = testFunc(context)
}
}
return result
return result, nil
}
func (e *FakeExecutor) Return(refId string, series TimeSeriesSlice) {
+9 -13
View File
@@ -37,8 +37,8 @@ func init() {
tsdb.RegisterTsdbQueryEndpoint("graphite", NewGraphiteExecutor)
}
func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{}
func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{}
from := "-" + formatTimeRange(tsdbQuery.TimeRange.From)
until := formatTimeRange(tsdbQuery.TimeRange.To)
@@ -67,14 +67,12 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
req, err := e.createRequest(dsInfo, formData)
if err != nil {
result.Error = err
return result
return nil, err
}
httpClient, err := dsInfo.GetHttpClient()
if err != nil {
result.Error = err
return result
return nil, err
}
span, ctx := opentracing.StartSpanFromContext(ctx, "graphite query")
@@ -90,17 +88,15 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
res, err := ctxhttp.Do(ctx, httpClient, req)
if err != nil {
result.Error = err
return result
return nil, err
}
data, err := e.parseResponse(res)
if err != nil {
result.Error = err
return result
return nil, err
}
result.QueryResults = make(map[string]*tsdb.QueryResult)
result.Results = make(map[string]*tsdb.QueryResult)
queryRes := tsdb.NewQueryResult()
for _, series := range data {
@@ -114,8 +110,8 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
}
}
result.QueryResults["A"] = queryRes
return result
result.Results["A"] = queryRes
return result, nil
}
func (e *GraphiteExecutor) parseResponse(res *http.Response) ([]TargetResponseDTO, error) {
+13 -13
View File
@@ -39,17 +39,17 @@ func init() {
tsdb.RegisterTsdbQueryEndpoint("influxdb", NewInfluxDBExecutor)
}
func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{}
func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{}
query, err := e.getQuery(dsInfo, tsdbQuery.Queries, tsdbQuery)
if err != nil {
return result.WithError(err)
return nil, err
}
rawQuery, err := query.Build(tsdbQuery)
if err != nil {
return result.WithError(err)
return nil, err
}
if setting.Env == setting.DEV {
@@ -58,21 +58,21 @@ func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
req, err := e.createRequest(dsInfo, rawQuery)
if err != nil {
return result.WithError(err)
return nil, err
}
httpClient, err := dsInfo.GetHttpClient()
if err != nil {
return result.WithError(err)
return nil, err
}
resp, err := ctxhttp.Do(ctx, httpClient, req)
if err != nil {
return result.WithError(err)
return nil, err
}
if resp.StatusCode/100 != 2 {
return result.WithError(fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status))
return nil, fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status)
}
var response Response
@@ -82,17 +82,17 @@ func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
err = dec.Decode(&response)
if err != nil {
return result.WithError(err)
return nil, err
}
if response.Err != nil {
return result.WithError(response.Err)
return nil, response.Err
}
result.QueryResults = make(map[string]*tsdb.QueryResult)
result.QueryResults["A"] = e.ResponseParser.Parse(&response, query)
result.Results = make(map[string]*tsdb.QueryResult)
result.Results["A"] = e.ResponseParser.Parse(&response, query)
return result
return result, nil
}
func (e *InfluxDBExecutor) getQuery(dsInfo *models.DataSource, queries []*tsdb.Query, context *tsdb.TsdbQuery) (*Query, error) {
+2 -18
View File
@@ -22,24 +22,8 @@ type Query struct {
}
type Response struct {
BatchTimings []*BatchTiming `json:"timings"`
Results map[string]*QueryResult `json:"results"`
Message string `json:"message,omitempty"`
}
type BatchTiming struct {
TimeElapsed int64
}
type BatchResult struct {
Error error
QueryResults map[string]*QueryResult
Timings *BatchTiming
}
func (br *BatchResult) WithError(err error) *BatchResult {
br.Error = err
return br
Results map[string]*QueryResult `json:"results"`
Message string `json:"message,omitempty"`
}
type QueryResult struct {
+5 -5
View File
@@ -85,9 +85,9 @@ func (e *MysqlExecutor) initEngine(dsInfo *models.DataSource) error {
return nil
}
func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{
QueryResults: make(map[string]*tsdb.QueryResult),
func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{
Results: make(map[string]*tsdb.QueryResult),
}
macroEngine := NewMysqlMacroEngine(tsdbQuery.TimeRange)
@@ -102,7 +102,7 @@ func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, ts
}
queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: query.RefId}
result.QueryResults[query.RefId] = queryResult
result.Results[query.RefId] = queryResult
rawSql, err := macroEngine.Interpolate(rawSql)
if err != nil {
@@ -138,7 +138,7 @@ func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, ts
}
}
return result
return result, nil
}
func (e MysqlExecutor) TransformToTable(query *tsdb.Query, rows *core.Rows, result *tsdb.QueryResult) error {
+8 -11
View File
@@ -50,8 +50,8 @@ func init() {
tsdb.RegisterTsdbQueryEndpoint("opentsdb", NewOpenTsdbExecutor)
}
func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource, queryContext *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{}
func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{}
var tsdbQuery OpenTsdbQuery
@@ -69,29 +69,26 @@ func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource,
req, err := e.createRequest(dsInfo, tsdbQuery)
if err != nil {
result.Error = err
return result
return nil, err
}
httpClient, err := dsInfo.GetHttpClient()
if err != nil {
result.Error = err
return result
return nil, err
}
res, err := ctxhttp.Do(ctx, httpClient, req)
if err != nil {
result.Error = err
return result
return nil, err
}
queryResult, err := e.parseResponse(tsdbQuery, res)
if err != nil {
return result.WithError(err)
return nil, err
}
result.QueryResults = queryResult
return result
result.Results = queryResult
return result, nil
}
func (e *OpenTsdbExecutor) createRequest(dsInfo *models.DataSource, data OpenTsdbQuery) (*http.Request, error) {
+8 -8
View File
@@ -80,17 +80,17 @@ func (e *PrometheusExecutor) getClient(dsInfo *models.DataSource) (apiv1.API, er
return apiv1.NewAPI(client), nil
}
func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{}
func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{}
client, err := e.getClient(dsInfo)
if err != nil {
return result.WithError(err)
return nil, err
}
query, err := parseQuery(tsdbQuery.Queries, tsdbQuery)
if err != nil {
return result.WithError(err)
return nil, err
}
timeRange := apiv1.Range{
@@ -108,15 +108,15 @@ func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSourc
value, err := client.QueryRange(ctx, query.Expr, timeRange)
if err != nil {
return result.WithError(err)
return nil, err
}
queryResult, err := parseResponse(value, query)
if err != nil {
return result.WithError(err)
return nil, err
}
result.QueryResults = queryResult
return result
result.Results = queryResult
return result, nil
}
func formatLegend(metric model.Metric, query *PrometheusQuery) string {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
)
type TsdbQueryEndpoint interface {
Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) *BatchResult
Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) (*Response, error)
}
var registry map[string]GetTsdbQueryEndpointFn
+6 -14
View File
@@ -2,25 +2,17 @@ package tsdb
import (
"context"
"github.com/grafana/grafana/pkg/models"
)
type HandleRequestFunc func(ctx context.Context, req *TsdbQuery) (*Response, error)
type HandleRequestFunc func(ctx context.Context, dsInfo *models.DataSource, req *TsdbQuery) (*Response, error)
func HandleRequest(ctx context.Context, req *TsdbQuery) (*Response, error) {
//TODO niceify
ds := req.Queries[0].DataSource
endpoint, err := getTsdbQueryEndpointFor(ds)
func HandleRequest(ctx context.Context, dsInfo *models.DataSource, req *TsdbQuery) (*Response, error) {
endpoint, err := getTsdbQueryEndpointFor(dsInfo)
if err != nil {
return nil, err
}
res := endpoint.Query(ctx, ds, req)
if res.Error != nil {
return nil, res.Error
}
return &Response{
Results: res.QueryResults,
BatchTimings: []*BatchTiming{res.Timings},
}, nil
return endpoint.Query(ctx, dsInfo, req)
}
+61
View File
@@ -29,6 +29,67 @@ func init() {
logger.Debug("Initializing TestData Scenario")
registerScenario(&Scenario{
Id: "exponential_heatmap_bucket_data",
Name: "Exponential heatmap bucket data",
Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
to := context.TimeRange.GetToAsMsEpoch()
var series []*tsdb.TimeSeries
start := 1
factor := 2
for i := 0; i < 10; i++ {
timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
serie := &tsdb.TimeSeries{Name: strconv.Itoa(start)}
start *= factor
points := make(tsdb.TimeSeriesPoints, 0)
for j := int64(0); j < 100 && timeWalkerMs < to; j++ {
v := float64(rand.Int63n(100))
points = append(points, tsdb.NewTimePoint(null.FloatFrom(v), float64(timeWalkerMs)))
timeWalkerMs += query.IntervalMs * 50
}
serie.Points = points
series = append(series, serie)
}
queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, series...)
return queryRes
},
})
registerScenario(&Scenario{
Id: "linear_heatmap_bucket_data",
Name: "Linear heatmap bucket data",
Handler: func(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.QueryResult {
to := context.TimeRange.GetToAsMsEpoch()
var series []*tsdb.TimeSeries
for i := 0; i < 10; i++ {
timeWalkerMs := context.TimeRange.GetFromAsMsEpoch()
serie := &tsdb.TimeSeries{Name: strconv.Itoa(i * 10)}
points := make(tsdb.TimeSeriesPoints, 0)
for j := int64(0); j < 100 && timeWalkerMs < to; j++ {
v := float64(rand.Int63n(100))
points = append(points, tsdb.NewTimePoint(null.FloatFrom(v), float64(timeWalkerMs)))
timeWalkerMs += query.IntervalMs * 50
}
serie.Points = points
series = append(series, serie)
}
queryRes := tsdb.NewQueryResult()
queryRes.Series = append(queryRes.Series, series...)
return queryRes
},
})
registerScenario(&Scenario{
Id: "random_walk",
Name: "Random Walk",
+6 -6
View File
@@ -24,19 +24,19 @@ func init() {
tsdb.RegisterTsdbQueryEndpoint("grafana-testdata-datasource", NewTestDataExecutor)
}
func (e *TestDataExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult {
result := &tsdb.BatchResult{}
result.QueryResults = make(map[string]*tsdb.QueryResult)
func (e *TestDataExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) {
result := &tsdb.Response{}
result.Results = make(map[string]*tsdb.QueryResult)
for _, query := range tsdbQuery.Queries {
scenarioId := query.Model.Get("scenarioId").MustString("random_walk")
if scenario, exist := ScenarioRegistry[scenarioId]; exist {
result.QueryResults[query.RefId] = scenario.Handler(query, tsdbQuery)
result.QueryResults[query.RefId].RefId = query.RefId
result.Results[query.RefId] = scenario.Handler(query, tsdbQuery)
result.Results[query.RefId].RefId = query.RefId
} else {
e.log.Error("Scenario not found", "scenarioId", scenarioId)
}
}
return result
return result, nil
}
+3 -8
View File
@@ -19,7 +19,7 @@ func TestMetricQuery(t *testing.T) {
fakeExecutor := registerFakeExecutor()
fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}})
res, err := HandleRequest(context.TODO(), req)
res, err := HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req)
So(err, ShouldBeNil)
Convey("Should return query results", func() {
@@ -40,18 +40,13 @@ func TestMetricQuery(t *testing.T) {
fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}})
fakeExecutor.Return("B", TimeSeriesSlice{&TimeSeries{Name: "barg"}})
res, err := HandleRequest(context.TODO(), req)
res, err := HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req)
So(err, ShouldBeNil)
Convey("Should return query results", func() {
So(len(res.Results), ShouldEqual, 2)
So(res.Results["B"].Series[0].Name, ShouldEqual, "barg")
})
Convey("Should have been batched in one request", func() {
So(len(res.BatchTimings), ShouldEqual, 1)
})
})
Convey("When query uses data source of unknown type", t, func() {
@@ -61,7 +56,7 @@ func TestMetricQuery(t *testing.T) {
},
}
_, err := HandleRequest(context.TODO(), req)
_, err := HandleRequest(context.TODO(), &models.DataSource{Id: 12, Type: "testjughjgjg"}, req)
So(err, ShouldNotBeNil)
})
}