Skip to content

Commit 4e48b30

Browse files
committed
enable separate metrics for content resources
to enable dashboards and library panels to track their fetch operations separately, split up the metrics by resource. this is accomplished by adding a new interface method to the GrafanaContentResource, and the returned struct holds references to the relevant metrics, if any. this also adds an additional guard to the http round tripper so that if no metric is defined, we don't panic.
1 parent bc7c713 commit 4e48b30

File tree

8 files changed

+50
-5
lines changed

8 files changed

+50
-5
lines changed

api/v1beta1/content.go

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package v1beta1
22

33
import (
4+
"github.com/prometheus/client_golang/prometheus"
45
v1 "k8s.io/api/core/v1"
56
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
67
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -124,4 +125,13 @@ type GrafanaContentResource interface {
124125
client.Object
125126
GrafanaContentSpec() *GrafanaContentSpec
126127
GrafanaContentStatus() *GrafanaContentStatus
128+
GrafanaContentMetrics() GrafanaContentMetrics
129+
}
130+
131+
// GrafanaContentMetrics holds runtime information about telemetry configured for a particular
132+
// content resource, allowing for resources to have different logical metrics.
133+
// +kubebuilder:object:generate=false
134+
type GrafanaContentMetrics struct {
135+
URLRequestCounter *prometheus.CounterVec
136+
GrafanaComRevisionRequestCounter *prometheus.CounterVec
127137
}

api/v1beta1/grafanadashboard_types.go

+11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v1beta1
1919
import (
2020
"time"
2121

22+
"github.com/grafana/grafana-operator/v5/controllers/metrics"
2223
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2324
)
2425

@@ -124,6 +125,16 @@ func (in *GrafanaDashboard) GrafanaContentStatus() *GrafanaContentStatus {
124125
return &in.Status.GrafanaContentStatus
125126
}
126127

128+
// GrafanaContentMetrics implements GrafanaContentResource
129+
func (in *GrafanaDashboard) GrafanaContentMetrics() GrafanaContentMetrics {
130+
return GrafanaContentMetrics{
131+
URLRequestCounter: metrics.DashboardUrlRequests,
132+
GrafanaComRevisionRequestCounter: metrics.GrafanaComApiRevisionRequests,
133+
}
134+
}
135+
136+
var _ GrafanaContentResource = &GrafanaDashboard{}
137+
127138
func (in *GrafanaDashboard) IsAllowCrossNamespaceImport() bool {
128139
return in.Spec.AllowCrossNamespaceImport
129140
}

api/v1beta1/grafanalibrarypanel_types.go

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package v1beta1
33
import (
44
"time"
55

6+
"github.com/grafana/grafana-operator/v5/controllers/metrics"
67
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
78
)
89

@@ -108,6 +109,16 @@ func (in *GrafanaLibraryPanel) GrafanaContentStatus() *GrafanaContentStatus {
108109
return &in.Status.GrafanaContentStatus
109110
}
110111

112+
// GrafanaContentMetrics implements GrafanaContentResource
113+
func (in *GrafanaLibraryPanel) GrafanaContentMetrics() GrafanaContentMetrics {
114+
return GrafanaContentMetrics{
115+
URLRequestCounter: metrics.LibraryPanelUrlRequests,
116+
// NOTE: we do not export the grafana.com request metric here b/c it's not supported.
117+
}
118+
}
119+
120+
var _ GrafanaContentResource = &GrafanaLibraryPanel{}
121+
111122
func (in *GrafanaLibraryPanelList) Find(namespace string, name string) *GrafanaLibraryPanel {
112123
for _, e := range in.Items {
113124
if e.Namespace == namespace && e.Name == name {

controllers/client/round_tripper.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (in *instrumentedRoundTripper) RoundTrip(r *http.Request) (*http.Response,
4949
}
5050

5151
resp, err := in.wrapped.RoundTrip(r)
52-
if resp != nil {
52+
if resp != nil && in.metric != nil {
5353
in.metric.WithLabelValues(
5454
in.relatedResource,
5555
r.Method,

controllers/content/fetchers/grafana_com_fetcher.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/grafana/grafana-operator/v5/api/v1beta1"
1313
client2 "github.com/grafana/grafana-operator/v5/controllers/client"
1414
"github.com/grafana/grafana-operator/v5/controllers/content/cache"
15-
"github.com/grafana/grafana-operator/v5/controllers/metrics"
1615
)
1716

1817
const grafanaComDashboardApiUrlRoot = "https://grafana.com/api/dashboards"
@@ -59,7 +58,9 @@ func getLatestGrafanaComRevision(cr v1beta1.GrafanaContentResource, tlsConfig *t
5958
return -1, err
6059
}
6160

62-
client := client2.NewInstrumentedRoundTripper(fmt.Sprintf("%v/%v", cr.GetNamespace(), cr.GetName()), metrics.GrafanaComApiRevisionRequests, true, tlsConfig)
61+
metric := cr.GrafanaContentMetrics().GrafanaComRevisionRequestCounter
62+
63+
client := client2.NewInstrumentedRoundTripper(fmt.Sprintf("%v/%v", cr.GetNamespace(), cr.GetName()), metric, true, tlsConfig)
6364
response, err := client.RoundTrip(request)
6465
if err != nil {
6566
return -1, err

controllers/content/fetchers/url_fetcher.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"github.com/grafana/grafana-operator/v5/api/v1beta1"
1515
grafanaClient "github.com/grafana/grafana-operator/v5/controllers/client"
1616
"github.com/grafana/grafana-operator/v5/controllers/content/cache"
17-
"github.com/grafana/grafana-operator/v5/controllers/metrics"
1817

1918
client2 "github.com/grafana/grafana-operator/v5/controllers/client"
2019
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -38,7 +37,9 @@ func FetchFromUrl(ctx context.Context, cr v1beta1.GrafanaContentResource, c clie
3837
return nil, err
3938
}
4039

41-
client := client2.NewInstrumentedRoundTripper(fmt.Sprintf("%v/%v", cr.GetNamespace(), cr.GetName()), metrics.DashboardUrlRequests, true, tlsConfig)
40+
metric := cr.GrafanaContentMetrics().URLRequestCounter
41+
42+
client := client2.NewInstrumentedRoundTripper(fmt.Sprintf("%v/%v", cr.GetNamespace(), cr.GetName()), metric, true, tlsConfig)
4243
// basic auth is supported for dashboards from url
4344
if spec.UrlAuthorization != nil && spec.UrlAuthorization.BasicAuth != nil {
4445
username, err := grafanaClient.GetValueFromSecretKey(ctx, spec.UrlAuthorization.BasicAuth.Username, c, cr.GetNamespace())

controllers/content/suite_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ func (n *NopContentResource) GrafanaContentStatus() *v1beta1.GrafanaContentStatu
5353
return &n.Status
5454
}
5555

56+
func (n *NopContentResource) GrafanaContentMetrics() v1beta1.GrafanaContentMetrics {
57+
return v1beta1.GrafanaContentMetrics{}
58+
}
59+
5660
func (in *NopContentResource) DeepCopyObject() runtime.Object {
5761
if c := in.DeepCopy(); c != nil {
5862
return c

controllers/metrics/metrics.go

+7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ var (
3434
Help: "requests to fetch dashboards from urls",
3535
}, []string{"dashboard", "method", "status"})
3636

37+
LibraryPanelUrlRequests = prometheus.NewCounterVec(prometheus.CounterOpts{
38+
Namespace: "grafana_operator",
39+
Subsystem: "librarypanels",
40+
Name: "requests",
41+
Help: "requests to fetch library panels from urls",
42+
}, []string{"librarypanel", "method", "status"})
43+
3744
GrafanaComApiRevisionRequests = prometheus.NewCounterVec(prometheus.CounterOpts{
3845
Namespace: "grafana_operator",
3946
Subsystem: "dashboards",

0 commit comments

Comments
 (0)