From 66af6c98a3b2222c3846276a78f35c7e00226b23 Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 17 Dec 2024 22:03:12 -0500 Subject: [PATCH] *: update ResponseError type (#142) * Show Code/Message so that it's easy to generate database schema * Add URL in error Signed-off-by: Wei Fu --- api/types/metric.go | 6 ++++-- metrics/request.go | 5 +++-- metrics/request_test.go | 19 +++++++++++++++++-- request/schedule.go | 2 +- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/api/types/metric.go b/api/types/metric.go index 8c89a05..870f376 100644 --- a/api/types/metric.go +++ b/api/types/metric.go @@ -22,6 +22,8 @@ const ( // ResponseError is the record about that error. type ResponseError struct { + // URL indicates target resource. + URL string `json:"url"` // Timestamp indicates when this error was received. Timestamp time.Time `json:"timestamp"` // Duration records timespan in seconds. @@ -29,11 +31,11 @@ type ResponseError struct { // Type indicates that category to which the error belongs. Type ResponseErrorType `json:"type"` // Code only works when Type is http. - Code int `json:"code,omitempty"` + Code int `json:"code"` // Message shows error message for this error. // // NOTE: When Type is http, this field will be empty. - Message string `json:"message,omitempty"` + Message string `json:"message"` } // ResponseStats is the report about benchmark result. diff --git a/metrics/request.go b/metrics/request.go index 979ad22..bf4106c 100644 --- a/metrics/request.go +++ b/metrics/request.go @@ -17,7 +17,7 @@ type ResponseMetric interface { // ObserveLatency observes latency. ObserveLatency(url string, seconds float64) // ObserveFailure observes failure response. - ObserveFailure(now time.Time, seconds float64, err error) + ObserveFailure(url string, now time.Time, seconds float64, err error) // ObserveReceivedBytes observes the bytes read from apiserver. ObserveReceivedBytes(bytes int64) // Gather returns the summary. @@ -52,7 +52,7 @@ func (m *responseMetricImpl) ObserveLatency(url string, seconds float64) { } // ObserveFailure implements ResponseMetric. -func (m *responseMetricImpl) ObserveFailure(now time.Time, seconds float64, err error) { +func (m *responseMetricImpl) ObserveFailure(url string, now time.Time, seconds float64, err error) { if err == nil { return } @@ -61,6 +61,7 @@ func (m *responseMetricImpl) ObserveFailure(now time.Time, seconds float64, err defer m.mu.Unlock() oerr := types.ResponseError{ + URL: url, Timestamp: now, Duration: seconds, } diff --git a/metrics/request_test.go b/metrics/request_test.go index 557923e..2395ba1 100644 --- a/metrics/request_test.go +++ b/metrics/request_test.go @@ -25,90 +25,105 @@ func TestResponseMetric_ObserveFailure(t *testing.T) { expectedErrors := []types.ResponseError{ { + URL: "0", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP, Code: 429, }, { + URL: "1", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP, Code: 500, }, { + URL: "2", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP, Code: 504, }, { + URL: "3", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP2Protocol, Message: "http2: server sent GOAWAY and closed the connection; ErrCode=NO_ERROR, debug=", }, { + URL: "4", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP2Protocol, Message: "http2: server sent GOAWAY and closed the connection; ErrCode=PROTOCOL_ERROR, debug=", }, { + URL: "5", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP2Protocol, Message: "http2: client connection lost", }, { + URL: "6", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP2Protocol, Message: "http2: client connection lost", }, { + URL: "7", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeHTTP2Protocol, Message: http2.ErrCode(10).String(), }, { + URL: "8", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: "net/http: TLS handshake timeout", }, { + URL: "9", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: "net/http: TLS handshake timeout", }, { + URL: "10", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: "context deadline exceeded", }, { + URL: "11", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: syscall.ECONNRESET.Error(), }, { + URL: "12", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: syscall.ECONNREFUSED.Error(), }, { + URL: "13", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeConnection, Message: io.ErrUnexpectedEOF.Error(), }, { + URL: "14", Timestamp: observedAt, Duration: dur.Seconds(), Type: types.ResponseErrorTypeUnknown, @@ -150,8 +165,8 @@ func TestResponseMetric_ObserveFailure(t *testing.T) { } m := NewResponseMetric() - for _, err := range errs { - m.ObserveFailure(observedAt, dur.Seconds(), err) + for idx, err := range errs { + m.ObserveFailure(fmt.Sprintf("%d", idx), observedAt, dur.Seconds(), err) } errors := m.Gather().Errors assert.Equal(t, expectedErrors, errors) diff --git a/request/schedule.go b/request/schedule.go index 80f345a..07caf02 100644 --- a/request/schedule.go +++ b/request/schedule.go @@ -109,7 +109,7 @@ func Schedule(ctx context.Context, spec *types.LoadProfileSpec, restCli []rest.I respMetric.ObserveReceivedBytes(bytes) if err != nil { - respMetric.ObserveFailure(end, latency, err) + respMetric.ObserveFailure(req.URL().String(), end, latency, err) klog.V(5).Infof("Request stream failed: %v", err) return }