Skip to content

Commit

Permalink
Add bytes processed stats to existing Server-Timing header
Browse files Browse the repository at this point in the history
  • Loading branch information
madhu-reddy-peram committed Oct 16, 2024
1 parent cc5c647 commit 92f6c5c
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 15 deletions.
22 changes: 9 additions & 13 deletions pkg/frontend/transport/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ import (

const (
// StatusClientClosedRequest is the status code for when a client request cancellation of an http request
StatusClientClosedRequest = 499
ServiceTimingHeaderName = "Server-Timing"
cacheControlHeader = "Cache-Control"
cacheControlLogField = "header_cache_control"
ServiceTotalBytesProcessed = "X-Total-Bytes-Processed"
StatusClientClosedRequest = 499
ServiceTimingHeaderName = "Server-Timing"
cacheControlHeader = "Cache-Control"
cacheControlLogField = "header_cache_control"
)

var (
Expand Down Expand Up @@ -247,7 +246,6 @@ func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

if f.cfg.QueryStatsEnabled {
writeServiceTimingHeader(queryResponseTime, hs, queryDetails.QuerierStats)
writeTotalBytesProcessedHeader(hs, queryDetails.QuerierStats)
}

w.WriteHeader(resp.StatusCode)
Expand Down Expand Up @@ -486,22 +484,20 @@ func writeServiceTimingHeader(queryResponseTime time.Duration, headers http.Head
parts := make([]string, 0)
parts = append(parts, statsValue("querier_wall_time", stats.LoadWallTime()))
parts = append(parts, statsValue("response_time", queryResponseTime))
parts = append(parts, statsBytesProcessedValue("bytes_processed", stats.LoadFetchedChunkBytes()+stats.LoadFetchedIndexBytes()))
headers.Set(ServiceTimingHeaderName, strings.Join(parts, ", "))
}
}

func writeTotalBytesProcessedHeader(headers http.Header, stats *querier_stats.Stats) {
if stats != nil {
totalBytes := stats.LoadFetchedChunkBytes() + stats.LoadFetchedIndexBytes()
headers.Set(ServiceTotalBytesProcessed, strconv.FormatUint(totalBytes, 10))
}
}

func statsValue(name string, d time.Duration) string {
durationInMs := strconv.FormatFloat(float64(d)/float64(time.Millisecond), 'f', -1, 64)
return name + ";dur=" + durationInMs
}

func statsBytesProcessedValue(name string, value uint64) string {
return name + "=" + strconv.FormatUint(value, 10)
}

func httpRequestActivity(request *http.Request, userAgent string, requestParams url.Values) string {
tenantID := "(unknown)"
if tenantIDs, err := tenant.TenantIDs(request.Context()); err == nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/frontend/transport/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func TestHandler_ServeHTTP(t *testing.T) {
expectedReadConsistency: "",
},
{
name: "handler with stats enabled, check ServiceTotalBytesProcessed header",
name: "handler with stats enabled, check ServiceTimingHeader",
cfg: HandlerConfig{QueryStatsEnabled: true, MaxBodySize: 1024},
request: func() *http.Request {
req := httptest.NewRequest(http.MethodPost, "/api/v1/query", strings.NewReader("query=some_metric&time=42"))
Expand All @@ -303,7 +303,7 @@ func TestHandler_ServeHTTP(t *testing.T) {
expectedActivity: "user:12345 UA: req:POST /api/v1/query query=some_metric&time=42",
expectedReadConsistency: "",
assertHeaders: func(t *testing.T, headers http.Header) {
assert.Equal(t, "0", headers.Get(ServiceTotalBytesProcessed))
assert.Contains(t, headers.Get(ServiceTimingHeaderName), "bytes_processed=0")
},
},
} {
Expand Down

0 comments on commit 92f6c5c

Please sign in to comment.