Add gathering of RabbitMQ federation link metrics (#6283)
This commit is contained in:
parent
1761e25c96
commit
8b3a8d1113
|
@ -48,6 +48,13 @@ For additional details reference the [RabbitMQ Management HTTP Stats][management
|
||||||
## specified, metrics for all exchanges are gathered.
|
## specified, metrics for all exchanges are gathered.
|
||||||
# exchanges = ["telegraf"]
|
# exchanges = ["telegraf"]
|
||||||
|
|
||||||
|
## A list of federation upstreams to gather as the rabbitmq_federation measurement.
|
||||||
|
## If not specified, metrics for all federation upstreams are gathered.
|
||||||
|
## Federation link metrics will only be gathered for queues and exchanges
|
||||||
|
## whose non-federation metrics will be collected (e.g a queue excluded
|
||||||
|
## by the 'queue_name_exclude' option will also be excluded from federation).
|
||||||
|
# federation_upstreams = ["dataCentre2"]
|
||||||
|
|
||||||
## Queues to include and exclude. Globs accepted.
|
## Queues to include and exclude. Globs accepted.
|
||||||
## Note that an empty array for both will include all queues
|
## Note that an empty array for both will include all queues
|
||||||
# queue_name_include = []
|
# queue_name_include = []
|
||||||
|
@ -158,6 +165,16 @@ For additional details reference the [RabbitMQ Management HTTP Stats][management
|
||||||
- messages_publish_out (int, count)
|
- messages_publish_out (int, count)
|
||||||
- messages_publish_out_rate (int, messages per second)
|
- messages_publish_out_rate (int, messages per second)
|
||||||
|
|
||||||
|
- rabbitmq_federation
|
||||||
|
- acks_uncommitted (int, count)
|
||||||
|
- consumers (int, count)
|
||||||
|
- messages_unacknowledged (int, count)
|
||||||
|
- messages_uncommitted (int, count)
|
||||||
|
- messages_unconfirmed (int, count)
|
||||||
|
- messages_confirm (int, count)
|
||||||
|
- messages_publish (int, count)
|
||||||
|
- messages_return_unroutable (int, count)
|
||||||
|
|
||||||
### Tags:
|
### Tags:
|
||||||
|
|
||||||
- All measurements have the following tags:
|
- All measurements have the following tags:
|
||||||
|
@ -187,6 +204,14 @@ For additional details reference the [RabbitMQ Management HTTP Stats][management
|
||||||
- durable
|
- durable
|
||||||
- auto_delete
|
- auto_delete
|
||||||
|
|
||||||
|
- rabbitmq_federation
|
||||||
|
- url
|
||||||
|
- vhost
|
||||||
|
- type
|
||||||
|
- upstream
|
||||||
|
- local_entity
|
||||||
|
- upstream_entity
|
||||||
|
|
||||||
### Sample Queries:
|
### Sample Queries:
|
||||||
|
|
||||||
Message rates for the entire node can be calculated from total message counts. For instance, to get the rate of messages published per minute, use this query:
|
Message rates for the entire node can be calculated from total message counts. For instance, to get the rate of messages published per minute, use this query:
|
||||||
|
|
|
@ -49,12 +49,15 @@ type RabbitMQ struct {
|
||||||
|
|
||||||
QueueInclude []string `toml:"queue_name_include"`
|
QueueInclude []string `toml:"queue_name_include"`
|
||||||
QueueExclude []string `toml:"queue_name_exclude"`
|
QueueExclude []string `toml:"queue_name_exclude"`
|
||||||
|
FederationUpstreamInclude []string `toml:"federation_upstream_include"`
|
||||||
|
FederationUpstreamExclude []string `toml:"federation_upstream_exclude"`
|
||||||
|
|
||||||
Client *http.Client
|
Client *http.Client
|
||||||
|
|
||||||
filterCreated bool
|
filterCreated bool
|
||||||
excludeEveryQueue bool
|
excludeEveryQueue bool
|
||||||
queueFilter filter.Filter
|
queueFilter filter.Filter
|
||||||
|
upstreamFilter filter.Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
// OverviewResponse ...
|
// OverviewResponse ...
|
||||||
|
@ -178,6 +181,38 @@ type Exchange struct {
|
||||||
AutoDelete bool `json:"auto_delete"`
|
AutoDelete bool `json:"auto_delete"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FederationLinkChannelMessageStats ...
|
||||||
|
type FederationLinkChannelMessageStats struct {
|
||||||
|
Confirm int64 `json:"confirm"`
|
||||||
|
ConfirmDetails Details `json:"confirm_details"`
|
||||||
|
Publish int64 `json:"publish"`
|
||||||
|
PublishDetails Details `json:"publish_details"`
|
||||||
|
ReturnUnroutable int64 `json:"return_unroutable"`
|
||||||
|
ReturnUnroutableDetails Details `json:"return_unroutable_details"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FederationLinkChannel ...
|
||||||
|
type FederationLinkChannel struct {
|
||||||
|
AcksUncommitted int64 `json:"acks_uncommitted"`
|
||||||
|
ConsumerCount int64 `json:"consumer_count"`
|
||||||
|
MessagesUnacknowledged int64 `json:"messages_unacknowledged"`
|
||||||
|
MessagesUncommitted int64 `json:"messages_uncommitted"`
|
||||||
|
MessagesUnconfirmed int64 `json:"messages_unconfirmed"`
|
||||||
|
MessageStats FederationLinkChannelMessageStats `json:"message_stats"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FederationLink ...
|
||||||
|
type FederationLink struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Queue string `json:"queue"`
|
||||||
|
UpstreamQueue string `json:"upstream_queue"`
|
||||||
|
Exchange string `json:"exchange"`
|
||||||
|
UpstreamExchange string `json:"upstream_exchange"`
|
||||||
|
Vhost string `json:"vhost"`
|
||||||
|
Upstream string `json:"upstream"`
|
||||||
|
LocalChannel FederationLinkChannel `json:"local_channel"`
|
||||||
|
}
|
||||||
|
|
||||||
type HealthCheck struct {
|
type HealthCheck struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
@ -214,7 +249,7 @@ type Memory struct {
|
||||||
// gatherFunc ...
|
// gatherFunc ...
|
||||||
type gatherFunc func(r *RabbitMQ, acc telegraf.Accumulator)
|
type gatherFunc func(r *RabbitMQ, acc telegraf.Accumulator)
|
||||||
|
|
||||||
var gatherFunctions = []gatherFunc{gatherOverview, gatherNodes, gatherQueues, gatherExchanges}
|
var gatherFunctions = []gatherFunc{gatherOverview, gatherNodes, gatherQueues, gatherExchanges, gatherFederationLinks}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
## Management Plugin url. (default: http://localhost:15672)
|
## Management Plugin url. (default: http://localhost:15672)
|
||||||
|
@ -258,6 +293,15 @@ var sampleConfig = `
|
||||||
## Note that an empty array for both will include all queues
|
## Note that an empty array for both will include all queues
|
||||||
queue_name_include = []
|
queue_name_include = []
|
||||||
queue_name_exclude = []
|
queue_name_exclude = []
|
||||||
|
|
||||||
|
## Federation upstreams include and exclude when gathering the rabbitmq_federation measurement.
|
||||||
|
## If neither are specified, metrics for all federation upstreams are gathered.
|
||||||
|
## Federation link metrics will only be gathered for queues and exchanges
|
||||||
|
## whose non-federation metrics will be collected (e.g a queue excluded
|
||||||
|
## by the 'queue_name_exclude' option will also be excluded from federation).
|
||||||
|
## Globs accepted.
|
||||||
|
# federation_upstream_include = ["dataCentre-*"]
|
||||||
|
# federation_upstream_exclude = []
|
||||||
`
|
`
|
||||||
|
|
||||||
func boolToInt(b bool) int64 {
|
func boolToInt(b bool) int64 {
|
||||||
|
@ -294,12 +338,16 @@ func (r *RabbitMQ) Gather(acc telegraf.Accumulator) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create queue filter if not already created
|
// Create gather filters if not already created
|
||||||
if !r.filterCreated {
|
if !r.filterCreated {
|
||||||
err := r.createQueueFilter()
|
err := r.createQueueFilter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = r.createUpstreamFilter()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
r.filterCreated = true
|
r.filterCreated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +646,7 @@ func gatherExchanges(r *RabbitMQ, acc telegraf.Accumulator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, exchange := range exchanges {
|
for _, exchange := range exchanges {
|
||||||
if !r.shouldGatherExchange(exchange) {
|
if !r.shouldGatherExchange(exchange.Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tags := map[string]string{
|
tags := map[string]string{
|
||||||
|
@ -624,6 +672,52 @@ func gatherExchanges(r *RabbitMQ, acc telegraf.Accumulator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gatherFederationLinks(r *RabbitMQ, acc telegraf.Accumulator) {
|
||||||
|
// Gather information about federation links
|
||||||
|
federationLinks := make([]FederationLink, 0)
|
||||||
|
err := r.requestJSON("/api/federation-links", &federationLinks)
|
||||||
|
if err != nil {
|
||||||
|
acc.AddError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, link := range federationLinks {
|
||||||
|
if !r.shouldGatherFederationLink(link) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tags := map[string]string{
|
||||||
|
"url": r.URL,
|
||||||
|
"type": link.Type,
|
||||||
|
"vhost": link.Vhost,
|
||||||
|
"upstream": link.Upstream,
|
||||||
|
}
|
||||||
|
|
||||||
|
if link.Type == "exchange" {
|
||||||
|
tags["exchange"] = link.Exchange
|
||||||
|
tags["upstream_exchange"] = link.UpstreamExchange
|
||||||
|
} else {
|
||||||
|
tags["queue"] = link.Queue
|
||||||
|
tags["upstream_queue"] = link.UpstreamQueue
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields(
|
||||||
|
"rabbitmq_federation",
|
||||||
|
map[string]interface{}{
|
||||||
|
"acks_uncommitted": link.LocalChannel.AcksUncommitted,
|
||||||
|
"consumers": link.LocalChannel.ConsumerCount,
|
||||||
|
"messages_unacknowledged": link.LocalChannel.MessagesUnacknowledged,
|
||||||
|
"messages_uncommitted": link.LocalChannel.MessagesUncommitted,
|
||||||
|
"messages_unconfirmed": link.LocalChannel.MessagesUnconfirmed,
|
||||||
|
"messages_confirm": link.LocalChannel.MessageStats.Confirm,
|
||||||
|
"messages_publish": link.LocalChannel.MessageStats.Publish,
|
||||||
|
"messages_return_unroutable": link.LocalChannel.MessageStats.ReturnUnroutable,
|
||||||
|
},
|
||||||
|
tags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RabbitMQ) shouldGatherNode(node Node) bool {
|
func (r *RabbitMQ) shouldGatherNode(node Node) bool {
|
||||||
if len(r.Nodes) == 0 {
|
if len(r.Nodes) == 0 {
|
||||||
return true
|
return true
|
||||||
|
@ -659,13 +753,23 @@ func (r *RabbitMQ) createQueueFilter() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RabbitMQ) shouldGatherExchange(exchange Exchange) bool {
|
func (r *RabbitMQ) createUpstreamFilter() error {
|
||||||
|
upstreamFilter, err := filter.NewIncludeExcludeFilter(r.FederationUpstreamInclude, r.FederationUpstreamExclude)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
r.upstreamFilter = upstreamFilter
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RabbitMQ) shouldGatherExchange(exchangeName string) bool {
|
||||||
if len(r.Exchanges) == 0 {
|
if len(r.Exchanges) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range r.Exchanges {
|
for _, name := range r.Exchanges {
|
||||||
if name == exchange.Name {
|
if name == exchangeName {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,6 +777,21 @@ func (r *RabbitMQ) shouldGatherExchange(exchange Exchange) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *RabbitMQ) shouldGatherFederationLink(link FederationLink) bool {
|
||||||
|
if !r.upstreamFilter.Match(link.Upstream) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch link.Type {
|
||||||
|
case "exchange":
|
||||||
|
return r.shouldGatherExchange(link.Exchange)
|
||||||
|
case "queue":
|
||||||
|
return r.queueFilter.Match(link.Queue)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
inputs.Add("rabbitmq", func() telegraf.Input {
|
inputs.Add("rabbitmq", func() telegraf.Input {
|
||||||
return &RabbitMQ{
|
return &RabbitMQ{
|
||||||
|
|
|
@ -28,6 +28,8 @@ func TestRabbitMQGeneratesMetrics(t *testing.T) {
|
||||||
jsonFilePath = "testdata/exchanges.json"
|
jsonFilePath = "testdata/exchanges.json"
|
||||||
case "/api/healthchecks/node/rabbit@vagrant-ubuntu-trusty-64":
|
case "/api/healthchecks/node/rabbit@vagrant-ubuntu-trusty-64":
|
||||||
jsonFilePath = "testdata/healthchecks.json"
|
jsonFilePath = "testdata/healthchecks.json"
|
||||||
|
case "/api/federation-links":
|
||||||
|
jsonFilePath = "testdata/federation-links.json"
|
||||||
case "/api/nodes/rabbit@vagrant-ubuntu-trusty-64/memory":
|
case "/api/nodes/rabbit@vagrant-ubuntu-trusty-64/memory":
|
||||||
jsonFilePath = "testdata/memory.json"
|
jsonFilePath = "testdata/memory.json"
|
||||||
default:
|
default:
|
||||||
|
@ -162,6 +164,18 @@ func TestRabbitMQGeneratesMetrics(t *testing.T) {
|
||||||
"messages_publish_out_rate": 5.1,
|
"messages_publish_out_rate": 5.1,
|
||||||
}
|
}
|
||||||
compareMetrics(t, exchangeMetrics, acc, "rabbitmq_exchange")
|
compareMetrics(t, exchangeMetrics, acc, "rabbitmq_exchange")
|
||||||
|
|
||||||
|
federationLinkMetrics := map[string]interface{}{
|
||||||
|
"acks_uncommitted": 1,
|
||||||
|
"consumers": 2,
|
||||||
|
"messages_unacknowledged": 3,
|
||||||
|
"messages_uncommitted": 4,
|
||||||
|
"messages_unconfirmed": 5,
|
||||||
|
"messages_confirm": 67,
|
||||||
|
"messages_publish": 890,
|
||||||
|
"messages_return_unroutable": 1,
|
||||||
|
}
|
||||||
|
compareMetrics(t, federationLinkMetrics, acc, "rabbitmq_federation")
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareMetrics(t *testing.T, expectedMetrics map[string]interface{},
|
func compareMetrics(t *testing.T, expectedMetrics map[string]interface{},
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "rabbit@rmqlocal",
|
||||||
|
"queue": "exampleLocalQueue",
|
||||||
|
"upstream_queue": "exampleUpstreamQueue",
|
||||||
|
"type": "queue",
|
||||||
|
"vhost": "/",
|
||||||
|
"upstream": "ExampleFederationUpstream",
|
||||||
|
"id": "8ba5218f",
|
||||||
|
"status": "running",
|
||||||
|
"local_connection": "<rabbit@somehost>",
|
||||||
|
"uri": "amqp://appsv03",
|
||||||
|
"timestamp": "2019-08-19 15:34:15",
|
||||||
|
"local_channel": {
|
||||||
|
"acks_uncommitted": 1,
|
||||||
|
"confirm": true,
|
||||||
|
"connection_details": {
|
||||||
|
"name": "<rabbit@somehost>",
|
||||||
|
"peer_host": "undefined",
|
||||||
|
"peer_port": "undefined"
|
||||||
|
},
|
||||||
|
"consumer_count": 2,
|
||||||
|
"garbage_collection": {
|
||||||
|
"fullsweep_after": 65535,
|
||||||
|
"max_heap_size": 0,
|
||||||
|
"min_bin_vheap_size": 46422,
|
||||||
|
"min_heap_size": 233,
|
||||||
|
"minor_gcs": 203
|
||||||
|
},
|
||||||
|
"global_prefetch_count": 0,
|
||||||
|
"message_stats": {
|
||||||
|
"confirm": 67,
|
||||||
|
"confirm_details": {
|
||||||
|
"rate": 2
|
||||||
|
},
|
||||||
|
"publish": 890,
|
||||||
|
"publish_details": {
|
||||||
|
"rate": 2
|
||||||
|
},
|
||||||
|
"return_unroutable": 1,
|
||||||
|
"return_unroutable_details": {
|
||||||
|
"rate": 0.1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"messages_unacknowledged": 3,
|
||||||
|
"messages_uncommitted": 4,
|
||||||
|
"messages_unconfirmed": 5,
|
||||||
|
"name": "<rabbit@somehost>",
|
||||||
|
"node": "rabbit@rmqlocal",
|
||||||
|
"number": 1,
|
||||||
|
"prefetch_count": 0,
|
||||||
|
"reductions": 1926653,
|
||||||
|
"reductions_details": {
|
||||||
|
"rate": 1068
|
||||||
|
},
|
||||||
|
"state": "running",
|
||||||
|
"transactional": false,
|
||||||
|
"user": "none",
|
||||||
|
"user_who_performed_action": "none",
|
||||||
|
"vhost": "sorandomsorandom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue