pt-galera-log-explainer: add whois tree output

This commit is contained in:
Yoann La Cancellera
2024-03-12 23:03:05 +01:00
parent 6636265ef2
commit 421cadb1a8
8 changed files with 187 additions and 68 deletions

View File

@@ -48,34 +48,18 @@ You can filter by type of events
pt-galera-log-explainer list --sst --views *.log
..
whois
~~~~~
Find out information about nodes, using any type of info
Find out information about nodes, using any type of information
.. code-block:: bash
pt-galera-log-explainer [flags] whois [--json] [--type { nodename | ip | uuid | auto }] <information to search> <paths ...>
.. code-block:: bash
pt-galera-log-explainer whois '218469b2' mysql.log
{
"input": "218469b2",
"IPs": [
"172.17.0.3"
],
"nodeNames": [
"galera-node2"
],
"hostname": "",
"nodeUUIDs:": [
"218469b2",
"259b78a0",
"fa81213d",
]
}
Using any type of information
.. code-block:: bash
pt-galera-log-explainer whois '172.17.0.3' mysql.log
pt-galera-log-explainer whois 'galera-node2' mysql.log
@@ -219,6 +203,24 @@ Example outputs
2023-03-12T19:44:59.855443Z | node1 left |
2023-03-12T19:44:59.855491Z | PRIMARY(n=2) |
$ pt-galera-log-explainer whois 172.17.0.2 --no-color tests/logs/upgrade/*
ip:
└── 172.17.0.2
├── nodename:
│ └── node1 (2023-03-12 19:35:07.644683 +0000 UTC)
└── uuid:
├── 1d3ea8f5 (2023-03-12 07:24:13.789261 +0000 UTC)
├── 54ab931e (2023-03-12 07:43:08.563339 +0000 UTC)
├── fecde235 (2023-03-12 08:46:48.963504 +0000 UTC)
├── a07872e1 (2023-03-12 08:49:41.206124 +0000 UTC)
├── 60da0bf9-aa9c (2023-03-12 12:29:48.873397 +0000 UTC)
├── 35b62086-902c (2023-03-12 13:04:23.979636 +0000 UTC)
├── ca2c2a5f-a82a (2023-03-12 19:35:05.878879 +0000 UTC)
└── eefb9c8a-b69a (2023-03-12 19:43:17.133756 +0000 UTC)
Requirements
============

1
go.mod
View File

@@ -25,6 +25,7 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
github.com/xlab/treeprint v1.2.0
go.mongodb.org/mongo-driver v1.14.0
golang.org/x/crypto v0.21.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29

2
go.sum
View File

@@ -108,6 +108,8 @@ github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk=
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

View File

@@ -48,34 +48,18 @@ You can filter by type of events
pt-galera-log-explainer list --sst --views *.log
..
whois
~~~~~
Find out information about nodes, using any type of info
Find out information about nodes, using any type of information
.. code-block:: bash
pt-galera-log-explainer [flags] whois [--json] [--type { nodename | ip | uuid | auto }] <information to search> <paths ...>
.. code-block:: bash
pt-galera-log-explainer whois '218469b2' mysql.log
{
"input": "218469b2",
"IPs": [
"172.17.0.3"
],
"nodeNames": [
"galera-node2"
],
"hostname": "",
"nodeUUIDs:": [
"218469b2",
"259b78a0",
"fa81213d",
]
}
Using any type of information
.. code-block:: bash
pt-galera-log-explainer whois '172.17.0.3' mysql.log
pt-galera-log-explainer whois 'galera-node2' mysql.log
@@ -219,6 +203,24 @@ Example outputs
2023-03-12T19:44:59.855443Z | node1 left |
2023-03-12T19:44:59.855491Z | PRIMARY(n=2) |
$ pt-galera-log-explainer whois 172.17.0.2 --no-color tests/logs/upgrade/*
ip:
└── 172.17.0.2
├── nodename:
│ └── node1 (2023-03-12 19:35:07.644683 +0000 UTC)
└── uuid:
├── 1d3ea8f5 (2023-03-12 07:24:13.789261 +0000 UTC)
├── 54ab931e (2023-03-12 07:43:08.563339 +0000 UTC)
├── fecde235 (2023-03-12 08:46:48.963504 +0000 UTC)
├── a07872e1 (2023-03-12 08:49:41.206124 +0000 UTC)
├── 60da0bf9-aa9c (2023-03-12 12:29:48.873397 +0000 UTC)
├── 35b62086-902c (2023-03-12 13:04:23.979636 +0000 UTC)
├── ca2c2a5f-a82a (2023-03-12 19:35:05.878879 +0000 UTC)
└── eefb9c8a-b69a (2023-03-12 19:43:17.133756 +0000 UTC)
Requirements
============

View File

@@ -139,24 +139,29 @@ func TestMain(t *testing.T) {
},
{
name: "operator_ambiguous_ips_whois_cluster1-1",
cmd: []string{"whois", "cluster1-1", "--pxc-operator"},
cmd: []string{"whois", "cluster1-1", "--pxc-operator", "--json"},
path: "tests/logs/operator_ambiguous_ips/*",
},
{
name: "operator_ambiguous_ips_whois_e2239bca-93a3",
cmd: []string{"whois", "e2239bca-93a3", "--pxc-operator"},
cmd: []string{"whois", "e2239bca-93a3", "--pxc-operator", "--json"},
path: "tests/logs/operator_ambiguous_ips/*",
},
{ // symlink to the output of the test above, should be identical
name: "operator_ambiguous_ips_whois_e2239bca-256c-11ee-93a3-e23704b1e880",
cmd: []string{"whois", "e2239bca-256c-11ee-93a3-e23704b1e880", "--pxc-operator"},
cmd: []string{"whois", "e2239bca-256c-11ee-93a3-e23704b1e880", "--pxc-operator", "--json"},
path: "tests/logs/operator_ambiguous_ips/*",
},
{
name: "operator_ambiguous_ips_whois_tree_no_color_e2239bca-93a3",
cmd: []string{"whois", "e2239bca-93a3", "--pxc-operator", "--no-color"},
path: "tests/logs/operator_ambiguous_ips/*",
},
{
name: "operator_ambiguous_ips_whois_10.16.27.98",
cmd: []string{"whois", "10.16.27.98", "--pxc-operator"},
cmd: []string{"whois", "10.16.27.98", "--pxc-operator", "--json"},
path: "tests/logs/operator_ambiguous_ips/*",
},
}

View File

@@ -0,0 +1,46 @@
uuid:
└── e2239bca-93a3
├── nodename:
│ └── cluster1-1 (2023-05-18 13:13:27.582217 +0000 UTC)
│ ├── ip:
│ │ ├── 10.16.27.195 (2023-05-10 09:06:21.290854 +0000 UTC)
│ │ ├── 10.16.27.93 (2023-05-10 10:49:15.965568 +0000 UTC)
│ │ ├── 10.16.27.67 (2023-05-10 11:43:19.838842 +0000 UTC)
│ │ ├── 10.16.27.149 (2023-05-21 00:55:34.59855 +0000 UTC)
│ │ └── 10.16.27.203 (2023-05-21 01:21:12.237121 +0000 UTC)
│ │
│ └── uuid:
│ ├── 09afeef6-a69d (2023-05-10 09:06:21.310966 +0000 UTC)
│ ├── 106cd5a8-8e1c (2023-05-10 09:42:20.096709 +0000 UTC)
│ ├── 6a146d09-8747 (2023-05-10 10:49:15.98352 +0000 UTC)
│ ├── f7946b60-bf31 (2023-05-10 11:43:19.859843 +0000 UTC)
│ ├── 2cc76c37-becc (2023-05-10 11:51:58.610014 +0000 UTC)
│ ├── 2cc76c37-becd (2023-05-12 19:13:56.828375 +0000 UTC)
│ ├── 2cc76c37-bece (2023-05-12 19:29:34.102395 +0000 UTC)
│ ├── 2cc76c37-becf (2023-05-16 02:56:58.102204 +0000 UTC)
│ ├── 96435e8a-bab8 (2023-05-16 02:58:05.880842 +0000 UTC)
│ ├── d0e11ff4-be29 (2023-05-16 02:59:44.222891 +0000 UTC)
│ ├── 215101e1-b61d (2023-05-16 03:01:59.175607 +0000 UTC)
│ ├── 87e7065b-bf25 (2023-05-16 03:04:51.285176 +0000 UTC)
│ ├── 87e7065b-bf26 (2023-05-16 07:52:26.432272 +0000 UTC)
│ ├── 3c016ef3-af4c (2023-05-18 08:51:06.97503 +0000 UTC)
│ ├── 5fd057e4-bab5 (2023-05-18 11:15:16.987418 +0000 UTC)
│ ├── 250ac3d5-8380 (2023-05-18 13:15:19.825195 +0000 UTC)
│ ├── 70a8263e-989f (2023-05-18 13:17:26.686853 +0000 UTC)
│ ├── 7a3b782e-96c0 (2023-05-18 14:00:39.734694 +0000 UTC)
│ ├── 4ca2c784-a878 (2023-05-21 00:55:34.619148 +0000 UTC)
│ ├── e123e2f3-ace4 (2023-05-21 01:21:12.258721 +0000 UTC)
│ ├── e123e2f3-ace5 (2023-05-24 09:08:00.784586 +0000 UTC)
│ ├── c943db75-9035 (2023-05-25 04:36:13.482766 +0000 UTC)
│ ├── c943db75-9036 (2023-05-28 08:23:24.701198 +0000 UTC)
│ ├── 8e6f32b6-bf89 (2023-05-28 08:55:54.185342 +0000 UTC)
│ │ └── nodename:
│ │ └── unspecified (2023-05-29 07:16:49.686673 +0000 UTC)
│ │
│ └── 66e2b7bf-8000 (2023-05-29 07:20:31.719983 +0000 UTC)
└── ip:
└── 10.16.27.98 (2023-05-18 13:13:27.582217 +0000 UTC)

View File

@@ -3,6 +3,10 @@ package translate
import (
"encoding/json"
"time"
"github.com/percona/percona-toolkit/src/go/pt-galera-log-explainer/utils"
"github.com/xlab/treeprint"
"golang.org/x/exp/slices"
)
type WhoisNode struct {
@@ -60,6 +64,57 @@ func (n *WhoisNode) MarshalJSON() ([]byte, error) {
return json.Marshal(n.Values)
}
func (n *WhoisNode) String() string {
return n.tree().String()
}
func (n *WhoisNode) tree() treeprint.Tree {
root := treeprint.NewWithRoot(utils.Paint(utils.GreenText, n.nodetype) + ":")
for _, value := range n.valuesSortedByTimestamps() {
valueData := n.Values[value]
str := value
if valueData.Timestamp != nil {
str += utils.Paint(utils.BlueText, " ("+valueData.Timestamp.String()+")")
}
if len(valueData.SubNodes) == 0 {
root.AddNode(str)
continue
}
subtree := root.AddBranch(str)
// forcing map iteration for repeatable outputs
for _, subNodeType := range forcedIterationOrder {
subnode, ok := valueData.SubNodes[subNodeType]
if ok {
subtree.AddNode(subnode.tree())
}
}
}
return root
}
func (n *WhoisNode) valuesSortedByTimestamps() []string {
values := []string{}
for value := range n.Values {
values = append(values, value)
}
// keep nil timestamps at the top
slices.SortFunc(values, func(a, b string) bool {
if n.Values[a].Timestamp == nil && n.Values[b].Timestamp == nil {
return a < b
}
if n.Values[a].Timestamp == nil { // implied b!=nil
return true // meaning, nil < nonnil, a < b
}
if n.Values[b].Timestamp == nil { // implied a!=nil
return false // meaning a is greater than b
}
return n.Values[a].Timestamp.Before(*n.Values[b].Timestamp)
})
return values
}
func (n *WhoisNode) addKey(value string, timestamp time.Time) bool {
storedValue := n.rootNode.GetValueData(value, n.nodetype)
if storedValue != nil {

View File

@@ -16,6 +16,7 @@ type whois struct {
Search string `arg:"" name:"search" help:"the identifier (node name, ip, uuid) to search"`
SearchType string `name:"type" help:"what kind of information is the input (node name, ip, uuid). Auto-detected when possible." enum:"nodename,ip,uuid,auto" default:"auto"`
Paths []string `arg:"" name:"paths" help:"paths of the log to use"`
Json bool
}
func (w *whois) Help() string {
@@ -68,12 +69,17 @@ func (w *whois) Run() error {
}
log.Debug().Str("searchType", w.SearchType).Msg("whois searchType")
out := translate.Whois(w.Search, w.SearchType)
if w.Json {
json, err := json.MarshalIndent(out, "", "\t")
if err != nil {
return err
}
fmt.Println(string(json))
} else {
fmt.Println(out)
}
return nil
}