Refactor query log fields (#6694)

* Refactor query log fields

Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
This commit is contained in:
Julien Pivotto 2020-01-27 10:53:10 +01:00 committed by Brian Brazil
parent c1e49d50c5
commit 5f27ac3583
5 changed files with 59 additions and 39 deletions

View file

@ -146,24 +146,27 @@ func (p *queryLogTest) queryString() string {
// test parameters. // test parameters.
func (p *queryLogTest) validateLastQuery(t *testing.T, ql []queryLogLine) { func (p *queryLogTest) validateLastQuery(t *testing.T, ql []queryLogLine) {
q := ql[len(ql)-1] q := ql[len(ql)-1]
testutil.Equals(t, q["query"].(string), p.queryString()) testutil.Equals(t, p.queryString(), q.Params.Query)
switch p.origin { testutil.Equals(t, 0, q.Params.Step)
case consoleOrigin:
testutil.Equals(t, q["path"].(string), p.prefix+"/consoles/test.html")
case apiOrigin:
testutil.Equals(t, q["path"].(string), p.prefix+"/api/v1/query")
case ruleOrigin:
testutil.Equals(t, q["groupName"].(string), "querylogtest")
testutil.Equals(t, q["groupFile"].(string), filepath.Join(p.cwd, "testdata", "rules", "test.yml"))
default:
panic("unknown origin")
}
if p.origin != ruleOrigin { if p.origin != ruleOrigin {
host := p.host host := p.host
if host == "[::1]" { if host == "[::1]" {
host = "::1" host = "::1"
} }
testutil.Equals(t, q["clientIP"].(string), host) testutil.Equals(t, host, q.Request.ClientIP)
}
switch p.origin {
case apiOrigin:
testutil.Equals(t, p.prefix+"/api/v1/query", q.Request.Path)
case consoleOrigin:
testutil.Equals(t, p.prefix+"/consoles/test.html", q.Request.Path)
case ruleOrigin:
testutil.Equals(t, "querylogtest", q.RuleGroup.Name)
testutil.Equals(t, filepath.Join(p.cwd, "testdata", "rules", "test.yml"), q.RuleGroup.File)
default:
panic("unknown origin")
} }
} }
@ -342,7 +345,20 @@ func (p *queryLogTest) run(t *testing.T) {
} }
} }
type queryLogLine map[string]interface{} type queryLogLine struct {
Params struct {
Query string `json:"query"`
Step int `json:"step"`
} `json:"params"`
Request struct {
Path string `json:"path"`
ClientIP string `json:"clientIP"`
} `json:"httpRequest"`
RuleGroup struct {
File string `json:"file"`
Name string `json:"name"`
} `json:"ruleGroup"`
}
// readQueryLog unmarshal a json-formatted query log into query log lines. // readQueryLog unmarshal a json-formatted query log into query log lines.
func readQueryLog(t *testing.T, path string) []queryLogLine { func readQueryLog(t *testing.T, path string) []queryLogLine {

View file

@ -437,20 +437,20 @@ func (ng *Engine) exec(ctx context.Context, q *query) (v Value, w storage.Warnin
defer func() { defer func() {
ng.queryLoggerLock.RLock() ng.queryLoggerLock.RLock()
if l := ng.queryLogger; l != nil { if l := ng.queryLogger; l != nil {
f := []interface{}{"query", q.q} params := make(map[string]interface{}, 4)
params["query"] = q.q
if eq, ok := q.Statement().(*EvalStmt); ok {
params["start"] = formatDate(eq.Start)
params["end"] = formatDate(eq.End)
params["step"] = eq.Interval
}
f := []interface{}{"params", params}
if err != nil { if err != nil {
f = append(f, "error", err) f = append(f, "error", err)
} }
if eq, ok := q.Statement().(*EvalStmt); ok {
f = append(f,
"start", formatDate(eq.Start),
"end", formatDate(eq.End),
"step", eq.Interval.String(),
)
}
f = append(f, "stats", stats.NewQueryStats(q.Stats())) f = append(f, "stats", stats.NewQueryStats(q.Stats()))
if origin := ctx.Value(queryOrigin); origin != nil { if origin := ctx.Value(queryOrigin); origin != nil {
for k, v := range origin.(map[string]string) { for k, v := range origin.(map[string]interface{}) {
f = append(f, k, v) f = append(f, k, v)
} }
} }
@ -2096,7 +2096,7 @@ func shouldDropMetricName(op ItemType) bool {
} }
// NewOriginContext returns a new context with data about the origin attached. // NewOriginContext returns a new context with data about the origin attached.
func NewOriginContext(ctx context.Context, data map[string]string) context.Context { func NewOriginContext(ctx context.Context, data map[string]interface{}) context.Context {
return context.WithValue(ctx, queryOrigin, data) return context.WithValue(ctx, queryOrigin, data)
} }

View file

@ -1154,13 +1154,13 @@ func TestQueryLogger_basic(t *testing.T) {
f1 := NewFakeQueryLogger() f1 := NewFakeQueryLogger()
engine.SetQueryLogger(f1) engine.SetQueryLogger(f1)
queryExec() queryExec()
for i, field := range []string{"query", "test statement"} { for i, field := range []interface{}{"params", map[string]interface{}{"query": "test statement"}} {
testutil.Assert(t, f1.logs[i].(string) == field, "expected %v as key, got %v", field, f1.logs[i]) testutil.Equals(t, field, f1.logs[i])
} }
l := len(f1.logs) l := len(f1.logs)
queryExec() queryExec()
testutil.Assert(t, 2*l == len(f1.logs), "expected %d fields in logs, got %v", 2*l, len(f1.logs)) testutil.Equals(t, 2*l, len(f1.logs))
// Test that we close the query logger when unsetting it. // Test that we close the query logger when unsetting it.
testutil.Assert(t, !f1.closed, "expected f1 to be open, got closed") testutil.Assert(t, !f1.closed, "expected f1 to be open, got closed")
@ -1194,7 +1194,7 @@ func TestQueryLogger_fields(t *testing.T) {
engine.SetQueryLogger(f1) engine.SetQueryLogger(f1)
ctx, cancelCtx := context.WithCancel(context.Background()) ctx, cancelCtx := context.WithCancel(context.Background())
ctx = NewOriginContext(ctx, map[string]string{"foo": "bar"}) ctx = NewOriginContext(ctx, map[string]interface{}{"foo": "bar"})
defer cancelCtx() defer cancelCtx()
query := engine.newTestQuery(func(ctx context.Context) error { query := engine.newTestQuery(func(ctx context.Context) error {
return contextDone(ctx, "test statement execution") return contextDone(ctx, "test statement execution")
@ -1206,7 +1206,7 @@ func TestQueryLogger_fields(t *testing.T) {
expected := []string{"foo", "bar"} expected := []string{"foo", "bar"}
for i, field := range expected { for i, field := range expected {
v := f1.logs[len(f1.logs)-len(expected)+i].(string) v := f1.logs[len(f1.logs)-len(expected)+i].(string)
testutil.Assert(t, field == v, "expected %v as key, got %v", field, v) testutil.Equals(t, field, v)
} }
} }
@ -1224,7 +1224,7 @@ func TestQueryLogger_error(t *testing.T) {
engine.SetQueryLogger(f1) engine.SetQueryLogger(f1)
ctx, cancelCtx := context.WithCancel(context.Background()) ctx, cancelCtx := context.WithCancel(context.Background())
ctx = NewOriginContext(ctx, map[string]string{"foo": "bar"}) ctx = NewOriginContext(ctx, map[string]interface{}{"foo": "bar"})
defer cancelCtx() defer cancelCtx()
testErr := errors.New("failure") testErr := errors.New("failure")
query := engine.newTestQuery(func(ctx context.Context) error { query := engine.newTestQuery(func(ctx context.Context) error {
@ -1234,7 +1234,7 @@ func TestQueryLogger_error(t *testing.T) {
res := query.Exec(ctx) res := query.Exec(ctx)
testutil.NotOk(t, res.Err, "query should have failed") testutil.NotOk(t, res.Err, "query should have failed")
for i, field := range []interface{}{"query", "test statement", "error", testErr} { for i, field := range []interface{}{"params", map[string]interface{}{"query": "test statement"}, "error", testErr} {
testutil.Assert(t, f1.logs[i] == field, "expected %v as key, got %v", field, f1.logs[i]) testutil.Equals(t, f1.logs[i], field)
} }
} }

View file

@ -287,9 +287,11 @@ func (g *Group) run(ctx context.Context) {
return return
} }
ctx = promql.NewOriginContext(ctx, map[string]string{ ctx = promql.NewOriginContext(ctx, map[string]interface{}{
"groupFile": g.File(), "ruleGroup": map[string]string{
"groupName": g.Name(), "file": g.File(),
"name": g.Name(),
},
}) })
iter := func() { iter := func() {

View file

@ -42,9 +42,11 @@ func ContextFromRequest(ctx context.Context, r *http.Request) (context.Context,
if v := ctx.Value(pathParam); v != nil { if v := ctx.Value(pathParam); v != nil {
path = v.(string) path = v.(string)
} }
return promql.NewOriginContext(ctx, map[string]string{ return promql.NewOriginContext(ctx, map[string]interface{}{
"clientIP": ip, "httpRequest": map[string]string{
"method": r.Method, "clientIP": ip,
"path": path, "method": r.Method,
"path": path,
},
}), nil }), nil
} }