From 39a562c5340adc407c85adcd1b2bec0f5be76344 Mon Sep 17 00:00:00 2001 From: Thomas Hardy Date: Thu, 16 Jun 2022 21:11:30 -0400 Subject: [PATCH] sql: add plan gist to sampled query telemetry log Partially resolves: #71328 This change adds a plan gist field to the sampled query telemetry log. The plan gist is written as a base64 encoded string. Release note (sql change): The sampled query telemetry log now includes a plan gist field. The plan gist field provides a compact representation of a logical plan for the sampled query, the field is written as a base64 encoded string. --- docs/generated/eventlog.md | 1 + pkg/sql/exec_log.go | 1 + pkg/sql/telemetry_logging_test.go | 5 +++++ pkg/util/log/eventpb/json_encode_generated.go | 10 ++++++++++ pkg/util/log/eventpb/telemetry.proto | 3 +++ 5 files changed, 20 insertions(+) diff --git a/docs/generated/eventlog.md b/docs/generated/eventlog.md index 1525b438f0d7..7ce22dbc7c8c 100644 --- a/docs/generated/eventlog.md +++ b/docs/generated/eventlog.md @@ -2458,6 +2458,7 @@ contains common SQL event/execution details. | `SkippedQueries` | skipped_queries indicate how many SQL statements were not considered for sampling prior to this one. If the field is omitted, or its value is zero, this indicates that no statement was omitted since the last event. | no | | `CostEstimate` | Cost of the query as estimated by the optimizer. | no | | `Distribution` | The distribution of the DistSQL query plan (local, full, or partial). | no | +| `PlanGist` | The query's plan gist bytes as a base64 encoded string. | no | #### Common fields diff --git a/pkg/sql/exec_log.go b/pkg/sql/exec_log.go index b44143c233e9..c28cc67ee2b2 100644 --- a/pkg/sql/exec_log.go +++ b/pkg/sql/exec_log.go @@ -389,6 +389,7 @@ func (p *planner) maybeLogStatementInternal( SkippedQueries: skippedQueries, CostEstimate: p.curPlan.instrumentation.costEstimate, Distribution: p.curPlan.instrumentation.distribution.String(), + PlanGist: p.curPlan.instrumentation.planGist.String(), }}) } else { telemetryMetrics.incSkippedQueryCount() diff --git a/pkg/sql/telemetry_logging_test.go b/pkg/sql/telemetry_logging_test.go index 39d8b5d3c560..2bae4296dd28 100644 --- a/pkg/sql/telemetry_logging_test.go +++ b/pkg/sql/telemetry_logging_test.go @@ -231,6 +231,11 @@ func TestTelemetryLogging(t *testing.T) { if !distRe.MatchString(e.Message) { t.Errorf("expected to find Distribution but none was found") } + // Match plan gist on any non-empty string value. + planGist := regexp.MustCompile("\"PlanGist\":(\"\\S+\")") + if !planGist.MatchString(e.Message) { + t.Errorf("expected to find PlanGist but none was found in: %s", e.Message) + } for _, eTag := range tc.expectedUnredactedTags { for _, tag := range strings.Split(e.Tags, ",") { kv := strings.Split(tag, "=") diff --git a/pkg/util/log/eventpb/json_encode_generated.go b/pkg/util/log/eventpb/json_encode_generated.go index 1a87e36e7a1e..f11fb41af51a 100644 --- a/pkg/util/log/eventpb/json_encode_generated.go +++ b/pkg/util/log/eventpb/json_encode_generated.go @@ -3285,6 +3285,16 @@ func (m *SampledQuery) AppendJSONFields(printComma bool, b redact.RedactableByte b = append(b, '"') } + if m.PlanGist != "" { + if printComma { + b = append(b, ',') + } + printComma = true + b = append(b, "\"PlanGist\":\""...) + b = redact.RedactableBytes(jsonbytes.EncodeString([]byte(b), string(m.PlanGist))) + b = append(b, '"') + } + return printComma, b } diff --git a/pkg/util/log/eventpb/telemetry.proto b/pkg/util/log/eventpb/telemetry.proto index c8256a73c9d0..186dd8e0de7f 100644 --- a/pkg/util/log/eventpb/telemetry.proto +++ b/pkg/util/log/eventpb/telemetry.proto @@ -43,6 +43,9 @@ message SampledQuery { // The distribution of the DistSQL query plan (local, full, or partial). string distribution = 6 [(gogoproto.jsontag) = ",omitempty", (gogoproto.moretags) = "redact:\"nonsensitive\""]; + + // The query's plan gist bytes as a base64 encoded string. + string plan_gist = 7 [(gogoproto.jsontag) = ',omitempty', (gogoproto.moretags) = "redact:\"nonsensitive\""]; } // CapturedIndexUsageStats