Skip to content

Conversation

@theo303
Copy link

@theo303 theo303 commented Sep 19, 2025

What does this PR do?

The goal is to have error from the gin context in the ext.Error span tag instead of the "500: Internal Server Error" that we currently have. This propagation is disabled by default, so the behavior stay the same for users that don't want that.

Motivation

Fixes #2815

Reviewer's Checklist

  • Changed code has unit tests for its functionality at or near 100% coverage.
  • System-Tests covering this feature have been added and enabled with the va.b.c-dev version tag.
  • There is a benchmark for any new code, or changes to existing code.
  • If this interacts with the agent in a new way, a system test has been added.
  • New code is free of linting errors. You can check this by running ./scripts/lint.sh locally.
  • Add an appropriate team label so this PR gets put in the right place for the release notes.
  • Non-trivial go.mod changes, e.g. adding new modules, are reviewed by @DataDog/dd-trace-go-guild.

@theo303 theo303 requested review from a team as code owners September 19, 2025 23:04
@theo303 theo303 force-pushed the gin-enhance-span-error-handling branch 2 times, most recently from d4643e4 to f28e644 Compare September 25, 2025 09:24
@rarguelloF rarguelloF added the apm:ecosystem contrib/* related feature requests or bugs label Oct 3, 2025
defer func() {
finishSpans(c.Writer.Status(), nil)
status := c.Writer.Status()
err := c.Errors.Last()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Can c.Errors be nil?
  2. In the case where ErrorPropagation has been configured (set to true), does a user always want the last error in the chain to be surfaced as the tag? If not, maybe there's a better, more descriptive name for this option.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right !
I just added a commit to join errors instead of using .Last(). It should solve the nil issue (I added a test case) and be more intuitive I think.
Tell me if you think Last was a better solution, and I will find a more descriptive name like you suggested.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just learned that you can call method on nil pointers. So the solution with .Last() did work, even if c.Errors was nil

@theo303 theo303 force-pushed the gin-enhance-span-error-handling branch from f28e644 to 92daacb Compare October 10, 2025 14:12
Copy link
Contributor

@rarguelloF rarguelloF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! Just some minor changes and should be good to go :)


// WithErrorPropagation enables the propagation of gin's errors to the span.
// If there are multiple errors in the gin context, they will be all added to the span.
func WithErrorPropagation() OptionFn {
Copy link
Contributor

@rarguelloF rarguelloF Oct 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this name could be slightly confusing to other users (it was not immediate clear to me what it was before reading the description).

WDYT about WithUseGinErrors?

Comment on lines 60 to 62
for _, e := range c.Errors {
err = errors.Join(err, e.Err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are already setting gin.errors equal to c.Errors.String() at line 80. Could we use the same strategy here?

Additionally, what if isStatusError and propagateError both return true, but c.Errors has length 0? is that possible?

In that case we should fallback to the previous method as well (crafting a custom error based on the status code), so you should additionally check in the condition && len(c.Errors) > 0

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, you are right I missed that.

c.Errors has length 0 is possible, in this case err will be nil, and therefore tracer.WithError(err) will do nothing. In this case the custom error based on the status code will be crafted. I think it is exactly what happens in the second test case that I added.
Do you think this behavior is not obvious and the condition should be added ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind, using c.Errors().String(), the condition should be added

@rarguelloF rarguelloF changed the title feat(contrib/gin): allow to propagate errors to spans feat(contrib/gin): add WithStatusCheck and WithUseGinErrors options Oct 14, 2025
@rarguelloF rarguelloF changed the title feat(contrib/gin): add WithStatusCheck and WithUseGinErrors options feat(contrib/gin-gonic/gin): add WithStatusCheck and WithUseGinErrors options Oct 14, 2025
@theo303 theo303 force-pushed the gin-enhance-span-error-handling branch from 300f983 to b7f83ac Compare October 14, 2025 14:29
@rarguelloF rarguelloF self-requested a review October 14, 2025 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apm:ecosystem contrib/* related feature requests or bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

More precise span error in gin middleware

3 participants