PublicDashboards: Dont support exemplars (#54933)

Don't support exemplars in public dashboards
This commit is contained in:
owensmallwood
2022-09-14 09:49:10 -06:00
committed by GitHub
parent 926a3396ab
commit deb86e3250
6 changed files with 27 additions and 14 deletions

View File

@@ -56,5 +56,6 @@ publicDashboards = true
- Panels that use frontend datasources will fail to fetch data.
- Template variables are currently not supported, but are planned to be in the future.
- The time range is permanently set to the default time range on the dashboard. If you update the default time range for a dashboard, it will be reflected in the public dashboard.
- Exemplars will be omitted from the panel.
We are excited to share this enhancement with you and wed love your feedback! Please check out the [Github](https://github.com/grafana/grafana/discussions/49253) discussion and join the conversation.

View File

@@ -1,4 +1,4 @@
package query
package queries
import (
"github.com/grafana/grafana/pkg/components/simplejson"
@@ -45,6 +45,9 @@ func GroupQueriesByPanelId(dashboard *simplejson.Json) map[int64][]*simplejson.J
for _, queryObj := range panel.Get("targets").MustArray() {
query := simplejson.NewFromAny(queryObj)
// We dont support exemplars for public dashboards currently
query.Del("exemplar")
// if query target has no datasource, set it to have the datasource on the panel
if _, ok := query.CheckGet("datasource"); !ok {
uid := GetDataSourceUidFromJson(panel)

View File

@@ -1,4 +1,4 @@
package query
package queries
import (
"testing"
@@ -51,7 +51,7 @@ const (
"schemaVersion": 35
}`
dashboardWithQueries = `
dashboardWithQueriesExemplarEnabled = `
{
"panels": [
{
@@ -362,6 +362,18 @@ func TestGroupQueriesByPanelId(t *testing.T) {
queriesByDatasource := GroupQueriesByDataSource(queries[panelId])
require.Len(t, queriesByDatasource[0], 1)
})
t.Run("will delete exemplar property from target if exists", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithQueriesExemplarEnabled))
require.NoError(t, err)
queries := GroupQueriesByPanelId(json)
panelId := int64(2)
queriesByDatasource := GroupQueriesByDataSource(queries[panelId])
for _, query := range queriesByDatasource[0] {
_, ok := query.CheckGet("exemplar")
require.False(t, ok)
}
})
t.Run("can extract queries from dashboard with panel json datasource that has no datasource on panel targets", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithTargetsWithNoDatasources))
require.NoError(t, err)
@@ -390,7 +402,7 @@ func TestGroupQueriesByPanelId(t *testing.T) {
})
t.Run("can extract queries from panels", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithQueries))
json, err := simplejson.NewJson([]byte(dashboardWithQueriesExemplarEnabled))
require.NoError(t, err)
queries := GroupQueriesByPanelId(json)
@@ -404,7 +416,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
@@ -417,7 +428,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"type": "prometheus",
"uid": "promds2"
},
"exemplar": true,
"expr": "query2",
"interval": "",
"legendFormat": "",
@@ -440,7 +450,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"uid": "_yxMP8Ynk",
"type": "public-ds"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",

View File

@@ -13,9 +13,9 @@ import (
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/publicdashboards"
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
"github.com/grafana/grafana/pkg/services/publicdashboards/queries"
"github.com/grafana/grafana/pkg/services/publicdashboards/validation"
"github.com/grafana/grafana/pkg/services/query"
queryModels "github.com/grafana/grafana/pkg/services/query/models"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
@@ -231,7 +231,7 @@ func (pd *PublicDashboardServiceImpl) GetMetricRequest(ctx context.Context, dash
// dashboard and returns a metrics request to be sent to query backend
func (pd *PublicDashboardServiceImpl) buildMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
// group queries by panel
queriesByPanel := queryModels.GroupQueriesByPanelId(dashboard.Data)
queriesByPanel := queries.GroupQueriesByPanelId(dashboard.Data)
queries, ok := queriesByPanel[panelId]
if !ok {
return dtos.MetricRequest{}, ErrPublicDashboardPanelNotFound
@@ -255,7 +255,7 @@ func (pd *PublicDashboardServiceImpl) buildMetricRequest(ctx context.Context, da
// BuildAnonymousUser creates a user with permissions to read from all datasources used in the dashboard
func (pd *PublicDashboardServiceImpl) BuildAnonymousUser(ctx context.Context, dashboard *models.Dashboard) (*user.SignedInUser, error) {
datasourceUids := queryModels.GetUniqueDashboardDatasourceUids(dashboard.Data)
datasourceUids := queries.GetUniqueDashboardDatasourceUids(dashboard.Data)
// Create a temp user with read-only datasource permissions
anonymousUser := &user.SignedInUser{OrgID: dashboard.OrgId, Permissions: make(map[int64]map[string][]string)}

View File

@@ -16,7 +16,7 @@ import (
"github.com/grafana/grafana/pkg/plugins/adapters"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/oauthtoken"
queryModels "github.com/grafana/grafana/pkg/services/query/models"
publicDashboards "github.com/grafana/grafana/pkg/services/publicdashboards/queries"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/tsdb/grafanads"
@@ -81,10 +81,10 @@ func (s *Service) QueryData(ctx context.Context, user *user.SignedInUser, skipCa
// QueryData can process queries and return query responses.
func (s *Service) QueryDataMultipleSources(ctx context.Context, user *user.SignedInUser, skipCache bool, reqDTO dtos.MetricRequest, handleExpressions bool) (*backend.QueryDataResponse, error) {
byDataSource := queryModels.GroupQueriesByDataSource(reqDTO.Queries)
byDataSource := publicDashboards.GroupQueriesByDataSource(reqDTO.Queries)
// The expression service will handle mixed datasources, so we don't need to group them when an expression is present.
if queryModels.HasExpressionQuery(reqDTO.Queries) || len(byDataSource) == 1 {
if publicDashboards.HasExpressionQuery(reqDTO.Queries) || len(byDataSource) == 1 {
return s.QueryData(ctx, user, skipCache, reqDTO, handleExpressions)
} else {
resp := backend.NewQueryDataResponse()

View File

@@ -65,7 +65,7 @@ const isHeatmapResult = (dataFrame: DataFrame, options: DataQueryRequest<PromQue
return target?.format === 'heatmap';
};
// V2 result trasnformer used to transform query results from queries that were run trough prometheus backend
// V2 result transformer used to transform query results from queries that were run through prometheus backend
export function transformV2(
response: DataQueryResponse,
request: DataQueryRequest<PromQuery>,