Files
percona-toolkit/src/go/pt-galera-log-explainer/conflicts.go
2023-12-22 23:10:34 +03:00

99 lines
2.4 KiB
Go

package main
import (
"encoding/json"
"fmt"
"strings"
"github.com/percona/percona-toolkit/src/go/pt-galera-log-explainer/regex"
"github.com/percona/percona-toolkit/src/go/pt-galera-log-explainer/utils"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v2"
)
type conflicts struct {
Paths []string `arg:"" name:"paths" help:"paths of the log to use"`
Yaml bool `xor:"format"`
Json bool `xor:"format"`
}
func (c *conflicts) Help() string {
return "Summarize every replication conflicts, from every node's point of view"
}
func (c *conflicts) Run() error {
regexes := regex.IdentsMap.Merge(regex.ApplicativeMap)
timeline, err := timelineFromPaths(c.Paths, regexes)
if err != nil {
return err
}
logCtxs := timeline.GetLatestContextsByNodes()
for _, logCtx := range logCtxs {
if len(logCtx.Conflicts) == 0 {
continue
}
var out string
switch {
case c.Yaml:
tmp, err := yaml.Marshal(logCtx.Conflicts)
if err != nil {
return err
}
out = string(tmp)
case c.Json:
tmp, err := json.Marshal(logCtx.Conflicts)
if err != nil {
return err
}
out = string(tmp)
default:
var b strings.Builder
for _, conflict := range logCtx.Conflicts {
b.WriteString("\n\n")
b.WriteString(utils.Paint(utils.BlueText, "seqno: "))
b.WriteString(conflict.Seqno)
b.WriteString("\n\t")
b.WriteString(utils.Paint(utils.BlueText, "winner: "))
b.WriteString(conflict.Winner)
b.WriteString("\n\t")
b.WriteString(utils.Paint(utils.BlueText, "votes per nodes:"))
nodes := []string{}
for node := range conflict.VotePerNode {
nodes = append(nodes, node)
}
// do not iterate over VotePerNode map
// map accesses are random, it will make regression tests harder
slices.Sort(nodes)
for _, node := range nodes {
vote := conflict.VotePerNode[node]
displayVote := utils.Paint(utils.RedText, vote.MD5)
if vote.MD5 == conflict.Winner {
displayVote = utils.Paint(utils.GreenText, vote.MD5)
}
b.WriteString("\n\t\t")
b.WriteString(utils.Paint(utils.BlueText, node))
b.WriteString(": (")
b.WriteString(displayVote)
b.WriteString(") ")
b.WriteString(vote.Error)
}
b.WriteString("\n\t")
b.WriteString(utils.Paint(utils.BlueText, "initiated by: "))
b.WriteString(fmt.Sprintf("%v", conflict.InitiatedBy))
out = b.String()[2:]
}
}
fmt.Println(out)
return nil
}
return nil
}