Skip to content

Commit add0ce9

Browse files
committed
contrib/gin-gonic/gin: propagate gin errors to tracing spans
1 parent 847743a commit add0ce9

File tree

3 files changed

+21
-2
lines changed

3 files changed

+21
-2
lines changed

contrib/gin-gonic/gin/gintrace.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ func Middleware(service string, opts ...Option) gin.HandlerFunc {
5353
opts = append(opts, httptrace.HeaderTagsFromRequest(c.Request, cfg.headerTags))
5454
span, ctx, finishSpans := httptrace.StartRequestSpan(c.Request, opts...)
5555
defer func() {
56-
finishSpans(c.Writer.Status(), nil)
56+
status := c.Writer.Status()
57+
err := c.Errors.Last()
58+
if err != nil && cfg.isStatusError(status) {
59+
finishSpans(status, cfg.isStatusError, tracer.WithError(err))
60+
}
61+
finishSpans(status, cfg.isStatusError)
5762
}()
5863

5964
// pass the span through the request context

contrib/gin-gonic/gin/gintrace_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ func TestError(t *testing.T) {
210210
assert.Equal("500", span.Tag(ext.HTTPCode))
211211
assert.Equal(fmt.Sprintf("Error #01: %s\n", responseErr), span.Tag("gin.errors"))
212212
// server errors set the ext.ErrorMsg tag
213-
assert.Equal("500: Internal Server Error", span.Tag(ext.ErrorMsg))
213+
assert.Equal("oh no", span.Tag(ext.ErrorMsg))
214214
assert.Equal(ext.SpanKindServer, span.Tag(ext.SpanKind))
215215
assert.Equal("gin-gonic/gin", span.Tag(ext.Component))
216216
assert.Equal(componentName, span.Integration())

contrib/gin-gonic/gin/option.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type config struct {
1919
resourceNamer func(c *gin.Context) string
2020
serviceName string
2121
ignoreRequest func(c *gin.Context) bool
22+
isStatusError func(statusCode int) bool
2223
headerTags instrumentation.HeaderTags
2324
}
2425

@@ -32,6 +33,7 @@ func newConfig(serviceName string) *config {
3233
resourceNamer: defaultResourceNamer,
3334
serviceName: serviceName,
3435
ignoreRequest: func(_ *gin.Context) bool { return false },
36+
isStatusError: isServerError,
3537
headerTags: instr.HTTPHeadersAsTags(),
3638
}
3739
}
@@ -79,6 +81,18 @@ func WithResourceNamer(namer func(c *gin.Context) string) OptionFn {
7981
}
8082
}
8183

84+
// WithStatusCheck specifies a function fn which reports whether the passed
85+
// statusCode should be considered an error.
86+
func WithStatusCheck(fn func(statusCode int) bool) OptionFn {
87+
return func(cfg *config) {
88+
cfg.isStatusError = fn
89+
}
90+
}
91+
92+
func isServerError(statusCode int) bool {
93+
return statusCode >= 500 && statusCode < 600
94+
}
95+
8296
// WithHeaderTags enables the integration to attach HTTP request headers as span tags.
8397
// Warning:
8498
// Using this feature can risk exposing sensitive data such as authorization tokens to Datadog.

0 commit comments

Comments
 (0)