mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-06 12:27:56 +00:00
Rename ctx to logCtx, remove any mention of ctx
This commit is contained in:

committed by
Sveta Smirnova

parent
bb6c5e1abd
commit
955fd75ca9
@@ -29,22 +29,22 @@ func (c *conflicts) Run() error {
|
||||
return err
|
||||
}
|
||||
|
||||
ctxs := timeline.GetLatestContextsByNodes()
|
||||
for _, ctx := range ctxs {
|
||||
if len(ctx.Conflicts) == 0 {
|
||||
logCtxs := timeline.GetLatestContextsByNodes()
|
||||
for _, logCtx := range logCtxs {
|
||||
if len(logCtx.Conflicts) == 0 {
|
||||
continue
|
||||
}
|
||||
var out string
|
||||
|
||||
switch {
|
||||
case c.Yaml:
|
||||
tmp, err := yaml.Marshal(ctx.Conflicts)
|
||||
tmp, err := yaml.Marshal(logCtx.Conflicts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = string(tmp)
|
||||
case c.Json:
|
||||
tmp, err := json.Marshal(ctx.Conflicts)
|
||||
tmp, err := json.Marshal(logCtx.Conflicts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -52,7 +52,7 @@ func (c *conflicts) Run() error {
|
||||
|
||||
default:
|
||||
var b strings.Builder
|
||||
for _, conflict := range ctx.Conflicts {
|
||||
for _, conflict := range logCtx.Conflicts {
|
||||
b.WriteString("\n\n")
|
||||
b.WriteString(utils.Paint(utils.BlueText, "seqno: "))
|
||||
b.WriteString(conflict.Seqno)
|
||||
|
@@ -30,7 +30,7 @@ func (c *ctx) Run() error {
|
||||
out.DB = translate.GetDB()
|
||||
|
||||
for _, t := range timeline {
|
||||
out.Contexts = append(out.Contexts, t[len(t)-1].Ctx)
|
||||
out.Contexts = append(out.Contexts, t[len(t)-1].LogCtx)
|
||||
}
|
||||
|
||||
outjson, err := json.MarshalIndent(out, "", "\t")
|
||||
|
@@ -60,13 +60,13 @@ func TimelineCLI(timeline types.Timeline, verbosity types.Verbosity) {
|
||||
if !utils.SliceContains(nextNodes, node) {
|
||||
// if there are no events, having a | is needed for tabwriter
|
||||
// A few color can also help highlighting how the node is doing
|
||||
ctx := currentContext[node]
|
||||
args = append(args, utils.PaintForState("| ", ctx.State()))
|
||||
logCtx := currentContext[node]
|
||||
args = append(args, utils.PaintForState("| ", logCtx.State()))
|
||||
continue
|
||||
}
|
||||
loginfo := timeline[node][0]
|
||||
lastContext[node] = currentContext[node]
|
||||
currentContext[node] = loginfo.Ctx
|
||||
currentContext[node] = loginfo.LogCtx
|
||||
|
||||
timeline.Dequeue(node)
|
||||
|
||||
@@ -75,7 +75,7 @@ func TimelineCLI(timeline types.Timeline, verbosity types.Verbosity) {
|
||||
args = append(args, msg)
|
||||
displayedValue++
|
||||
} else {
|
||||
args = append(args, utils.PaintForState("| ", loginfo.Ctx.State()))
|
||||
args = append(args, utils.PaintForState("| ", loginfo.LogCtx.State()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ func initKeysContext(timeline types.Timeline) ([]string, map[string]types.LogCtx
|
||||
for node := range timeline {
|
||||
keys = append(keys, node)
|
||||
if len(timeline[node]) > 0 {
|
||||
currentContext[node] = timeline[node][0].Ctx
|
||||
currentContext[node] = timeline[node][0].LogCtx
|
||||
} else {
|
||||
// Avoid crashing, but not ideal: we could have a better default Ctx with filepath at least
|
||||
currentContext[node] = types.NewLogCtx()
|
||||
@@ -145,14 +145,14 @@ func headerNodes(keys []string) string {
|
||||
return "identifier\t" + strings.Join(keys, "\t") + "\t"
|
||||
}
|
||||
|
||||
func headerFilePath(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
func headerFilePath(keys []string, logCtxs map[string]types.LogCtx) string {
|
||||
header := "current path\t"
|
||||
for _, node := range keys {
|
||||
if ctx, ok := ctxs[node]; ok {
|
||||
if len(ctx.FilePath) < 50 {
|
||||
header += ctx.FilePath + "\t"
|
||||
if logCtx, ok := logCtxs[node]; ok {
|
||||
if len(logCtx.FilePath) < 50 {
|
||||
header += logCtx.FilePath + "\t"
|
||||
} else {
|
||||
header += "..." + ctx.FilePath[len(ctx.FilePath)-50:] + "\t"
|
||||
header += "..." + logCtx.FilePath[len(logCtx.FilePath)-50:] + "\t"
|
||||
}
|
||||
} else {
|
||||
header += " \t"
|
||||
@@ -161,11 +161,11 @@ func headerFilePath(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
return header
|
||||
}
|
||||
|
||||
func headerIP(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
func headerIP(keys []string, logCtxs map[string]types.LogCtx) string {
|
||||
header := "last known ip\t"
|
||||
for _, node := range keys {
|
||||
if ctx, ok := ctxs[node]; ok && len(ctx.OwnIPs) > 0 {
|
||||
header += ctx.OwnIPs[len(ctx.OwnIPs)-1] + "\t"
|
||||
if logCtx, ok := logCtxs[node]; ok && len(logCtx.OwnIPs) > 0 {
|
||||
header += logCtx.OwnIPs[len(logCtx.OwnIPs)-1] + "\t"
|
||||
} else {
|
||||
header += " \t"
|
||||
}
|
||||
@@ -173,21 +173,21 @@ func headerIP(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
return header
|
||||
}
|
||||
|
||||
func headerVersion(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
func headerVersion(keys []string, logCtxs map[string]types.LogCtx) string {
|
||||
header := "mysql version\t"
|
||||
for _, node := range keys {
|
||||
if ctx, ok := ctxs[node]; ok {
|
||||
header += ctx.Version + "\t"
|
||||
if logCtx, ok := logCtxs[node]; ok {
|
||||
header += logCtx.Version + "\t"
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func headerName(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
func headerName(keys []string, logCtxs map[string]types.LogCtx) string {
|
||||
header := "last known name\t"
|
||||
for _, node := range keys {
|
||||
if ctx, ok := ctxs[node]; ok && len(ctx.OwnNames) > 0 {
|
||||
header += ctx.OwnNames[len(ctx.OwnNames)-1] + "\t"
|
||||
if logCtx, ok := logCtxs[node]; ok && len(logCtx.OwnNames) > 0 {
|
||||
header += logCtx.OwnNames[len(logCtx.OwnNames)-1] + "\t"
|
||||
} else {
|
||||
header += " \t"
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func headerName(keys []string, ctxs map[string]types.LogCtx) string {
|
||||
func removeEmptyColumns(timeline types.Timeline, verbosity types.Verbosity) types.Timeline {
|
||||
|
||||
for key := range timeline {
|
||||
if !timeline[key][len(timeline[key])-1].Ctx.HasVisibleEvents(verbosity) {
|
||||
if !timeline[key][len(timeline[key])-1].LogCtx.HasVisibleEvents(verbosity) {
|
||||
delete(timeline, key)
|
||||
}
|
||||
}
|
||||
@@ -245,27 +245,27 @@ const NumberOfPossibleTransition = 4
|
||||
// it needs an element on each columns so that we don't break columns
|
||||
// The rows can't have a variable count of elements: it has to be strictly identical each time
|
||||
// so the whole next functions are here to ensure it takes minimal spaces, while giving context and preserving columns
|
||||
func transitionSeparator(keys []string, oldctxs, ctxs map[string]types.LogCtx) string {
|
||||
func transitionSeparator(keys []string, oldlogCtxs, logCtxs map[string]types.LogCtx) string {
|
||||
|
||||
ts := map[string]*transitions{}
|
||||
|
||||
// For each columns to print, we build tests
|
||||
for _, node := range keys {
|
||||
ctx, ok1 := ctxs[node]
|
||||
oldctx, ok2 := oldctxs[node]
|
||||
logCtx, ok1 := logCtxs[node]
|
||||
oldlogCtx, ok2 := oldlogCtxs[node]
|
||||
|
||||
ts[node] = &transitions{tests: []*transition{}}
|
||||
if ok1 && ok2 {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldctx.FilePath, s2: ctx.FilePath, changeType: "file path"})
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldlogCtx.FilePath, s2: logCtx.FilePath, changeType: "file path"})
|
||||
|
||||
if len(oldctx.OwnNames) > 0 && len(ctx.OwnNames) > 0 {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldctx.OwnNames[len(oldctx.OwnNames)-1], s2: ctx.OwnNames[len(ctx.OwnNames)-1], changeType: "node name"})
|
||||
if len(oldlogCtx.OwnNames) > 0 && len(logCtx.OwnNames) > 0 {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldlogCtx.OwnNames[len(oldlogCtx.OwnNames)-1], s2: logCtx.OwnNames[len(logCtx.OwnNames)-1], changeType: "node name"})
|
||||
}
|
||||
if len(oldctx.OwnIPs) > 0 && len(ctx.OwnIPs) > 0 {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldctx.OwnIPs[len(oldctx.OwnIPs)-1], s2: ctx.OwnIPs[len(ctx.OwnIPs)-1], changeType: "node ip"})
|
||||
if len(oldlogCtx.OwnIPs) > 0 && len(logCtx.OwnIPs) > 0 {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldlogCtx.OwnIPs[len(oldlogCtx.OwnIPs)-1], s2: logCtx.OwnIPs[len(logCtx.OwnIPs)-1], changeType: "node ip"})
|
||||
}
|
||||
if oldctx.Version != "" && ctx.Version != "" {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldctx.Version, s2: ctx.Version, changeType: "version"})
|
||||
if oldlogCtx.Version != "" && logCtx.Version != "" {
|
||||
ts[node].tests = append(ts[node].tests, &transition{s1: oldlogCtx.Version, s2: logCtx.Version, changeType: "version"})
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -10,19 +10,19 @@ import (
|
||||
func TestTransitionSeparator(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
keys []string
|
||||
oldctxs, ctxs map[string]types.LogCtx
|
||||
expectedOut string
|
||||
name string
|
||||
keys []string
|
||||
oldlogCtxs, logCtxs map[string]types.LogCtx
|
||||
expectedOut string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "no changes",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
|
||||
"node0": {},
|
||||
"node1": {},
|
||||
@@ -32,11 +32,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "filepath changed on node0",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {FilePath: "path1"},
|
||||
"node1": {},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
|
||||
"node0": {FilePath: "path2"},
|
||||
"node1": {},
|
||||
@@ -52,11 +52,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "filepath changed on node1",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {FilePath: "path1"},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
|
||||
"node0": {},
|
||||
"node1": {FilePath: "path2"},
|
||||
@@ -66,11 +66,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "filepath changed on both",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {FilePath: "path1_0"},
|
||||
"node1": {FilePath: "path1_1"},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {FilePath: "path2_0"},
|
||||
"node1": {FilePath: "path2_1"},
|
||||
},
|
||||
@@ -79,11 +79,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "node name changed on node1",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnNames: []string{"name1"}},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnNames: []string{"name1", "name2"}},
|
||||
},
|
||||
@@ -92,11 +92,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "node ip changed on node1",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnIPs: []string{"ip1"}},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnIPs: []string{"ip1", "ip2"}},
|
||||
},
|
||||
@@ -105,11 +105,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "version changed on node1",
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {Version: "8.0.28"},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {Version: "8.0.30"},
|
||||
},
|
||||
@@ -118,11 +118,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "node ip, node name and filepath changed on node1", // very possible with operators
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnIPs: []string{"ip1"}, OwnNames: []string{"name1"}, FilePath: "path1"},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {},
|
||||
"node1": {OwnIPs: []string{"ip1", "ip2"}, OwnNames: []string{"name1", "name2"}, FilePath: "path2"},
|
||||
},
|
||||
@@ -148,11 +148,11 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
{
|
||||
name: "node ip, node name and filepath changed on node1, nodename changed on node2", // very possible with operators
|
||||
keys: []string{"node0", "node1"},
|
||||
oldctxs: map[string]types.LogCtx{
|
||||
oldlogCtxs: map[string]types.LogCtx{
|
||||
"node0": {OwnNames: []string{"name1_0"}},
|
||||
"node1": {OwnIPs: []string{"ip1"}, OwnNames: []string{"name1_1"}, FilePath: "path1"},
|
||||
},
|
||||
ctxs: map[string]types.LogCtx{
|
||||
logCtxs: map[string]types.LogCtx{
|
||||
"node0": {OwnNames: []string{"name1_0", "name2_0"}},
|
||||
"node1": {OwnIPs: []string{"ip1", "ip2"}, OwnNames: []string{"name1_1", "name2_1"}, FilePath: "path2"},
|
||||
},
|
||||
@@ -178,7 +178,7 @@ func TestTransitionSeparator(t *testing.T) {
|
||||
|
||||
utils.SkipColor = true
|
||||
for _, test := range tests {
|
||||
out := transitionSeparator(test.keys, test.oldctxs, test.ctxs)
|
||||
out := transitionSeparator(test.keys, test.oldlogCtxs, test.logCtxs)
|
||||
if out != test.expectedOut {
|
||||
t.Errorf("testname: %s, expected: \n%#v\n got: \n%#v", test.name, test.expectedOut, out)
|
||||
}
|
||||
|
@@ -177,8 +177,8 @@ func iterateOnGrepResults(path string, regexes types.RegexMap, grepStdout <-chan
|
||||
displayer types.LogDisplayer
|
||||
timestamp time.Time
|
||||
)
|
||||
ctx := types.NewLogCtx()
|
||||
ctx.FilePath = path
|
||||
logCtx := types.NewLogCtx()
|
||||
logCtx.FilePath = path
|
||||
|
||||
for line := range grepStdout {
|
||||
line = sanitizeLine(line)
|
||||
@@ -203,7 +203,7 @@ func iterateOnGrepResults(path string, regexes types.RegexMap, grepStdout <-chan
|
||||
}
|
||||
|
||||
filetype := regex.FileType(line, CLI.PxcOperator)
|
||||
ctx.FileType = filetype
|
||||
logCtx.FileType = filetype
|
||||
|
||||
// We have to find again what regex worked to get this log line
|
||||
// it can match multiple regexes
|
||||
@@ -211,8 +211,8 @@ func iterateOnGrepResults(path string, regexes types.RegexMap, grepStdout <-chan
|
||||
if !regex.Regex.MatchString(line) || utils.SliceContains(CLI.ExcludeRegexes, key) {
|
||||
continue
|
||||
}
|
||||
ctx, displayer = regex.Handle(ctx, line, timestamp)
|
||||
li := types.NewLogInfo(date, displayer, line, regex, key, ctx, filetype)
|
||||
logCtx, displayer = regex.Handle(logCtx, line, timestamp)
|
||||
li := types.NewLogInfo(date, displayer, line, regex, key, logCtx, filetype)
|
||||
lt = lt.Add(li)
|
||||
}
|
||||
|
||||
|
@@ -49,7 +49,7 @@ var CLI struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := kong.Parse(&CLI,
|
||||
kongcli := kong.Parse(&CLI,
|
||||
kong.Name(toolname),
|
||||
kong.Description("An utility to merge and help analyzing Galera logs"),
|
||||
kong.UsageOnError(),
|
||||
@@ -68,6 +68,6 @@ func main() {
|
||||
utils.SkipColor = CLI.NoColor
|
||||
translate.AssumeIPStable = !CLI.PxcOperator
|
||||
|
||||
err := ctx.Run()
|
||||
ctx.FatalIfErrorf(err)
|
||||
err := kongcli.Run()
|
||||
kongcli.FatalIfErrorf(err)
|
||||
}
|
||||
|
@@ -17,12 +17,12 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexDesync": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("desyncs itself from group"),
|
||||
InternalRegex: regexp.MustCompile("\\(" + regexNodeName + "\\) desyncs"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.Desynced = true
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.Desynced = true
|
||||
|
||||
node := submatches[groupNodeName]
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
if utils.SliceContains(ctx.OwnNames, node) {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
if utils.SliceContains(logCtx.OwnNames, node) {
|
||||
return utils.Paint(utils.YellowText, "desyncs itself from group")
|
||||
}
|
||||
return node + utils.Paint(utils.YellowText, " desyncs itself from group")
|
||||
@@ -33,11 +33,11 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexResync": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("resyncs itself to group"),
|
||||
InternalRegex: regexp.MustCompile("\\(" + regexNodeName + "\\) resyncs"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.Desynced = false
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.Desynced = false
|
||||
node := submatches[groupNodeName]
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
if utils.SliceContains(ctx.OwnNames, node) {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
if utils.SliceContains(logCtx.OwnNames, node) {
|
||||
return utils.Paint(utils.YellowText, "resyncs itself to group")
|
||||
}
|
||||
return node + utils.Paint(utils.YellowText, " resyncs itself to group")
|
||||
@@ -48,7 +48,7 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexInconsistencyVoteInit": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("initiates vote on"),
|
||||
InternalRegex: regexp.MustCompile("Member " + regexIdx + "\\(" + regexNodeName + "\\) initiates vote on " + regexUUID + ":" + regexSeqno + "," + regexErrorMD5 + ": (?P<error>.*), Error_code:"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
node := submatches[groupNodeName]
|
||||
seqno := submatches[groupSeqno]
|
||||
@@ -61,11 +61,11 @@ var ApplicativeMap = types.RegexMap{
|
||||
VotePerNode: map[string]types.ConflictVote{node: types.ConflictVote{MD5: errormd5, Error: errorstring}},
|
||||
}
|
||||
|
||||
ctx.Conflicts = ctx.Conflicts.Merge(c)
|
||||
logCtx.Conflicts = logCtx.Conflicts.Merge(c)
|
||||
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
|
||||
if utils.SliceContains(ctx.OwnNames, node) {
|
||||
if utils.SliceContains(logCtx.OwnNames, node) {
|
||||
return utils.Paint(utils.YellowText, "inconsistency vote started") + "(seqno:" + seqno + ")"
|
||||
}
|
||||
|
||||
@@ -77,22 +77,22 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexInconsistencyVoteRespond": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("responds to vote on "),
|
||||
InternalRegex: regexp.MustCompile("Member " + regexIdx + "\\(" + regexNodeName + "\\) responds to vote on " + regexUUID + ":" + regexSeqno + "," + regexErrorMD5 + ": (?P<error>.*)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
node := submatches[groupNodeName]
|
||||
seqno := submatches[groupSeqno]
|
||||
errormd5 := submatches[groupErrorMD5]
|
||||
errorstring := submatches["error"]
|
||||
|
||||
latestConflict := ctx.Conflicts.ConflictWithSeqno(seqno)
|
||||
latestConflict := logCtx.Conflicts.ConflictWithSeqno(seqno)
|
||||
if latestConflict == nil {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
latestConflict.VotePerNode[node] = types.ConflictVote{MD5: errormd5, Error: errorstring}
|
||||
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
|
||||
for _, name := range ctx.OwnNames {
|
||||
for _, name := range logCtx.OwnNames {
|
||||
vote, ok := latestConflict.VotePerNode[name]
|
||||
if !ok {
|
||||
continue
|
||||
@@ -115,38 +115,38 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexInconsistencyVoteInconsistentWithGroup": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("is inconsistent with group. Leaving cluster"),
|
||||
InternalRegex: regexp.MustCompile("Vote [0-9] \\(success\\) on " + regexUUID + ":" + regexSeqno + " is inconsistent with group. Leaving cluster"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
seqno := submatches[groupSeqno]
|
||||
latestConflict := ctx.Conflicts.ConflictWithSeqno(seqno)
|
||||
latestConflict := logCtx.Conflicts.ConflictWithSeqno(seqno)
|
||||
if latestConflict == nil {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
if len(ctx.OwnNames) > 0 {
|
||||
latestConflict.VotePerNode[ctx.OwnNames[len(ctx.OwnNames)-1]] = types.ConflictVote{Error: "Success", MD5: "0000000000000000"}
|
||||
if len(logCtx.OwnNames) > 0 {
|
||||
latestConflict.VotePerNode[logCtx.OwnNames[len(logCtx.OwnNames)-1]] = types.ConflictVote{Error: "Success", MD5: "0000000000000000"}
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "vote (success) inconsistent, leaving cluster"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "vote (success) inconsistent, leaving cluster"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexInconsistencyVoted": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Inconsistency detected: Inconsistent by consensus"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "found inconsistent by vote"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "found inconsistent by vote"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexInconsistencyWinner": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Winner: "),
|
||||
InternalRegex: regexp.MustCompile("Winner: " + regexErrorMD5),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
errormd5 := submatches[groupErrorMD5]
|
||||
|
||||
if len(ctx.Conflicts) == 0 {
|
||||
return ctx, nil // nothing to guess
|
||||
if len(logCtx.Conflicts) == 0 {
|
||||
return logCtx, nil // nothing to guess
|
||||
}
|
||||
|
||||
c := ctx.Conflicts.ConflictFromMD5(errormd5)
|
||||
c := logCtx.Conflicts.ConflictFromMD5(errormd5)
|
||||
if c == nil {
|
||||
// some votes have been observed to be logged again
|
||||
// sometimes days after the initial one
|
||||
@@ -154,13 +154,13 @@ var ApplicativeMap = types.RegexMap{
|
||||
|
||||
// as they don't add any helpful context, we should ignore
|
||||
// plus, it would need multiline regexes, which is not supported here
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
c.Winner = errormd5
|
||||
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
out := "consistency vote(seqno:" + c.Seqno + "): "
|
||||
for _, name := range ctx.OwnNames {
|
||||
for _, name := range logCtx.OwnNames {
|
||||
|
||||
vote, ok := c.VotePerNode[name]
|
||||
if !ok {
|
||||
@@ -180,21 +180,21 @@ var ApplicativeMap = types.RegexMap{
|
||||
"RegexInconsistencyRecovery": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Recovering vote result from history"),
|
||||
InternalRegex: regexp.MustCompile("Recovering vote result from history: " + regexUUID + ":" + regexSeqno + "," + regexErrorMD5),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
if len(ctx.OwnNames) == 0 {
|
||||
return ctx, nil
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
if len(logCtx.OwnNames) == 0 {
|
||||
return logCtx, nil
|
||||
}
|
||||
|
||||
errormd5 := submatches[groupErrorMD5]
|
||||
seqno := submatches[groupSeqno]
|
||||
c := ctx.Conflicts.ConflictWithSeqno(seqno)
|
||||
c := logCtx.Conflicts.ConflictWithSeqno(seqno)
|
||||
if c == nil { // the actual vote could have been lost
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
vote := types.ConflictVote{MD5: errormd5}
|
||||
c.VotePerNode[ctx.OwnNames[len(ctx.OwnNames)-1]] = vote
|
||||
c.VotePerNode[logCtx.OwnNames[len(logCtx.OwnNames)-1]] = vote
|
||||
|
||||
return ctx, types.SimpleDisplayer(voteResponse(vote, *c))
|
||||
return logCtx, types.SimpleDisplayer(voteResponse(vote, *c))
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
|
@@ -11,7 +11,7 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01 1:01:01 0 [Note] WSREP: Member 0.0 (node) desyncs itself from group",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Desynced: true},
|
||||
LogCtx: types.LogCtx{Desynced: true},
|
||||
},
|
||||
expectedOut: "node desyncs itself from group",
|
||||
key: "RegexDesync",
|
||||
@@ -20,10 +20,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01 1:01:01 0 [Note] WSREP: Member 0.0 (node) resyncs itself to group",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Desynced: false},
|
||||
LogCtx: types.LogCtx{Desynced: false},
|
||||
},
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{Desynced: true},
|
||||
LogCtx: types.LogCtx{Desynced: true},
|
||||
},
|
||||
expectedOut: "node resyncs itself to group",
|
||||
key: "RegexResync",
|
||||
@@ -33,17 +33,17 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 1(node1) initiates vote on 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,bdb2b9234ae75cb3: some error, Error_code: 123;\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
expectedOut: "inconsistency vote started by node1(seqno:20)",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
key: "RegexInconsistencyVoteInit",
|
||||
},
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 1(node1) initiates vote on 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,bdb2b9234ae75cb3: some error, Error_code: 123;\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expectedOut: "inconsistency vote started(seqno:20)",
|
||||
key: "RegexInconsistencyVoteInit",
|
||||
@@ -52,10 +52,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 2(node2) responds to vote on 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,0000000000000000: Success\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): voted Success",
|
||||
key: "RegexInconsistencyVoteRespond",
|
||||
@@ -63,10 +63,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 2(node2) responds to vote on 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,bdb2b9234ae75cb3: some error\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): voted same error",
|
||||
key: "RegexInconsistencyVoteRespond",
|
||||
@@ -75,10 +75,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
// could not actually find a "responds to" with any error for now
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 2(node2) responds to vote on 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,ed9774a3cad44656: some different error\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "ed9774a3cad44656", Error: "some different error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "ed9774a3cad44656", Error: "some different error"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): voted different error",
|
||||
key: "RegexInconsistencyVoteRespond",
|
||||
@@ -93,10 +93,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "Winner: bdb2b9234ae75cb3",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): won",
|
||||
key: "RegexInconsistencyWinner",
|
||||
@@ -104,10 +104,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "Winner: 0000000000000000",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "0000000000000000", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "0000000000000000", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000", Error: "Success"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): lost",
|
||||
key: "RegexInconsistencyWinner",
|
||||
@@ -116,10 +116,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
name: "already voted conflict, should not print anything",
|
||||
log: "Winner: 0000000000000000",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node1"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
displayerExpectedNil: true,
|
||||
key: "RegexInconsistencyWinner",
|
||||
@@ -128,10 +128,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 1 [ERROR] [MY-000000] [Galera] Recovering vote result from history: 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,bdb2b9234ae75cb3\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "bdb2b9234ae75cb3"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "bdb2b9234ae75cb3"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): voted same error",
|
||||
key: "RegexInconsistencyRecovery",
|
||||
@@ -139,10 +139,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 1 [ERROR] [MY-000000] [Galera] Recovering vote result from history: 8c9b5610-e020-11ed-a5ea-e253cc5f629d:20,0000000000000000\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{MD5: "0000000000000000"}}}}},
|
||||
},
|
||||
expectedOut: "consistency vote(seqno:20): voted Success",
|
||||
key: "RegexInconsistencyRecovery",
|
||||
@@ -151,10 +151,10 @@ func TestApplicativeRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 16 [ERROR] [MY-000000] [Galera] Vote 0 (success) on 7b1a6710-18da-11ed-b777-42b15728f657:20 is inconsistent with group. Leaving cluster.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}}}}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{Error: "Success", MD5: "0000000000000000"}}}}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"node2"}, Conflicts: types.Conflicts{&types.Conflict{InitiatedBy: []string{"node1"}, Winner: "bdb2b9234ae75cb3", Seqno: "20", VotePerNode: map[string]types.ConflictVote{"node1": types.ConflictVote{MD5: "bdb2b9234ae75cb3", Error: "some error"}, "node2": types.ConflictVote{Error: "Success", MD5: "0000000000000000"}}}}},
|
||||
},
|
||||
expectedOut: "vote (success) inconsistent, leaving cluster",
|
||||
key: "RegexInconsistencyVoteInconsistentWithGroup",
|
||||
|
@@ -17,99 +17,99 @@ var EventsMap = types.RegexMap{
|
||||
"RegexStarting": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("starting as process"),
|
||||
InternalRegex: regexp.MustCompile("\\(mysqld " + regexVersion + ".*\\)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.Version = submatches[groupVersion]
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.Version = submatches[groupVersion]
|
||||
|
||||
msg := "starting(" + ctx.Version
|
||||
if isShutdownReasonMissing(ctx) {
|
||||
msg := "starting(" + logCtx.Version
|
||||
if isShutdownReasonMissing(logCtx) {
|
||||
msg += ", " + utils.Paint(utils.YellowText, "could not catch how/when it stopped")
|
||||
}
|
||||
msg += ")"
|
||||
ctx.SetState("OPEN")
|
||||
logCtx.SetState("OPEN")
|
||||
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
},
|
||||
},
|
||||
"RegexShutdownComplete": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("mysqld: Shutdown complete"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "shutdown complete"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "shutdown complete"))
|
||||
},
|
||||
},
|
||||
"RegexTerminated": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("mysqld: Terminated"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "terminated"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "terminated"))
|
||||
},
|
||||
},
|
||||
"RegexGotSignal6": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("mysqld got signal 6"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "crash: got signal 6"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "crash: got signal 6"))
|
||||
},
|
||||
},
|
||||
"RegexGotSignal11": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("mysqld got signal 11"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "crash: got signal 11"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "crash: got signal 11"))
|
||||
},
|
||||
},
|
||||
"RegexShutdownSignal": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Normal|Received shutdown"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "received shutdown"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "received shutdown"))
|
||||
},
|
||||
},
|
||||
|
||||
// 2023-06-12T07:51:38.135646Z 0 [Warning] [MY-000000] [Galera] Exception while mapping writeset addr: 0x7fb668d4e568, seqno: 2770385572449823232, size: 73316, ctx: 0x56128412e0c0, flags: 1. store: 1, type: 32 into [555, 998): 'deque::_M_new_elements_at_back'. Aborting GCache recovery.
|
||||
// 2023-06-12T07:51:38.135646Z 0 [Warning] [MY-000000] [Galera] Exception while mapping writeset addr: 0x7fb668d4e568, seqno: 2770385572449823232, size: 73316, logCtx: 0x56128412e0c0, flags: 1. store: 1, type: 32 into [555, 998): 'deque::_M_new_elements_at_back'. Aborting GCache recovery.
|
||||
|
||||
"RegexAborting": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Aborting"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "ABORTING"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "ABORTING"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexWsrepLoad": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("wsrep_load\\(\\): loading provider library"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("OPEN")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("OPEN")
|
||||
if regexWsrepLoadNone.MatchString(log) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "started(standalone)"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "started(standalone)"))
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "started(cluster)"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "started(cluster)"))
|
||||
},
|
||||
},
|
||||
"RegexWsrepRecovery": &types.LogRegex{
|
||||
// INFO: WSREP: Recovered position 00000000-0000-0000-0000-000000000000:-1
|
||||
Regex: regexp.MustCompile("Recovered position"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
msg := "wsrep recovery"
|
||||
// if state is joiner, it can be due to sst
|
||||
// if state is open, it is just a start sequence depending on platform
|
||||
if isShutdownReasonMissing(ctx) && ctx.State() != "JOINER" && ctx.State() != "OPEN" {
|
||||
if isShutdownReasonMissing(logCtx) && logCtx.State() != "JOINER" && logCtx.State() != "OPEN" {
|
||||
msg += "(" + utils.Paint(utils.YellowText, "could not catch how/when it stopped") + ")"
|
||||
}
|
||||
ctx.SetState("RECOVERY")
|
||||
logCtx.SetState("RECOVERY")
|
||||
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexUnknownConf": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("unknown variable"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
split := strings.Split(log, "'")
|
||||
v := "?"
|
||||
if len(split) > 0 {
|
||||
@@ -118,47 +118,47 @@ var EventsMap = types.RegexMap{
|
||||
if len(v) > 20 {
|
||||
v = v[:20] + "..."
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "unknown variable") + ": " + v)
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "unknown variable") + ": " + v)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexAssertionFailure": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Assertion failure"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "ASSERTION FAILURE"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "ASSERTION FAILURE"))
|
||||
},
|
||||
},
|
||||
"RegexBindAddressAlreadyUsed": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("asio error .bind: Address already in use"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "bind address already used"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "bind address already used"))
|
||||
},
|
||||
},
|
||||
"RegexTooManyConnections": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Too many connections"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "too many connections"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "too many connections"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexReversingHistory": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Reversing history"),
|
||||
InternalRegex: regexp.MustCompile("Reversing history: " + regexSeqno + " -> [0-9]*, this member has applied (?P<diff>[0-9]*) more events than the primary component"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.BrightRedText, "having "+submatches["diff"]+" more events than the other nodes, data loss possible"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.BrightRedText, "having "+submatches["diff"]+" more events than the other nodes, data loss possible"))
|
||||
},
|
||||
},
|
||||
}
|
||||
var regexWsrepLoadNone = regexp.MustCompile("none")
|
||||
|
||||
// isShutdownReasonMissing is returning true if the latest wsrep state indicated a "working" node
|
||||
func isShutdownReasonMissing(ctx types.LogCtx) bool {
|
||||
return ctx.State() != "DESTROYED" && ctx.State() != "CLOSED" && ctx.State() != "RECOVERY" && ctx.State() != ""
|
||||
func isShutdownReasonMissing(logCtx types.LogCtx) bool {
|
||||
return logCtx.State() != "DESTROYED" && logCtx.State() != "CLOSED" && logCtx.State() != "RECOVERY" && logCtx.State() != ""
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -12,8 +12,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "8.0.30-22",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.30-22) starting as process 1",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(8.0.30)",
|
||||
key: "RegexStarting",
|
||||
@@ -22,8 +22,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "8.0.2-22",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.2-22) starting as process 1",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "8.0.2"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "8.0.2"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(8.0.2)",
|
||||
key: "RegexStarting",
|
||||
@@ -32,8 +32,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "5.7.31-34-log",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.31-34-log) starting as process 2 ...",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "5.7.31"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "5.7.31"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(5.7.31)",
|
||||
key: "RegexStarting",
|
||||
@@ -42,8 +42,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "10.4.25-MariaDB-log",
|
||||
log: "2001-01-01 01:01:01 0 [Note] /usr/sbin/mysqld (mysqld 10.4.25-MariaDB-log) starting as process 2 ...",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "10.4.25"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "10.4.25"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(10.4.25)",
|
||||
key: "RegexStarting",
|
||||
@@ -52,8 +52,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "10.2.31-MariaDB-1:10.2.31+maria~bionic-log",
|
||||
log: "2001-01-01 01:01:01 0 [Note] /usr/sbin/mysqld (mysqld 10.2.31-MariaDB-1:10.2.31+maria~bionic-log) starting as process 2 ...",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "10.2.31"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "10.2.31"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(10.2.31)",
|
||||
key: "RegexStarting",
|
||||
@@ -62,8 +62,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "5.7.28-enterprise-commercial-advanced-log",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] /usr/sbin/mysqld (mysqld 5.7.28-enterprise-commercial-advanced-log) starting as process 2 ...",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "5.7.28"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "5.7.28"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(5.7.28)",
|
||||
key: "RegexStarting",
|
||||
@@ -72,8 +72,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "8.0.30 operator",
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.30-22.1) starting as process 1\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
},
|
||||
expectedOut: "starting(8.0.30)",
|
||||
key: "RegexStarting",
|
||||
@@ -94,8 +94,8 @@ func TestEventsRegex(t *testing.T) {
|
||||
name: "could not catch how it stopped",
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.30-22.1) starting as process 1\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
LogCtx: types.LogCtx{Version: "8.0.30"},
|
||||
State: "OPEN",
|
||||
},
|
||||
input: regexTestState{
|
||||
State: "OPEN",
|
||||
|
@@ -20,11 +20,11 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexSourceNode": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("(local endpoint for a connection, blacklisting address)|(points to own listening address, blacklisting)"),
|
||||
InternalRegex: regexp.MustCompile("\\(" + regexNodeHash + ", '.+'\\).+" + regexNodeIPMethod),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
ctx.AddOwnIP(ip, date)
|
||||
return ctx, types.SimpleDisplayer(ip + " is local")
|
||||
logCtx.AddOwnIP(ip, date)
|
||||
return logCtx, types.SimpleDisplayer(ip + " is local")
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -33,11 +33,11 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexBaseHost": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("base_host"),
|
||||
InternalRegex: regexp.MustCompile("base_host = " + regexNodeIP),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
ctx.AddOwnIP(ip, date)
|
||||
return ctx, types.SimpleDisplayer(ctx.OwnIPs[len(ctx.OwnIPs)-1] + " is local")
|
||||
logCtx.AddOwnIP(ip, date)
|
||||
return logCtx, types.SimpleDisplayer(logCtx.OwnIPs[len(logCtx.OwnIPs)-1] + " is local")
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -48,7 +48,7 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexMemberAssociations": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("[0-9]: [a-z0-9]+-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]+, [a-zA-Z0-9-_]+"),
|
||||
InternalRegex: regexp.MustCompile(regexIdx + ": " + regexUUID + ", " + regexNodeName),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
idx := submatches[groupIdx]
|
||||
hash := utils.UUIDToShortUUID(submatches[groupUUID])
|
||||
@@ -56,16 +56,16 @@ var IdentsMap = types.RegexMap{
|
||||
|
||||
// nodenames are truncated after 32 characters ...
|
||||
if len(nodename) == 31 {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
translate.AddHashToNodeName(hash, nodename, date)
|
||||
|
||||
if ctx.MyIdx == idx && (ctx.IsPrimary() || ctx.MemberCount == 1) {
|
||||
ctx.AddOwnHash(hash, date)
|
||||
ctx.AddOwnName(nodename, date)
|
||||
if logCtx.MyIdx == idx && (logCtx.IsPrimary() || logCtx.MemberCount == 1) {
|
||||
logCtx.AddOwnHash(hash, date)
|
||||
logCtx.AddOwnName(nodename, date)
|
||||
}
|
||||
|
||||
return ctx, types.SimpleDisplayer(hash + " is " + nodename)
|
||||
return logCtx, types.SimpleDisplayer(hash + " is " + nodename)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -73,17 +73,17 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexMemberCount": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("members.[0-9]+.:"),
|
||||
InternalRegex: regexp.MustCompile(regexMembers),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
members := submatches[groupMembers]
|
||||
|
||||
membercount, err := strconv.Atoi(members)
|
||||
if err != nil {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
ctx.MemberCount = membercount
|
||||
logCtx.MemberCount = membercount
|
||||
|
||||
return ctx, types.SimpleDisplayer("view member count: " + members)
|
||||
return logCtx, types.SimpleDisplayer("view member count: " + members)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -92,13 +92,13 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexOwnUUID": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("My UUID"),
|
||||
InternalRegex: regexp.MustCompile("My UUID: " + regexUUID),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
hash := utils.UUIDToShortUUID(submatches[groupUUID])
|
||||
|
||||
ctx.AddOwnHash(hash, date)
|
||||
logCtx.AddOwnHash(hash, date)
|
||||
|
||||
return ctx, types.SimpleDisplayer(hash + " is local")
|
||||
return logCtx, types.SimpleDisplayer(hash + " is local")
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -107,12 +107,12 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexOwnUUIDFromMessageRelay": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("turning message relay requesting"),
|
||||
InternalRegex: regexp.MustCompile("\\(" + regexNodeHash + ", '" + regexNodeIPMethod + "'\\)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
hash := submatches[groupNodeHash]
|
||||
ctx.AddOwnHash(hash, date)
|
||||
logCtx.AddOwnHash(hash, date)
|
||||
|
||||
return ctx, types.SimpleDisplayer(hash + " is local")
|
||||
return logCtx, types.SimpleDisplayer(hash + " is local")
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -121,11 +121,11 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexMyIDXFromComponent": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("New COMPONENT:"),
|
||||
InternalRegex: regexp.MustCompile("New COMPONENT:.*my_idx = " + regexIdx),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
idx := submatches[groupIdx]
|
||||
ctx.MyIdx = idx
|
||||
return ctx, types.SimpleDisplayer("my_idx=" + idx)
|
||||
logCtx.MyIdx = idx
|
||||
return logCtx, types.SimpleDisplayer("my_idx=" + idx)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -154,24 +154,24 @@ var IdentsMap = types.RegexMap{
|
||||
"RegexOwnNameFromStateExchange": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("STATE EXCHANGE: got state msg"),
|
||||
InternalRegex: regexp.MustCompile("STATE EXCHANGE:.* from " + regexIdx + " \\(" + regexNodeName + "\\)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
r, err := internalRegexSubmatch(internalRegex, log)
|
||||
if err != nil {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
|
||||
idx := submatches[groupIdx]
|
||||
name := submatches[groupNodeName]
|
||||
if idx != ctx.MyIdx {
|
||||
return ctx, types.SimpleDisplayer("name(" + name + ") from unknown idx")
|
||||
if idx != logCtx.MyIdx {
|
||||
return logCtx, types.SimpleDisplayer("name(" + name + ") from unknown idx")
|
||||
}
|
||||
|
||||
if ctx.State == "NON-PRIMARY" {
|
||||
return ctx, types.SimpleDisplayer("name(" + name + ") can't be trusted as it's non-primary")
|
||||
if logCtx.State == "NON-PRIMARY" {
|
||||
return logCtx, types.SimpleDisplayer("name(" + name + ") can't be trusted as it's non-primary")
|
||||
}
|
||||
|
||||
ctx.AddOwnName(name)
|
||||
return ctx, types.SimpleDisplayer("local name:" + name)
|
||||
logCtx.AddOwnName(name)
|
||||
return logCtx, types.SimpleDisplayer("local name:" + name)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -183,8 +183,8 @@ func init_add_regexes() {
|
||||
IdentsMap["RegexOwnUUIDFromEstablished"] = &types.LogRegex{
|
||||
Regex: regexp.MustCompile("connection established to"),
|
||||
InternalRegex: IdentsMap["RegexOwnUUIDFromMessageRelay"].InternalRegex,
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexOwnUUIDFromMessageRelay"].Handler(submatches, ctx, log, date)
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexOwnUUIDFromMessageRelay"].Handler(submatches, logCtx, log, date)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
}
|
||||
@@ -192,8 +192,8 @@ func init_add_regexes() {
|
||||
IdentsMap["RegexOwnIndexFromView"] = &types.LogRegex{
|
||||
Regex: regexp.MustCompile("own_index:"),
|
||||
InternalRegex: regexp.MustCompile("own_index: " + regexIdx),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexMyIDXFromComponent"].Handler(submatches, ctx, log, date)
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexMyIDXFromComponent"].Handler(submatches, logCtx, log, date)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
}
|
||||
@@ -204,8 +204,8 @@ func init_add_regexes() {
|
||||
IdentsMap["RegexMyIDXFromClusterView"] = &types.LogRegex{
|
||||
Regex: regexp.MustCompile("New cluster view:"),
|
||||
InternalRegex: regexp.MustCompile("New cluster view:.*my index: " + regexIdx + ","),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexMyIDXFromComponent"].Handler(internalRegex, ctx, log)
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return IdentsMap["RegexMyIDXFromComponent"].Handler(internalRegex, logCtx, log)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] (90002222-1111, 'ssl://0.0.0.0:4567') Found matching local endpoint for a connection, blacklisting address ssl://127.0.0.1:4567",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnIPs: []string{"127.0.0.1"}},
|
||||
LogCtx: types.LogCtx{OwnIPs: []string{"127.0.0.1"}},
|
||||
},
|
||||
expectedOut: "127.0.0.1 is local",
|
||||
key: "RegexSourceNode",
|
||||
@@ -20,7 +20,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Passing config to GCS: base_dir = /var/lib/mysql/; base_host = 127.0.0.1; base_port = 4567; cert.log_conflicts = no; cert.optimistic_pa = no; debug = no; evs.auto_evict = 0; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.join_retrans_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 10; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.user_send_window = 4; evs.view_forget_timeout = PT24H; gcache.dir = /data/mysql/; gcache.freeze_purge_at_seqno = -1; gcache.keep_pages_count = 0; gcache.keep_pages_size = 0; gcache.mem_size = 0; gcache.name = galera.cache; gcache.page_size = 128M; gcache.recover = yes; gcache.size = 128M; gcomm.thread_prio = ; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 100; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; gcs.recv_q_hard_limit = 9223372036854775807; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; gmcast.segment = 0; gmcast.version = 0; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = PT30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT30S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 10; socket.checksum = 2; socket.recv_buf_size = auto; socket.send_buf_size = auto; socket.ssl_ca = ca.pem; socket.ssl_cert = server-cert.pem; socket.ssl_cipher = ; socket.ssl_compression = YES; socket.ssl_key = server-key.pem;",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnIPs: []string{"127.0.0.1"}},
|
||||
LogCtx: types.LogCtx{OwnIPs: []string{"127.0.0.1"}},
|
||||
},
|
||||
expectedOut: "127.0.0.1 is local",
|
||||
key: "RegexBaseHost",
|
||||
@@ -29,7 +29,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, node1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{},
|
||||
@@ -39,7 +39,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{"015702fc-a4ca"},
|
||||
@@ -54,7 +54,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, node1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{},
|
||||
@@ -64,7 +64,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "NON-PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{"015702fc-a4ca"},
|
||||
@@ -79,7 +79,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, node1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 2,
|
||||
},
|
||||
@@ -87,7 +87,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "NON-PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 2,
|
||||
},
|
||||
@@ -100,7 +100,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 1: 015702fc-32f5-11ed-a4ca-267f97316394, node1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{},
|
||||
@@ -110,7 +110,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
OwnHashes: []string{"015702fc-a4ca"},
|
||||
@@ -125,7 +125,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, node1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
@@ -133,7 +133,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
@@ -146,7 +146,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, node1.with.complete.fqdn",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
@@ -154,7 +154,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
@@ -168,14 +168,14 @@ func TestIdentsRegex(t *testing.T) {
|
||||
name: "name too long and truncated",
|
||||
log: " 0: 015702fc-32f5-11ed-a4ca-267f97316394, name_so_long_it_will_get_trunca",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
MemberCount: 1,
|
||||
},
|
||||
@@ -190,7 +190,7 @@ func TestIdentsRegex(t *testing.T) {
|
||||
log: " members(1):",
|
||||
expectedOut: "view member count: 1",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{MemberCount: 1},
|
||||
LogCtx: types.LogCtx{MemberCount: 1},
|
||||
},
|
||||
key: "RegexMemberCount",
|
||||
},
|
||||
@@ -198,10 +198,10 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 1 [Note] [MY-000000] [Galera] ####### My UUID: 60205de0-5cf6-11ec-8884-3a01908be11a",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnHashes: []string{"60205de0-8884"},
|
||||
},
|
||||
},
|
||||
@@ -212,10 +212,10 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: (9509c194, 'tcp://0.0.0.0:4567') turning message relay requesting on, nonlive peers:",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnHashes: []string{"9509c194"},
|
||||
},
|
||||
},
|
||||
@@ -226,10 +226,10 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: New COMPONENT: primary = yes, bootstrap = no, my_idx = 0, memb_num = 2",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
},
|
||||
},
|
||||
@@ -240,10 +240,10 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: (9509c194, 'tcp://0.0.0.0:4567') connection established to 838ebd6d tcp://172.17.0.2:4567",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnHashes: []string{"9509c194"},
|
||||
},
|
||||
},
|
||||
@@ -254,10 +254,10 @@ func TestIdentsRegex(t *testing.T) {
|
||||
{
|
||||
log: " own_index: 1",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "1",
|
||||
},
|
||||
},
|
||||
|
@@ -20,12 +20,12 @@ var PXCOperatorMap = types.RegexMap{
|
||||
"RegexNodeNameFromEnv": &types.LogRegex{
|
||||
Regex: regexp.MustCompile(". NODE_NAME="),
|
||||
InternalRegex: regexp.MustCompile("NODE_NAME=" + regexNodeName),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
nodename := submatches[groupNodeName]
|
||||
nodename, _, _ = strings.Cut(nodename, ".")
|
||||
ctx.AddOwnName(nodename, date)
|
||||
return ctx, types.SimpleDisplayer("local name:" + nodename)
|
||||
logCtx.AddOwnName(nodename, date)
|
||||
return logCtx, types.SimpleDisplayer("local name:" + nodename)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -33,11 +33,11 @@ var PXCOperatorMap = types.RegexMap{
|
||||
"RegexNodeIPFromEnv": &types.LogRegex{
|
||||
Regex: regexp.MustCompile(". NODE_IP="),
|
||||
InternalRegex: regexp.MustCompile("NODE_IP=" + regexNodeIP),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
ctx.AddOwnIP(ip, date)
|
||||
return ctx, types.SimpleDisplayer("local ip:" + ip)
|
||||
logCtx.AddOwnIP(ip, date)
|
||||
return logCtx, types.SimpleDisplayer("local ip:" + ip)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -49,8 +49,8 @@ var PXCOperatorMap = types.RegexMap{
|
||||
// those "operators" regexes do not have the log prefix added implicitly. It's not strictly needed, but
|
||||
// it will help to avoid catching random piece of log out of order
|
||||
Regex: regexp.MustCompile(k8sprefix + ".*GCache::RingBuffer initial scan"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer("recovering gcache")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer("recovering gcache")
|
||||
},
|
||||
},
|
||||
|
||||
@@ -60,28 +60,28 @@ var PXCOperatorMap = types.RegexMap{
|
||||
"RegexOperatorMemberAssociations": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("================================================.*View:"),
|
||||
InternalRegex: regexp.MustCompile("own_index: " + regexIdx + ".*(?P<memberlog>" + IdentsMap["RegexMemberCount"].Regex.String() + ")(?P<compiledAssociations>(....-?[0-9]{1,2}(\\.-?[0-9])?: [a-z0-9]+-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]+, [a-zA-Z0-9-_\\.]+)+)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ctx.MyIdx = submatches[groupIdx]
|
||||
logCtx.MyIdx = submatches[groupIdx]
|
||||
|
||||
var (
|
||||
displayer types.LogDisplayer
|
||||
msg string
|
||||
)
|
||||
|
||||
ctx, displayer = IdentsMap["RegexMemberCount"].Handle(ctx, submatches["memberlog"], date)
|
||||
msg += displayer(ctx) + "; "
|
||||
logCtx, displayer = IdentsMap["RegexMemberCount"].Handle(logCtx, submatches["memberlog"], date)
|
||||
msg += displayer(logCtx) + "; "
|
||||
|
||||
subAssociations := strings.Split(submatches["compiledAssociations"], "\\n\\t")
|
||||
if len(subAssociations) < 2 {
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
}
|
||||
for _, subAssociation := range subAssociations[1:] {
|
||||
// better to reuse the idents regex
|
||||
ctx, displayer = IdentsMap["RegexMemberAssociations"].Handle(ctx, subAssociation, date)
|
||||
msg += displayer(ctx) + "; "
|
||||
logCtx, displayer = IdentsMap["RegexMemberAssociations"].Handle(logCtx, subAssociation, date)
|
||||
msg += displayer(logCtx) + "; "
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
|
@@ -12,7 +12,7 @@ func TestPXCOperatorRegex(t *testing.T) {
|
||||
{
|
||||
log: "{\"log\":\"2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] ================================================\\nView:\\n id: 9f191762-2542-11ee-89be-13bdb1218f0e:9375811\\n status: primary\\n protocol_version: 4\\n capabilities: MULTI-MASTER, CERTIFICATION, PARALLEL_APPLYING, REPLAY, ISOLATION, PAUSE, CAUSAL_READ, INCREMENTAL_WS, UNORDERED, PREORDERED, STREAMING, NBO\\n final: no\\n own_index: 0\\n members(3):\\n\\t0: 45406e8d-2de0-11ee-95fc-f29a5fdf1ee0, cluster1-0\\n\\t1: 5bf18376-2de0-11ee-8333-6e755a3456ca, cluster1-2\\n\\t2: 66e2b7bf-2de0-11ee-8000-f7d68b5cf6f6, cluster1-1\\n=================================================\\n\",\"file\":\"/var/lib/mysql/mysqld-error.log\"}",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnHashes: []string{},
|
||||
OwnNames: []string{},
|
||||
},
|
||||
@@ -20,7 +20,7 @@ func TestPXCOperatorRegex(t *testing.T) {
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
MyIdx: "0",
|
||||
MemberCount: 3,
|
||||
OwnHashes: []string{"45406e8d-95fc"},
|
||||
@@ -36,7 +36,7 @@ func TestPXCOperatorRegex(t *testing.T) {
|
||||
{
|
||||
log: "+ NODE_NAME=cluster1-pxc-0.cluster1-pxc.test-percona.svc.cluster.local",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnNames: []string{"cluster1-pxc-0"}},
|
||||
LogCtx: types.LogCtx{OwnNames: []string{"cluster1-pxc-0"}},
|
||||
},
|
||||
expectedOut: "local name:cluster1-pxc-0",
|
||||
key: "RegexNodeNameFromEnv",
|
||||
@@ -45,7 +45,7 @@ func TestPXCOperatorRegex(t *testing.T) {
|
||||
{
|
||||
log: "+ NODE_IP=172.17.0.2",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{OwnIPs: []string{"172.17.0.2"}},
|
||||
LogCtx: types.LogCtx{OwnIPs: []string{"172.17.0.2"}},
|
||||
},
|
||||
expectedOut: "local ip:172.17.0.2",
|
||||
key: "RegexNodeIPFromEnv",
|
||||
|
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
type regexTestState struct {
|
||||
State string
|
||||
Ctx types.LogCtx
|
||||
LogCtx types.LogCtx
|
||||
HashToNodeNames map[string]string
|
||||
HashToIP map[string]string
|
||||
IPToMethods map[string]string
|
||||
@@ -74,15 +74,15 @@ func iterateRegexTest(t *testing.T, regexmap types.RegexMap, tests []regexTest)
|
||||
}
|
||||
|
||||
if test.input.State != "" {
|
||||
test.input.Ctx.SetState(test.input.State)
|
||||
test.input.LogCtx.SetState(test.input.State)
|
||||
}
|
||||
|
||||
// Test 3
|
||||
// Get the message to display using the input context
|
||||
ctx, displayer := regexmap[test.key].Handle(test.input.Ctx, test.log, time.Time{})
|
||||
logCtx, displayer := regexmap[test.key].Handle(test.input.LogCtx, test.log, time.Time{})
|
||||
msg := ""
|
||||
if displayer != nil {
|
||||
msg = displayer(ctx)
|
||||
msg = displayer(logCtx)
|
||||
} else if !test.displayerExpectedNil {
|
||||
t.Errorf("key: %s\ntestname: %s\ndisplayer is nil\nexpected: not nil", test.key, test.name)
|
||||
}
|
||||
@@ -91,16 +91,16 @@ func iterateRegexTest(t *testing.T, regexmap types.RegexMap, tests []regexTest)
|
||||
// Making sure the updated context is what we expect
|
||||
|
||||
// alternative to reflect.deepequal, it enables to avoid comparing "states" map
|
||||
res := cmp.Equal(ctx, test.expected.Ctx, cmpopts.IgnoreUnexported(types.LogCtx{}))
|
||||
if !res || ctx.State() != test.expected.State {
|
||||
t.Errorf("context is not as expected: \nkey: %s\ntestname: %s\nctx: %+v\nexpected ctx: %+v\nout: %s\nexpected out: %s\nstate: %s\nexpected state: %s", test.key, test.name, spew.Sdump(ctx), spew.Sdump(test.expected.Ctx), msg, test.expectedOut, ctx.State(), test.expected.State)
|
||||
res := cmp.Equal(logCtx, test.expected.LogCtx, cmpopts.IgnoreUnexported(types.LogCtx{}))
|
||||
if !res || logCtx.State() != test.expected.State {
|
||||
t.Errorf("context is not as expected: \nkey: %s\ntestname: %s\nlogCtx: %+v\nexpected logCtx: %+v\nout: %s\nexpected out: %s\nstate: %s\nexpected state: %s", test.key, test.name, spew.Sdump(logCtx), spew.Sdump(test.expected.LogCtx), msg, test.expectedOut, logCtx.State(), test.expected.State)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Test 5
|
||||
// Making sure the displayed message is correct
|
||||
if msg != test.expectedOut {
|
||||
t.Errorf("displayed message is not as expected: \nkey: %s\ntestname: %s\nctx: %+v\nout: %s\nexpected out: %s\nstate: %s", test.key, test.name, spew.Sdump(ctx), msg, test.expectedOut, ctx.State())
|
||||
t.Errorf("displayed message is not as expected: \nkey: %s\ntestname: %s\nlogCtx: %+v\nout: %s\nexpected out: %s\nstate: %s", test.key, test.name, spew.Sdump(logCtx), msg, test.expectedOut, logCtx.State())
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
@@ -110,25 +110,25 @@ func iterateRegexTest(t *testing.T, regexmap types.RegexMap, tests []regexTest)
|
||||
maxTime, _ := time.Parse(time.RFC3339, "2100-01-01T01:01:01Z")
|
||||
for hash, expectedValue := range test.expected.HashToNodeNames {
|
||||
if value := translate.GetNodeNameFromHash(hash, maxTime); value != expectedValue {
|
||||
t.Errorf("wrong HashToNodeNames\ntest key: %s\ntestname: %s\nctx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(ctx), msg, hash, expectedValue, value)
|
||||
t.Errorf("wrong HashToNodeNames\ntest key: %s\ntestname: %s\nlogCtx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(logCtx), msg, hash, expectedValue, value)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
for hash, expectedValue := range test.expected.HashToIP {
|
||||
if value := translate.GetIPFromHash(hash); value != expectedValue {
|
||||
t.Errorf("wrong HashToIP\ntest key: %s\ntestname: %s\nctx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(ctx), msg, hash, expectedValue, value)
|
||||
t.Errorf("wrong HashToIP\ntest key: %s\ntestname: %s\nlogCtx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(logCtx), msg, hash, expectedValue, value)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
for ip, expectedValue := range test.expected.IPToMethods {
|
||||
if value := translate.GetMethodFromIP(ip, maxTime); value != expectedValue {
|
||||
t.Errorf("wrong IPToMethods\ntest key: %s\ntestname: %s\nctx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(ctx), msg, ip, expectedValue, value)
|
||||
t.Errorf("wrong IPToMethods\ntest key: %s\ntestname: %s\nlogCtx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(logCtx), msg, ip, expectedValue, value)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
for ip, expectedValue := range test.expected.IPToNodeNames {
|
||||
if value := translate.GetNodeNameFromIP(ip, maxTime); value != expectedValue {
|
||||
t.Errorf("wrong IPToNodeNames\ntest key: %s\ntestname: %s\nctx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(ctx), msg, ip, expectedValue, value)
|
||||
t.Errorf("wrong IPToNodeNames\ntest key: %s\ntestname: %s\nlogCtx: %+v\nout: %s\nhash: %s\nexpectedValue: %s\nvalue: %s", test.key, test.name, spew.Sdump(logCtx), msg, ip, expectedValue, value)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ var SSTMap = types.RegexMap{
|
||||
"RegexSSTRequestSuccess": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("requested state transfer.*Selected"),
|
||||
InternalRegex: regexp.MustCompile("Member " + regexIdx + " \\(" + regexNodeName + "\\) requested state transfer.*Selected " + regexIdx + " \\(" + regexNodeName2 + "\\)\\("),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
joiner := utils.ShortNodeName(submatches[groupNodeName])
|
||||
donor := utils.ShortNodeName(submatches[groupNodeName2])
|
||||
@@ -34,13 +34,13 @@ var SSTMap = types.RegexMap{
|
||||
sst.SelectionTimestamp = &selectionTimestamp
|
||||
}
|
||||
|
||||
ctx.SSTs[donor] = sst
|
||||
logCtx.SSTs[donor] = sst
|
||||
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
if utils.SliceContains(ctx.OwnNames, joiner) {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
if utils.SliceContains(logCtx.OwnNames, joiner) {
|
||||
return donor + utils.Paint(utils.GreenText, " will resync local node")
|
||||
}
|
||||
if utils.SliceContains(ctx.OwnNames, donor) {
|
||||
if utils.SliceContains(logCtx.OwnNames, donor) {
|
||||
return utils.Paint(utils.GreenText, "local node will resync ") + joiner
|
||||
}
|
||||
|
||||
@@ -52,15 +52,15 @@ var SSTMap = types.RegexMap{
|
||||
"RegexSSTResourceUnavailable": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("requested state transfer.*Resource temporarily unavailable"),
|
||||
InternalRegex: regexp.MustCompile("Member .* \\(" + regexNodeName + "\\) requested state transfer"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
joiner := submatches[groupNodeName]
|
||||
if utils.SliceContains(ctx.OwnNames, joiner) {
|
||||
if utils.SliceContains(logCtx.OwnNames, joiner) {
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "cannot find donor"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "cannot find donor"))
|
||||
}
|
||||
|
||||
return ctx, types.SimpleDisplayer(joiner + utils.Paint(utils.YellowText, " cannot find donor"))
|
||||
return logCtx, types.SimpleDisplayer(joiner + utils.Paint(utils.YellowText, " cannot find donor"))
|
||||
},
|
||||
},
|
||||
|
||||
@@ -68,21 +68,21 @@ var SSTMap = types.RegexMap{
|
||||
"RegexSSTComplete": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("State transfer to.*complete"),
|
||||
InternalRegex: regexp.MustCompile(regexIdx + " \\(" + regexNodeName + "\\): State transfer to " + regexIdx + " \\(" + regexNodeName2 + "\\) complete"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
donor := utils.ShortNodeName(submatches[groupNodeName])
|
||||
joiner := utils.ShortNodeName(submatches[groupNodeName2])
|
||||
displayType := "SST"
|
||||
if ctx.SSTs[donor].Type != "" {
|
||||
displayType = ctx.SSTs[donor].Type
|
||||
if logCtx.SSTs[donor].Type != "" {
|
||||
displayType = logCtx.SSTs[donor].Type
|
||||
}
|
||||
delete(ctx.SSTs, donor)
|
||||
delete(logCtx.SSTs, donor)
|
||||
|
||||
return ctx, func(ctx types.LogCtx) string {
|
||||
if utils.SliceContains(ctx.OwnNames, joiner) {
|
||||
return logCtx, func(logCtx types.LogCtx) string {
|
||||
if utils.SliceContains(logCtx.OwnNames, joiner) {
|
||||
return utils.Paint(utils.GreenText, "got "+displayType+" from ") + donor
|
||||
}
|
||||
if utils.SliceContains(ctx.OwnNames, donor) {
|
||||
if utils.SliceContains(logCtx.OwnNames, donor) {
|
||||
return utils.Paint(utils.GreenText, "finished sending "+displayType+" to ") + joiner
|
||||
}
|
||||
|
||||
@@ -96,81 +96,81 @@ var SSTMap = types.RegexMap{
|
||||
"RegexSSTCompleteUnknown": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("State transfer to.*left the group.*complete"),
|
||||
InternalRegex: regexp.MustCompile(regexIdx + " \\(" + regexNodeName + "\\): State transfer.*\\(left the group\\) complete"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
donor := utils.ShortNodeName(submatches[groupNodeName])
|
||||
delete(ctx.SSTs, donor)
|
||||
return ctx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " synced ??(node left)"))
|
||||
delete(logCtx.SSTs, donor)
|
||||
return logCtx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " synced ??(node left)"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTFailedUnknown": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("State transfer to.*left the group.*failed"),
|
||||
InternalRegex: regexp.MustCompile(regexIdx + " \\(" + regexNodeName + "\\): State transfer.*\\(left the group\\) failed"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
donor := utils.ShortNodeName(submatches[groupNodeName])
|
||||
delete(ctx.SSTs, donor)
|
||||
return ctx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " failed to sync ??(node left)"))
|
||||
delete(logCtx.SSTs, donor)
|
||||
return logCtx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " failed to sync ??(node left)"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTStateTransferFailed": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("State transfer to.*failed:"),
|
||||
InternalRegex: regexp.MustCompile(regexIdx + " \\(" + regexNodeName + "\\): State transfer to " + regexIdx + " \\(" + regexNodeName2 + "\\) failed"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
donor := utils.ShortNodeName(submatches[groupNodeName])
|
||||
joiner := utils.ShortNodeName(submatches[groupNodeName2])
|
||||
delete(ctx.SSTs, donor)
|
||||
return ctx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " failed to sync ") + joiner)
|
||||
delete(logCtx.SSTs, donor)
|
||||
return logCtx, types.SimpleDisplayer(donor + utils.Paint(utils.RedText, " failed to sync ") + joiner)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTError": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Process completed with error: wsrep_sst"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "SST error"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "SST error"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTInitiating": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Initiating SST.IST transfer on DONOR side"),
|
||||
InternalRegex: regexp.MustCompile("DONOR side \\((?P<scriptname>[a-zA-Z0-9-_]*) --role 'donor' --address '" + regexNodeIP + ":(?P<sstport>[0-9]*)\\)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
return ctx, types.SimpleDisplayer("init sst using " + submatches["scriptname"])
|
||||
return logCtx, types.SimpleDisplayer("init sst using " + submatches["scriptname"])
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTCancellation": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Initiating SST cancellation"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "former SST cancelled"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "former SST cancelled"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTProceeding": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Proceeding with SST"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("JOINER")
|
||||
ctx.SetSSTTypeMaybe("SST")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("JOINER")
|
||||
logCtx.SetSSTTypeMaybe("SST")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "receiving SST"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "receiving SST"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSSTStreamingTo": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Streaming the backup to"),
|
||||
InternalRegex: regexp.MustCompile("Streaming the backup to joiner at " + regexNodeIP),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ctx.SetState("DONOR")
|
||||
logCtx.SetState("DONOR")
|
||||
joiner := submatches[groupNodeIP]
|
||||
|
||||
return ctx, types.FormatByIPDisplayer(utils.Paint(utils.YellowText, "SST to ")+"%s", joiner, date)
|
||||
return logCtx, types.FormatByIPDisplayer(utils.Paint(utils.YellowText, "SST to ")+"%s", joiner, date)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -179,10 +179,10 @@ var SSTMap = types.RegexMap{
|
||||
|
||||
// the UUID here is not from a node, it's a cluster state UUID, this is only used to ensure it's correctly parsed
|
||||
InternalRegex: regexp.MustCompile("IST received: " + regexUUID + ":" + regexSeqno),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
seqno := submatches[groupSeqno]
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "IST received") + "(seqno:" + seqno + ")")
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.GreenText, "IST received") + "(seqno:" + seqno + ")")
|
||||
},
|
||||
},
|
||||
|
||||
@@ -191,14 +191,14 @@ var SSTMap = types.RegexMap{
|
||||
|
||||
// TODO: sometimes, it's a hostname here
|
||||
InternalRegex: regexp.MustCompile("IST sender starting to serve " + regexNodeIPMethod + " sending [0-9]+-" + regexSeqno),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("DONOR")
|
||||
ctx.SetSSTTypeMaybe("IST")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("DONOR")
|
||||
logCtx.SetSSTTypeMaybe("IST")
|
||||
|
||||
seqno := submatches[groupSeqno]
|
||||
joiner := submatches[groupNodeIP]
|
||||
|
||||
return ctx, types.FormatByIPDisplayer(utils.Paint(utils.YellowText, "IST to ")+"%s(seqno:"+seqno+")", joiner, date)
|
||||
return logCtx, types.FormatByIPDisplayer(utils.Paint(utils.YellowText, "IST to ")+"%s(seqno:"+seqno+")", joiner, date)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -206,8 +206,8 @@ var SSTMap = types.RegexMap{
|
||||
Regex: regexp.MustCompile("Prepared IST receiver"),
|
||||
|
||||
InternalRegex: regexp.MustCompile("Prepared IST receiver( for (?P<startingseqno>[0-9]+)-" + regexSeqno + ")?"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("JOINER")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("JOINER")
|
||||
|
||||
seqno := submatches[groupSeqno]
|
||||
msg := utils.Paint(utils.YellowText, "will receive ")
|
||||
@@ -215,35 +215,35 @@ var SSTMap = types.RegexMap{
|
||||
startingseqno := submatches["startingseqno"]
|
||||
// if it's 0, it will go to SST without a doubt
|
||||
if startingseqno == "0" {
|
||||
ctx.SetSSTTypeMaybe("SST")
|
||||
logCtx.SetSSTTypeMaybe("SST")
|
||||
msg += "SST"
|
||||
|
||||
// not totally correct, but need more logs to get proper pattern
|
||||
// in some cases it does IST before going with SST
|
||||
} else {
|
||||
ctx.SetSSTTypeMaybe("IST")
|
||||
logCtx.SetSSTTypeMaybe("IST")
|
||||
msg += "IST"
|
||||
if seqno != "" {
|
||||
msg += "(seqno:" + seqno + ")"
|
||||
}
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexFailedToPrepareIST": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Failed to prepare for incremental state transfer"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetSSTTypeMaybe("SST")
|
||||
return ctx, types.SimpleDisplayer("IST is not applicable")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetSSTTypeMaybe("SST")
|
||||
return logCtx, types.SimpleDisplayer("IST is not applicable")
|
||||
},
|
||||
},
|
||||
|
||||
"RegexXtrabackupISTReceived": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("xtrabackup_ist received from donor"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetSSTTypeMaybe("IST")
|
||||
return ctx, types.SimpleDisplayer("IST running")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetSSTTypeMaybe("IST")
|
||||
return logCtx, types.SimpleDisplayer("IST running")
|
||||
},
|
||||
Verbosity: types.DebugMySQL, // that one is not really helpful, except for tooling constraints
|
||||
},
|
||||
@@ -251,50 +251,50 @@ var SSTMap = types.RegexMap{
|
||||
// could not find production examples yet, but it did exist in older version there also was "Bypassing state dump"
|
||||
"RegexBypassSST": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Bypassing SST"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetSSTTypeMaybe("IST")
|
||||
return ctx, types.SimpleDisplayer("IST will be used")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetSSTTypeMaybe("IST")
|
||||
return logCtx, types.SimpleDisplayer("IST will be used")
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSocatConnRefused": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("E connect.*Connection refused"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "socat: connection refused"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "socat: connection refused"))
|
||||
},
|
||||
},
|
||||
|
||||
// 2023-05-12T02:52:33.767132Z 0 [Note] [MY-000000] [WSREP-SST] Preparing the backup at /var/lib/mysql/sst-xb-tmpdir
|
||||
"RegexPreparingBackup": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Preparing the backup at"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer("preparing SST backup")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer("preparing SST backup")
|
||||
},
|
||||
},
|
||||
|
||||
"RegexTimeoutReceivingFirstData": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Possible timeout in receving first data from donor in gtid/keyring stage"), // typo is in Galera lib
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "timeout from donor in gtid/keyring stage"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "timeout from donor in gtid/keyring stage"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexWillNeverReceive": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Will never receive state. Need to abort"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "will never receive SST, aborting"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "will never receive SST, aborting"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexISTFailed": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("async IST sender failed to serve"),
|
||||
InternalRegex: regexp.MustCompile("IST sender failed to serve " + regexNodeIPMethod + ":.*asio error '.*: [0-9]+ \\((?P<error>[\\w\\s]+)\\)"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
joiner := submatches[groupNodeIP]
|
||||
istError := submatches["error"]
|
||||
|
||||
return ctx, types.FormatByIPDisplayer("IST to %s"+utils.Paint(utils.RedText, " failed: ")+istError, joiner, date)
|
||||
return logCtx, types.FormatByIPDisplayer("IST to %s"+utils.Paint(utils.RedText, " failed: ")+istError, joiner, date)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -11,10 +11,10 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: Member 2.0 (node2) requested state transfer from '*any*'. Selected 0.0 (node1)(SYNCED) as donor.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{SSTs: map[string]types.SST{}},
|
||||
LogCtx: types.LogCtx{SSTs: map[string]types.SST{}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}}},
|
||||
LogCtx: types.LogCtx{SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}}},
|
||||
},
|
||||
expectedOut: "node1 will resync node2",
|
||||
key: "RegexSSTRequestSuccess",
|
||||
@@ -23,10 +23,10 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "with fqdn",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Member 2.0 (node2.host.com) requested state transfer from '*any*'. Selected 0.0 (node1.host.com)(SYNCED) as donor.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{SSTs: map[string]types.SST{}},
|
||||
LogCtx: types.LogCtx{SSTs: map[string]types.SST{}},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}}},
|
||||
LogCtx: types.LogCtx{SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}}},
|
||||
},
|
||||
expectedOut: "node1 will resync node2",
|
||||
key: "RegexSSTRequestSuccess",
|
||||
@@ -35,13 +35,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "joining",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: Member 2.0 (node2) requested state transfer from '*any*'. Selected 0.0 (node1)(SYNCED) as donor.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
SSTs: map[string]types.SST{},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}},
|
||||
},
|
||||
@@ -53,13 +53,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "donor",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: Member 2.0 (node2) requested state transfer from '*any*'. Selected 0.0 (node1)(SYNCED) as donor.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node1"},
|
||||
SSTs: map[string]types.SST{},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node1"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", SelectionTimestamp: timeMustParse("2001-01-01T01:01:01.000000Z")}},
|
||||
},
|
||||
@@ -71,10 +71,10 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01 01:01:01.164 WARN: Member 1.0 (node2) requested state transfer from 'node1', but it is impossible to select State Transfer donor: Resource temporarily unavailable",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expectedOut: "node2 cannot find donor",
|
||||
key: "RegexSSTResourceUnavailable",
|
||||
@@ -83,12 +83,12 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "local",
|
||||
log: "2001-01-01 01:01:01.164 WARN: Member 1.0 (node2) requested state transfer from 'node1', but it is impossible to select State Transfer donor: Resource temporarily unavailable",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
@@ -99,12 +99,12 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to 2.0 (node2) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{},
|
||||
},
|
||||
},
|
||||
@@ -115,13 +115,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "joiner",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to 2.0 (node2) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -133,13 +133,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "joiner ist",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to 2.0 (node2) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node2"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -151,13 +151,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "donor",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to 2.0 (node2) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node1"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{},
|
||||
OwnNames: []string{"node1"},
|
||||
},
|
||||
@@ -169,13 +169,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "donor ist",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to 2.0 (node2) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnNames: []string{"node1"},
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{},
|
||||
OwnNames: []string{"node1"},
|
||||
},
|
||||
@@ -187,10 +187,10 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: 0.0 (node1): State transfer to -1.-1 (left the group) complete.",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{},
|
||||
LogCtx: types.LogCtx{},
|
||||
},
|
||||
expectedOut: "node1 synced ??(node left)",
|
||||
key: "RegexSSTCompleteUnknown",
|
||||
@@ -211,13 +211,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z WSREP_SST: [INFO] Proceeding with SST.........",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "SST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -245,13 +245,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01 1:01:01 140433613571840 [Note] WSREP: async IST sender starting to serve tcp://172.17.0.2:4568 sending 2-116",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node1"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
OwnNames: []string{"node1"},
|
||||
},
|
||||
@@ -264,13 +264,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Prepared IST receiver for 114-116, listening at: ssl://172.17.0.2:4568",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -282,13 +282,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] Prepared IST receiver for 0-116, listening at: ssl://172.17.0.2:4568",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "SST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -301,13 +301,13 @@ func TestSSTRegex(t *testing.T) {
|
||||
name: "mdb variant",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: Prepared IST receiver, listening at: ssl://172.17.0.2:4568",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -337,14 +337,14 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 1 [Note] WSREP: Failed to prepare for incremental state transfer: Local state UUID (00000000-0000-0000-0000-000000000000) does not match group state UUID (ed16c932-84b3-11ed-998c-8e3ae5bc328f): 1 (Operation not permitted)",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
State: "JOINER",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "SST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -356,14 +356,14 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 1 [Warning] WSREP: Failed to prepare for incremental state transfer: Local state seqno is undefined: 1 (Operation not permitted)",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
State: "JOINER",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "SST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -376,14 +376,14 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z WSREP_SST: [INFO] Bypassing SST. Can work it through IST",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
State: "JOINER",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
@@ -396,14 +396,14 @@ func TestSSTRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [WSREP-SST] xtrabackup_ist received from donor: Running IST",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
State: "JOINER",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
SSTs: map[string]types.SST{"node1": types.SST{Donor: "node1", Joiner: "node2", Type: "IST"}},
|
||||
OwnNames: []string{"node2"},
|
||||
},
|
||||
|
@@ -13,18 +13,18 @@ func init() {
|
||||
}
|
||||
|
||||
var (
|
||||
shiftFunc = func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
shiftFunc = func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
newState := submatches["state2"]
|
||||
ctx.SetState(newState)
|
||||
logCtx.SetState(newState)
|
||||
|
||||
if newState == "DONOR" || newState == "JOINER" {
|
||||
ctx.ConfirmSSTMetadata(date)
|
||||
logCtx.ConfirmSSTMetadata(date)
|
||||
}
|
||||
|
||||
log = utils.PaintForState(submatches["state1"], submatches["state1"]) + " -> " + utils.PaintForState(submatches["state2"], submatches["state2"])
|
||||
|
||||
return ctx, types.SimpleDisplayer(log)
|
||||
return logCtx, types.SimpleDisplayer(log)
|
||||
}
|
||||
shiftRegex = regexp.MustCompile("(?P<state1>[A-Z]+) -> (?P<state2>[A-Z]+)")
|
||||
)
|
||||
@@ -39,11 +39,11 @@ var StatesMap = types.RegexMap{
|
||||
"RegexRestoredState": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Restored state"),
|
||||
InternalRegex: shiftRegex,
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
var displayer types.LogDisplayer
|
||||
ctx, displayer = shiftFunc(submatches, ctx, log, date)
|
||||
logCtx, displayer = shiftFunc(submatches, logCtx, log, date)
|
||||
|
||||
return ctx, types.SimpleDisplayer("(restored)" + displayer(ctx))
|
||||
return logCtx, types.SimpleDisplayer("(restored)" + displayer(logCtx))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -20,15 +20,15 @@ var ViewsMap = types.RegexMap{
|
||||
"RegexNodeEstablished": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("connection established"),
|
||||
InternalRegex: regexp.MustCompile("established to " + regexNodeHash + " " + regexNodeIPMethod),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
hash := submatches[groupNodeHash]
|
||||
translate.AddHashToIP(hash, ip, date)
|
||||
if utils.SliceContains(ctx.OwnIPs, ip) {
|
||||
return ctx, nil
|
||||
if utils.SliceContains(logCtx.OwnIPs, ip) {
|
||||
return logCtx, nil
|
||||
}
|
||||
return ctx, types.FormatByHashDisplayer("%s established", hash, date)
|
||||
return logCtx, types.FormatByHashDisplayer("%s established", hash, date)
|
||||
},
|
||||
Verbosity: types.DebugMySQL,
|
||||
},
|
||||
@@ -36,26 +36,26 @@ var ViewsMap = types.RegexMap{
|
||||
"RegexNodeJoined": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("declaring .* stable"),
|
||||
InternalRegex: regexp.MustCompile("declaring " + regexNodeHash + " at " + regexNodeIPMethod),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
hash := submatches[groupNodeHash]
|
||||
translate.AddHashToIP(hash, ip, date)
|
||||
translate.AddIPToMethod(ip, submatches[groupMethod], date)
|
||||
return ctx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.GreenText, " joined"), hash, date)
|
||||
return logCtx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.GreenText, " joined"), hash, date)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexNodeLeft": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("forgetting"),
|
||||
InternalRegex: regexp.MustCompile("forgetting " + regexNodeHash + " \\(" + regexNodeIPMethod),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
ip := submatches[groupNodeIP]
|
||||
hash := submatches[groupNodeHash]
|
||||
translate.AddHashToIP(hash, ip, date)
|
||||
translate.AddIPToMethod(ip, submatches[groupMethod], date)
|
||||
return ctx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.RedText, " left"), hash, date)
|
||||
return logCtx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.RedText, " left"), hash, date)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -63,106 +63,106 @@ var ViewsMap = types.RegexMap{
|
||||
"RegexNewComponent": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("New COMPONENT:"),
|
||||
InternalRegex: regexp.MustCompile("New COMPONENT: primary = (?P<primary>.+), bootstrap = (?P<bootstrap>.*), my_idx = .*, memb_num = (?P<memb_num>[0-9]{1,2})"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
primary := submatches["primary"] == "yes"
|
||||
membNum := submatches["memb_num"]
|
||||
bootstrap := submatches["bootstrap"] == "yes"
|
||||
memberCount, err := strconv.Atoi(membNum)
|
||||
if err != nil {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
|
||||
ctx.MemberCount = memberCount
|
||||
logCtx.MemberCount = memberCount
|
||||
if primary {
|
||||
// we don't always store PRIMARY because we could have found DONOR/JOINER/SYNCED/DESYNCED just earlier
|
||||
// and we do not want to override these as they have more value
|
||||
if !ctx.IsPrimary() {
|
||||
ctx.SetState("PRIMARY")
|
||||
if !logCtx.IsPrimary() {
|
||||
logCtx.SetState("PRIMARY")
|
||||
}
|
||||
msg := utils.Paint(utils.GreenText, "PRIMARY") + "(n=" + membNum + ")"
|
||||
if bootstrap {
|
||||
msg += ",bootstrap"
|
||||
}
|
||||
return ctx, types.SimpleDisplayer(msg)
|
||||
return logCtx, types.SimpleDisplayer(msg)
|
||||
}
|
||||
|
||||
ctx.SetState("NON-PRIMARY")
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "NON-PRIMARY") + "(n=" + membNum + ")")
|
||||
logCtx.SetState("NON-PRIMARY")
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "NON-PRIMARY") + "(n=" + membNum + ")")
|
||||
},
|
||||
},
|
||||
|
||||
"RegexNodeSuspect": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("suspecting node"),
|
||||
InternalRegex: regexp.MustCompile("suspecting node: " + regexNodeHash),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
hash := submatches[groupNodeHash]
|
||||
|
||||
return ctx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.YellowText, " suspected to be down"), hash, date)
|
||||
return logCtx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.YellowText, " suspected to be down"), hash, date)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexNodeChangedIdentity": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("remote endpoint.*changed identity"),
|
||||
InternalRegex: regexp.MustCompile("remote endpoint " + regexNodeIPMethod + " changed identity " + regexNodeHash + " -> " + strings.Replace(regexNodeHash, groupNodeHash, groupNodeHash+"2", -1)),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
|
||||
hash := utils.UUIDToShortUUID(submatches[groupNodeHash])
|
||||
hash2 := utils.UUIDToShortUUID(submatches[groupNodeHash+"2"])
|
||||
if ip := translate.GetIPFromHash(hash); ip != "" {
|
||||
translate.AddHashToIP(hash2, ip, date)
|
||||
}
|
||||
return ctx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.YellowText, " changed identity"), hash, date)
|
||||
return logCtx, types.FormatByHashDisplayer("%s"+utils.Paint(utils.YellowText, " changed identity"), hash, date)
|
||||
},
|
||||
},
|
||||
|
||||
"RegexWsrepUnsafeBootstrap": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("ERROR.*not be safe to bootstrap"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "not safe to bootstrap"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "not safe to bootstrap"))
|
||||
},
|
||||
},
|
||||
"RegexWsrepConsistenctyCompromised": &types.LogRegex{
|
||||
Regex: regexp.MustCompile(".ode consistency compromi.ed"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
ctx.SetState("CLOSED")
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
logCtx.SetState("CLOSED")
|
||||
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.RedText, "consistency compromised"))
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.RedText, "consistency compromised"))
|
||||
},
|
||||
},
|
||||
"RegexWsrepNonPrimary": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("failed to reach primary view"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer("received " + utils.Paint(utils.RedText, "non primary"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer("received " + utils.Paint(utils.RedText, "non primary"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexBootstrap": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("gcomm: bootstrapping new group"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "bootstrapping"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "bootstrapping"))
|
||||
},
|
||||
},
|
||||
|
||||
"RegexSafeToBootstrapSet": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("safe_to_bootstrap: 1"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "safe_to_bootstrap: 1"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "safe_to_bootstrap: 1"))
|
||||
},
|
||||
},
|
||||
"RegexNoGrastate": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Could not open state file for reading.*grastate.dat"),
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "no grastate.dat file"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "no grastate.dat file"))
|
||||
},
|
||||
},
|
||||
"RegexBootstrappingDefaultState": &types.LogRegex{
|
||||
Regex: regexp.MustCompile("Bootstraping with default state"), // typo is in Galera lib
|
||||
Handler: func(submatches map[string]string, ctx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return ctx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "bootstrapping(empty grastate)"))
|
||||
Handler: func(submatches map[string]string, logCtx types.LogCtx, log string, date time.Time) (types.LogCtx, types.LogDisplayer) {
|
||||
return logCtx, types.SimpleDisplayer(utils.Paint(utils.YellowText, "bootstrapping(empty grastate)"))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@@ -24,13 +24,13 @@ func TestViewsRegex(t *testing.T) {
|
||||
name: "established to node's own ip",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] [MY-000000] [Galera] (60205de0-8884, 'ssl://0.0.0.0:4567') connection established to 5873acd0-baa8 ssl://172.17.0.2:4567",
|
||||
input: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnIPs: []string{"172.17.0.2"},
|
||||
},
|
||||
HashToIP: map[string]string{},
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{
|
||||
LogCtx: types.LogCtx{
|
||||
OwnIPs: []string{"172.17.0.2"},
|
||||
},
|
||||
HashToIP: map[string]string{"5873acd0-baa8": "172.17.0.2"},
|
||||
@@ -77,8 +77,8 @@ func TestViewsRegex(t *testing.T) {
|
||||
{
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: New COMPONENT: primary = yes, bootstrap = no, my_idx = 0, memb_num = 2",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{MemberCount: 2},
|
||||
State: "PRIMARY",
|
||||
LogCtx: types.LogCtx{MemberCount: 2},
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expectedOut: "PRIMARY(n=2)",
|
||||
key: "RegexNewComponent",
|
||||
@@ -87,8 +87,8 @@ func TestViewsRegex(t *testing.T) {
|
||||
name: "bootstrap",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: New COMPONENT: primary = yes, bootstrap = yes, my_idx = 0, memb_num = 2",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{MemberCount: 2},
|
||||
State: "PRIMARY",
|
||||
LogCtx: types.LogCtx{MemberCount: 2},
|
||||
State: "PRIMARY",
|
||||
},
|
||||
expectedOut: "PRIMARY(n=2),bootstrap",
|
||||
key: "RegexNewComponent",
|
||||
@@ -100,8 +100,8 @@ func TestViewsRegex(t *testing.T) {
|
||||
State: "JOINER",
|
||||
},
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{MemberCount: 2},
|
||||
State: "JOINER",
|
||||
LogCtx: types.LogCtx{MemberCount: 2},
|
||||
State: "JOINER",
|
||||
},
|
||||
expectedOut: "PRIMARY(n=2)",
|
||||
key: "RegexNewComponent",
|
||||
@@ -110,8 +110,8 @@ func TestViewsRegex(t *testing.T) {
|
||||
name: "non-primary",
|
||||
log: "2001-01-01T01:01:01.000000Z 0 [Note] WSREP: New COMPONENT: primary = no, bootstrap = no, my_idx = 0, memb_num = 2",
|
||||
expected: regexTestState{
|
||||
Ctx: types.LogCtx{MemberCount: 2},
|
||||
State: "NON-PRIMARY",
|
||||
LogCtx: types.LogCtx{MemberCount: 2},
|
||||
State: "NON-PRIMARY",
|
||||
},
|
||||
expectedOut: "NON-PRIMARY(n=2)",
|
||||
key: "RegexNewComponent",
|
||||
|
@@ -37,13 +37,13 @@ type LogCtx struct {
|
||||
}
|
||||
|
||||
func NewLogCtx() LogCtx {
|
||||
ctx := LogCtx{minVerbosity: Debug}
|
||||
ctx.InitMaps()
|
||||
return ctx
|
||||
logCtx := LogCtx{minVerbosity: Debug}
|
||||
logCtx.InitMaps()
|
||||
return logCtx
|
||||
}
|
||||
|
||||
func (ctx *LogCtx) InitMaps() {
|
||||
ctx.SSTs = map[string]SST{}
|
||||
func (logCtx *LogCtx) InitMaps() {
|
||||
logCtx.SSTs = map[string]SST{}
|
||||
}
|
||||
|
||||
// State will return the wsrep state of the current file type
|
||||
@@ -51,23 +51,23 @@ func (ctx *LogCtx) InitMaps() {
|
||||
// Not tracking and differentiating by file types led to confusions in most subcommands
|
||||
// as it would seem that sometimes mysql is restarting after a crash, while actually
|
||||
// the operator was simply launching a "wsrep-recover" instance while mysql was still running
|
||||
func (ctx LogCtx) State() string {
|
||||
switch ctx.FileType {
|
||||
func (logCtx LogCtx) State() string {
|
||||
switch logCtx.FileType {
|
||||
case "post.processing.log":
|
||||
return ctx.statePostProcessingLog
|
||||
return logCtx.statePostProcessingLog
|
||||
case "recovery.log":
|
||||
return ctx.stateRecoveryLog
|
||||
return logCtx.stateRecoveryLog
|
||||
case "backup.log":
|
||||
return ctx.stateBackupLog
|
||||
return logCtx.stateBackupLog
|
||||
case "error.log":
|
||||
fallthrough
|
||||
default:
|
||||
return ctx.stateErrorLog
|
||||
return logCtx.stateErrorLog
|
||||
}
|
||||
}
|
||||
|
||||
// SetState will double-check if the STATE exists, and also store it on the correct status
|
||||
func (ctx *LogCtx) SetState(s string) {
|
||||
func (logCtx *LogCtx) SetState(s string) {
|
||||
|
||||
// NON-PRIMARY and RECOVERY are not a real wsrep state, but it's helpful here
|
||||
// DONOR and DESYNCED are merged in wsrep, but we are able to distinguish here
|
||||
@@ -75,68 +75,68 @@ func (ctx *LogCtx) SetState(s string) {
|
||||
if !utils.SliceContains([]string{"SYNCED", "JOINED", "DONOR", "DESYNCED", "JOINER", "PRIMARY", "NON-PRIMARY", "OPEN", "CLOSED", "DESTROYED", "ERROR", "RECOVERY"}, s) {
|
||||
return
|
||||
}
|
||||
switch ctx.FileType {
|
||||
switch logCtx.FileType {
|
||||
case "post.processing.log":
|
||||
ctx.statePostProcessingLog = s
|
||||
logCtx.statePostProcessingLog = s
|
||||
case "recovery.log":
|
||||
ctx.stateRecoveryLog = s
|
||||
logCtx.stateRecoveryLog = s
|
||||
case "backup.log":
|
||||
ctx.stateBackupLog = s
|
||||
logCtx.stateBackupLog = s
|
||||
case "error.log":
|
||||
fallthrough
|
||||
default:
|
||||
ctx.stateErrorLog = s
|
||||
logCtx.stateErrorLog = s
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *LogCtx) HasVisibleEvents(level Verbosity) bool {
|
||||
return level >= ctx.minVerbosity
|
||||
func (logCtx *LogCtx) HasVisibleEvents(level Verbosity) bool {
|
||||
return level >= logCtx.minVerbosity
|
||||
}
|
||||
|
||||
func (ctx *LogCtx) IsPrimary() bool {
|
||||
return utils.SliceContains([]string{"SYNCED", "DONOR", "DESYNCED", "JOINER", "PRIMARY"}, ctx.State())
|
||||
func (logCtx *LogCtx) IsPrimary() bool {
|
||||
return utils.SliceContains([]string{"SYNCED", "DONOR", "DESYNCED", "JOINER", "PRIMARY"}, logCtx.State())
|
||||
}
|
||||
|
||||
// AddOwnName propagates a name into the translation maps using the trusted node's known own hashes and ips
|
||||
func (ctx *LogCtx) AddOwnName(name string, date time.Time) {
|
||||
func (logCtx *LogCtx) AddOwnName(name string, date time.Time) {
|
||||
// used to be a simple "if utils.SliceContains", changed to "is it the last known name?"
|
||||
// because some names/ips come back and forth, we should keep track of that
|
||||
name = utils.ShortNodeName(name)
|
||||
if len(ctx.OwnNames) > 0 && ctx.OwnNames[len(ctx.OwnNames)-1] == name {
|
||||
if len(logCtx.OwnNames) > 0 && logCtx.OwnNames[len(logCtx.OwnNames)-1] == name {
|
||||
return
|
||||
}
|
||||
ctx.OwnNames = append(ctx.OwnNames, name)
|
||||
for _, hash := range ctx.OwnHashes {
|
||||
logCtx.OwnNames = append(logCtx.OwnNames, name)
|
||||
for _, hash := range logCtx.OwnHashes {
|
||||
translate.AddHashToNodeName(hash, name, date)
|
||||
}
|
||||
for _, ip := range ctx.OwnIPs {
|
||||
for _, ip := range logCtx.OwnIPs {
|
||||
translate.AddIPToNodeName(ip, name, date)
|
||||
}
|
||||
}
|
||||
|
||||
// AddOwnHash propagates a hash into the translation maps
|
||||
func (ctx *LogCtx) AddOwnHash(hash string, date time.Time) {
|
||||
if utils.SliceContains(ctx.OwnHashes, hash) {
|
||||
func (logCtx *LogCtx) AddOwnHash(hash string, date time.Time) {
|
||||
if utils.SliceContains(logCtx.OwnHashes, hash) {
|
||||
return
|
||||
}
|
||||
ctx.OwnHashes = append(ctx.OwnHashes, hash)
|
||||
logCtx.OwnHashes = append(logCtx.OwnHashes, hash)
|
||||
|
||||
for _, ip := range ctx.OwnIPs {
|
||||
for _, ip := range logCtx.OwnIPs {
|
||||
translate.AddHashToIP(hash, ip, date)
|
||||
}
|
||||
for _, name := range ctx.OwnNames {
|
||||
for _, name := range logCtx.OwnNames {
|
||||
translate.AddHashToNodeName(hash, name, date)
|
||||
}
|
||||
}
|
||||
|
||||
// AddOwnIP propagates a ip into the translation maps
|
||||
func (ctx *LogCtx) AddOwnIP(ip string, date time.Time) {
|
||||
func (logCtx *LogCtx) AddOwnIP(ip string, date time.Time) {
|
||||
// see AddOwnName comment
|
||||
if len(ctx.OwnIPs) > 0 && ctx.OwnIPs[len(ctx.OwnIPs)-1] == ip {
|
||||
if len(logCtx.OwnIPs) > 0 && logCtx.OwnIPs[len(logCtx.OwnIPs)-1] == ip {
|
||||
return
|
||||
}
|
||||
ctx.OwnIPs = append(ctx.OwnIPs, ip)
|
||||
for _, name := range ctx.OwnNames {
|
||||
logCtx.OwnIPs = append(logCtx.OwnIPs, ip)
|
||||
for _, name := range logCtx.OwnNames {
|
||||
translate.AddIPToNodeName(ip, name, date)
|
||||
}
|
||||
}
|
||||
@@ -145,37 +145,37 @@ func (ctx *LogCtx) AddOwnIP(ip string, date time.Time) {
|
||||
// into the base
|
||||
// It is used when merging, so that we do not start from nothing
|
||||
// It helps when dealing with many small files
|
||||
func (base *LogCtx) Inherit(ctx LogCtx) {
|
||||
base.OwnHashes = append(ctx.OwnHashes, base.OwnHashes...)
|
||||
base.OwnNames = append(ctx.OwnNames, base.OwnNames...)
|
||||
base.OwnIPs = append(ctx.OwnIPs, base.OwnIPs...)
|
||||
func (base *LogCtx) Inherit(logCtx LogCtx) {
|
||||
base.OwnHashes = append(logCtx.OwnHashes, base.OwnHashes...)
|
||||
base.OwnNames = append(logCtx.OwnNames, base.OwnNames...)
|
||||
base.OwnIPs = append(logCtx.OwnIPs, base.OwnIPs...)
|
||||
if base.Version == "" {
|
||||
base.Version = ctx.Version
|
||||
base.Version = logCtx.Version
|
||||
}
|
||||
base.Conflicts = append(ctx.Conflicts, base.Conflicts...)
|
||||
base.Conflicts = append(logCtx.Conflicts, base.Conflicts...)
|
||||
}
|
||||
|
||||
func (ctx *LogCtx) SetSSTTypeMaybe(ssttype string) {
|
||||
for key, sst := range ctx.SSTs {
|
||||
if len(ctx.SSTs) == 1 || (ctx.State() == "DONOR" && utils.SliceContains(ctx.OwnNames, key)) || (ctx.State() == "JOINER" && utils.SliceContains(ctx.OwnNames, sst.Joiner)) {
|
||||
func (logCtx *LogCtx) SetSSTTypeMaybe(ssttype string) {
|
||||
for key, sst := range logCtx.SSTs {
|
||||
if len(logCtx.SSTs) == 1 || (logCtx.State() == "DONOR" && utils.SliceContains(logCtx.OwnNames, key)) || (logCtx.State() == "JOINER" && utils.SliceContains(logCtx.OwnNames, sst.Joiner)) {
|
||||
sst.Type = ssttype
|
||||
ctx.SSTs[key] = sst
|
||||
logCtx.SSTs[key] = sst
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *LogCtx) ConfirmSSTMetadata(shiftTimestamp time.Time) {
|
||||
if ctx.State() != "DONOR" && ctx.State() != "JOINER" {
|
||||
func (logCtx *LogCtx) ConfirmSSTMetadata(shiftTimestamp time.Time) {
|
||||
if logCtx.State() != "DONOR" && logCtx.State() != "JOINER" {
|
||||
return
|
||||
}
|
||||
for key, sst := range ctx.SSTs {
|
||||
for key, sst := range logCtx.SSTs {
|
||||
if sst.MustHaveHappenedLocally(shiftTimestamp) {
|
||||
if ctx.State() == "DONOR" {
|
||||
ctx.AddOwnName(key, shiftTimestamp)
|
||||
if logCtx.State() == "DONOR" {
|
||||
logCtx.AddOwnName(key, shiftTimestamp)
|
||||
}
|
||||
if ctx.State() == "JOINER" {
|
||||
ctx.AddOwnName(sst.Joiner, shiftTimestamp)
|
||||
if logCtx.State() == "JOINER" {
|
||||
logCtx.AddOwnName(sst.Joiner, shiftTimestamp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func (ctx *LogCtx) ConfirmSSTMetadata(shiftTimestamp time.Time) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l LogCtx) MarshalJSON() ([]byte, error) {
|
||||
func (logCtx *LogCtx) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
FilePath string
|
||||
FileType string
|
||||
@@ -202,20 +202,20 @@ func (l LogCtx) MarshalJSON() ([]byte, error) {
|
||||
MinVerbosity Verbosity
|
||||
Conflicts Conflicts
|
||||
}{
|
||||
FilePath: l.FilePath,
|
||||
FileType: l.FileType,
|
||||
OwnIPs: l.OwnIPs,
|
||||
OwnHashes: l.OwnHashes,
|
||||
StateErrorLog: l.stateErrorLog,
|
||||
StateRecoveryLog: l.stateRecoveryLog,
|
||||
StatePostProcessingLog: l.statePostProcessingLog,
|
||||
StateBackupLog: l.stateBackupLog,
|
||||
Version: l.Version,
|
||||
SSTs: l.SSTs,
|
||||
MyIdx: l.MyIdx,
|
||||
MemberCount: l.MemberCount,
|
||||
Desynced: l.Desynced,
|
||||
MinVerbosity: l.minVerbosity,
|
||||
Conflicts: l.Conflicts,
|
||||
FilePath: logCtx.FilePath,
|
||||
FileType: logCtx.FileType,
|
||||
OwnIPs: logCtx.OwnIPs,
|
||||
OwnHashes: logCtx.OwnHashes,
|
||||
StateErrorLog: logCtx.stateErrorLog,
|
||||
StateRecoveryLog: logCtx.stateRecoveryLog,
|
||||
StatePostProcessingLog: logCtx.statePostProcessingLog,
|
||||
StateBackupLog: logCtx.stateBackupLog,
|
||||
Version: logCtx.Version,
|
||||
SSTs: logCtx.SSTs,
|
||||
MyIdx: logCtx.MyIdx,
|
||||
MemberCount: logCtx.MemberCount,
|
||||
Desynced: logCtx.Desynced,
|
||||
MinVerbosity: logCtx.minVerbosity,
|
||||
Conflicts: logCtx.Conflicts,
|
||||
})
|
||||
}
|
@@ -24,18 +24,18 @@ type LogInfo struct {
|
||||
Log string // the raw log
|
||||
RegexType RegexType
|
||||
RegexUsed string
|
||||
Ctx LogCtx // the context is copied for each logInfo, so that it is easier to handle some info (current state), and this is also interesting to check how it evolved
|
||||
LogCtx LogCtx // the context is copied for each logInfo, so that it is easier to handle some info (current state), and this is also interesting to check how it evolved
|
||||
Verbosity Verbosity
|
||||
RepetitionCount int
|
||||
extraNotes map[string]string
|
||||
}
|
||||
|
||||
func NewLogInfo(date *Date, displayer LogDisplayer, log string, regex *LogRegex, regexkey string, ctx LogCtx, filetype string) LogInfo {
|
||||
func NewLogInfo(date *Date, displayer LogDisplayer, log string, regex *LogRegex, regexkey string, logCtx LogCtx, filetype string) LogInfo {
|
||||
li := LogInfo{
|
||||
Date: date,
|
||||
Log: log,
|
||||
displayer: displayer,
|
||||
Ctx: ctx,
|
||||
LogCtx: logCtx,
|
||||
RegexType: regex.Type,
|
||||
RegexUsed: regexkey,
|
||||
Verbosity: regex.Verbosity,
|
||||
@@ -47,7 +47,7 @@ func NewLogInfo(date *Date, displayer LogDisplayer, log string, regex *LogRegex,
|
||||
return li
|
||||
}
|
||||
|
||||
func (li *LogInfo) Msg(ctx LogCtx) string {
|
||||
func (li *LogInfo) Msg(logCtx LogCtx) string {
|
||||
if li.displayer == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func (li *LogInfo) Msg(ctx LogCtx) string {
|
||||
if li.RepetitionCount > 0 {
|
||||
msg += utils.Paint(utils.BlueText, fmt.Sprintf("(repeated x%d)", li.RepetitionCount))
|
||||
}
|
||||
msg += li.displayer(ctx)
|
||||
msg += li.displayer(logCtx)
|
||||
for _, note := range li.extraNotes {
|
||||
msg += utils.Paint(utils.BlueText, fmt.Sprintf("(%s)", note))
|
||||
}
|
||||
@@ -67,9 +67,9 @@ func (li *LogInfo) Msg(ctx LogCtx) string {
|
||||
func (current *LogInfo) IsDuplicatedEvent(base, previous LogInfo) bool {
|
||||
return base.RegexUsed == previous.RegexUsed &&
|
||||
base.displayer != nil && previous.displayer != nil && current.displayer != nil &&
|
||||
base.displayer(base.Ctx) == previous.displayer(previous.Ctx) &&
|
||||
base.displayer(base.LogCtx) == previous.displayer(previous.LogCtx) &&
|
||||
previous.RegexUsed == current.RegexUsed &&
|
||||
previous.displayer(previous.Ctx) == current.displayer(current.Ctx)
|
||||
previous.displayer(previous.LogCtx) == current.displayer(current.LogCtx)
|
||||
}
|
||||
|
||||
type Date struct {
|
||||
|
@@ -20,17 +20,17 @@ type LogRegex struct {
|
||||
Verbosity Verbosity // To be able to hide details from summaries
|
||||
}
|
||||
|
||||
func (l *LogRegex) Handle(ctx LogCtx, line string, date time.Time) (LogCtx, LogDisplayer) {
|
||||
if ctx.minVerbosity > l.Verbosity {
|
||||
ctx.minVerbosity = l.Verbosity
|
||||
func (l *LogRegex) Handle(logCtx LogCtx, line string, date time.Time) (LogCtx, LogDisplayer) {
|
||||
if logCtx.minVerbosity > l.Verbosity {
|
||||
logCtx.minVerbosity = l.Verbosity
|
||||
}
|
||||
mergedResults := map[string]string{}
|
||||
if l.InternalRegex == nil {
|
||||
return l.Handler(mergedResults, ctx, line, date)
|
||||
return l.Handler(mergedResults, logCtx, line, date)
|
||||
}
|
||||
slice := l.InternalRegex.FindStringSubmatch(line)
|
||||
if len(slice) == 0 {
|
||||
return ctx, nil
|
||||
return logCtx, nil
|
||||
}
|
||||
for _, subexpname := range l.InternalRegex.SubexpNames() {
|
||||
if subexpname == "" { // 1st element is always empty for the complete regex
|
||||
@@ -38,7 +38,7 @@ func (l *LogRegex) Handle(ctx LogCtx, line string, date time.Time) (LogCtx, LogD
|
||||
}
|
||||
mergedResults[subexpname] = slice[l.InternalRegex.SubexpIndex(subexpname)]
|
||||
}
|
||||
return l.Handler(mergedResults, ctx, line, date)
|
||||
return l.Handler(mergedResults, logCtx, line, date)
|
||||
}
|
||||
|
||||
func (l *LogRegex) MarshalJSON() ([]byte, error) {
|
||||
|
@@ -31,7 +31,7 @@ func (timeline Timeline) MergeByIdentifier(lt LocalTimeline) {
|
||||
// identify the node with the easiest to read information
|
||||
// this is critical part to aggregate logs: this is what enable to merge logs
|
||||
// ultimately the "identifier" will be used for columns header
|
||||
node := Identifier(lt[len(lt)-1].Ctx, getlasttime(lt))
|
||||
node := Identifier(lt[len(lt)-1].LogCtx, getlasttime(lt))
|
||||
if lt2, ok := timeline[node]; ok {
|
||||
lt = MergeTimeline(lt2, lt)
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func (timeline Timeline) MergeByIdentifier(lt LocalTimeline) {
|
||||
func (timeline Timeline) MergeByDirectory(path string, lt LocalTimeline) {
|
||||
node := filepath.Base(filepath.Dir(path))
|
||||
for _, lt2 := range timeline {
|
||||
if len(lt2) > 0 && node == filepath.Base(filepath.Dir(lt2[0].Ctx.FilePath)) {
|
||||
if len(lt2) > 0 && node == filepath.Base(filepath.Dir(lt2[0].LogCtx.FilePath)) {
|
||||
lt = MergeTimeline(lt2, lt)
|
||||
}
|
||||
}
|
||||
@@ -108,18 +108,18 @@ func MergeTimeline(t1, t2 LocalTimeline) LocalTimeline {
|
||||
//>t : --O----OOO-- won't try to get things between t1.end and t2.start
|
||||
// we assume they're identical, they're supposed to be from the same server
|
||||
t2 = CutTimelineAt(t2, endt1)
|
||||
// no return here, to avoid repeating the ctx.inherit
|
||||
// no return here, to avoid repeating the logCtx.inherit
|
||||
}
|
||||
|
||||
// t1: --O--O------
|
||||
// t2: ------O--O--
|
||||
t2[len(t2)-1].Ctx.Inherit(t1[len(t1)-1].Ctx)
|
||||
t2[len(t2)-1].LogCtx.Inherit(t1[len(t1)-1].LogCtx)
|
||||
return append(t1, t2...)
|
||||
}
|
||||
|
||||
func getfirsttime(l LocalTimeline) time.Time {
|
||||
for _, event := range l {
|
||||
if event.Date != nil && (event.Ctx.FileType == "error.log" || event.Ctx.FileType == "") {
|
||||
if event.Date != nil && (event.LogCtx.FileType == "error.log" || event.LogCtx.FileType == "") {
|
||||
return event.Date.Time
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func getfirsttime(l LocalTimeline) time.Time {
|
||||
}
|
||||
func getlasttime(l LocalTimeline) time.Time {
|
||||
for i := len(l) - 1; i >= 0; i-- {
|
||||
if l[i].Date != nil && (l[i].Ctx.FileType == "error.log" || l[i].Ctx.FileType == "") {
|
||||
if l[i].Date != nil && (l[i].LogCtx.FileType == "error.log" || l[i].LogCtx.FileType == "") {
|
||||
return l[i].Date.Time
|
||||
}
|
||||
}
|
||||
@@ -148,13 +148,13 @@ func CutTimelineAt(t LocalTimeline, at time.Time) LocalTimeline {
|
||||
}
|
||||
|
||||
func (t *Timeline) GetLatestContextsByNodes() map[string]LogCtx {
|
||||
latestctxs := map[string]LogCtx{}
|
||||
latestlogCtxs := make(map[string]LogCtx, len(*t))
|
||||
|
||||
for key, localtimeline := range *t {
|
||||
latestctxs[key] = localtimeline[len(localtimeline)-1].Ctx
|
||||
latestlogCtxs[key] = localtimeline[len(localtimeline)-1].LogCtx
|
||||
}
|
||||
|
||||
return latestctxs
|
||||
return latestlogCtxs
|
||||
}
|
||||
|
||||
// iterateNode is used to search the source node(s) that contains the next chronological events
|
||||
|
@@ -11,17 +11,17 @@ import (
|
||||
// It will also impacts how logs are merged if we have multiple logs per nodes
|
||||
//
|
||||
// In order of preference: wsrep_node_name (or galera "node" name), hostname, ip, filepath
|
||||
func Identifier(ctx LogCtx, date time.Time) string {
|
||||
if len(ctx.OwnNames) > 0 {
|
||||
return ctx.OwnNames[len(ctx.OwnNames)-1]
|
||||
func Identifier(logCtx LogCtx, date time.Time) string {
|
||||
if len(logCtx.OwnNames) > 0 {
|
||||
return logCtx.OwnNames[len(logCtx.OwnNames)-1]
|
||||
}
|
||||
if len(ctx.OwnIPs) > 0 {
|
||||
return translate.SimplestInfoFromIP(ctx.OwnIPs[len(ctx.OwnIPs)-1], date)
|
||||
if len(logCtx.OwnIPs) > 0 {
|
||||
return translate.SimplestInfoFromIP(logCtx.OwnIPs[len(logCtx.OwnIPs)-1], date)
|
||||
}
|
||||
for _, hash := range ctx.OwnHashes {
|
||||
for _, hash := range logCtx.OwnHashes {
|
||||
if out := translate.SimplestInfoFromHash(hash, date); out != hash {
|
||||
return out
|
||||
}
|
||||
}
|
||||
return ctx.FilePath
|
||||
return logCtx.FilePath
|
||||
}
|
||||
|
Reference in New Issue
Block a user