Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(valkey): Make error checking configurable and fix inconsistency #3297

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

rwynn
Copy link

@rwynn rwynn commented Mar 13, 2025

All tracer.WithError calls first run through a configurable error check function.

What does this PR do?

Fixes an inconsistency in the Do method where errors were not being checked for valkey nil.

Makes error checking configurable.

Motivation

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.
  • 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.
  • For internal contributors, a matching PR should be created to the v2-dev branch and reviewed by @DataDog/apm-go.

Unsure? Have a question? Request a review!

@rwynn rwynn requested review from a team as code owners March 13, 2025 14:57
@@ -80,14 +83,14 @@ func (c *client) Do(ctx context.Context, cmd valkey.Completed) valkey.ValkeyResu
span, ctx := c.startSpan(ctx, processCommand(&cmd))
resp := c.client.Do(ctx, cmd)
setClientCacheTags(span, resp)
span.Finish(tracer.WithError(resp.Error()))
Copy link
Author

Choose a reason for hiding this comment

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

A valkey nil error will get attached to the span here currently.

@darccio
Copy link
Member

darccio commented Mar 18, 2025

@keisku Please, can you check this?

@rwynn
Copy link
Author

rwynn commented Mar 20, 2025

Updated this to apply same treatment to rueidis to maintain consistency.

@keisku
Copy link
Contributor

keisku commented Mar 21, 2025

@rwynn

Thank you for fixing this. I wonder why changes other than the following are necessary.

func (c *client) Do(ctx context.Context, cmd valkey.Completed) valkey.ValkeyResult {
	span, ctx := c.startSpan(ctx, processCommand(&cmd))
	resp := c.client.Do(ctx, cmd)
	setClientCacheTags(span, resp)
- 	span.Finish(tracer.WithError(resp.Error()))
+ 	c.finishSpan(span, resp.Error())
	return resp
}

When do we need WithErrorCheck()? I think we need to separate concerns.

@rwynn
Copy link
Author

rwynn commented Mar 21, 2025

@rwynn

Thank you for fixing this. I wonder why changes other than the following are necessary.

func (c *client) Do(ctx context.Context, cmd valkey.Completed) valkey.ValkeyResult {
	span, ctx := c.startSpan(ctx, processCommand(&cmd))
	resp := c.client.Do(ctx, cmd)
	setClientCacheTags(span, resp)
- 	span.Finish(tracer.WithError(resp.Error()))
+ 	c.finishSpan(span, resp.Error())
	return resp
}

When do we need WithErrorCheck()? I think we need to separate concerns.

Hi @keisku ,

Apologies, I didn't go into detail about the addition of WithErrorCheck in the description because we have been using it with other contrib plugins like aws and go-redis and I presumed that already justified it's existence.

func WithErrorCheck(fn func(err error) bool) Option {

func WithErrorCheck(fn func(err error) bool) ClientOption {

We use WithErrorCheck to specify addition types of errors that we don't classify as errors that should not influence the error statistics reported when we check a service in Datadog. One example would be the use of WithErrorCheck included in the test I added. Often a http request into our services will first initiate a redis (or now valkey) get on a key. If the client quickly cancels this request before the get call completes we handle the resulting context.Canceled and return a http status 400 to the client. However, without our custom WithErrorCheck this trace is still marked as an error and negatively impacts the error rate as reported in Datadog. We generally like to see that error rate accurately report what we consider to be errors that need attention. The WithErrorCheck allows the user of the library to determine what those spurious errors might be.

I do see you point that this change address 2 separate concerns and could be 2 separate MRs. I can split into 2 if that is desirable.

@keisku
Copy link
Contributor

keisku commented Mar 24, 2025

Appreciate you explaining it!
For consistency of other redis integrations, adding WithErrorCheck makes sense to me.

// WithErrorCheck specifies a function fn which determines whether the passed
// error should be marked as an error.
func WithErrorCheck(fn func(err error) bool) ClientOption {
return func(cfg *clientConfig) {
cfg.errCheck = fn
}
}

Can we have the default errCheck like this? I think we can remove isTracedError().

func defaultConfig() *config {
	return &config{
		// Do not include the raw command by default since it could contain sensitive data.
		rawCommand:  internal.BoolEnv("DD_TRACE_VALKEY_RAW_COMMAND", false),
		serviceName: namingschema.ServiceName(defaultServiceName),
+ 		errCheck: func(err error) bool { return err != nil && !valkey.IsValkeyNil(err) },
	}
}

@rwynn
Copy link
Author

rwynn commented Mar 24, 2025

thank you @keisku. I have updated the PR as you described and added an additional test.

All tracer.WithError calls first run through a configurable
error check function.

Apply same treatment to rueidis to maintain consistency.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants