Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

## master / unreleased
* [ENHANCEMENT] Query Frontend: Log `X-Grafana-User` header in query stats, slow query, and query request logs when Grafana's `send_user_header` is enabled. #7797

@SungJin1212 SungJin1212 Aug 21, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, Can you fix a changelog? (order and pr number)

* [FEATURE] Engine: Add `-querier.selector-batch-size` and `-ruler.selector-batch-size` flags to configure series batching in the Thanos promQL engine. 0 disables batching. #7763
* [CHANGE] Querier: Make query time range configurations per-tenant: `query_ingesters_within`, `query_store_after`, and `shuffle_sharding_ingesters_lookback_period`. Uses `model.Duration` instead of `time.Duration` to support serialization but has minimum unit of 1ms (nanoseconds/microseconds not supported). #7160
* [CHANGE] Cache: Setting `-blocks-storage.bucket-store.metadata-cache.bucket-index-content-ttl` to 0 will disable the bucket-index cache. #7446
Expand Down
7 changes: 6 additions & 1 deletion pkg/frontend/transport/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,18 @@ func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func formatGrafanaStatsFields(r *http.Request) []any {
// NOTE(GiedriusS): see https://github.com/grafana/grafana/pull/60301 for more info.

fields := make([]any, 0, 4)
fields := make([]any, 0, 6)
if dashboardUID := r.Header.Get("X-Dashboard-Uid"); dashboardUID != "" {
fields = append(fields, "X-Dashboard-Uid", dashboardUID)
}
if panelID := r.Header.Get("X-Panel-Id"); panelID != "" {
fields = append(fields, "X-Panel-Id", panelID)
}
// X-Grafana-User is sent by Grafana when [dataproxy] send_user_header is enabled.
// See https://github.com/grafana/grafana/pull/15998 for more info.
if grafanaUser := r.Header.Get("X-Grafana-User"); grafanaUser != "" {
fields = append(fields, "X-Grafana-User", grafanaUser)
}
return fields
}

Expand Down
14 changes: 14 additions & 0 deletions pkg/frontend/transport/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,11 @@ func TestReportQueryStatsFormat(t *testing.T) {
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 response_series_count=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 samples_scanned=0 user_agent=Grafana`,
source: requestmeta.SourceAPI,
},
"should include grafana user header": {
header: http.Header{"X-Grafana-User": []string{"admin"}},
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 response_series_count=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 samples_scanned=0 X-Grafana-User=admin`,
source: requestmeta.SourceAPI,
},
"should include engine type": {
header: http.Header{http.CanonicalHeaderKey(engine.TypeHeader): []string{string(engine.Thanos)}},
expectedLog: `level=info msg="query stats" component=query-frontend method=GET path=/prometheus/api/v1/query response_time=1s query_wall_time_seconds=0 response_series_count=0 fetched_series_count=0 fetched_chunks_count=0 fetched_samples_count=0 fetched_chunks_bytes=0 fetched_data_bytes=0 split_queries=0 status_code=200 response_size=1000 samples_scanned=0 engine_type=thanos`,
Expand Down Expand Up @@ -634,6 +639,15 @@ func TestReportSlowQueryFormat(t *testing.T) {
},
expectedLog: `level=info msg="slow query detected" method=GET host=localhost:8080 path=/prometheus/api/v1/query source=api time_taken_ms=1000 X-Dashboard-Uid=dashboard-1 X-Panel-Id=panel-1`,
},
"should include grafana user header": {
source: requestmeta.SourceAPI,
header: http.Header{
"X-Dashboard-Uid": []string{"dashboard-1"},
"X-Panel-Id": []string{"panel-1"},
"X-Grafana-User": []string{"admin"},
},
expectedLog: `level=info msg="slow query detected" method=GET host=localhost:8080 path=/prometheus/api/v1/query source=api time_taken_ms=1000 X-Dashboard-Uid=dashboard-1 X-Panel-Id=panel-1 X-Grafana-User=admin`,
},
"should include user agent, engine type and block store type headers": {
source: requestmeta.SourceAPI,
header: http.Header{
Expand Down