Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PublicDashboards: Dont support exemplars #54933

Merged
merged 7 commits into from Sep 14, 2022
1 change: 1 addition & 0 deletions docs/sources/dashboards/dashboard-public.md
Expand Up @@ -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 we’d love your feedback! Please check out the [Github](https://github.com/grafana/grafana/discussions/49253) discussion and join the conversation.
@@ -1,4 +1,4 @@
package query
package queries

import (
"github.com/grafana/grafana/pkg/components/simplejson"
Expand Down Expand Up @@ -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)
Expand Down
@@ -1,4 +1,4 @@
package query
package queries

import (
"testing"
Expand Down Expand Up @@ -51,7 +51,7 @@ const (
"schemaVersion": 35
}`

dashboardWithQueries = `
dashboardWithQueriesExemplarEnabled = `
{
"panels": [
{
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -404,7 +416,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
Expand All @@ -417,7 +428,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"type": "prometheus",
"uid": "promds2"
},
"exemplar": true,
"expr": "query2",
"interval": "",
"legendFormat": "",
Expand All @@ -440,7 +450,6 @@ func TestGroupQueriesByPanelId(t *testing.T) {
"uid": "_yxMP8Ynk",
"type": "public-ds"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
Expand Down
6 changes: 3 additions & 3 deletions pkg/services/publicdashboards/service/service.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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)}
Expand Down
6 changes: 3 additions & 3 deletions pkg/services/query/query.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand Down
Expand Up @@ -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
evictorero marked this conversation as resolved.
Show resolved Hide resolved
export function transformV2(
response: DataQueryResponse,
request: DataQueryRequest<PromQuery>,
Expand Down