mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 23:16:16 -06:00
Add usage stats preview endpoint (#43899)
* Stats: add preview route for usage statistics * Stats: respect reporting settings * Stats: add tests to api endpoint * Stats: unregister route * Stats: always possible to preview stats * Update pkg/infra/usagestats/service/api.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
parent
bedc5cccaa
commit
1e9818a69f
27
pkg/infra/usagestats/service/api.go
Normal file
27
pkg/infra/usagestats/service/api.go
Normal file
@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
const rootUrl = "/api/admin"
|
||||
|
||||
func (uss *UsageStats) registerAPIEndpoints() {
|
||||
uss.RouteRegister.Group(rootUrl, func(subrouter routing.RouteRegister) {
|
||||
subrouter.Get("/usage-report-preview", middleware.ReqGrafanaAdmin, routing.Wrap(uss.getUsageReportPreview))
|
||||
})
|
||||
}
|
||||
|
||||
func (uss *UsageStats) getUsageReportPreview(ctx *models.ReqContext) response.Response {
|
||||
usageReport, err := uss.GetUsageReport(ctx.Req.Context())
|
||||
if err != nil {
|
||||
return response.Error(http.StatusInternalServerError, "failed to get usage report", err)
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, usageReport)
|
||||
}
|
134
pkg/infra/usagestats/service/api_test.go
Normal file
134
pkg/infra/usagestats/service/api_test.go
Normal file
@ -0,0 +1,134 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestApi_getUsageStats(t *testing.T) {
|
||||
type getUsageStatsTestCase struct {
|
||||
desc string
|
||||
expectedStatus int
|
||||
expectedCall bool
|
||||
IsGrafanaAdmin bool
|
||||
enabled bool
|
||||
}
|
||||
tests := []getUsageStatsTestCase{
|
||||
{
|
||||
desc: "expect usage stats",
|
||||
enabled: true,
|
||||
IsGrafanaAdmin: true,
|
||||
expectedCall: true,
|
||||
expectedStatus: 200,
|
||||
},
|
||||
{
|
||||
desc: "expect usage stat preview still there after disabling",
|
||||
enabled: false,
|
||||
IsGrafanaAdmin: true,
|
||||
expectedCall: true,
|
||||
expectedStatus: 200,
|
||||
},
|
||||
{
|
||||
desc: "expect http status 403 when not admin",
|
||||
enabled: false,
|
||||
IsGrafanaAdmin: false,
|
||||
expectedCall: false,
|
||||
expectedStatus: 403,
|
||||
},
|
||||
}
|
||||
|
||||
uss := createService(t, setting.Cfg{})
|
||||
uss.registerAPIEndpoints()
|
||||
getSystemStatsWasCalled := false
|
||||
|
||||
uss.Bus.AddHandler(func(ctx context.Context, query *models.GetSystemStatsQuery) error {
|
||||
query.Result = &models.SystemStats{}
|
||||
getSystemStatsWasCalled = true
|
||||
return nil
|
||||
})
|
||||
|
||||
uss.Bus.AddHandler(func(ctx context.Context, query *models.GetDataSourceStatsQuery) error {
|
||||
query.Result = []*models.DataSourceStats{}
|
||||
return nil
|
||||
})
|
||||
|
||||
uss.Bus.AddHandler(func(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
query.Result = []*models.DataSource{}
|
||||
return nil
|
||||
})
|
||||
|
||||
uss.Bus.AddHandler(func(ctx context.Context, query *models.GetDataSourceAccessStatsQuery) error {
|
||||
query.Result = []*models.DataSourceAccessStats{}
|
||||
return nil
|
||||
})
|
||||
|
||||
uss.Bus.AddHandler(func(ctx context.Context, query *models.GetAlertNotifierUsageStatsQuery) error {
|
||||
query.Result = []*models.NotifierUsageStats{}
|
||||
return nil
|
||||
})
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
getSystemStatsWasCalled = false
|
||||
uss.Cfg.ReportingEnabled = tt.enabled
|
||||
server := setupTestServer(t, &models.SignedInUser{OrgId: 1, IsGrafanaAdmin: tt.IsGrafanaAdmin}, uss)
|
||||
|
||||
usageStats, recorder := getUsageStats(t, server)
|
||||
require.Equal(t, tt.expectedCall, getSystemStatsWasCalled)
|
||||
require.Equal(t, tt.expectedStatus, recorder.Code)
|
||||
|
||||
if tt.expectedStatus == http.StatusOK {
|
||||
require.NotNil(t, usageStats)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getUsageStats(t *testing.T, server *web.Mux) (*models.SystemStats, *httptest.ResponseRecorder) {
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/admin/usage-report-preview", http.NoBody)
|
||||
require.NoError(t, err)
|
||||
recorder := httptest.NewRecorder()
|
||||
server.ServeHTTP(recorder, req)
|
||||
|
||||
var usageStats *models.SystemStats
|
||||
if recorder.Code == http.StatusOK {
|
||||
require.NoError(t, json.NewDecoder(recorder.Body).Decode(&usageStats))
|
||||
}
|
||||
return usageStats, recorder
|
||||
}
|
||||
|
||||
func setupTestServer(t *testing.T, user *models.SignedInUser, service *UsageStats) *web.Mux {
|
||||
server := web.New()
|
||||
server.UseMiddleware(web.Renderer(path.Join(setting.StaticRootPath, "views"), "[[", "]]"))
|
||||
server.Use(contextProvider(&testContext{user}))
|
||||
service.RouteRegister.Register(server)
|
||||
return server
|
||||
}
|
||||
|
||||
type testContext struct {
|
||||
user *models.SignedInUser
|
||||
}
|
||||
|
||||
func contextProvider(tc *testContext) web.Handler {
|
||||
return func(c *web.Context) {
|
||||
signedIn := tc.user != nil
|
||||
reqCtx := &models.ReqContext{
|
||||
Context: c,
|
||||
SignedInUser: tc.user,
|
||||
IsSignedIn: signedIn,
|
||||
SkipCache: true,
|
||||
Logger: log.New("test"),
|
||||
}
|
||||
c.Map(reqCtx)
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@ -22,6 +23,7 @@ type UsageStats struct {
|
||||
pluginStore plugins.Store
|
||||
SocialService social.Service
|
||||
kvStore *kvstore.NamespacedKVStore
|
||||
RouteRegister routing.RouteRegister
|
||||
|
||||
log log.MultiLoggers
|
||||
|
||||
@ -33,18 +35,22 @@ type UsageStats struct {
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, bus bus.Bus, sqlStore *sqlstore.SQLStore, pluginStore plugins.Store,
|
||||
socialService social.Service, kvStore kvstore.KVStore) *UsageStats {
|
||||
socialService social.Service, kvStore kvstore.KVStore, routeRegister routing.RouteRegister,
|
||||
) *UsageStats {
|
||||
s := &UsageStats{
|
||||
Cfg: cfg,
|
||||
Bus: bus,
|
||||
SQLStore: sqlStore,
|
||||
oauthProviders: socialService.GetOAuthProviders(),
|
||||
RouteRegister: routeRegister,
|
||||
pluginStore: pluginStore,
|
||||
kvStore: kvstore.WithNamespace(kvStore, 0, "infra.usagestats"),
|
||||
log: log.New("infra.usagestats"),
|
||||
startTime: time.Now(),
|
||||
}
|
||||
|
||||
s.registerAPIEndpoints()
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
@ -619,5 +620,6 @@ func createService(t *testing.T, cfg setting.Cfg) *UsageStats {
|
||||
kvStore: kvstore.WithNamespace(kvstore.ProvideService(sqlStore), 0, "infra.usagestats"),
|
||||
log: log.New("infra.usagestats"),
|
||||
startTime: time.Now().Add(-1 * time.Minute),
|
||||
RouteRegister: routing.NewRouteRegister(),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user