示例#1
0
func (this *TopBroker) drawDashboard() {
	termui.Init()
	width := termui.TermWidth()
	height := termui.TermHeight()
	termui.Close()
	maxWidth := width - 23

	var totalMaxQps, totalMaxBrokerQps float64
	for {
		time.Sleep(this.interval)

		this.startAll()
		this.collectAll()

		datas, maxQps, totalQps := this.showAndResetCounters()
		if maxQps < 1 {
			// draw empty lines
			for _, data := range datas {
				this.Ui.Output(fmt.Sprintf("%20s", data.host))
			}

			continue
		}

		if maxQps > totalMaxBrokerQps {
			totalMaxBrokerQps = maxQps
		}
		if totalQps > totalMaxQps {
			totalMaxQps = totalQps
		}

		refreshScreen()

		for idx, data := range datas {
			if idx >= height-2 {
				break
			}

			if data.qps < 0 {
				panic("negative qps")
			}

			this.renderQpsRow(data.host, data.qps, maxQps, maxWidth)
		}

		this.Ui.Output(fmt.Sprintf("%20s brokers:%d total:%s cum max[broker:%.1f total:%.1f]",
			"-SUMMARY-",
			len(datas), color.Green("%.1f", totalQps), totalMaxBrokerQps, totalMaxQps))
	}

}
示例#2
0
文件: top.go 项目: funkygao/gafka
func (this *Top) Run(args []string) (exitCode int) {
	cmdFlags := flag.NewFlagSet("top", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&this.zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&this.topicPattern, "t", "", "")
	cmdFlags.DurationVar(&this.topInterval, "i", time.Second*5, "refresh interval")
	cmdFlags.StringVar(&this.clusterPattern, "c", "", "")
	cmdFlags.IntVar(&this.limit, "n", 0, "")
	cmdFlags.BoolVar(&this.skipIpPrefix, "shortip", true, "")
	cmdFlags.StringVar(&this.who, "who", "producer", "")
	cmdFlags.BoolVar(&this.dashboardGraph, "d", false, "")
	cmdFlags.DurationVar(&this.duration, "for", time.Hour, "")
	cmdFlags.BoolVar(&this.longFmt, "l", false, "")
	cmdFlags.BoolVar(&this.batchMode, "b", false, "")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if this.limit == 0 {
		termui.Init()
		this.limit = termui.TermHeight() - 6 // 5=header+footer+cursor line
		termui.Close()
	}

	if this.dashboardGraph {
		if this.topInterval.Seconds() < 20 {
			this.topInterval = 20 * time.Second
		}
		this.who = "both"
		go this.clusterOffsetSummary()
	}

	if this.who == "c" || this.who == "consumer" {
		if this.topInterval.Seconds() < 20 {
			this.topInterval = 20 * time.Second // consumer groups only refresh offset per minute
		}

	}

	this.brokers = make(map[string][]string)
	this.counters = make(map[string]float64)
	this.lastCounters = make(map[string]float64)
	this.partitions = make(map[string]int)
	this.consumerCounters = make(map[string]float64)
	this.totalMps = make([]float64, 0, 1000)
	this.totalConsumerMps = make([]float64, 0, 1000)

	zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone)))
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		if !patternMatched(zkcluster.Name(), this.clusterPattern) {
			return
		}

		switch this.who {
		case "p", "producer":
			go this.clusterTopProducers(zkcluster)

		case "c", "consumer":
			go this.clusterTopConsumers(zkcluster)

		case "both":
			go this.clusterTopConsumers(zkcluster)
			go this.clusterTopProducers(zkcluster)

		default:
			this.Ui.Error(fmt.Sprintf("unknown type: %s", this.who))
		}
	})

	if this.dashboardGraph {
		this.drawDashboard()
		return
	}

	ticker := time.NewTicker(this.topInterval)
	defer ticker.Stop()
	keyboardPressed := make(chan struct{})
	go func() {
		var b []byte = make([]byte, 1)
		for {
			os.Stdin.Read(b)
			keyboardPressed <- struct{}{}
		}
	}()

	startAt := time.Now()
	for {
		select {
		case <-keyboardPressed:
		case <-ticker.C:
		}

		if time.Since(startAt) >= this.duration {
			break
		}

		if this.batchMode {
			this.Ui.Output(bjtime.TimeToString(bjtime.NowBj()))
		} else {
			refreshScreen()
		}

		// header
		if this.longFmt {
			this.Ui.Output(fmt.Sprintf("%-9s %15s %-30s %42s %20s %15s",
				this.who, "cluster", "brokers", "topic", "cum num", "mps")) // mps=msg per second
			this.Ui.Output(fmt.Sprintf(strings.Repeat("-", 136)))
		} else {
			this.Ui.Output(fmt.Sprintf("%-9s %20s %50s %20s %15s",
				this.who, "cluster", "topic", "cum num", "mps")) // mps=msg per second
			this.Ui.Output(fmt.Sprintf(strings.Repeat("-", 118)))
		}

		this.showAndResetCounters()
	}

	return
}
示例#3
0
文件: top.go 项目: funkygao/gafka
func (this *Top) drawDashboard() {
	err := termui.Init()
	swallow(err)
	defer termui.Close()

	termui.UseTheme("helloworld")

	maxRound := termui.TermWidth() / 2
	refreshProducerData := func(round int) []float64 {
		this.showAndResetCounters()
		if round%maxRound == (maxRound - 5) {
			this.mu.Lock()
			tailLen := len(this.totalMps) - 2
			tail := this.totalMps[tailLen:]
			this.totalMps = make([]float64, 2, 1000)
			copy(this.totalMps, tail)
			this.mu.Unlock()
		}
		return this.totalMps
	}

	refreshConsumerData := func(round int) []float64 {
		if round%maxRound == (maxRound - 5) {
			this.mu.Lock()
			tailLen := len(this.totalConsumerMps) - 2
			tail := this.totalConsumerMps[tailLen:]
			this.totalConsumerMps = make([]float64, 2, 1000)
			copy(this.totalConsumerMps, tail)
			this.mu.Unlock()
		}
		return this.totalConsumerMps
	}

	producerChart := termui.NewLineChart()
	producerChart.Mode = "dot"
	producerChart.Border.Label = fmt.Sprintf("producer mps totals: %s %s %s",
		this.zone, this.clusterPattern, this.topicPattern)
	producerChart.Data = refreshProducerData(0)
	producerChart.Width = termui.TermWidth() / 2
	producerChart.Height = termui.TermHeight()
	producerChart.X = 0
	producerChart.Y = 0
	producerChart.AxesColor = termui.ColorWhite
	producerChart.LineColor = termui.ColorGreen | termui.AttrBold

	consumerChart := termui.NewLineChart()
	consumerChart.Mode = "dot"
	consumerChart.Border.Label = fmt.Sprintf("consumer mps totals: %s %s %s",
		this.zone, this.clusterPattern, this.topicPattern)
	consumerChart.Data = refreshConsumerData(0)
	consumerChart.Width = termui.TermWidth() / 2
	consumerChart.Height = termui.TermHeight()
	consumerChart.X = termui.TermWidth() / 2
	consumerChart.Y = 0
	consumerChart.AxesColor = termui.ColorWhite
	consumerChart.LineColor = termui.ColorRed | termui.AttrBold

	evt := make(chan termbox.Event)
	go func() {
		for {
			evt <- termbox.PollEvent()
		}
	}()

	termui.Render(producerChart, consumerChart)
	tick := time.NewTicker(this.topInterval)
	defer tick.Stop()
	rounds := 0
	for {
		select {
		case e := <-evt:
			if e.Type == termbox.EventKey && e.Ch == 'q' {
				return
			}

		case <-tick.C:
			// refresh data, and skip the first 2 rounds
			rounds++
			if rounds > 1 {
				producerChart.Data = refreshProducerData(rounds)
				consumerChart.Data = refreshConsumerData(rounds)
				termui.Render(producerChart, consumerChart)
			}

		}
	}
}