Skip to content

Commit 92daacb

Browse files
committed
contrib/gin-gonic/gin: join errors instead of using Last()
1 parent 87e371e commit 92daacb

File tree

3 files changed

+43
-3
lines changed

3 files changed

+43
-3
lines changed

contrib/gin-gonic/gin/gintrace.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package gin // import "github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2"
88

99
import (
10+
"errors"
1011
"fmt"
1112
"math"
1213

@@ -54,8 +55,11 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc {
5455
span, ctx, finishSpans := httptrace.StartRequestSpan(c.Request, opts...)
5556
defer func() {
5657
status := c.Writer.Status()
57-
err := c.Errors.Last()
58-
if err != nil && cfg.propagateError && cfg.isStatusError(status) {
58+
if cfg.propagateError && cfg.isStatusError(status) {
59+
var err error
60+
for _, e := range c.Errors {
61+
err = errors.Join(err, e.Err)
62+
}
5963
finishSpans(status, cfg.isStatusError, tracer.WithError(err))
6064
}
6165
finishSpans(status, cfg.isStatusError)

contrib/gin-gonic/gin/gintrace_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,41 @@ func TestError(t *testing.T) {
216216
assert.Equal(componentName, span.Integration())
217217
})
218218

219+
t.Run("server error - with error propagation - nil Errors in gin context", func(*testing.T) {
220+
defer mt.Reset()
221+
222+
router := gin.New()
223+
router.Use(Middleware("foobar", WithErrorPropagation()))
224+
225+
// configure a handler that returns an error and 5xx status code
226+
router.GET("/server_err", func(c *gin.Context) {
227+
c.AbortWithStatus(500)
228+
})
229+
r := httptest.NewRequest("GET", "/server_err", nil)
230+
w := httptest.NewRecorder()
231+
router.ServeHTTP(w, r)
232+
response := w.Result()
233+
defer response.Body.Close()
234+
assert.Equal(response.StatusCode, 500)
235+
236+
// verify the errors and status are correct
237+
spans := mt.FinishedSpans()
238+
assert.Len(spans, 1)
239+
if len(spans) < 1 {
240+
t.Fatalf("no spans")
241+
}
242+
span := spans[0]
243+
assert.Equal("http.request", span.OperationName())
244+
assert.Equal("foobar", span.Tag(ext.ServiceName))
245+
assert.Equal("500", span.Tag(ext.HTTPCode))
246+
assert.Empty(span.Tag("gin.errors"))
247+
// server errors set the ext.ErrorMsg tag
248+
assert.Equal("500: Internal Server Error", span.Tag(ext.ErrorMsg))
249+
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
250+
assert.Equal("gin-gonic/gin", span.Tag(ext.Component))
251+
assert.Equal(componentName, span.Integration())
252+
})
253+
219254
t.Run("server error - without error propagation", func(*testing.T) {
220255
defer mt.Reset()
221256

contrib/gin-gonic/gin/option.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ func isServerError(statusCode int) bool {
9595
return statusCode >= 500 && statusCode < 600
9696
}
9797

98-
// WithErrorPropagation enables the propagation of gin's error to the span.
98+
// WithErrorPropagation enables the propagation of gin's errors to the span.
99+
// If there are multiple errors in the gin context, they will be all added to the span.
99100
func WithErrorPropagation() OptionFn {
100101
return func(cfg *config) {
101102
cfg.propagateError = true

0 commit comments

Comments
 (0)