[v7.5.x]: FrontendMetrics: Adds new backend api that frontend can use to push frontend measurements and counters to prometheus (#33255)
* Backport of https://github.com/grafana/grafana/pull/32593 * Update prometheus.yml
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/frontendlogging"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
@@ -397,6 +398,8 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
annotationsRoute.Post("/graphite", reqEditorRole, bind(dtos.PostGraphiteAnnotationsCmd{}), routing.Wrap(PostGraphiteAnnotation))
|
||||
})
|
||||
|
||||
apiRoute.Post("/frontend-metrics", bind(metrics.PostFrontendMetricsCommand{}), routing.Wrap(hs.PostFrontendMetrics))
|
||||
|
||||
// short urls
|
||||
apiRoute.Post("/short-urls", bind(dtos.CreateShortURLCmd{}), routing.Wrap(hs.createShortURL))
|
||||
}, reqSignedIn)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) PostFrontendMetrics(c *models.ReqContext, cmd metrics.PostFrontendMetricsCommand) response.Response {
|
||||
for _, event := range cmd.Events {
|
||||
name := strings.Replace(event.Name, "-", "_", -1)
|
||||
if recorder, ok := metrics.FrontendMetrics[name]; ok {
|
||||
recorder(event)
|
||||
} else {
|
||||
c.Logger.Debug("Received unknown frontend metric", "metric", name)
|
||||
}
|
||||
}
|
||||
return response.Empty(200)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package metrics
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
// PostPostFrontendMetricsCommand sent by frontend to record frontend metrics
|
||||
type PostFrontendMetricsCommand struct {
|
||||
Events []FrontendMetricEvent `json:"events"`
|
||||
}
|
||||
|
||||
// FrontendMetricEvent a single metric measurement event
|
||||
type FrontendMetricEvent struct {
|
||||
Name string `json:"name"`
|
||||
Value float64 `json:"value"`
|
||||
}
|
||||
|
||||
// FrontendMetricsRecorder handles the recording of the event, ie passes it to a prometheus metric
|
||||
type FrontendMetricsRecorder func(event FrontendMetricEvent)
|
||||
|
||||
// FrontendMetrics contains all the valid frontend metrics and a handler function for recording events
|
||||
var FrontendMetrics map[string]FrontendMetricsRecorder = map[string]FrontendMetricsRecorder{}
|
||||
|
||||
func registerFrontendHistogram(name string, help string) {
|
||||
defBuckets := []float64{.1, .25, .5, 1, 1.5, 2, 5, 10, 20, 40}
|
||||
|
||||
histogram := prometheus.NewHistogram(prometheus.HistogramOpts{
|
||||
Name: name,
|
||||
Help: help,
|
||||
Buckets: defBuckets,
|
||||
Namespace: ExporterName,
|
||||
})
|
||||
|
||||
FrontendMetrics[name] = func(event FrontendMetricEvent) {
|
||||
histogram.Observe(event.Value)
|
||||
}
|
||||
|
||||
prometheus.MustRegister(histogram)
|
||||
}
|
||||
|
||||
func initFrontendMetrics() {
|
||||
registerFrontendHistogram("frontend_boot_load_time_seconds", "Frontend boot time measurement")
|
||||
registerFrontendHistogram("frontend_boot_first_paint_time_seconds", "Frontend boot first paint")
|
||||
registerFrontendHistogram("frontend_boot_js_done_time_seconds", "Frontend boot initial js load")
|
||||
}
|
||||
@@ -22,6 +22,7 @@ func (lw *logWrapper) Println(v ...interface{}) {
|
||||
func init() {
|
||||
registry.RegisterService(&InternalMetricsService{})
|
||||
initMetricVars()
|
||||
initFrontendMetrics()
|
||||
}
|
||||
|
||||
type InternalMetricsService struct {
|
||||
|
||||
Reference in New Issue
Block a user