Skip to content

Commit

Permalink
feat: add transaction to summary report
Browse files Browse the repository at this point in the history
Signed-off-by: Andres Taylor <[email protected]>
  • Loading branch information
systay committed Nov 27, 2024
1 parent ec151b3 commit a7b187a
Show file tree
Hide file tree
Showing 17 changed files with 245 additions and 99 deletions.
42 changes: 38 additions & 4 deletions go/summarize/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"slices"
"sort"
"strconv"
"strings"

humanize "github.com/dustin/go-humanize"
"vitess.io/vitess/go/vt/vtgate/planbuilder/operators"
Expand Down Expand Up @@ -147,10 +148,6 @@ func renderColumnUsageTable(md *markdown.MarkDown, summary *TableSummary) {
}

func renderTablesJoined(md *markdown.MarkDown, summary *Summary) {
if len(summary.queryGraph) > 0 {
md.PrintHeader("Tables Joined", 2)
}

type joinDetails struct {
Tbl1, Tbl2 string
Occurrences int
Expand All @@ -175,6 +172,14 @@ func renderTablesJoined(md *markdown.MarkDown, summary *Summary) {
})
}

if len(joins) == 0 {
return
}

if len(summary.queryGraph) > 0 {
md.PrintHeader("Tables Joined", 2)
}

sort.Slice(joins, func(i, j int) bool {
if joins[i].Occurrences != joins[j].Occurrences {
return joins[i].Occurrences > joins[j].Occurrences
Expand Down Expand Up @@ -215,3 +220,32 @@ func renderFailures(md *markdown.MarkDown, failures []FailuresSummary) {
}
md.PrintTable(headers, rows)
}

func renderTransactions(md *markdown.MarkDown, transactions []TransactionSummary) {
if len(transactions) == 0 {
return
}

md.PrintHeader("Transaction Patterns", 2)

for i, tx := range transactions {
var tables []string
for _, query := range tx.Queries {
tables = append(tables, query.Table)
}
tables = uniquefy(tables)
md.NewLine()
md.Printf("Pattern %d (Observed %d times)\n\n", i+1, tx.Count)
md.Printf("Tables Involved: %s\n", strings.Join(tables, ", "))
md.PrintHeader("Query Patterns", 3)
for i, query := range tx.Queries {
md.Printf("%d. **%s** on `%s` \n", i+1, strings.ToTitle(query.Type), query.Table)
md.Printf(" Predicates: %s\n\n", strings.Join(query.Predicates, " AND "))
}
}
}

func uniquefy(s []string) []string {
sort.Strings(s)
return slices.Compact(s)
}
5 changes: 3 additions & 2 deletions go/summarize/reading.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ func readTransactionFile(fileName string) func(s *Summary) error {
if err != nil {
exit("Error parsing json: " + err.Error())
}
return func(*Summary) error {
return nil
return func(s *Summary) error {
s.analyzedFiles = append(s.analyzedFiles, fileName)
return summarizeTransactions(s, to.Signatures)
}
}

Expand Down
10 changes: 0 additions & 10 deletions go/summarize/summarize-keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,6 @@ type (
Pos Position
}

TableSummary struct {
Table string
ReadQueryCount int
WriteQueryCount int
ColumnUses map[ColumnInformation]ColumnUsage
JoinPredicates []operators.JoinPredicate
Failed bool
RowCount int
}

FailuresSummary struct {
Error string
Count int
Expand Down
File renamed without changes.
28 changes: 28 additions & 0 deletions go/summarize/summarize-transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,31 @@ limitations under the License.
*/

package summarize

import (
"vitess.io/vitess/go/slice"

"github.com/vitessio/vt/go/transactions"
)

func summarizeTransactions(s *Summary, txs []transactions.Signature) error {
for _, tx := range txs {
s.transactions = append(s.transactions, TransactionSummary{
Count: tx.Count,
Queries: summarizeQueries(tx.Queries),
})
}
return nil
}

func summarizeQueries(queries []transactions.Query) (patterns []QueryPattern) {
for _, q := range queries {
patterns = append(patterns, QueryPattern{
Type: q.Op,
Table: q.AffectedTable,
Predicates: slice.Map(q.Predicates, func(p transactions.PredicateInfo) string { return p.String() }),
UpdatedColumns: q.UpdatedColumns,
})
}
return
}
32 changes: 32 additions & 0 deletions go/summarize/summarize-transactions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package summarize

import (
"os"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSummarizeTransactionsFile(t *testing.T) {
sb := &strings.Builder{}
now := time.Date(2024, time.January, 1, 1, 2, 3, 0, time.UTC)

fnTx := readTransactionFile("../testdata/small-slow-query-transactions.json")

s := NewSummary("")

err := fnTx(s)
require.NoError(t, err)

s.PrintMarkdown(sb, now)

expected, err := os.ReadFile("../testdata/transactions-summary.md")
require.NoError(t, err)
assert.Equal(t, string(expected), sb.String())
if t.Failed() {
_ = os.WriteFile("../testdata/expected/transactions-summary.md", []byte(sb.String()), 0o644)
}
}
57 changes: 0 additions & 57 deletions go/summarize/summarize.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,15 @@ import (

"github.com/alecthomas/chroma/quick"
"golang.org/x/term"

"github.com/vitessio/vt/go/keys"
"github.com/vitessio/vt/go/markdown"
)

type (
Summary struct {
tables []*TableSummary
failures []FailuresSummary
hotQueries []keys.QueryAnalysisResult
hotQueryFn getMetric
analyzedFiles []string
queryGraph queryGraph
hasRowCount bool
}

traceSummary struct {
Name string
TracedQueries []TracedQuery
}
)

func NewSummary(hotMetric string) *Summary {
return &Summary{
queryGraph: make(queryGraph),
hotQueryFn: getMetricForHotness(hotMetric),
}
}

type summaryWorker = func(s *Summary) error

func Run(files []string, hotMetric string) {
Expand Down Expand Up @@ -105,43 +85,6 @@ func printSummary(hotMetric string, workers []summaryWorker) {
s.PrintMarkdown(os.Stdout, time.Now())
}

func (s *Summary) PrintMarkdown(out io.Writer, now time.Time) {
md := &markdown.MarkDown{}
msg := `# Query Analysis Report
**Date of Analysis**: %s
**Analyzed Files**: ` + "%s" + `
`

for i, file := range s.analyzedFiles {
s.analyzedFiles[i] = "`" + file + "`"
}
md.Printf(msg, now.Format(time.DateTime), strings.Join(s.analyzedFiles, ", "))
renderHotQueries(md, s.hotQueries, s.hotQueryFn)
renderTableUsage(md, s.tables, s.hasRowCount)
renderTablesJoined(md, s)
renderFailures(md, s.failures)

_, err := md.WriteTo(out)
if err != nil {
panic(err)
}
}

func (s *Summary) GetTable(name string) *TableSummary {
for _, table := range s.tables {
if table.Table == name {
return table
}
}
return nil
}

func (s *Summary) AddTable(table *TableSummary) {
s.tables = append(s.tables, table)
}

func checkTraceConditions(traces []traceSummary, workers []summaryWorker, hotMetric string) {
if len(workers) > 0 {
panic("Trace files cannot be mixed with other file types")
Expand Down
111 changes: 111 additions & 0 deletions go/summarize/summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
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 summarize

import (
"io"
"strings"
"time"

"vitess.io/vitess/go/vt/vtgate/planbuilder/operators"

"github.com/vitessio/vt/go/keys"
"github.com/vitessio/vt/go/markdown"
)

type (
Summary struct {
tables []*TableSummary
failures []FailuresSummary
transactions []TransactionSummary
hotQueries []keys.QueryAnalysisResult
hotQueryFn getMetric
analyzedFiles []string
queryGraph queryGraph
hasRowCount bool
}

TableSummary struct {
Table string
ReadQueryCount int
WriteQueryCount int
ColumnUses map[ColumnInformation]ColumnUsage
JoinPredicates []operators.JoinPredicate
Failed bool
RowCount int
}

TransactionSummary struct {
Count int
Queries []QueryPattern
}

QueryPattern struct {
Type string
Table string
Predicates []string
UpdatedColumns []string
}
)

func NewSummary(hotMetric string) *Summary {
return &Summary{
queryGraph: make(queryGraph),
hotQueryFn: getMetricForHotness(hotMetric),
}
}

func (s *Summary) PrintMarkdown(out io.Writer, now time.Time) {
md := &markdown.MarkDown{}
filePlural := ""
msg := `# Query Analysis Report
**Date of Analysis**: %s
**Analyzed File%s**: ` + "%s" + `
`
if len(s.analyzedFiles) > 1 {
filePlural = "s"
}
for i, file := range s.analyzedFiles {
s.analyzedFiles[i] = "`" + file + "`"
}
md.Printf(msg, now.Format(time.DateTime), filePlural, strings.Join(s.analyzedFiles, ", "))
renderHotQueries(md, s.hotQueries, s.hotQueryFn)
renderTableUsage(md, s.tables, s.hasRowCount)
renderTablesJoined(md, s)
renderTransactions(md, s.transactions)
renderFailures(md, s.failures)

_, err := md.WriteTo(out)
if err != nil {
panic(err)
}
}

func (s *Summary) GetTable(name string) *TableSummary {
for _, table := range s.tables {
if table.Table == name {
return table
}
}
return nil
}

func (s *Summary) AddTable(table *TableSummary) {
s.tables = append(s.tables, table)
}
2 changes: 1 addition & 1 deletion go/testdata/bigger_slow_log_avg-rows-examined.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Query Analysis Report

**Date of Analysis**: 2024-01-01 01:02:03
**Analyzed Files**: `../testdata/bigger_slow_query_log.json`
**Analyzed File**: `../testdata/bigger_slow_query_log.json`

## Top Queries
|Query ID|Usage Count|Total Query Time (ms)|Avg Query Time (ms)|Total Rows Examined|
Expand Down
2 changes: 1 addition & 1 deletion go/testdata/bigger_slow_log_avg-time.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Query Analysis Report

**Date of Analysis**: 2024-01-01 01:02:03
**Analyzed Files**: `../testdata/bigger_slow_query_log.json`
**Analyzed File**: `../testdata/bigger_slow_query_log.json`

## Top Queries
|Query ID|Usage Count|Total Query Time (ms)|Avg Query Time (ms)|Total Rows Examined|
Expand Down
2 changes: 1 addition & 1 deletion go/testdata/bigger_slow_log_total-rows-examined.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Query Analysis Report

**Date of Analysis**: 2024-01-01 01:02:03
**Analyzed Files**: `../testdata/bigger_slow_query_log.json`
**Analyzed File**: `../testdata/bigger_slow_query_log.json`

## Top Queries
|Query ID|Usage Count|Total Query Time (ms)|Avg Query Time (ms)|Total Rows Examined|
Expand Down
2 changes: 1 addition & 1 deletion go/testdata/bigger_slow_log_total-time.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Query Analysis Report

**Date of Analysis**: 2024-01-01 01:02:03
**Analyzed Files**: `../testdata/bigger_slow_query_log.json`
**Analyzed File**: `../testdata/bigger_slow_query_log.json`

## Top Queries
|Query ID|Usage Count|Total Query Time (ms)|Avg Query Time (ms)|Total Rows Examined|
Expand Down
2 changes: 1 addition & 1 deletion go/testdata/bigger_slow_log_usage-count.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Query Analysis Report

**Date of Analysis**: 2024-01-01 01:02:03
**Analyzed Files**: `../testdata/bigger_slow_query_log.json`
**Analyzed File**: `../testdata/bigger_slow_query_log.json`

## Top Queries
|Query ID|Usage Count|Total Query Time (ms)|Avg Query Time (ms)|Total Rows Examined|
Expand Down
Loading

0 comments on commit a7b187a

Please sign in to comment.