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

feat: HTTP headers in Error type #404

Merged
merged 15 commits into from
Aug 9, 2024
Merged

feat: HTTP headers in Error type #404

merged 15 commits into from
Aug 9, 2024

Conversation

karel-rehor
Copy link
Contributor

@karel-rehor karel-rehor commented Aug 7, 2024

Proposed Changes

  • Add http.Header as Header property to api/http/Error type to expose response headers for analysis and debugging.
  • leverage this in api/http/service,go.
  • add selected headers to error message log.
  • add new tests covering the new property.
  • update example to show how the new property can be used.

Checklist

  • CHANGELOG.md updated
  • Rebased/mergeable
  • A test has been added if appropriate
  • Tests pass
  • Commit messages are in semantic format
  • Sign CLA (if not already signed)

@codecov-commenter
Copy link

codecov-commenter commented Aug 7, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.99%. Comparing base (b3496ca) to head (5858f61).

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #404      +/-   ##
==========================================
+ Coverage   92.94%   92.99%   +0.04%     
==========================================
  Files          25       25              
  Lines        2310     2326      +16     
==========================================
+ Hits         2147     2163      +16     
  Misses        123      123              
  Partials       40       40              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@bednar bednar removed their request for review August 7, 2024 11:36
assert.Equal(t, calls, 3)
}

func TestWriteErrorHeaderToString(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a unit test for http.Error. Move this to error_test.go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

refactored to error_test.go

@@ -164,6 +164,7 @@ func (w *Service) HandleWrite(ctx context.Context, batch *Batch) error {
if batchToWrite != nil {
perror := w.WriteBatch(ctx, batchToWrite)
if perror != nil {
// fmt.Printf("DEBUG perror type %s\n", reflect.TypeOf(perror))
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove commented code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

"X-Influxdb-Version",
})
if len(logHeaders) > 0 {
logMessage += fmt.Sprintf("\nSelect Response Headers:\n%s", logHeaders)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
logMessage += fmt.Sprintf("\nSelect Response Headers:\n%s", logHeaders)
logMessage += fmt.Sprintf("\nSelected Response Headers:\n%s", logHeaders)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to "Selected"

Comment on lines 340 to 341
//fmt.Printf("DEBUG err %v\n", err)
//fmt.Printf("DEBUG err %v\n", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove commented code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

require.NotNil(t, err)
// 1st Batch expires and writing 2nd trows error
assert.Equal(t, "write failed (attempts 1): Unexpected status code 429", err.Error())
assert.Equal(t, 1, srv.retryQueue.list.Len())
// fmt.Printf("DEBUG Header len: %d\n", len(err.(*http.Error).Header))
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove commented code

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

Comment on lines 214 to 222
return &http2.Error{
StatusCode: int(perror.StatusCode),
Code: perror.Code,
Message: fmt.Errorf(
"write failed (attempts %d): %w", batchToWrite.RetryAttempts, perror,
).Error(),
Err: perror.Err,
RetryAfter: perror.RetryAfter,
Header: perror.Header,
Copy link
Contributor

@vlastahajek vlastahajek Aug 7, 2024

Choose a reason for hiding this comment

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

It doesn't look good from the API perspective to return http.Error from the write service. And the more serious problem is that the final message looks silly: "400 Bad Request: write failed (attempts 0): 400 Bad Request: { \"code\": \"bad request\", \"message\": \"test header\".

The solution could be to create a write error that would wrap the previous:

package write

type Error struct {
	origin  error
	message string
}

func NewError(err error, message string) *Error {
	return &Error{
		origin:  err,
		message: message,
	}
}

func (e *Error) Error() string {
	return fmt.Sprintf("%s: %s", e.message, e.origin)
}

func (e *Error) Unwrap() error {
	return e.origin
}

Then this code would be:

return write.NewError(perror, fmt.Sprintf("write failed (attempts %d)", batchToWrite.RetryAttempts))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agree. When I wrote it, I was thinking there has to be a more elegant way of implementing this. I'm still fairly new to golang and the suggested solution did not occur to me. Implemented as suggested, and with helper methods for extracting header values.

@karel-rehor karel-rehor requested a review from vlastahajek August 8, 2024 15:33
Comment on lines 71 to 79
err := Error{
StatusCode: test.statusCode,
Code: test.code,
Message: test.message,
Err: test.err,
RetryAfter: 0,
Header: ihttp.Header{},
}
assert.Equal(t, test.expected, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

Use t.Run() construct for data-driven test (also add a test name to the table)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

refactored using t.Run()

Comment on lines 8 to 13
"errors"
"fmt"
"github.com/influxdata/influxdb-client-go/v2/api/http"
iHttp "net/http"
"net/textproto"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Use go imports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

file removed

Comment on lines 8 to 13
"errors"
"fmt"
"github.com/influxdata/influxdb-client-go/v2/api/http"
"github.com/stretchr/testify/assert"
ihttp "net/http"
"testing"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use go imports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

file removed

Comment on lines 8 to 17
"fmt"
"io"
"math"
ihttp "net/http"
"net/http/httptest"
"runtime"
"strconv"
"strings"
"sync"
"testing"
Copy link
Contributor

Choose a reason for hiding this comment

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

Use go imports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

activated goimports in IDE. Updated.

}
return fmt.Errorf("write failed (attempts %d): %w", batchToWrite.RetryAttempts, perror)
return write.NewError(perror, fmt.Sprintf("write failed (retry attempts %d)", batchToWrite.RetryAttempts))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm sorry for the previous suggestion which now looks misleading. I looked at WriteAPI and WriteBlockingAPI and also at several issues regarding complaints about errors. The best solution will be to return perror, and log a message about attempts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

now logs failed attempt count and status code before returning perror directly.


### Features

- [#404](https://github.com/influxdata/influxdb-client-go/pull/404) Expose HTTP response headers in the Error type to aid analysis and debugging of error results. Add selected response headers to the error log.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- [#404](https://github.com/influxdata/influxdb-client-go/pull/404) Expose HTTP response headers in the Error type to aid analysis and debugging of error results. Add selected response headers to the error log.
- [#404](https://github.com/influxdata/influxdb-client-go/pull/404) Expose HTTP response headers in the Error type to aid analysis and debugging of error results. Add selected response headers to the error log.
Also, unified errors returned by WriteAPI, which now always returns `http.Error`

Copy link
Contributor

@vlastahajek vlastahajek left a comment

Choose a reason for hiding this comment

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

Nice improvement 👍
Good job!

@karel-rehor karel-rehor merged commit 017c8c8 into master Aug 9, 2024
2 checks passed
@bednar bednar added this to the 2.14.0 milestone Aug 12, 2024
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