Skip to content

Commit

Permalink
chore: add query-frontend option to select request headers in query logs
Browse files Browse the repository at this point in the history
  • Loading branch information
Juraj Michalek committed Dec 15, 2023
1 parent 6034063 commit 2dabec3
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
22 changes: 19 additions & 3 deletions pkg/lokifrontend/frontend/transport/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"flag"
"fmt"
"github.com/grafana/dskit/flagext"
"io"
"net/http"
"net/url"
Expand Down Expand Up @@ -41,13 +42,15 @@ var (

// Config for a Handler.
type HandlerConfig struct {
LogQueriesLongerThan time.Duration `yaml:"log_queries_longer_than"`
MaxBodySize int64 `yaml:"max_body_size"`
QueryStatsEnabled bool `yaml:"query_stats_enabled"`
LogQueriesLongerThan time.Duration `yaml:"log_queries_longer_than"`
LogQueryRequestHeaders flagext.StringSliceCSV `yaml:"log_query_request_headers"`
MaxBodySize int64 `yaml:"max_body_size"`
QueryStatsEnabled bool `yaml:"query_stats_enabled"`
}

func (cfg *HandlerConfig) RegisterFlags(f *flag.FlagSet) {
f.DurationVar(&cfg.LogQueriesLongerThan, "frontend.log-queries-longer-than", 0, "Log queries that are slower than the specified duration. Set to 0 to disable. Set to < 0 to enable on all queries.")
f.Var(&cfg.LogQueryRequestHeaders, "query-frontend.log-query-request-headers", "Comma-separated list of request header names to include in query logs. Applies to both query stats and slow queries logs.")
f.Int64Var(&cfg.MaxBodySize, "frontend.max-body-size", 10*1024*1024, "Max body size for downstream prometheus.")
f.BoolVar(&cfg.QueryStatsEnabled, "frontend.query-stats-enabled", false, "True to enable query statistics tracking. When enabled, a message with some statistics is logged for every query.")
}
Expand Down Expand Up @@ -205,9 +208,22 @@ func (f *Handler) reportQueryStats(r *http.Request, queryString url.Values, quer
"fetched_chunks_bytes", numBytes,
}, formatQueryString(queryString)...)

if len(f.cfg.LogQueryRequestHeaders) != 0 {
logMessage = append(logMessage, formatRequestHeaders(&r.Header, f.cfg.LogQueryRequestHeaders)...)
}

level.Info(util_log.WithContext(r.Context(), f.log)).Log(logMessage...)
}

func formatRequestHeaders(h *http.Header, headersToLog []string) (fields []interface{}) {
for _, s := range headersToLog {
if v := h.Get(s); v != "" {
fields = append(fields, fmt.Sprintf("header_%s", strings.ReplaceAll(strings.ToLower(s), "-", "_")), v)
}
}
return fields
}

func (f *Handler) parseRequestQueryString(r *http.Request, bodyBuf bytes.Buffer) url.Values {
// Use previously buffered body.
r.Body = io.NopCloser(&bodyBuf)
Expand Down
15 changes: 15 additions & 0 deletions pkg/lokifrontend/frontend/transport/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,18 @@ func TestWriteError(t *testing.T) {
})
}
}

func TestFormatRequestHeaders(t *testing.T) {
h := http.Header{}
h.Add("X-Header-To-Log", "i should be logged!")
h.Add("X-Header-To-Not-Log", "i shouldn't be logged!")

fields := formatRequestHeaders(&h, []string{"X-Header-To-Log", "X-Header-Not-Present"})

expected := []interface{}{
"header_x_header_to_log",
"i should be logged!",
}

require.Equal(t, expected, fields)
}

0 comments on commit 2dabec3

Please sign in to comment.