@@ -9,11 +9,15 @@ import (
99 "net/url"
1010 "regexp"
1111 "strconv"
12+ "strings"
1213 "time"
1314 _ "time/tzdata" // fallback where we have no tzdata on the distro; used in LoadLocation
1415
1516 "github.com/grafana/grafana-image-renderer/pkg/service"
1617 "github.com/prometheus/client_golang/prometheus"
18+ "go.opentelemetry.io/otel/attribute"
19+ "go.opentelemetry.io/otel/codes"
20+ "go.opentelemetry.io/otel/trace"
1721)
1822
1923var (
@@ -37,39 +41,52 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
3741
3842 rawTargetURL := r .URL .Query ().Get ("url" )
3943 if rawTargetURL == "" {
44+ span .SetStatus (codes .Error , "url query param empty" )
4045 http .Error (w , "missing 'url' query parameter" , http .StatusBadRequest )
4146 return
4247 }
4348 targetURL , err := url .Parse (rawTargetURL )
4449 if err != nil {
50+ span .SetStatus (codes .Error , "url query param was unparseable" )
51+ span .RecordError (err , trace .WithAttributes (attribute .String ("url" , rawTargetURL )))
4552 http .Error (w , fmt .Sprintf ("invalid 'url' query parameter: %v" , err ), http .StatusBadRequest )
4653 return
4754 }
55+ span .SetAttributes (attribute .String ("url" , targetURL .String ()))
56+
4857 var options []service.RenderingOption
4958
5059 width , height := - 1 , - 1
5160 if widthStr := r .URL .Query ().Get ("width" ); widthStr != "" {
5261 var err error
5362 width , err = strconv .Atoi (widthStr )
5463 if err != nil {
64+ span .SetStatus (codes .Error , "invalid width query param" )
65+ span .RecordError (err , trace .WithAttributes (attribute .String ("width" , widthStr )))
5566 http .Error (w , fmt .Sprintf ("invalid 'width' query parameter: %v" , err ), http .StatusBadRequest )
5667 return
5768 }
69+ span .SetAttributes (attribute .Int ("width" , width ))
5870 }
5971 if heightStr := r .URL .Query ().Get ("height" ); heightStr != "" {
6072 var err error
6173 height , err = strconv .Atoi (heightStr )
6274 if err != nil {
75+ span .SetStatus (codes .Error , "invalid height query param" )
76+ span .RecordError (err , trace .WithAttributes (attribute .String ("height" , heightStr )))
6377 http .Error (w , fmt .Sprintf ("invalid 'height' query parameter: %v" , err ), http .StatusBadRequest )
6478 return
6579 }
80+ span .SetAttributes (attribute .Int ("height" , height ))
6681 }
6782 options = append (options , service .WithViewport (width , height ))
6883 if timeout := r .URL .Query ().Get ("timeout" ); timeout != "" {
6984 var dur time.Duration
7085 if regexpOnlyNumbers .MatchString (timeout ) {
7186 seconds , err := strconv .Atoi (timeout )
7287 if err != nil {
88+ span .SetStatus (codes .Error , "invalid timeout query param (Atoi)" )
89+ span .RecordError (err , trace .WithAttributes (attribute .String ("timeout" , timeout )))
7390 http .Error (w , fmt .Sprintf ("invalid 'timeout' query parameter: %v" , err ), http .StatusBadRequest )
7491 return
7592 }
@@ -78,43 +95,54 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
7895 var err error
7996 dur , err = time .ParseDuration (timeout )
8097 if err != nil {
98+ span .SetStatus (codes .Error , "invalid timeout query param (ParseDuration)" )
99+ span .RecordError (err , trace .WithAttributes (attribute .String ("timeout" , timeout )))
81100 http .Error (w , fmt .Sprintf ("invalid 'timeout' query parameter: %v" , err ), http .StatusBadRequest )
82101 return
83102 }
84103 }
85104 if dur > 0 {
105+ span .SetAttributes (attribute .String ("timeout" , dur .String ()))
86106 timeoutCtx , cancelTimeout := context .WithTimeout (ctx , dur )
87107 defer cancelTimeout ()
88108 ctx = timeoutCtx
89109 }
90110 }
91111 if scaleFactor := r .URL .Query ().Get ("deviceScaleFactor" ); scaleFactor != "" {
92- scaleFactor , err := strconv .ParseFloat (scaleFactor , 64 )
112+ pageScaleFactor , err := strconv .ParseFloat (scaleFactor , 64 )
93113 if err != nil {
114+ span .SetStatus (codes .Error , "invalid deviceScaleFactor query param" )
115+ span .RecordError (err , trace .WithAttributes (attribute .String ("scaleFactor" , scaleFactor )))
94116 http .Error (w , fmt .Sprintf ("invalid 'deviceScaleFactor' query parameter: %v" , err ), http .StatusBadRequest )
95117 return
96118 }
97- options = append (options , service .WithPageScaleFactor (scaleFactor ))
119+ options = append (options , service .WithPageScaleFactor (pageScaleFactor ))
120+ span .SetAttributes (attribute .Float64 ("deviceScaleFactor" , pageScaleFactor ))
98121 }
99122 if timeZone := r .URL .Query ().Get ("timeZone" ); timeZone != "" {
100- timeZone , err := time .LoadLocation (timeZone )
123+ timeLocation , err := time .LoadLocation (timeZone )
101124 if err != nil {
125+ span .SetStatus (codes .Error , "invalid timeZone query param" )
126+ span .RecordError (err , trace .WithAttributes (attribute .String ("timeZone" , timeZone )))
102127 http .Error (w , fmt .Sprintf ("invalid 'timeZone' query parameter: %v" , err ), http .StatusBadRequest )
103128 return
104129 }
105- options = append (options , service .WithTimeZone (timeZone ))
130+ options = append (options , service .WithTimeZone (timeLocation ))
131+ span .SetAttributes (attribute .String ("timeZone" , timeZone ))
106132 }
107133 if landscape := r .URL .Query ().Get ("landscape" ); landscape != "" {
108134 options = append (options , service .WithLandscape (landscape == "true" ))
135+ span .SetAttributes (attribute .Bool ("landscape" , landscape == "true" ))
109136 }
110137 renderKey := r .URL .Query ().Get ("renderKey" )
111138 domain := r .URL .Query ().Get ("domain" )
112139 if renderKey != "" && domain != "" {
113140 options = append (options , service .WithCookie ("renderKey" , renderKey , domain ))
141+ span .AddEvent ("added renderKey cookie" , trace .WithAttributes (attribute .String ("domain" , domain )))
114142 }
115143 encoding := r .URL .Query ().Get ("encoding" )
116144 var printer service.Printer
117- switch encoding {
145+ switch strings . ToLower ( encoding ) {
118146 case "" , "pdf" :
119147 var printerOpts []service.PDFPrinterOption
120148
@@ -126,10 +154,13 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
126154 if paper != "" {
127155 var psz service.PaperSize
128156 if err := psz .UnmarshalText ([]byte (paper )); err != nil {
157+ span .SetStatus (codes .Error , "invalid pdf.format query param" )
158+ span .RecordError (err , trace .WithAttributes (attribute .String ("pdf.format" , paper )))
129159 http .Error (w , fmt .Sprintf ("invalid 'pdf.format' query parameter: %v" , err ), http .StatusBadRequest )
130160 return
131161 }
132162 printerOpts = append (printerOpts , service .WithPaperSize (psz ))
163+ span .SetAttributes (attribute .String ("pdf.format" , paper ))
133164 }
134165
135166 printBackground := r .URL .Query ().Get ("pdf.printBackground" )
@@ -139,6 +170,7 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
139170 }
140171 if printBackground != "" {
141172 printerOpts = append (printerOpts , service .WithPrintingBackground (printBackground == "true" ))
173+ span .SetAttributes (attribute .Bool ("pdf.printBackground" , printBackground == "true" ))
142174 }
143175
144176 pageRanges := r .URL .Query ().Get ("pdf.pageRanges" )
@@ -148,43 +180,57 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
148180 }
149181 if pageRanges != "" {
150182 printerOpts = append (printerOpts , service .WithPageRanges (pageRanges ))
183+ span .SetAttributes (attribute .String ("pdf.pageRanges" , pageRanges ))
151184 }
152185
153186 var err error
154187 printer , err = service .NewPDFPrinter (printerOpts ... )
155188 if err != nil {
189+ span .SetStatus (codes .Error , "invalid pdf printer option" )
190+ span .RecordError (err )
156191 http .Error (w , fmt .Sprintf ("invalid request: %v" , err ), http .StatusBadRequest )
157192 return
158193 }
194+ span .SetAttributes (attribute .String ("encoding" , "pdf" ))
159195
160196 if pdfLandscape := r .URL .Query ().Get ("pdfLandscape" ); pdfLandscape != "" {
161197 options = append (options , service .WithLandscape (pdfLandscape == "true" ))
198+ span .SetAttributes (attribute .Bool ("pdfLandscape" , pdfLandscape == "true" ))
162199 }
163200 case "png" :
164201 var printerOpts []service.PNGPrinterOption
165202 if height == - 1 {
166203 printerOpts = append (printerOpts , service .WithFullHeight (true ))
167204 options = append (options , service .WithViewport (width , 1080 )) // add some height to make scrolling faster
205+ span .SetAttributes (attribute .Bool ("fullHeight" , true ))
168206 }
169207
170208 var err error
171209 printer , err = service .NewPNGPrinter (printerOpts ... )
172210 if err != nil {
211+ span .SetStatus (codes .Error , "invalid png printer option" )
212+ span .RecordError (err )
173213 http .Error (w , fmt .Sprintf ("invalid request: %v" , err ), http .StatusBadRequest )
174214 return
175215 }
216+ span .SetAttributes (attribute .String ("encoding" , "png" ))
176217 default :
218+ span .SetStatus (codes .Error , "invalid encoding query param" )
219+ span .RecordError (errors .New ("invalid encoding" ), trace .WithAttributes (attribute .String ("encoding" , encoding )))
177220 http .Error (w , fmt .Sprintf ("invalid 'encoding' query parameter: %q" , encoding ), http .StatusBadRequest )
178221 return
179222 }
180223 if acceptLanguage := r .Header .Get ("Accept-Language" ); acceptLanguage != "" {
181224 options = append (options , service .WithHeader ("Accept-Language" , acceptLanguage ))
225+ span .SetAttributes (attribute .String ("Accept-Language" , acceptLanguage ))
182226 }
183227
184228 start := time .Now ()
185229 body , contentType , err := browser .Render (ctx , rawTargetURL , printer , options ... )
186230 if err != nil {
187231 MetricRenderDuration .WithLabelValues ("error" ).Observe (time .Since (start ).Seconds ())
232+ span .SetStatus (codes .Error , "rendering failed" )
233+ span .RecordError (err )
188234 if errors .Is (err , context .DeadlineExceeded ) ||
189235 errors .Is (err , context .Canceled ) {
190236 http .Error (w , "Request timed out" , http .StatusRequestTimeout )
@@ -198,6 +244,7 @@ func HandleGetRender(browser *service.BrowserService) http.Handler {
198244 return
199245 }
200246 MetricRenderDuration .WithLabelValues ("success" ).Observe (time .Since (start ).Seconds ())
247+ span .SetStatus (codes .Ok , "rendered successfully" )
201248
202249 w .Header ().Set ("Content-Type" , contentType )
203250 w .Header ().Set ("Content-Length" , fmt .Sprintf ("%d" , len (body )))
0 commit comments