Merge branch 'master' of github.com:grafana/grafana into develop
This commit is contained in:
@@ -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
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
Vendored
+61
@@ -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",
|
||||
|
||||
Vendored
+6
-6
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user