Skip to content

Commit

Permalink
connection specific info now output with 'info --consumer' command
Browse files Browse the repository at this point in the history
minor changes to output of "info" command
  • Loading branch information
jandelgado committed Apr 27, 2018
1 parent f268d76 commit 5275430
Show file tree
Hide file tree
Showing 10 changed files with 393 additions and 171 deletions.
17 changes: 9 additions & 8 deletions cmd/main/broker_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ type BrokerInfo struct {
Exchanges []rabtap.RabbitExchange
Queues []rabtap.RabbitQueue
Bindings []rabtap.RabbitBinding
Consumers []rabtap.RabbitConsumer
Channels []rabtap.RabbitChannel
Connections []rabtap.RabbitConnection
Consumers []rabtap.RabbitConsumer
// Channels []rabtap.RabbitChannel // not yet used.
}

// NewBrokerInfo obtains infos on broker using the provided client object
Expand Down Expand Up @@ -42,19 +42,20 @@ func NewBrokerInfo(client *rabtap.RabbitHTTPClient) (BrokerInfo, error) {
return bi, err
}

bi.Consumers, err = client.Consumers()
bi.Connections, err = client.Connections()
if err != nil {
return bi, err
}

bi.Channels, err = client.Channels()
bi.Consumers, err = client.Consumers()
if err != nil {
return bi, err
}

bi.Connections, err = client.Connections()
if err != nil {
return bi, err
}
// bi.Channels, err = client.Channels()
// if err != nil {
// return bi, err
// }

return bi, nil
}
236 changes: 148 additions & 88 deletions cmd/main/broker_info_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

package main

// TODO factor out templates, make configurable.

import (
"bytes"
"fmt"
Expand All @@ -16,31 +14,69 @@ import (
"github.com/jandelgado/rabtap/pkg"
)

const (
tplRootNode = `
{{- printf "%s://%s%s" .URL.Scheme .URL.Host .URL.Path | URLColor }}
{{- if .Overview }} (broker ver='{{ .Overview.RabbitmqVersion }}',
{{- "" }} mgmt ver='{{ .Overview.ManagementVersion }}',
{{- "" }} cluster='{{ .Overview.ClusterName }}{{end}}')`

tplConsumer = `
{{- ConsumerColor .Consumer.ConsumerTag }} (consumer
{{- ""}} user='{{ .Consumer.ChannelDetails.User }}', chan='
{{- .Consumer.ChannelDetails.Name }}')`

tplConnection = `
{{- ""}}'{{ ConnectionColor .Connection.Name }}' (connection
{{- ""}} client='{{ .Connection.ClientProperties.Product}}',
{{- ""}} host='{{ .Connection.Host }}:{{ .Connection.Port }}',
{{- ""}} peer='{{ .Connection.PeerHost }}:{{ .Connection.PeerPort }}')`

tplExchange = `
{{- ExchangeColor .PrintName }} (exchange, type '{{ .Exchange.Type }}'
{{- if and .Config.ShowStats .Exchange.MessageStats }}, in=(
{{- .Exchange.MessageStats.PublishIn }}, {{printf "%.1f" .Exchange.MessageStats.PublishInDetails.Rate}}/s) msg, out=(
{{- .Exchange.MessageStats.PublishOut }}, {{printf "%.1f" .Exchange.MessageStats.PublishOutDetails.Rate}}/s) msg
{{- end }}, {{ .ExchangeFlags }})`

tplQueue = `
{{- QueueColor .Binding.Destination }} (queue,
{{- with .Binding.RoutingKey }} key='{{ KeyColor .}}',{{end}}
{{- with .Binding.Arguments}} args='{{ KeyColor .}}',{{end}}
{{- if .Config.ShowStats }}
{{- .Queue.Consumers }} cons, (
{{- .Queue.Messages }}, {{printf "%.1f" .Queue.MessagesDetails.Rate}}/s) msg, (
{{- .Queue.MessagesReady }}, {{printf "%.1f" .Queue.MessagesReadyDetails.Rate}}/s) msg ready,
{{- end }}
{{- if .Queue.IdleSince}}{{- " idle since "}}{{ .Queue.IdleSince}}{{else}}{{ " running" }}{{end}}
{{- ""}}, {{ .QueueFlags}})`
)

// BrokerInfoPrinterConfig controls bevaviour auf PrintBrokerInfo
type BrokerInfoPrinterConfig struct {
ShowDefaultExchange bool
ShowConsumers bool
ShowStats bool
NoColor bool
}

// BrokerInfoPrinter prints nicely treeish infos desribing a brokers
// topology
type BrokerInfoPrinter struct {
//brokerInfo BrokerInfo
config PrintBrokerInfoConfig
config BrokerInfoPrinterConfig
colorizer ColorPrinter
}

// NewBrokerInfoPrinter constructs a new object to print a broker info
func NewBrokerInfoPrinter(config PrintBrokerInfoConfig) *BrokerInfoPrinter {
func NewBrokerInfoPrinter(config BrokerInfoPrinterConfig) *BrokerInfoPrinter {
s := BrokerInfoPrinter{
config: config,
colorizer: NewColorPrinter(config.NoColor),
}
return &s
}

// PrintBrokerInfoConfig controls bevaviour auf PrintBrokerInfo
type PrintBrokerInfoConfig struct {
ShowDefaultExchange bool
ShowConsumers bool
ShowStats bool
NoColor bool
}

// findQueueByName searches in the queues array for a queue with the given
// name and vhost. RabbitQueue element is returned on succes, otherwise nil.
func findQueueByName(queues []rabtap.RabbitQueue,
Expand All @@ -63,6 +99,59 @@ func findExchangeByName(exchanges []rabtap.RabbitExchange,
return nil
}

// currently not used.
// func findChannelByName(channels []rabtap.RabbitChannel,
// vhost, channelName string) *rabtap.RabbitChannel {
// for _, channel := range channels {
// if channel.Name == channelName && channel.Vhost == vhost {
// return &channel
// }
// }
// return nil
// }

func findConnectionByName(conns []rabtap.RabbitConnection,
vhost, connName string) *rabtap.RabbitConnection {
for _, conn := range conns {
if conn.Name == connName && conn.Vhost == vhost {
return &conn
}
}
return nil
}

func findConsumerByQueue(consumers []rabtap.RabbitConsumer,
vhost, queueName string) *rabtap.RabbitConsumer {
for _, consumer := range consumers {
if consumer.Queue.Vhost == vhost &&
consumer.Queue.Name == queueName {
return &consumer
}
}
return nil
}

func getBindingsForExchange(exchange *rabtap.RabbitExchange, bindings []rabtap.RabbitBinding) []rabtap.RabbitBinding {
var result []rabtap.RabbitBinding
for _, binding := range bindings {
if binding.Source == exchange.Name &&
binding.Vhost == exchange.Vhost {
result = append(result, binding)
}
}
return result
}

func filterStringList(flags []bool, list []string) []string {
result := []string{}
for i, s := range list {
if flags[i] {
result = append(result, s)
}
}
return result
}

// resolveTemplate resolves a template for use in the broker info printer,
// with support for colored output. name is just an informational name
// passed to the template ctor. tpl is the actual template and args
Expand All @@ -80,80 +169,58 @@ func (s BrokerInfoPrinter) resolveTemplate(name string, tpl string, args interfa
}

func (s BrokerInfoPrinter) renderQueueFlagsAsString(queue *rabtap.RabbitQueue) string {
var flags []string
if queue.Durable {
flags = append(flags, "D")
}
if queue.AutoDelete {
flags = append(flags, "AD")
}
if queue.Exclusive {
flags = append(flags, "EX")
}
return "[" + strings.Join(flags, "|") + "]"
flags := []bool{queue.Durable, queue.AutoDelete, queue.Exclusive}
names := []string{"D", "AD", "EX"}
return "[" + strings.Join(filterStringList(flags, names), "|") + "]"
}

func (s BrokerInfoPrinter) renderExchangeFlagsAsString(exchange *rabtap.RabbitExchange) string {
var flags []string
if exchange.Durable {
flags = append(flags, "D")
}
if exchange.AutoDelete {
flags = append(flags, "AD")
}
if exchange.Internal {
flags = append(flags, "I")
}
return "[" + strings.Join(flags, "|") + "]"
flags := []bool{exchange.Durable, exchange.AutoDelete, exchange.Internal}
names := []string{"D", "AD", "I"}
return "[" + strings.Join(filterStringList(flags, names), "|") + "]"
}

func (s BrokerInfoPrinter) renderConsumerElementAsString(consumer *rabtap.RabbitConsumer) string {
return fmt.Sprintf("%s (consumer, %s)",
s.colorizer.Consumer(consumer.ConsumerTag),
consumer.ChannelDetails.Name)
type ConsumerInfo struct {
Config BrokerInfoPrinterConfig
Consumer *rabtap.RabbitConsumer
}
args := ConsumerInfo{s.config, consumer}
return s.resolveTemplate("consumer-tpl", tplConsumer, args)
}

func (s BrokerInfoPrinter) renderConnectionElementAsString(conn *rabtap.RabbitConnection) string {
type ConnectionInfo struct {
Config BrokerInfoPrinterConfig
Connection *rabtap.RabbitConnection
}
args := ConnectionInfo{s.config, conn}
return s.resolveTemplate("connnection-tpl", tplConnection, args)
}

func (s BrokerInfoPrinter) renderQueueElementAsString(queue *rabtap.RabbitQueue, binding *rabtap.RabbitBinding) string {

queueFlags := s.renderQueueFlagsAsString(queue)
type QueueInfo struct {
Config PrintBrokerInfoConfig
Config BrokerInfoPrinterConfig
Binding *rabtap.RabbitBinding
Queue *rabtap.RabbitQueue
QueueFlags string
}
args := QueueInfo{s.config, binding, queue, queueFlags}

const tpl = `
{{- QueueColor .Binding.Destination }} (queue,
{{- with .Binding.RoutingKey }} key={{ KeyColor .}},{{end}}
{{- with .Binding.Arguments}} args={{ KeyColor .}},{{end}}
{{- if .Config.ShowStats }}
{{- .Queue.Consumers }} cons, (
{{- .Queue.Messages }}, {{printf "%.1f" .Queue.MessagesDetails.Rate}}/s) msg, (
{{- .Queue.MessagesReady }}, {{printf "%.1f" .Queue.MessagesReadyDetails.Rate}}/s) msg ready,
{{- end }}
{{- if .Queue.IdleSince}}{{- " idle since "}}{{ .Queue.IdleSince}}{{else}}{{ " running" }}{{end}}
{{- ""}}, {{ .QueueFlags}})`

return s.resolveTemplate("queue-tpl", tpl, args)
return s.resolveTemplate("queue-tpl", tplQueue, args)
}

func (s BrokerInfoPrinter) renderRootNodeAsString(rabbitURL url.URL, overview rabtap.RabbitOverview) string {

type RootInfo struct {
Config PrintBrokerInfoConfig
Config BrokerInfoPrinterConfig
URL url.URL
Overview rabtap.RabbitOverview
}
args := RootInfo{s.config, rabbitURL, overview}

const tpl = `{{ printf "%s://%s%s" .URL.Scheme .URL.Host .URL.Path | URLColor }}
{{- if .Overview }} (broker ver={{ .Overview.RabbitmqVersion }},
{{- "" }} mgmt ver={{ .Overview.ManagementVersion }},
{{- "" }} cluster={{ .Overview.ClusterName }}{{end}})`

return s.resolveTemplate("rootnode", tpl, args)
return s.resolveTemplate("rootnode", tplRootNode, args)
}

func (s BrokerInfoPrinter) renderExchangeElementAsString(exchange *rabtap.RabbitExchange) string {
Expand All @@ -163,43 +230,36 @@ func (s BrokerInfoPrinter) renderExchangeElementAsString(exchange *rabtap.Rabbit
}

type ExchangeInfo struct {
Config PrintBrokerInfoConfig
Config BrokerInfoPrinterConfig
Exchange *rabtap.RabbitExchange
ExchangeFlags string
PrintName string
}
exchangeFlags := s.renderExchangeFlagsAsString(exchange)
args := ExchangeInfo{s.config, exchange, exchangeFlags, printName}

const tpl = `{{ ExchangeColor .PrintName }} (exchange, type '{{ .Exchange.Type }}'
{{- if and .Config.ShowStats .Exchange.MessageStats }}, in=(
{{- .Exchange.MessageStats.PublishIn }}, {{printf "%.1f" .Exchange.MessageStats.PublishInDetails.Rate}}/s) msg, out=(
{{- .Exchange.MessageStats.PublishOut }}, {{printf "%.1f" .Exchange.MessageStats.PublishOutDetails.Rate}}/s) msg
{{- end }}, {{ .ExchangeFlags }})`

return s.resolveTemplate("exchange-tpl", tpl, args)
return s.resolveTemplate("exchange-tpl", tplExchange, args)
}

func (s BrokerInfoPrinter) addConsumerNode(node *TreeNode, consumers []rabtap.RabbitConsumer,
exchange *rabtap.RabbitExchange, queue *rabtap.RabbitQueue) {
// TODO remove exchange, use queue.Vhost
func (s BrokerInfoPrinter) addConsumerNodes(node *TreeNode,
queue *rabtap.RabbitQueue, brokerInfo BrokerInfo) {

for _, consumer := range consumers {
if consumer.Queue.Vhost == exchange.Vhost &&
vhost := queue.Vhost
for _, consumer := range brokerInfo.Consumers {
if consumer.Queue.Vhost == vhost &&
consumer.Queue.Name == queue.Name {
node.AddChild(s.renderConsumerElementAsString(&consumer))
consumerNode := node.AddChild(s.renderConsumerElementAsString(&consumer))
s.addConnectionNode(consumerNode, vhost, consumer.ChannelDetails.ConnectionName, brokerInfo)
}
}
}

func getBindingsForExchange(exchange *rabtap.RabbitExchange, bindings []rabtap.RabbitBinding) []rabtap.RabbitBinding {
var result []rabtap.RabbitBinding
for _, binding := range bindings {
if binding.Source == exchange.Name &&
binding.Vhost == exchange.Vhost {
result = append(result, binding)
}
func (s BrokerInfoPrinter) addConnectionNode(node *TreeNode,
vhost string, connName string, brokerInfo BrokerInfo) {
connInfo := findConnectionByName(brokerInfo.Connections, vhost, connName)
if connInfo != nil {
node.AddChild(s.renderConnectionElementAsString(connInfo))
}
return result
}

func (s BrokerInfoPrinter) addQueue(node *TreeNode, binding *rabtap.RabbitBinding, exchange *rabtap.RabbitExchange, brokerInfo BrokerInfo) *TreeNode {
Expand All @@ -208,16 +268,15 @@ func (s BrokerInfoPrinter) addQueue(node *TreeNode, binding *rabtap.RabbitBindin
binding.Vhost,
binding.Destination)
if queue == nil {
// we test for nil because (at least in theory) a queue
// can disappear since we are making various non-transactional
// API calls
// we test for nil because (at least in theory) a queue can disappear
// since we are making various non-transactional API calls
queue = &rabtap.RabbitQueue{Name: binding.Destination}
}
queueText := s.renderQueueElementAsString(queue, binding)
queueNode := node.AddChild(queueText)
// add consumers of queue

if s.config.ShowConsumers {
s.addConsumerNode(queueNode, brokerInfo.Consumers, exchange, queue)
s.addConsumerNodes(queueNode, queue, brokerInfo)
}
return queueNode
}
Expand Down Expand Up @@ -266,10 +325,11 @@ func (s BrokerInfoPrinter) getExchangesToDisplay(

// Print render given brokerInfo into a tree-view:
// RabbitMQ-Host
// +--VHost
// +--VHosts
// +--Exchange
// +--Queue bound to exchange
// +--Consumer
// +--Consumers (optional)
//
func (s BrokerInfoPrinter) Print(brokerInfo BrokerInfo,
rootNode string, out io.Writer) error {

Expand Down

0 comments on commit 5275430

Please sign in to comment.