From 5f7cd4158daa708fa093c1b2f8f37cc5b39b0bce Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 09:47:24 -0500 Subject: [PATCH 01/10] chore: include request id in debug logs and diagnostics --- .env | 11 ++++++----- client/client.go | 2 +- client/errors.go | 7 +++++++ go.mod | 1 + go.sum | 2 ++ honeycombio/type_helpers.go | 1 + internal/helper/diag.go | 4 ++-- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.env b/.env index 7b16c12e..bb81be5b 100644 --- a/.env +++ b/.env @@ -1,6 +1,7 @@ -#HONEYCOMB_API_KEY= -#HONEYCOMB_KEY_ID= -#HONEYCOMB_KEY_SECRET= -#HONEYCOMB_API_ENDPOINT= -#HONEYCOMB_DATASET= +HONEYCOMB_API_KEY=uNJMtnUmGKcWe2Bup7JfcB +HONEYCOMB_KEY_ID=hccmk_01jd0q14vvwvw0vsb6k7s10bfk +HONEYCOMB_KEY_SECRET=szwp610jzrf2gkv1w4c1hr6a51ya5kfs +HONEYCOMB_API_ENDPOINT=https://api-dogfood.honeycomb.io +HONEYCOMB_DATASET=terraform-test TF_ACC=1 +HONEYCOMBIO_DEBUG=true \ No newline at end of file diff --git a/client/client.go b/client/client.go index 5e223971..07dd1473 100644 --- a/client/client.go +++ b/client/client.go @@ -141,7 +141,7 @@ func NewClientWithConfig(config *Config) (*Client, error) { // if enabled we log all requests and responses to sterr client.httpClient.Logger = log.New(os.Stderr, "", log.LstdFlags) client.httpClient.ResponseLogHook = func(l retryablehttp.Logger, resp *http.Response) { - l.Printf("[DEBUG] Response: %s %s", resp.Request.Method, resp.Request.URL.String()) + l.Printf("[DEBUG] Request: %s \"%s\" %s %s", resp.Request.Method, resp.Request.URL.String(), resp.Status, resp.Header.Get("Request-Id")) } } diff --git a/client/errors.go b/client/errors.go index fbba8c38..0fc355c7 100644 --- a/client/errors.go +++ b/client/errors.go @@ -14,6 +14,8 @@ type DetailedError struct { Status int `json:"status,omitempty"` // The error message Message string `json:"error,omitempty"` + // ID unique ID of the HTTP request that caused this error. + ID string `json:"request_id,omitempty"` // Type is a URI used to uniquely identify the type of error. Type string `json:"type,omitempty"` // Title is a human-readable summary that explains the type of the problem. @@ -87,6 +89,8 @@ func ErrorFromResponse(r *http.Response) error { return errors.New("invalid response") } + requestID := r.Header.Get("Request-Id") + switch r.Header.Get("Content-Type") { case jsonapi.MediaType: var detailedError DetailedError @@ -97,10 +101,12 @@ func ErrorFromResponse(r *http.Response) error { return DetailedError{ Status: r.StatusCode, Message: r.Status, + ID: requestID, } } detailedError = DetailedError{ + ID: requestID, Status: r.StatusCode, Title: errPayload.Errors[0].Title, } @@ -130,6 +136,7 @@ func ErrorFromResponse(r *http.Response) error { if err := json.NewDecoder(r.Body).Decode(&detailedError); err != nil { // If we can't decode the error, return a generic error return DetailedError{ + ID: requestID, Status: r.StatusCode, Message: r.Status, } diff --git a/go.mod b/go.mod index 5c895c52..7c2c9cb3 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect + github.com/tidwall/pretty v1.2.1 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect diff --git a/go.sum b/go.sum index 2e57862a..4d449ac5 100644 --- a/go.sum +++ b/go.sum @@ -147,6 +147,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= diff --git a/honeycombio/type_helpers.go b/honeycombio/type_helpers.go index cbfefb36..cc2eb435 100644 --- a/honeycombio/type_helpers.go +++ b/honeycombio/type_helpers.go @@ -251,6 +251,7 @@ func diagFromDetailedErr(err honeycombio.DetailedError) diag.Diagnostics { detail += d.Field + " " } detail += d.Description + detail += fmt.Sprintf(" - ID: %s", err.ID) diags = append(diags, diag.Diagnostic{ Severity: diag.Error, diff --git a/internal/helper/diag.go b/internal/helper/diag.go index 55666b62..7f099bbf 100644 --- a/internal/helper/diag.go +++ b/internal/helper/diag.go @@ -53,8 +53,8 @@ func AddDiagnosticOnError(diag *diag.Diagnostics, summary string, err error) boo } func (d DetailedErrorDiagnostic) Detail() string { + response := fmt.Sprintf("ID: %s\n", d.e.ID) if len(d.e.Details) > 0 { - var response string for i, dt := range d.e.Details { response += dt.Code + " - " + dt.Description @@ -65,7 +65,7 @@ func (d DetailedErrorDiagnostic) Detail() string { return response } - return d.e.Message + return response + d.e.Message } func (d DetailedErrorDiagnostic) Summary() string { From 65ea57b5319fd0cc31c5f531a2beb8568d5ac478 Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 13:23:12 -0500 Subject: [PATCH 02/10] woops don't commit that --- .env | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.env b/.env index bb81be5b..1a0c2058 100644 --- a/.env +++ b/.env @@ -1,7 +1,6 @@ -HONEYCOMB_API_KEY=uNJMtnUmGKcWe2Bup7JfcB -HONEYCOMB_KEY_ID=hccmk_01jd0q14vvwvw0vsb6k7s10bfk -HONEYCOMB_KEY_SECRET=szwp610jzrf2gkv1w4c1hr6a51ya5kfs -HONEYCOMB_API_ENDPOINT=https://api-dogfood.honeycomb.io -HONEYCOMB_DATASET=terraform-test +# HONEYCOMB_API_KEY= +# HONEYCOMB_KEY_ID= +# HONEYCOMB_KEY_SECRET= +# HONEYCOMB_API_ENDPOINT= +# HONEYCOMB_DATASET= TF_ACC=1 -HONEYCOMBIO_DEBUG=true \ No newline at end of file From e2c901bf3bd730662ed404287aa10f3769f5ef2a Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 14:28:13 -0500 Subject: [PATCH 03/10] remove spaces --- .env | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.env b/.env index 1a0c2058..7b16c12e 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ -# HONEYCOMB_API_KEY= -# HONEYCOMB_KEY_ID= -# HONEYCOMB_KEY_SECRET= -# HONEYCOMB_API_ENDPOINT= -# HONEYCOMB_DATASET= +#HONEYCOMB_API_KEY= +#HONEYCOMB_KEY_ID= +#HONEYCOMB_KEY_SECRET= +#HONEYCOMB_API_ENDPOINT= +#HONEYCOMB_DATASET= TF_ACC=1 From af49bec537583efab60165c8368ed9f3b8f8bf3f Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 14:29:25 -0500 Subject: [PATCH 04/10] update comment --- client/errors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/errors.go b/client/errors.go index 0fc355c7..611754b2 100644 --- a/client/errors.go +++ b/client/errors.go @@ -14,7 +14,7 @@ type DetailedError struct { Status int `json:"status,omitempty"` // The error message Message string `json:"error,omitempty"` - // ID unique ID of the HTTP request that caused this error. + // ID is the unique ID of the HTTP request that caused this error. ID string `json:"request_id,omitempty"` // Type is a URI used to uniquely identify the type of error. Type string `json:"type,omitempty"` From 4a6eb6371062bc343b48c0d16e6a6421dfa270f4 Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 14:31:24 -0500 Subject: [PATCH 05/10] remove dependency from testing --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index 7c2c9cb3..5c895c52 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect - github.com/tidwall/pretty v1.2.1 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect diff --git a/go.sum b/go.sum index 4d449ac5..2e57862a 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= -github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= From 1433b2330b2d26ee85dced2d4af0cb213e50de23 Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 14:37:02 -0500 Subject: [PATCH 06/10] add failing test for example --- client/marker_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/client/marker_test.go b/client/marker_test.go index 9e339bb9..78991bd6 100644 --- a/client/marker_test.go +++ b/client/marker_test.go @@ -95,6 +95,7 @@ func TestMarkers(t *testing.T) { _, err := c.Markers.Get(ctx, dataset, m.ID) var de client.DetailedError + require.NoError(t, err) require.Error(t, err) require.ErrorAs(t, err, &de) assert.True(t, de.IsNotFound()) From 0ddd75a6e936355094713bec887df291b598162c Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 15:11:07 -0500 Subject: [PATCH 07/10] populate request id --- client/errors.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/errors.go b/client/errors.go index 611754b2..82ae01ae 100644 --- a/client/errors.go +++ b/client/errors.go @@ -146,6 +146,12 @@ func ErrorFromResponse(r *http.Response) error { if detailedError.Status == 0 { detailedError.Status = r.StatusCode } + + // ensure we have the requestID set + if detailedError.ID == "" { + detailedError.ID = requestID + } + return detailedError } } From c81e65d996b1f8d96a2fbf32939e70dce15b59c7 Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 17:47:59 -0500 Subject: [PATCH 08/10] include request id in test errors --- client/errors.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/errors.go b/client/errors.go index 82ae01ae..5cf23394 100644 --- a/client/errors.go +++ b/client/errors.go @@ -3,6 +3,7 @@ package client import ( "encoding/json" "errors" + "fmt" "net/http" "github.com/hashicorp/jsonapi" @@ -65,9 +66,8 @@ func (e *DetailedError) IsNotFound() bool { // Error returns a pretty-printed representation of the error func (e DetailedError) Error() string { + response := fmt.Sprintf("ID: %s\n", e.ID) if len(e.Details) > 0 { - var response string - for index, details := range e.Details { response += details.String() @@ -81,7 +81,7 @@ func (e DetailedError) Error() string { return response } - return e.Message + return response + e.Message } func ErrorFromResponse(r *http.Response) error { From 272be03f40ce60e510c0cca4612f181e1f6b5fbf Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 18:00:26 -0500 Subject: [PATCH 09/10] what if we just turn debug on in tests always --- client/client_test.go | 3 +-- client/errors.go | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/client/client_test.go b/client/client_test.go index 1364ce4f..8c8960a9 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -24,11 +24,10 @@ func newTestClient(t *testing.T) *client.Client { if !ok { t.Fatal("expected environment variable " + client.DefaultAPIKeyEnv) } - _, debug := os.LookupEnv("HONEYCOMBIO_DEBUG") c, err := client.NewClientWithConfig(&client.Config{ APIKey: apiKey, - Debug: debug, + Debug: true, UserAgent: testUserAgent, }) require.NoError(t, err, "failed to create client") diff --git a/client/errors.go b/client/errors.go index 5cf23394..fc50c407 100644 --- a/client/errors.go +++ b/client/errors.go @@ -3,7 +3,6 @@ package client import ( "encoding/json" "errors" - "fmt" "net/http" "github.com/hashicorp/jsonapi" @@ -66,7 +65,7 @@ func (e *DetailedError) IsNotFound() bool { // Error returns a pretty-printed representation of the error func (e DetailedError) Error() string { - response := fmt.Sprintf("ID: %s\n", e.ID) + response := "" if len(e.Details) > 0 { for index, details := range e.Details { response += details.String() @@ -81,7 +80,7 @@ func (e DetailedError) Error() string { return response } - return response + e.Message + return e.Message } func ErrorFromResponse(r *http.Response) error { From bd2a59efdeb5129a981b47afa3002a156259af56 Mon Sep 17 00:00:00 2001 From: Elliott Krupa Date: Wed, 20 Nov 2024 18:05:07 -0500 Subject: [PATCH 10/10] update v2 client --- client/client.go | 3 +-- client/v2/client.go | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/client/client.go b/client/client.go index 07dd1473..48e30746 100644 --- a/client/client.go +++ b/client/client.go @@ -138,10 +138,9 @@ func NewClientWithConfig(config *Config) (*Client, error) { } if config.Debug { - // if enabled we log all requests and responses to sterr client.httpClient.Logger = log.New(os.Stderr, "", log.LstdFlags) client.httpClient.ResponseLogHook = func(l retryablehttp.Logger, resp *http.Response) { - l.Printf("[DEBUG] Request: %s \"%s\" %s %s", resp.Request.Method, resp.Request.URL.String(), resp.Status, resp.Header.Get("Request-Id")) + l.Printf("[DEBUG] %s \"%s\" %s %s", resp.Request.Method, resp.Request.URL.String(), resp.Status, resp.Header.Get("Request-Id")) } } diff --git a/client/v2/client.go b/client/v2/client.go index 9156c65f..51c5919e 100644 --- a/client/v2/client.go +++ b/client/v2/client.go @@ -104,11 +104,9 @@ func NewClientWithConfig(config *Config) (*Client, error) { } if config.Debug { - // if enabled we log all requests and responses to sterr client.http.Logger = log.New(os.Stderr, "", log.LstdFlags) client.http.ResponseLogHook = func(l retryablehttp.Logger, resp *http.Response) { - l.Printf("[DEBUG] Request: %s %s", resp.Request.Method, resp.Request.URL.String()) - // TODO: Log request body + l.Printf("[DEBUG] %s \"%s\" %s %s", resp.Request.Method, resp.Request.URL.String(), resp.Status, resp.Header.Get("Request-Id")) } }