func (this *Lags) printConsumersLag(zkcluster *zk.ZkCluster) { // sort by group name consumersByGroup := zkcluster.ConsumersByGroup(this.groupPattern) sortedGroups := make([]string, 0, len(consumersByGroup)) for group, _ := range consumersByGroup { sortedGroups = append(sortedGroups, group) } sort.Strings(sortedGroups) for _, group := range sortedGroups { lines := make([]string, 0, 100) sortedTopicAndPartitionIds := make([]string, 0) consumers := make(map[string]zk.ConsumerMeta) for _, t := range consumersByGroup[group] { key := fmt.Sprintf("%s:%s", t.Topic, t.PartitionId) sortedTopicAndPartitionIds = append(sortedTopicAndPartitionIds, key) consumers[key] = t } sort.Strings(sortedTopicAndPartitionIds) for _, topicAndPartitionId := range sortedTopicAndPartitionIds { consumer := consumers[topicAndPartitionId] if !patternMatched(consumer.Topic, this.topicPattern) { continue } var ( lagOutput string symbol string ) if consumer.Lag > int64(this.lagThreshold) { lagOutput = color.Red("%15s", gofmt.Comma(consumer.Lag)) if consumer.Online { symbol = color.Yellow("⚠︎︎") } else { symbol = color.Yellow("◎") } } else { lagOutput = color.Blue("%15s", gofmt.Comma(consumer.Lag)) if consumer.Online { symbol = color.Green("◉") } else { symbol = color.Yellow("◎") } } if consumer.Online { if this.problematicMode && consumer.Lag <= int64(this.lagThreshold) { continue } var ( host string uptime string ) if consumer.ConsumerZnode == nil { host = "unrecognized" uptime = "-" } else { host = color.Green("%s", consumer.ConsumerZnode.Host()) if time.Since(consumer.ConsumerZnode.Uptime()) < time.Hour { uptime = color.Magenta(gofmt.PrettySince(consumer.ConsumerZnode.Uptime())) } else { uptime = gofmt.PrettySince(consumer.ConsumerZnode.Uptime()) } } lines = append(lines, fmt.Sprintf("\t%s %35s/%-2s %12s -> %-15s %s %-10s %s %s", symbol, consumer.Topic, consumer.PartitionId, gofmt.Comma(consumer.ProducerOffset), gofmt.Comma(consumer.ConsumerOffset), lagOutput, gofmt.PrettySince(consumer.Mtime.Time()), host, uptime)) } else if !this.onlineOnly { lines = append(lines, fmt.Sprintf("\t%s %35s/%-2s %12s -> %-12s %s %s", symbol, consumer.Topic, consumer.PartitionId, gofmt.Comma(consumer.ProducerOffset), gofmt.Comma(consumer.ConsumerOffset), lagOutput, gofmt.PrettySince(consumer.Mtime.Time()))) } } if len(lines) > 0 { this.Ui.Output(strings.Repeat(" ", 4) + group) for _, l := range lines { this.Ui.Output(l) } } } }
func (this *Lags) printConsumersLagTable(zkcluster *zk.ZkCluster) { lines := make([]string, 0) header := "ConsumerGroup|Topic/Partition|Produced|Consumed|Lag|Committed|Uptime" lines = append(lines, header) // sort by group name consumersByGroup := zkcluster.ConsumersByGroup(this.groupPattern) sortedGroups := make([]string, 0, len(consumersByGroup)) for group, _ := range consumersByGroup { sortedGroups = append(sortedGroups, group) } sort.Strings(sortedGroups) for _, group := range sortedGroups { if !patternMatched(group, this.groupPattern) { continue } sortedTopicAndPartitionIds := make([]string, 0, len(consumersByGroup[group])) consumers := make(map[string]zk.ConsumerMeta) for _, t := range consumersByGroup[group] { key := fmt.Sprintf("%s:%s", t.Topic, t.PartitionId) sortedTopicAndPartitionIds = append(sortedTopicAndPartitionIds, key) consumers[key] = t } sort.Strings(sortedTopicAndPartitionIds) for _, topicAndPartitionId := range sortedTopicAndPartitionIds { consumer := consumers[topicAndPartitionId] if !patternMatched(consumer.Topic, this.topicPattern) { continue } if !consumer.Online { continue } if this.problematicMode && consumer.Lag <= int64(this.lagThreshold) { continue } if consumer.ConsumerZnode == nil { this.Ui.Warn(fmt.Sprintf("%+v has no znode", consumer)) continue } lines = append(lines, fmt.Sprintf("%s|%s/%s|%s|%s|%s|%s|%s", group, consumer.Topic, consumer.PartitionId, gofmt.Comma(consumer.ProducerOffset), gofmt.Comma(consumer.ConsumerOffset), gofmt.Comma(consumer.Lag), gofmt.PrettySince(consumer.Mtime.Time()), gofmt.PrettySince(consumer.ConsumerZnode.Uptime()))) } } if len(lines) > 1 { this.Ui.Info(fmt.Sprintf("%s ▾", zkcluster.Name())) this.Ui.Output(columnize.SimpleFormat(lines)) } }