Skip to content

Commit c931b2b

Browse files
authored
feat(go): add more metrics and traces (#770)
1 parent eb1dfd5 commit c931b2b

File tree

9 files changed

+530
-71
lines changed

9 files changed

+530
-71
lines changed

cmd/server/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/grafana/grafana-image-renderer/pkg/traces"
1313
"github.com/urfave/cli/v3"
1414
"go.opentelemetry.io/otel"
15+
"go.opentelemetry.io/otel/propagation"
1516
)
1617

1718
func NewCmd() *cli.Command {
@@ -69,6 +70,7 @@ func run(ctx context.Context, c *cli.Command) error {
6970
defer func() { _ = tracerProvider.Shutdown(ctx) }()
7071
ctx = traces.WithTracerProvider(ctx, tracerProvider)
7172
otel.SetTracerProvider(tracerProvider)
73+
otel.SetTextMapPropagator(propagation.TraceContext{})
7274
}
7375
browser := service.NewBrowserService(c.String("browser"), c.StringSlice("browser-flags"),
7476
service.WithViewport(1000, 500),

devenv/docker/go-build/dashboards/grafana-image-renderer.json

Lines changed: 274 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"editable": true,
1919
"fiscalYearStartMonth": 0,
2020
"graphTooltip": 0,
21-
"id": 1,
21+
"id": 0,
2222
"links": [],
2323
"panels": [
2424
{
@@ -214,7 +214,7 @@
214214
"uid": "${prom}"
215215
},
216216
"editorMode": "code",
217-
"expr": "sum by(path) (increase(http_request_duration_count{job=\"image-renderer\"}[$__rate_interval]))",
217+
"expr": "sum by(path) (rate(http_request_duration_count{job=\"image-renderer\"}[$__rate_interval]))",
218218
"legendFormat": "{{path}}",
219219
"range": true,
220220
"refId": "A"
@@ -414,7 +414,7 @@
414414
"uid": "${prom}"
415415
},
416416
"editorMode": "code",
417-
"expr": "sum by(path, status_code) (increase(http_request_duration_count{job=\"image-renderer\"}[$__rate_interval]))",
417+
"expr": "sum by(path, status_code) (rate(http_request_duration_count{job=\"image-renderer\"}[$__rate_interval]))",
418418
"legendFormat": "{{path}}: {{status_code}}",
419419
"range": true,
420420
"refId": "A"
@@ -686,6 +686,276 @@
686686
],
687687
"title": "Service HTTP panicking requests rate",
688688
"type": "timeseries"
689+
},
690+
{
691+
"datasource": {
692+
"type": "prometheus",
693+
"uid": "${prom}"
694+
},
695+
"description": "",
696+
"fieldConfig": {
697+
"defaults": {
698+
"custom": {
699+
"hideFrom": {
700+
"legend": false,
701+
"tooltip": false,
702+
"viz": false
703+
},
704+
"scaleDistribution": {
705+
"type": "linear"
706+
}
707+
}
708+
},
709+
"overrides": []
710+
},
711+
"gridPos": {
712+
"h": 10,
713+
"w": 12,
714+
"x": 12,
715+
"y": 26
716+
},
717+
"id": 8,
718+
"options": {
719+
"calculate": false,
720+
"cellGap": 1,
721+
"cellValues": {
722+
"unit": "s"
723+
},
724+
"color": {
725+
"exponent": 0.5,
726+
"fill": "dark-orange",
727+
"mode": "scheme",
728+
"reverse": false,
729+
"scale": "exponential",
730+
"scheme": "RdYlGn",
731+
"steps": 64
732+
},
733+
"exemplars": {
734+
"color": "rgba(255,0,255,0.7)"
735+
},
736+
"filterValues": {
737+
"le": 1e-9
738+
},
739+
"legend": {
740+
"show": true
741+
},
742+
"rowsFrame": {
743+
"layout": "auto"
744+
},
745+
"tooltip": {
746+
"mode": "single",
747+
"showColorScale": false,
748+
"yHistogram": false
749+
},
750+
"yAxis": {
751+
"axisPlacement": "left",
752+
"reverse": false
753+
}
754+
},
755+
"pluginVersion": "12.2.0-17567790421",
756+
"targets": [
757+
{
758+
"datasource": {
759+
"type": "prometheus",
760+
"uid": "${prom}"
761+
},
762+
"editorMode": "code",
763+
"expr": "max(histogram_quantile(0.95, browser_get_version_duration_bucket{job=\"image-renderer\", unit=\"seconds\"}))",
764+
"legendFormat": "BrowserService.GetVersion",
765+
"range": true,
766+
"refId": "A"
767+
}
768+
],
769+
"title": "Browser GetVersion durations (p95)",
770+
"type": "heatmap"
771+
},
772+
{
773+
"datasource": {
774+
"type": "prometheus",
775+
"uid": "${prom}"
776+
},
777+
"description": "",
778+
"fieldConfig": {
779+
"defaults": {
780+
"custom": {
781+
"hideFrom": {
782+
"legend": false,
783+
"tooltip": false,
784+
"viz": false
785+
},
786+
"scaleDistribution": {
787+
"type": "linear"
788+
}
789+
}
790+
},
791+
"overrides": []
792+
},
793+
"gridPos": {
794+
"h": 10,
795+
"w": 12,
796+
"x": 0,
797+
"y": 36
798+
},
799+
"id": 9,
800+
"options": {
801+
"calculate": false,
802+
"cellGap": 1,
803+
"cellValues": {
804+
"unit": "s"
805+
},
806+
"color": {
807+
"exponent": 0.5,
808+
"fill": "dark-orange",
809+
"mode": "scheme",
810+
"reverse": false,
811+
"scale": "exponential",
812+
"scheme": "RdYlGn",
813+
"steps": 64
814+
},
815+
"exemplars": {
816+
"color": "rgba(255,0,255,0.7)"
817+
},
818+
"filterValues": {
819+
"le": 1e-9
820+
},
821+
"legend": {
822+
"show": true
823+
},
824+
"rowsFrame": {
825+
"layout": "auto"
826+
},
827+
"tooltip": {
828+
"mode": "single",
829+
"showColorScale": false,
830+
"yHistogram": false
831+
},
832+
"yAxis": {
833+
"axisPlacement": "left",
834+
"reverse": false
835+
}
836+
},
837+
"pluginVersion": "12.2.0-17567790421",
838+
"targets": [
839+
{
840+
"datasource": {
841+
"type": "prometheus",
842+
"uid": "${prom}"
843+
},
844+
"editorMode": "code",
845+
"expr": "max(histogram_quantile(0.95, browser_render_duration_bucket{job=\"image-renderer\", unit=\"seconds\"}))",
846+
"legendFormat": "BrowserService.Render",
847+
"range": true,
848+
"refId": "A"
849+
},
850+
{
851+
"datasource": {
852+
"type": "prometheus",
853+
"uid": "${prom}"
854+
},
855+
"editorMode": "code",
856+
"expr": "max(histogram_quantile(0.95, browser_render_csv_duration_bucket{job=\"image-renderer\", unit=\"seconds\"}))",
857+
"hide": false,
858+
"legendFormat": "BrowserService.RenderCSV",
859+
"range": true,
860+
"refId": "B"
861+
},
862+
{
863+
"datasource": {
864+
"type": "prometheus",
865+
"uid": "${prom}"
866+
},
867+
"editorMode": "code",
868+
"expr": "max(histogram_quantile(0.95, browser_get_version_duration_bucket{job=\"image-renderer\", unit=\"seconds\"}))",
869+
"hide": false,
870+
"legendFormat": "BrowserService.GetVersion",
871+
"range": true,
872+
"refId": "C"
873+
}
874+
],
875+
"title": "BrowserService durations (p95)",
876+
"type": "heatmap"
877+
},
878+
{
879+
"datasource": {
880+
"type": "prometheus",
881+
"uid": "${prom}"
882+
},
883+
"description": "",
884+
"fieldConfig": {
885+
"defaults": {
886+
"custom": {
887+
"hideFrom": {
888+
"legend": false,
889+
"tooltip": false,
890+
"viz": false
891+
},
892+
"scaleDistribution": {
893+
"type": "linear"
894+
}
895+
}
896+
},
897+
"overrides": []
898+
},
899+
"gridPos": {
900+
"h": 10,
901+
"w": 12,
902+
"x": 12,
903+
"y": 36
904+
},
905+
"id": 10,
906+
"options": {
907+
"calculate": false,
908+
"cellGap": 1,
909+
"cellValues": {
910+
"unit": "s"
911+
},
912+
"color": {
913+
"exponent": 0.5,
914+
"fill": "dark-orange",
915+
"mode": "scheme",
916+
"reverse": false,
917+
"scale": "exponential",
918+
"scheme": "RdYlGn",
919+
"steps": 64
920+
},
921+
"exemplars": {
922+
"color": "rgba(255,0,255,0.7)"
923+
},
924+
"filterValues": {
925+
"le": 1e-9
926+
},
927+
"legend": {
928+
"show": true
929+
},
930+
"rowsFrame": {
931+
"layout": "auto"
932+
},
933+
"tooltip": {
934+
"mode": "single",
935+
"showColorScale": false,
936+
"yHistogram": false
937+
},
938+
"yAxis": {
939+
"axisPlacement": "left",
940+
"reverse": false
941+
}
942+
},
943+
"pluginVersion": "12.2.0-17567790421",
944+
"targets": [
945+
{
946+
"datasource": {
947+
"type": "prometheus",
948+
"uid": "${prom}"
949+
},
950+
"editorMode": "code",
951+
"expr": "max by(action) (histogram_quantile(0.95, browser_action_duration_bucket{job=\"image-renderer\", unit=\"seconds\"}))",
952+
"legendFormat": "__auto",
953+
"range": true,
954+
"refId": "A"
955+
}
956+
],
957+
"title": "Browser Render action durations (p95)",
958+
"type": "heatmap"
689959
}
690960
],
691961
"preload": false,
@@ -731,5 +1001,5 @@
7311001
"timezone": "browser",
7321002
"title": "grafana-image-renderer",
7331003
"uid": "grafana-image-renderer",
734-
"version": 12
1004+
"version": 13
7351005
}

devenv/docker/go-build/docker-compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ services:
4646
command:
4747
- server
4848
- --tracing-endpoint=http://tempo:4318/v1/traces
49+
- --log-level=debug
4950
ports:
5051
- 8081:8081
5152
depends_on:

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/unidoc/unipdf/v4 v4.2.0
1616
github.com/urfave/cli-altsrc/v3 v3.0.1
1717
github.com/urfave/cli/v3 v3.4.1
18+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0
1819
go.opentelemetry.io/otel v1.38.0
1920
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0
2021
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0
@@ -81,7 +82,6 @@ require (
8182
github.com/tklauser/numcpus v0.10.0 // indirect
8283
github.com/yusufpapurcu/wmi v1.2.4 // indirect
8384
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
84-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
8585
go.opentelemetry.io/otel/metric v1.38.0 // indirect
8686
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
8787
golang.org/x/crypto v0.41.0 // indirect

pkg/api/middleware/metrics.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package middleware
33
import (
44
"net/http"
55
"strconv"
6+
"sync"
67
"time"
78

89
"github.com/prometheus/client_golang/prometheus"
@@ -39,3 +40,38 @@ func RequestMetrics(h http.Handler) http.Handler {
3940
MetricRequestDurations.WithLabelValues(r.Method, r.Pattern, strconv.Itoa(recorder.status)).Observe(time.Since(now).Seconds())
4041
})
4142
}
43+
44+
var (
45+
_ http.ResponseWriter = (*statusRecordingResponseWriter)(nil)
46+
_ http.Flusher = (*statusRecordingResponseWriter)(nil)
47+
)
48+
49+
type statusRecordingResponseWriter struct {
50+
rw http.ResponseWriter
51+
once sync.Once
52+
status int
53+
}
54+
55+
func (s *statusRecordingResponseWriter) Header() http.Header {
56+
return s.rw.Header()
57+
}
58+
59+
func (s *statusRecordingResponseWriter) Write(b []byte) (int, error) {
60+
s.once.Do(func() {
61+
s.status = http.StatusOK
62+
})
63+
return s.rw.Write(b)
64+
}
65+
66+
func (s *statusRecordingResponseWriter) WriteHeader(statusCode int) {
67+
s.once.Do(func() {
68+
s.status = statusCode
69+
})
70+
s.rw.WriteHeader(statusCode)
71+
}
72+
73+
func (s *statusRecordingResponseWriter) Flush() {
74+
if flusher, ok := s.rw.(http.Flusher); ok {
75+
flusher.Flush()
76+
}
77+
}

0 commit comments

Comments
 (0)