You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
2.8 KiB
143 lines
2.8 KiB
package protocol
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
"text/tabwriter"
|
|
)
|
|
|
|
type Cluster struct {
|
|
ClusterID string
|
|
Controller int32
|
|
Brokers map[int32]Broker
|
|
Topics map[string]Topic
|
|
}
|
|
|
|
func (c Cluster) BrokerIDs() []int32 {
|
|
brokerIDs := make([]int32, 0, len(c.Brokers))
|
|
for id := range c.Brokers {
|
|
brokerIDs = append(brokerIDs, id)
|
|
}
|
|
sort.Slice(brokerIDs, func(i, j int) bool {
|
|
return brokerIDs[i] < brokerIDs[j]
|
|
})
|
|
return brokerIDs
|
|
}
|
|
|
|
func (c Cluster) TopicNames() []string {
|
|
topicNames := make([]string, 0, len(c.Topics))
|
|
for name := range c.Topics {
|
|
topicNames = append(topicNames, name)
|
|
}
|
|
sort.Strings(topicNames)
|
|
return topicNames
|
|
}
|
|
|
|
func (c Cluster) IsZero() bool {
|
|
return c.ClusterID == "" && c.Controller == 0 && len(c.Brokers) == 0 && len(c.Topics) == 0
|
|
}
|
|
|
|
func (c Cluster) Format(w fmt.State, _ rune) {
|
|
tw := new(tabwriter.Writer)
|
|
fmt.Fprintf(w, "CLUSTER: %q\n\n", c.ClusterID)
|
|
|
|
tw.Init(w, 0, 8, 2, ' ', 0)
|
|
fmt.Fprint(tw, " BROKER\tHOST\tPORT\tRACK\tCONTROLLER\n")
|
|
|
|
for _, id := range c.BrokerIDs() {
|
|
broker := c.Brokers[id]
|
|
fmt.Fprintf(tw, " %d\t%s\t%d\t%s\t%t\n", broker.ID, broker.Host, broker.Port, broker.Rack, broker.ID == c.Controller)
|
|
}
|
|
|
|
tw.Flush()
|
|
fmt.Fprintln(w)
|
|
|
|
tw.Init(w, 0, 8, 2, ' ', 0)
|
|
fmt.Fprint(tw, " TOPIC\tPARTITIONS\tBROKERS\n")
|
|
topicNames := c.TopicNames()
|
|
brokers := make(map[int32]struct{}, len(c.Brokers))
|
|
brokerIDs := make([]int32, 0, len(c.Brokers))
|
|
|
|
for _, name := range topicNames {
|
|
topic := c.Topics[name]
|
|
|
|
for _, p := range topic.Partitions {
|
|
for _, id := range p.Replicas {
|
|
brokers[id] = struct{}{}
|
|
}
|
|
}
|
|
|
|
for id := range brokers {
|
|
brokerIDs = append(brokerIDs, id)
|
|
}
|
|
|
|
fmt.Fprintf(tw, " %s\t%d\t%s\n", topic.Name, len(topic.Partitions), formatBrokerIDs(brokerIDs, -1))
|
|
|
|
for id := range brokers {
|
|
delete(brokers, id)
|
|
}
|
|
|
|
brokerIDs = brokerIDs[:0]
|
|
}
|
|
|
|
tw.Flush()
|
|
fmt.Fprintln(w)
|
|
|
|
if w.Flag('+') {
|
|
for _, name := range topicNames {
|
|
fmt.Fprintf(w, " TOPIC: %q\n\n", name)
|
|
|
|
tw.Init(w, 0, 8, 2, ' ', 0)
|
|
fmt.Fprint(tw, " PARTITION\tREPLICAS\tISR\tOFFLINE\n")
|
|
|
|
for _, p := range c.Topics[name].Partitions {
|
|
fmt.Fprintf(tw, " %d\t%s\t%s\t%s\n", p.ID,
|
|
formatBrokerIDs(p.Replicas, -1),
|
|
formatBrokerIDs(p.ISR, p.Leader),
|
|
formatBrokerIDs(p.Offline, -1),
|
|
)
|
|
}
|
|
|
|
tw.Flush()
|
|
fmt.Fprintln(w)
|
|
}
|
|
}
|
|
}
|
|
|
|
func formatBrokerIDs(brokerIDs []int32, leader int32) string {
|
|
if len(brokerIDs) == 0 {
|
|
return ""
|
|
}
|
|
|
|
if len(brokerIDs) == 1 {
|
|
return itoa(brokerIDs[0])
|
|
}
|
|
|
|
sort.Slice(brokerIDs, func(i, j int) bool {
|
|
id1 := brokerIDs[i]
|
|
id2 := brokerIDs[j]
|
|
|
|
if id1 == leader {
|
|
return true
|
|
}
|
|
|
|
if id2 == leader {
|
|
return false
|
|
}
|
|
|
|
return id1 < id2
|
|
})
|
|
|
|
brokerNames := make([]string, len(brokerIDs))
|
|
|
|
for i, id := range brokerIDs {
|
|
brokerNames[i] = itoa(id)
|
|
}
|
|
|
|
return strings.Join(brokerNames, ",")
|
|
}
|
|
|
|
var (
|
|
_ fmt.Formatter = Cluster{}
|
|
)
|
|
|