mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-20 02:44:58 +00:00
Add: merge by directory, Simplified: timeline merges
This commit is contained in:
@@ -32,6 +32,7 @@ var CLI struct {
|
|||||||
Verbosity types.Verbosity `type:"counter" short:"v" default:"1" help:"-v: Detailed (default), -vv: DebugMySQL (add every mysql info the tool used), -vvv: Debug (internal tool debug)"`
|
Verbosity types.Verbosity `type:"counter" short:"v" default:"1" help:"-v: Detailed (default), -vv: DebugMySQL (add every mysql info the tool used), -vvv: Debug (internal tool debug)"`
|
||||||
PxcOperator bool `default:"false" help:"Analyze logs from Percona PXC operator. Off by default because it negatively impacts performance for non-k8s setups"`
|
PxcOperator bool `default:"false" help:"Analyze logs from Percona PXC operator. Off by default because it negatively impacts performance for non-k8s setups"`
|
||||||
ExcludeRegexes []string `help:"Remove regexes from analysis. List regexes using 'pt-galera-log-explainer regex-list'"`
|
ExcludeRegexes []string `help:"Remove regexes from analysis. List regexes using 'pt-galera-log-explainer regex-list'"`
|
||||||
|
MergeByDirectory bool `help:"Instead of relying on identification, merge contexts and columns by base directory. Very useful when dealing with many small logs organized per directories."`
|
||||||
|
|
||||||
List list `cmd:""`
|
List list `cmd:""`
|
||||||
Whois whois `cmd:""`
|
Whois whois `cmd:""`
|
||||||
@@ -92,29 +93,17 @@ func timelineFromPaths(paths []string, toCheck types.RegexMap, since, until *tim
|
|||||||
found = true
|
found = true
|
||||||
extr.logger.Debug().Str("path", path).Msg("Finished searching")
|
extr.logger.Debug().Str("path", path).Msg("Finished searching")
|
||||||
|
|
||||||
// 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
|
|
||||||
var node string
|
|
||||||
if CLI.PxcOperator {
|
|
||||||
node = path
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Why it should not just identify using the file path:
|
// Why it should not just identify using the file path:
|
||||||
// so that we are able to merge files that belong to the same nodes
|
// so that we are able to merge files that belong to the same nodes
|
||||||
// we wouldn't want them to be shown as from different nodes
|
// we wouldn't want them to be shown as from different nodes
|
||||||
node = types.Identifier(localTimeline[len(localTimeline)-1].Ctx)
|
if CLI.PxcOperator {
|
||||||
if t, ok := timeline[node]; ok {
|
timeline[path] = localTimeline
|
||||||
|
} else if CLI.MergeByDirectory {
|
||||||
extr.logger.Debug().Str("path", path).Str("node", node).Msg("Merging with existing timeline")
|
timeline.MergeByDirectory(path, localTimeline)
|
||||||
localTimeline = types.MergeTimeline(t, localTimeline)
|
} else {
|
||||||
|
timeline.MergeByIdentifier(localTimeline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extr.logger.Debug().Str("path", path).Str("node", node).Msg("Storing timeline")
|
|
||||||
timeline[node] = localTimeline
|
|
||||||
|
|
||||||
}
|
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("Could not find data")
|
return nil, errors.New("Could not find data")
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,6 +27,27 @@ func (lt LocalTimeline) Add(li LogInfo) LocalTimeline {
|
|||||||
// "string" key is a node IP
|
// "string" key is a node IP
|
||||||
type Timeline map[string]LocalTimeline
|
type Timeline map[string]LocalTimeline
|
||||||
|
|
||||||
|
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)
|
||||||
|
if lt2, ok := timeline[node]; ok {
|
||||||
|
lt = MergeTimeline(lt2, lt)
|
||||||
|
}
|
||||||
|
timeline[node] = lt
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
lt = MergeTimeline(lt2, lt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timeline[node] = lt
|
||||||
|
}
|
||||||
|
|
||||||
// MergeTimeline is helpful when log files are split by date, it can be useful to be able to merge content
|
// MergeTimeline is helpful when log files are split by date, it can be useful to be able to merge content
|
||||||
// a "timeline" come from a log file. Log files that came from some node should not never have overlapping dates
|
// a "timeline" come from a log file. Log files that came from some node should not never have overlapping dates
|
||||||
func MergeTimeline(t1, t2 LocalTimeline) LocalTimeline {
|
func MergeTimeline(t1, t2 LocalTimeline) LocalTimeline {
|
||||||
|
Reference in New Issue
Block a user