Introduce TSDB service (#31520)

* Introduce TSDB service

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
Co-authored-by: Will Browne <will.browne@grafana.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
Arve Knudsen
2021-03-08 07:02:49 +01:00
committed by GitHub
parent c899bf3592
commit b79e61656a
203 changed files with 5270 additions and 4777 deletions

View File

@@ -128,19 +128,13 @@ func GetAlerts(c *models.ReqContext) response.Response {
}
// POST /api/alerts/test
func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) response.Response {
func (hs *HTTPServer) AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) response.Response {
if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil {
return response.Error(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
}
backendCmd := alerting.AlertTestCommand{
OrgID: c.OrgId,
Dashboard: dto.Dashboard,
PanelID: dto.PanelId,
User: c.SignedInUser,
}
if err := bus.Dispatch(&backendCmd); err != nil {
res, err := hs.AlertEngine.AlertTest(c.OrgId, dto.Dashboard, dto.PanelId, c.SignedInUser)
if err != nil {
var validationErr alerting.ValidationError
if errors.As(err, &validationErr) {
return response.Error(422, validationErr.Error(), nil)
@@ -151,7 +145,6 @@ func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) response.Respons
return response.Error(500, "Failed to test rule", err)
}
res := backendCmd.Result
dtoRes := &dtos.AlertTestResult{
Firing: res.Firing,
ConditionEvals: res.ConditionEvals,

View File

@@ -266,14 +266,14 @@ func (hs *HTTPServer) registerRoutes() {
apiRoute.Get("/plugins", routing.Wrap(hs.GetPluginList))
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(GetPluginSettingByID))
apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(GetPluginMarkdown))
apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(hs.GetPluginMarkdown))
apiRoute.Get("/plugins/:pluginId/health", routing.Wrap(hs.CheckHealth))
apiRoute.Any("/plugins/:pluginId/resources", hs.CallResource)
apiRoute.Any("/plugins/:pluginId/resources/*", hs.CallResource)
apiRoute.Any("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList))
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
pluginRoute.Get("/:pluginId/dashboards/", routing.Wrap(GetPluginDashboards))
pluginRoute.Get("/:pluginId/dashboards/", routing.Wrap(hs.GetPluginDashboards))
pluginRoute.Post("/:pluginId/settings", bind(models.UpdatePluginSettingCmd{}), routing.Wrap(UpdatePluginSetting))
pluginRoute.Get("/:pluginId/metrics", routing.Wrap(hs.CollectPluginMetrics))
}, reqOrgAdmin)
@@ -316,7 +316,7 @@ func (hs *HTTPServer) registerRoutes() {
dashboardRoute.Post("/db", bind(models.SaveDashboardCommand{}), routing.Wrap(hs.PostDashboard))
dashboardRoute.Get("/home", routing.Wrap(hs.GetHomeDashboard))
dashboardRoute.Get("/tags", GetDashboardTags)
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), routing.Wrap(ImportDashboard))
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), routing.Wrap(hs.ImportDashboard))
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) {
dashIdRoute.Get("/versions", routing.Wrap(GetDashboardVersions))
@@ -353,13 +353,13 @@ func (hs *HTTPServer) registerRoutes() {
// metrics
apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetrics))
apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, routing.Wrap(GenerateSQLTestData))
apiRoute.Get("/tsdb/testdata/random-walk", routing.Wrap(GetTestDataRandomWalk))
apiRoute.Get("/tsdb/testdata/random-walk", routing.Wrap(hs.GetTestDataRandomWalk))
// DataSource w/ expressions
apiRoute.Post("/ds/query", bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetricsV2))
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), routing.Wrap(AlertTest))
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), routing.Wrap(hs.AlertTest))
alertsRoute.Post("/:alertId/pause", reqEditorRole, bind(dtos.PauseAlertCommand{}), routing.Wrap(PauseAlert))
alertsRoute.Get("/:alertId", ValidateOrgAlert, routing.Wrap(GetAlert))
alertsRoute.Get("/", routing.Wrap(GetAlerts))

View File

@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/util"
macaron "gopkg.in/macaron.v1"
)
@@ -31,7 +32,7 @@ func (hs *HTTPServer) initAppPluginRoutes(r *macaron.Macaron) {
TLSHandshakeTimeout: 10 * time.Second,
}
for _, plugin := range plugins.Apps {
for _, plugin := range manager.Apps {
for _, route := range plugin.Routes {
url := util.JoinURLFragments("/api/plugin-proxy/"+plugin.Id, route.Path)
handlers := make([]macaron.Handler, 0)

View File

@@ -8,6 +8,7 @@ import (
"path/filepath"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/dashboards"
@@ -17,7 +18,6 @@ import (
"github.com/grafana/grafana/pkg/components/dashdiffs"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/util"
)
@@ -226,7 +226,7 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response {
}
}
err := dashboards.NewService().DeleteDashboard(dash.Id, c.OrgId)
err := dashboards.NewService(hs.DataService).DeleteDashboard(dash.Id, c.OrgId)
if err != nil {
var dashboardErr models.DashboardErr
if ok := errors.As(err, &dashboardErr); ok {
@@ -288,7 +288,7 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa
Overwrite: cmd.Overwrite,
}
dashboard, err := dashboards.NewService().SaveDashboard(dashItem, allowUiUpdate)
dashboard, err := dashboards.NewService(hs.DataService).SaveDashboard(dashItem, allowUiUpdate)
if err != nil {
return dashboardSaveErrorToApiResponse(err)
}
@@ -356,7 +356,7 @@ func dashboardSaveErrorToApiResponse(err error) response.Response {
if ok := errors.As(err, &pluginErr); ok {
message := fmt.Sprintf("The dashboard belongs to plugin %s.", pluginErr.PluginId)
// look up plugin name
if pluginDef, exist := plugins.Plugins[pluginErr.PluginId]; exist {
if pluginDef, exist := manager.Plugins[pluginErr.PluginId]; exist {
message = fmt.Sprintf("The dashboard belongs to plugin %s.", pluginDef.Name)
}
return response.JSON(412, util.DynMap{"status": "plugin-dashboard", "message": message})

View File

@@ -9,7 +9,7 @@ import (
"github.com/grafana/grafana/pkg/api/pluginproxy"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
)
// ProxyDataSourceRequest proxies datasource requests
@@ -34,7 +34,7 @@ func (hs *HTTPServer) ProxyDataSourceRequest(c *models.ReqContext) {
}
// find plugin
plugin, ok := plugins.DataSources[ds.Type]
plugin, ok := manager.DataSources[ds.Type]
if !ok {
c.JsonApiErr(http.StatusInternalServerError, "Unable to find datasource plugin", err)
return

View File

@@ -13,8 +13,8 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/datasource/wrapper"
"github.com/grafana/grafana/pkg/plugins/adapters"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/util"
)
@@ -47,7 +47,7 @@ func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response {
ReadOnly: ds.ReadOnly,
}
if plugin, exists := plugins.DataSources[ds.Type]; exists {
if plugin, exists := manager.DataSources[ds.Type]; exists {
dsItem.TypeLogoUrl = plugin.Info.Logos.Small
dsItem.TypeName = plugin.Name
} else {
@@ -363,19 +363,19 @@ func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) {
}
// find plugin
plugin, ok := plugins.DataSources[ds.Type]
plugin, ok := manager.DataSources[ds.Type]
if !ok {
c.JsonApiErr(500, "Unable to find datasource plugin", err)
return
}
dsInstanceSettings, err := wrapper.ModelToInstanceSettings(ds)
dsInstanceSettings, err := adapters.ModelToInstanceSettings(ds)
if err != nil {
c.JsonApiErr(500, "Unable to process datasource instance model", err)
}
pCtx := backend.PluginContext{
User: wrapper.BackendUserFromSignedInUser(c.SignedInUser),
User: adapters.BackendUserFromSignedInUser(c.SignedInUser),
OrgID: c.OrgId,
PluginID: plugin.Id,
DataSourceInstanceSettings: dsInstanceSettings,
@@ -433,12 +433,12 @@ func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Respo
return response.Error(500, "Unable to find datasource plugin", err)
}
dsInstanceSettings, err := wrapper.ModelToInstanceSettings(ds)
dsInstanceSettings, err := adapters.ModelToInstanceSettings(ds)
if err != nil {
return response.Error(500, "Unable to get datasource model", err)
}
pCtx := backend.PluginContext{
User: wrapper.BackendUserFromSignedInUser(c.SignedInUser),
User: adapters.BackendUserFromSignedInUser(c.SignedInUser),
OrgID: c.OrgId,
PluginID: plugin.Id,
DataSourceInstanceSettings: dsInstanceSettings,

View File

@@ -3,6 +3,7 @@ package dtos
import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
)
type PluginSetting struct {
@@ -63,6 +64,6 @@ type ImportDashboardCommand struct {
Path string `json:"path"`
Overwrite bool `json:"overwrite"`
Dashboard *simplejson.Json `json:"dashboard"`
Inputs []plugins.ImportDashboardInput `json:"inputs"`
Inputs []manager.ImportDashboardInput `json:"inputs"`
FolderId int64 `json:"folderId"`
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/setting"
log "github.com/inconshreveable/log15"
@@ -90,7 +91,7 @@ func TestFrontendLoggingEndpoint(t *testing.T) {
require.NoError(t, err)
// fake plugin route so we will try to find a source map there. I can't believe I can do this
plugins.StaticRoutes = append(plugins.StaticRoutes, &plugins.PluginStaticRoute{
manager.StaticRoutes = append(manager.StaticRoutes, &plugins.PluginStaticRoute{
Directory: "/usr/local/telepathic-panel",
PluginId: "telepathic",
})

View File

@@ -12,7 +12,7 @@ import (
sourcemap "github.com/go-sourcemap/sourcemap"
"github.com/getsentry/sentry-go"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/setting"
)
@@ -80,7 +80,7 @@ func (store *SourceMapStore) guessSourceMapLocation(sourceURL string) (*sourceMa
}
// if source comes from a plugin, look in plugin dir
} else if strings.HasPrefix(u.Path, "/public/plugins/") {
for _, route := range plugins.StaticRoutes {
for _, route := range manager.StaticRoutes {
pluginPrefix := filepath.Join("/public/plugins/", route.PluginId)
if strings.HasPrefix(u.Path, pluginPrefix) {
return &sourceMapLocation{

View File

@@ -5,6 +5,7 @@ import (
"strconv"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/util"
@@ -109,12 +110,12 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins *plu
// add data sources that are built in (meaning they are not added via data sources page, nor have any entry in
// the datasource table)
for _, ds := range plugins.DataSources {
for _, ds := range manager.DataSources {
if ds.BuiltIn {
dataSources[ds.Name] = map[string]interface{}{
"type": ds.Type,
"name": ds.Name,
"meta": plugins.DataSources[ds.Id],
"meta": manager.DataSources[ds.Id],
}
}
}
@@ -124,7 +125,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins *plu
// getFrontendSettingsMap returns a json object with all the settings needed for front end initialisation.
func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]interface{}, error) {
enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId)
enabledPlugins, err := hs.PluginManager.GetEnabledPlugins(c.OrgId)
if err != nil {
return nil, err
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/services/licensing"
@@ -50,7 +50,7 @@ func setupTestEnvironment(t *testing.T, cfg *setting.Cfg) (*macaron.Macaron, *HT
Bus: bus.GetBus(),
License: &licensing.OSSLicensingService{Cfg: cfg},
RenderService: r,
PluginManager: &plugins.PluginManager{Cfg: cfg},
PluginManager: &manager.PluginManager{Cfg: cfg},
}
m := macaron.New()

View File

@@ -13,12 +13,12 @@ import (
"strings"
"sync"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/live"
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/shorturls"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/tsdb"
"github.com/grafana/grafana/pkg/api/routing"
httpstatic "github.com/grafana/grafana/pkg/api/static"
@@ -29,7 +29,10 @@ import (
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
_ "github.com/grafana/grafana/pkg/plugins/backendplugin/manager"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/plugins/plugindashboards"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/datasources"
@@ -76,13 +79,16 @@ type HTTPServer struct {
License models.Licensing `inject:""`
BackendPluginManager backendplugin.Manager `inject:""`
PluginRequestValidator models.PluginRequestValidator `inject:""`
PluginManager *plugins.PluginManager `inject:""`
PluginManager *manager.PluginManager `inject:""`
SearchService *search.SearchService `inject:""`
ShortURLService *shorturls.ShortURLService `inject:""`
Live *live.GrafanaLive `inject:""`
ContextHandler *contexthandler.ContextHandler `inject:""`
SQLStore *sqlstore.SQLStore `inject:""`
LibraryPanelService *librarypanels.LibraryPanelService `inject:""`
DataService *tsdb.Service `inject:""`
PluginDashboardService *plugindashboards.Service `inject:""`
AlertEngine *alerting.AlertEngine `inject:""`
Listener net.Listener
}
@@ -312,7 +318,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
m.Use(middleware.Recovery(hs.Cfg))
for _, route := range plugins.StaticRoutes {
for _, route := range manager.StaticRoutes {
pluginRoute := path.Join("/public/plugins/", route.PluginId)
hs.log.Debug("Plugins: Adding route", "route", pluginRoute, "dir", route.Directory)
hs.mapStatic(m, route.Directory, "", pluginRoute)

View File

@@ -8,7 +8,6 @@ import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/setting"
)
@@ -63,8 +62,8 @@ func getProfileNode(c *models.ReqContext) *dtos.NavLink {
}
}
func getAppLinks(c *models.ReqContext) ([]*dtos.NavLink, error) {
enabledPlugins, err := plugins.GetEnabledPlugins(c.OrgId)
func (hs *HTTPServer) getAppLinks(c *models.ReqContext) ([]*dtos.NavLink, error) {
enabledPlugins, err := hs.PluginManager.GetEnabledPlugins(c.OrgId)
if err != nil {
return nil, err
}
@@ -213,7 +212,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
})
}
appLinks, err := getAppLinks(c)
appLinks, err := hs.getAppLinks(c)
if err != nil {
return nil, err
}

View File

@@ -7,12 +7,12 @@ import (
"github.com/grafana/grafana/pkg/expr"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/tsdb"
"github.com/grafana/grafana/pkg/util"
)
@@ -23,11 +23,12 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
return response.Error(http.StatusBadRequest, "No queries found in query", nil)
}
request := &tsdb.TsdbQuery{
TimeRange: tsdb.NewTimeRange(reqDTO.From, reqDTO.To),
timeRange := plugins.NewDataTimeRange(reqDTO.From, reqDTO.To)
request := plugins.DataQuery{
TimeRange: &timeRange,
Debug: reqDTO.Debug,
User: c.SignedInUser,
Queries: make([]*tsdb.Query, 0, len(reqDTO.Queries)),
Queries: make([]plugins.DataSubQuery, 0, len(reqDTO.Queries)),
}
// Loop to see if we have an expression.
@@ -57,10 +58,10 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
}
}
request.Queries = append(request.Queries, &tsdb.Query{
RefId: query.Get("refId").MustString("A"),
request.Queries = append(request.Queries, plugins.DataSubQuery{
RefID: query.Get("refId").MustString("A"),
MaxDataPoints: query.Get("maxDataPoints").MustInt64(100),
IntervalMs: query.Get("intervalMs").MustInt64(1000),
IntervalMS: query.Get("intervalMs").MustInt64(1000),
QueryType: query.Get("queryType").MustString(""),
Model: query,
DataSource: ds,
@@ -72,7 +73,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
return response.Error(http.StatusForbidden, "Access denied", err)
}
resp, err := tsdb.HandleRequest(c.Req.Context(), ds, request)
resp, err := hs.DataService.HandleRequest(c.Req.Context(), ds, request)
if err != nil {
return response.Error(http.StatusInternalServerError, "Metric request error", err)
}
@@ -91,11 +92,12 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
// handleExpressions handles POST /api/ds/query when there is an expression.
func (hs *HTTPServer) handleExpressions(c *models.ReqContext, reqDTO dtos.MetricRequest) response.Response {
request := &tsdb.TsdbQuery{
TimeRange: tsdb.NewTimeRange(reqDTO.From, reqDTO.To),
timeRange := plugins.NewDataTimeRange(reqDTO.From, reqDTO.To)
request := plugins.DataQuery{
TimeRange: &timeRange,
Debug: reqDTO.Debug,
User: c.SignedInUser,
Queries: make([]*tsdb.Query, 0, len(reqDTO.Queries)),
Queries: make([]plugins.DataSubQuery, 0, len(reqDTO.Queries)),
}
for _, query := range reqDTO.Queries {
@@ -116,16 +118,19 @@ func (hs *HTTPServer) handleExpressions(c *models.ReqContext, reqDTO dtos.Metric
}
}
request.Queries = append(request.Queries, &tsdb.Query{
RefId: query.Get("refId").MustString("A"),
request.Queries = append(request.Queries, plugins.DataSubQuery{
RefID: query.Get("refId").MustString("A"),
MaxDataPoints: query.Get("maxDataPoints").MustInt64(100),
IntervalMs: query.Get("intervalMs").MustInt64(1000),
IntervalMS: query.Get("intervalMs").MustInt64(1000),
QueryType: query.Get("queryType").MustString(""),
Model: query,
})
}
exprService := expr.Service{Cfg: hs.Cfg}
exprService := expr.Service{
Cfg: hs.Cfg,
DataService: hs.DataService,
}
resp, err := exprService.WrapTransformData(c.Req.Context(), request)
if err != nil {
return response.Error(500, "expression request error", err)
@@ -157,8 +162,6 @@ func (hs *HTTPServer) handleGetDataSourceError(err error, datasourceID int64) *r
// QueryMetrics returns query metrics
// POST /api/tsdb/query
func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricRequest) response.Response {
timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To)
if len(reqDto.Queries) == 0 {
return response.Error(http.StatusBadRequest, "No queries found in query", nil)
}
@@ -178,23 +181,24 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricReque
return response.Error(http.StatusForbidden, "Access denied", err)
}
request := &tsdb.TsdbQuery{
TimeRange: timeRange,
timeRange := plugins.NewDataTimeRange(reqDto.From, reqDto.To)
request := plugins.DataQuery{
TimeRange: &timeRange,
Debug: reqDto.Debug,
User: c.SignedInUser,
}
for _, query := range reqDto.Queries {
request.Queries = append(request.Queries, &tsdb.Query{
RefId: query.Get("refId").MustString("A"),
request.Queries = append(request.Queries, plugins.DataSubQuery{
RefID: query.Get("refId").MustString("A"),
MaxDataPoints: query.Get("maxDataPoints").MustInt64(100),
IntervalMs: query.Get("intervalMs").MustInt64(1000),
IntervalMS: query.Get("intervalMs").MustInt64(1000),
Model: query,
DataSource: ds,
})
}
resp, err := tsdb.HandleRequest(c.Req.Context(), ds, request)
resp, err := hs.DataService.HandleRequest(c.Req.Context(), ds, request)
if err != nil {
return response.Error(http.StatusInternalServerError, "Metric request error", err)
}
@@ -221,28 +225,28 @@ func GenerateSQLTestData(c *models.ReqContext) response.Response {
}
// GET /api/tsdb/testdata/random-walk
func GetTestDataRandomWalk(c *models.ReqContext) response.Response {
func (hs *HTTPServer) GetTestDataRandomWalk(c *models.ReqContext) response.Response {
from := c.Query("from")
to := c.Query("to")
intervalMs := c.QueryInt64("intervalMs")
intervalMS := c.QueryInt64("intervalMs")
timeRange := tsdb.NewTimeRange(from, to)
request := &tsdb.TsdbQuery{TimeRange: timeRange}
timeRange := plugins.NewDataTimeRange(from, to)
request := plugins.DataQuery{TimeRange: &timeRange}
dsInfo := &models.DataSource{
Type: "testdata",
JsonData: simplejson.New(),
}
request.Queries = append(request.Queries, &tsdb.Query{
RefId: "A",
IntervalMs: intervalMs,
request.Queries = append(request.Queries, plugins.DataSubQuery{
RefID: "A",
IntervalMS: intervalMS,
Model: simplejson.NewFromAny(&util.DynMap{
"scenario": "random_walk",
}),
DataSource: dsInfo,
})
resp, err := tsdb.HandleRequest(context.Background(), dsInfo, request)
resp, err := hs.DataService.HandleRequest(context.Background(), dsInfo, request)
if err != nil {
return response.Error(500, "Metric request error", err)
}

View File

@@ -14,7 +14,8 @@ import (
)
// ApplyRoute should use the plugin route data to set auth headers and custom headers.
func ApplyRoute(ctx context.Context, req *http.Request, proxyPath string, route *plugins.AppPluginRoute, ds *models.DataSource) {
func ApplyRoute(ctx context.Context, req *http.Request, proxyPath string, route *plugins.AppPluginRoute,
ds *models.DataSource) {
proxyPath = strings.TrimPrefix(proxyPath, route.Path)
data := templateData{

View File

@@ -14,6 +14,7 @@ import (
"github.com/grafana/grafana/pkg/api/datasource"
"github.com/grafana/grafana/pkg/components/securejsondata"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -23,7 +24,6 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)

View File

@@ -20,7 +20,8 @@ type templateData struct {
}
// NewApiPluginProxy create a plugin proxy
func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.AppPluginRoute, appID string, cfg *setting.Cfg) *httputil.ReverseProxy {
func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.AppPluginRoute,
appID string, cfg *setting.Cfg) *httputil.ReverseProxy {
director := func(req *http.Request) {
query := models.GetPluginSettingByIdQuery{OrgId: ctx.OrgId, PluginId: appID}
if err := bus.Dispatch(&query); err != nil {

View File

@@ -14,8 +14,9 @@ import (
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/adapters"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/plugins/datasource/wrapper"
"github.com/grafana/grafana/pkg/plugins/manager"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
)
@@ -25,7 +26,7 @@ var ErrPluginNotFound error = errors.New("plugin not found, no installed plugin
func (hs *HTTPServer) getPluginContext(pluginID string, user *models.SignedInUser) (backend.PluginContext, error) {
pc := backend.PluginContext{}
plugin, exists := plugins.Plugins[pluginID]
plugin, exists := manager.Plugins[pluginID]
if !exists {
return pc, ErrPluginNotFound
}
@@ -53,7 +54,7 @@ func (hs *HTTPServer) getPluginContext(pluginID string, user *models.SignedInUse
return backend.PluginContext{
OrgID: user.OrgId,
PluginID: plugin.Id,
User: wrapper.BackendUserFromSignedInUser(user),
User: adapters.BackendUserFromSignedInUser(user),
AppInstanceSettings: &backend.AppInstanceSettings{
JSONData: jsonData,
DecryptedSecureJSONData: decryptedSecureJSONData,
@@ -73,14 +74,14 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
coreFilter = "1"
}
pluginSettingsMap, err := plugins.GetPluginSettings(c.OrgId)
pluginSettingsMap, err := hs.PluginManager.GetPluginSettings(c.OrgId)
if err != nil {
return response.Error(500, "Failed to get list of plugins", err)
}
result := make(dtos.PluginList, 0)
for _, pluginDef := range plugins.Plugins {
for _, pluginDef := range manager.Plugins {
// filter out app sub plugins
if embeddedFilter == "0" && pluginDef.IncludedInAppId != "" {
continue
@@ -130,7 +131,7 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
}
// filter out built in data sources
if ds, exists := plugins.DataSources[pluginDef.Id]; exists {
if ds, exists := manager.DataSources[pluginDef.Id]; exists {
if ds.BuiltIn {
continue
}
@@ -146,7 +147,7 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
func GetPluginSettingByID(c *models.ReqContext) response.Response {
pluginID := c.Params(":pluginId")
def, exists := plugins.Plugins[pluginID]
def, exists := manager.Plugins[pluginID]
if !exists {
return response.Error(404, "Plugin not found, no installed plugin with that id", nil)
}
@@ -169,7 +170,7 @@ func GetPluginSettingByID(c *models.ReqContext) response.Response {
SignatureOrg: def.SignatureOrg,
}
if app, ok := plugins.Apps[def.Id]; ok {
if app, ok := manager.Apps[def.Id]; ok {
dto.Enabled = app.AutoEnabled
dto.Pinned = app.AutoEnabled
}
@@ -194,7 +195,7 @@ func UpdatePluginSetting(c *models.ReqContext, cmd models.UpdatePluginSettingCmd
cmd.OrgId = c.OrgId
cmd.PluginId = pluginID
if _, ok := plugins.Apps[cmd.PluginId]; !ok {
if _, ok := manager.Apps[cmd.PluginId]; !ok {
return response.Error(404, "Plugin not installed.", nil)
}
@@ -205,10 +206,10 @@ func UpdatePluginSetting(c *models.ReqContext, cmd models.UpdatePluginSettingCmd
return response.Success("Plugin settings updated")
}
func GetPluginDashboards(c *models.ReqContext) response.Response {
func (hs *HTTPServer) GetPluginDashboards(c *models.ReqContext) response.Response {
pluginID := c.Params(":pluginId")
list, err := plugins.GetPluginDashboards(c.OrgId, pluginID)
list, err := hs.PluginManager.GetPluginDashboards(c.OrgId, pluginID)
if err != nil {
var notFound plugins.PluginNotFoundError
if errors.As(err, &notFound) {
@@ -221,11 +222,11 @@ func GetPluginDashboards(c *models.ReqContext) response.Response {
return response.JSON(200, list)
}
func GetPluginMarkdown(c *models.ReqContext) response.Response {
func (hs *HTTPServer) GetPluginMarkdown(c *models.ReqContext) response.Response {
pluginID := c.Params(":pluginId")
name := c.Params(":name")
content, err := plugins.GetPluginMarkdown(pluginID, name)
content, err := hs.PluginManager.GetPluginMarkdown(pluginID, name)
if err != nil {
var notFound plugins.PluginNotFoundError
if errors.As(err, &notFound) {
@@ -237,7 +238,7 @@ func GetPluginMarkdown(c *models.ReqContext) response.Response {
// fallback try readme
if len(content) == 0 {
content, err = plugins.GetPluginMarkdown(pluginID, "readme")
content, err = hs.PluginManager.GetPluginMarkdown(pluginID, "readme")
if err != nil {
return response.Error(501, "Could not get markdown file", err)
}
@@ -248,27 +249,18 @@ func GetPluginMarkdown(c *models.ReqContext) response.Response {
return resp
}
func ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) response.Response {
func (hs *HTTPServer) ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) response.Response {
if apiCmd.PluginId == "" && apiCmd.Dashboard == nil {
return response.Error(422, "Dashboard must be set", nil)
}
cmd := plugins.ImportDashboardCommand{
OrgId: c.OrgId,
User: c.SignedInUser,
PluginId: apiCmd.PluginId,
Path: apiCmd.Path,
Inputs: apiCmd.Inputs,
Overwrite: apiCmd.Overwrite,
FolderId: apiCmd.FolderId,
Dashboard: apiCmd.Dashboard,
}
if err := bus.Dispatch(&cmd); err != nil {
dashInfo, err := hs.PluginManager.ImportDashboard(apiCmd.PluginId, apiCmd.Path, c.OrgId, apiCmd.FolderId,
apiCmd.Dashboard, apiCmd.Overwrite, apiCmd.Inputs, c.SignedInUser, hs.DataService)
if err != nil {
return dashboardSaveErrorToApiResponse(err)
}
return response.JSON(200, cmd.Result)
return response.JSON(200, dashInfo)
}
// CollectPluginMetrics collect metrics from a plugin.
@@ -276,7 +268,7 @@ func ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) r
// /api/plugins/:pluginId/metrics
func (hs *HTTPServer) CollectPluginMetrics(c *models.ReqContext) response.Response {
pluginID := c.Params("pluginId")
plugin, exists := plugins.Plugins[pluginID]
plugin, exists := manager.Plugins[pluginID]
if !exists {
return response.Error(404, "Plugin not found", nil)
}