From 18aef8572a6b1409c861c0a3f20b5f869b10f1da Mon Sep 17 00:00:00 2001 From: yisaer Date: Mon, 20 Dec 2021 18:56:28 +0800 Subject: [PATCH] flatten the json output Signed-off-by: yisaer --- util/tracing/opt_trace.go | 57 +++++++++++++++--- util/tracing/opt_trace_test.go | 105 +++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 util/tracing/opt_trace_test.go diff --git a/util/tracing/opt_trace.go b/util/tracing/opt_trace.go index e3d243b16ed33..506db98ee0d8d 100644 --- a/util/tracing/opt_trace.go +++ b/util/tracing/opt_trace.go @@ -16,17 +16,17 @@ package tracing // LogicalPlanTrace indicates for the LogicalPlan trace information type LogicalPlanTrace struct { - ID int `json:"id"` - TP string `json:"type"` - Children []*LogicalPlanTrace `json:"children"` + ID int + TP string + Children []*LogicalPlanTrace // ExplainInfo should be implemented by each implemented LogicalPlan - ExplainInfo string `json:"info"` + ExplainInfo string } // LogicalOptimizeTracer indicates the trace for the whole logicalOptimize processing type LogicalOptimizeTracer struct { - FinalLogicalPlan *LogicalPlanTrace `json:"final"` + FinalLogicalPlan []FlattenLogicalPlanTrace `json:"final"` Steps []*LogicalRuleOptimizeTracer `json:"steps"` // curRuleTracer indicates the current rule Tracer during optimize by rule curRuleTracer *LogicalRuleOptimizeTracer @@ -53,14 +53,14 @@ func (tracer *LogicalOptimizeTracer) AppendRuleTracerStepToCurrent(id int, tp, r // RecordFinalLogicalPlan add plan trace after logical optimize func (tracer *LogicalOptimizeTracer) RecordFinalLogicalPlan(final *LogicalPlanTrace) { - tracer.FinalLogicalPlan = final + tracer.FinalLogicalPlan = toFlattenLogicalPlanTrace(final) } // LogicalRuleOptimizeTracer indicates the trace for the LogicalPlan tree before and after // logical rule optimize type LogicalRuleOptimizeTracer struct { Index int `json:"index"` - Before *LogicalPlanTrace `json:"before"` + Before []FlattenLogicalPlanTrace `json:"before"` RuleName string `json:"name"` Steps []LogicalRuleOptimizeTraceStep `json:"steps"` } @@ -69,7 +69,7 @@ type LogicalRuleOptimizeTracer struct { func buildLogicalRuleOptimizeTracerBeforeOptimize(index int, name string, before *LogicalPlanTrace) *LogicalRuleOptimizeTracer { return &LogicalRuleOptimizeTracer{ Index: index, - Before: before, + Before: toFlattenLogicalPlanTrace(before), RuleName: name, Steps: make([]LogicalRuleOptimizeTraceStep, 0), } @@ -85,6 +85,47 @@ type LogicalRuleOptimizeTraceStep struct { Index int `json:"index"` } +// FlattenLogicalPlanTrace indicates the flatten LogicalPlanTrace +type FlattenLogicalPlanTrace struct { + ID int `json:"id"` + TP string `json:"type"` + Children []int `json:"children"` + + // ExplainInfo should be implemented by each implemented LogicalPlan + ExplainInfo string `json:"info"` +} + +// toFlattenLogicalPlanTrace transform LogicalPlanTrace into FlattenLogicalPlanTrace +func toFlattenLogicalPlanTrace(root *LogicalPlanTrace) []FlattenLogicalPlanTrace { + wrapper := &flattenWrapper{flatten: make([]FlattenLogicalPlanTrace, 0)} + flattenLogicalPlanTrace(root, wrapper) + return wrapper.flatten +} + +type flattenWrapper struct { + flatten []FlattenLogicalPlanTrace +} + +func flattenLogicalPlanTrace(node *LogicalPlanTrace, wrapper *flattenWrapper) { + flattenNode := FlattenLogicalPlanTrace{ + ID: node.ID, + TP: node.TP, + ExplainInfo: node.ExplainInfo, + Children: make([]int, 0), + } + if len(node.Children) < 1 { + wrapper.flatten = append(wrapper.flatten, flattenNode) + return + } + for _, child := range node.Children { + flattenNode.Children = append(flattenNode.Children, child.ID) + } + for _, child := range node.Children { + flattenLogicalPlanTrace(child, wrapper) + } + wrapper.flatten = append(wrapper.flatten, flattenNode) +} + // CETraceRecord records an expression and related cardinality estimation result. type CETraceRecord struct { TableID int64 `json:"-"` diff --git a/util/tracing/opt_trace_test.go b/util/tracing/opt_trace_test.go new file mode 100644 index 0000000000000..800749429ec0d --- /dev/null +++ b/util/tracing/opt_trace_test.go @@ -0,0 +1,105 @@ +// Copyright 2021 PingCAP, Inc. +// +// 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 tracing + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFlattenLogicalPlanTrace(t *testing.T) { + root1 := &LogicalPlanTrace{ + ID: 1, + TP: "foo1", + ExplainInfo: "bar1", + Children: []*LogicalPlanTrace{ + { + ID: 2, + TP: "foo2", + ExplainInfo: "bar2", + Children: nil, + }, + }, + } + root2 := &LogicalPlanTrace{ + ID: 1, + TP: "foo1", + ExplainInfo: "bar1", + Children: []*LogicalPlanTrace{ + { + ID: 2, + TP: "foo2", + ExplainInfo: "bar2", + Children: nil, + }, + { + ID: 3, + TP: "foo3", + ExplainInfo: "bar3", + Children: []*LogicalPlanTrace{ + { + ID: 4, + TP: "foo4", + ExplainInfo: "bar4", + Children: nil, + }, + }, + }, + }, + } + expect1 := []FlattenLogicalPlanTrace{ + { + ID: 2, + TP: "foo2", + ExplainInfo: "bar2", + Children: []int{}, + }, + { + ID: 1, + TP: "foo1", + ExplainInfo: "bar1", + Children: []int{2}, + }, + } + expect2 := []FlattenLogicalPlanTrace{ + { + ID: 2, + TP: "foo2", + ExplainInfo: "bar2", + Children: []int{}, + }, + { + ID: 4, + TP: "foo4", + ExplainInfo: "bar4", + Children: []int{}, + }, + { + ID: 3, + TP: "foo3", + ExplainInfo: "bar3", + Children: []int{4}, + }, + { + ID: 1, + TP: "foo1", + ExplainInfo: "bar1", + Children: []int{2, 3}, + }, + } + require.EqualValues(t, toFlattenLogicalPlanTrace(root1), expect1) + require.EqualValues(t, toFlattenLogicalPlanTrace(root2), expect2) +}