-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
querylog
: json format version 2
#15271
Changes from 5 commits
2fb06a7
fe608ba
8f63ad5
6d86698
150727c
4246773
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
Copyright 2024 The Vitess Authors. | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package streamlog | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
|
||
querypb "vitess.io/vitess/go/vt/proto/query" | ||
) | ||
|
||
var ErrUnrecognizedBindVarType = errors.New("unrecognized bind variable type") | ||
|
||
// BindVariable is a wrapper for marshal/unmarshaling querypb.BindVariable as json. | ||
type BindVariable querypb.BindVariable | ||
|
||
// NewBindVariable returns a wrapped *querypb.BindVariable object. | ||
func NewBindVariable(bv *querypb.BindVariable) BindVariable { | ||
return BindVariable(*bv) | ||
Check failure on line 33 in go/streamlog/bind_variable.go GitHub Actions / Static Code Checks Etc
|
||
} | ||
|
||
// NewBindVariables returns a string-map of wrapped *querypb.BindVariable objects. | ||
func NewBindVariables(bvs map[string]*querypb.BindVariable) map[string]BindVariable { | ||
out := make(map[string]BindVariable, len(bvs)) | ||
for key, bindVar := range bvs { | ||
out[key] = NewBindVariable(bindVar) | ||
} | ||
return out | ||
} | ||
|
||
// UnmarshalJSON unmarshals the custom BindVariable json-format. | ||
// See MarshalJSON for more information. | ||
func (bv *BindVariable) UnmarshalJSON(b []byte) error { | ||
in := struct { | ||
Type string | ||
Value []byte | ||
}{} | ||
if err := json.Unmarshal(b, &in); err != nil { | ||
return err | ||
} | ||
// convert type string to querypb.Type and pass along Value. | ||
typeVal, found := querypb.Type_value[in.Type] | ||
if !found { | ||
return ErrUnrecognizedBindVarType | ||
} | ||
bv.Type = querypb.Type(typeVal) | ||
bv.Value = in.Value | ||
return nil | ||
} | ||
|
||
// MarshalJSON renders the wrapped *querypb.BindVariable as json. It | ||
// ensures that the "Type" field is a string representation of the | ||
// variable type instead of an integer-based code that is less | ||
// portable and human-readable. | ||
// | ||
// This allows a *querypb.BindVariable that would have marshaled | ||
// to this: | ||
// | ||
// {"Type":10262,"Value":"FmtAtEq6S9Y="} | ||
// | ||
// to marshal to this: | ||
// | ||
// {"Type":"VARBINARY","Value":"FmtAtEq6S9Y="} | ||
// | ||
// or if query redaction is enabled, like this: | ||
// | ||
// {"Type":"VARBINARY","Value":null} | ||
func (bv BindVariable) MarshalJSON() ([]byte, error) { | ||
Check failure on line 82 in go/streamlog/bind_variable.go GitHub Actions / Static Code Checks Etc
|
||
// convert querypb.Type integer to string and pass along Value. | ||
out := map[string]interface{}{ | ||
"Type": bv.Type.String(), | ||
"Value": bv.Value, | ||
} | ||
if GetRedactDebugUIQueries() { | ||
out["Value"] = nil | ||
} | ||
return json.Marshal(out) | ||
} | ||
|
||
// BindVariablesToProto converts a string-map of BindVariable to a string-map of *querypb.BindVariable. | ||
func BindVariablesToProto(bvs map[string]BindVariable) map[string]*querypb.BindVariable { | ||
out := make(map[string]*querypb.BindVariable, len(bvs)) | ||
for key, bindVar := range bvs { | ||
Check failure on line 97 in go/streamlog/bind_variable.go GitHub Actions / Static Code Checks Etc
|
||
bv := querypb.BindVariable(bindVar) | ||
Check failure on line 98 in go/streamlog/bind_variable.go GitHub Actions / Static Code Checks Etc
|
||
out[key] = &bv | ||
} | ||
return out | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,14 +36,13 @@ import ( | |
querypb "vitess.io/vitess/go/vt/proto/query" | ||
) | ||
|
||
// LogStats records the stats for a single vtgate query | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep this. |
||
type LogStats struct { | ||
Ctx context.Context | ||
Ctx context.Context `json:"-"` | ||
Method string | ||
TabletType string | ||
StmtType string | ||
SQL string | ||
BindVariables map[string]*querypb.BindVariable | ||
BindVariables map[string]streamlog.BindVariable `json:",omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See below. |
||
StartTime time.Time | ||
EndTime time.Time | ||
ShardQueries uint64 | ||
|
@@ -52,13 +51,21 @@ type LogStats struct { | |
PlanTime time.Duration | ||
ExecuteTime time.Duration | ||
CommitTime time.Duration | ||
Error error | ||
Error error `json:",omitempty"` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems incorrect. Did you intend for |
||
TablesUsed []string | ||
SessionUUID string | ||
CachedPlan bool | ||
ActiveKeyspace string // ActiveKeyspace is the selected keyspace `use ks` | ||
} | ||
|
||
type LogStatsJSON struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Name with JSONv2 to separate from the base implementation? |
||
RemoteAddr string | ||
Username string | ||
ImmediateCaller string | ||
EffectiveCaller string | ||
LogStats | ||
} | ||
|
||
// NewLogStats constructs a new LogStats with supplied Method and ctx | ||
// field values, and the StartTime field set to the present time. | ||
func NewLogStats(ctx context.Context, methodName, sql, sessionUUID string, bindVars map[string]*querypb.BindVariable) *LogStats { | ||
|
@@ -67,7 +74,7 @@ func NewLogStats(ctx context.Context, methodName, sql, sessionUUID string, bindV | |
Method: methodName, | ||
SQL: sql, | ||
SessionUUID: sessionUUID, | ||
BindVariables: bindVars, | ||
BindVariables: streamlog.NewBindVariables(bindVars), | ||
StartTime: time.Now(), | ||
} | ||
} | ||
|
@@ -137,10 +144,10 @@ func (stats *LogStats) Logf(w io.Writer, params url.Values) error { | |
}() | ||
|
||
formattedBindVars := "\"[REDACTED]\"" | ||
if !streamlog.GetRedactDebugUIQueries() { | ||
if !streamlog.GetRedactDebugUIQueries() && !streamlog.UseQueryLogJSONV2() { | ||
_, fullBindParams := params["full"] | ||
formattedBindVars = sqltypes.FormatBindVariables( | ||
stats.BindVariables, | ||
streamlog.BindVariablesToProto(stats.BindVariables), | ||
fullBindParams, | ||
streamlog.GetQueryLogFormat() == streamlog.QueryLogFormatJSON, | ||
) | ||
|
@@ -154,6 +161,16 @@ func (stats *LogStats) Logf(w io.Writer, params url.Values) error { | |
case streamlog.QueryLogFormatText: | ||
fmtString = "%v\t%v\t%v\t'%v'\t'%v'\t%v\t%v\t%.6f\t%.6f\t%.6f\t%.6f\t%v\t%q\t%v\t%v\t%v\t%q\t%q\t%q\t%v\t%v\t%q\n" | ||
case streamlog.QueryLogFormatJSON: | ||
if streamlog.UseQueryLogJSONV2() { | ||
// flag --querylog-json-v2 | ||
return json.NewEncoder(w).Encode(LogStatsJSON{ | ||
EffectiveCaller: stats.EffectiveCaller(), | ||
ImmediateCaller: stats.ImmediateCaller(), | ||
LogStats: *stats, | ||
RemoteAddr: remoteAddr, | ||
Username: username, | ||
}) | ||
} | ||
fmtString = "{\"Method\": %q, \"RemoteAddr\": %q, \"Username\": %q, \"ImmediateCaller\": %q, \"Effective Caller\": %q, \"Start\": \"%v\", \"End\": \"%v\", \"TotalTime\": %.6f, \"PlanTime\": %v, \"ExecuteTime\": %v, \"CommitTime\": %v, \"StmtType\": %q, \"SQL\": %q, \"BindVars\": %v, \"ShardQueries\": %v, \"RowsAffected\": %v, \"Error\": %q, \"TabletType\": %q, \"SessionUUID\": %q, \"Cached Plan\": %v, \"TablesUsed\": %v, \"ActiveKeyspace\": %q}\n" | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we already have
--querylog-format=json
, why not--querylog-format=json-v2
rather than a new flag?