Пример #1
0
func (this *Redis) runPing(zkzone *zk.ZkZone) {
	var wg sync.WaitGroup
	allRedis := zkzone.AllRedis()
	this.topInfos = make([]redisTopInfo, 0, len(allRedis))

	for _, hostPort := range allRedis {
		host, port, err := net.SplitHostPort(hostPort)
		if err != nil {
			this.Ui.Error(hostPort)
			continue
		}

		nport, err := strconv.Atoi(port)
		if err != nil || nport < 0 {
			this.Ui.Error(hostPort)
			continue
		}

		wg.Add(1)
		go func(wg *sync.WaitGroup, host string, port int) {
			defer wg.Done()

			t0 := time.Now()

			spec := redis.DefaultSpec().Host(host).Port(port)
			client, err := redis.NewSynchClientWithSpec(spec)
			if err != nil {
				this.Ui.Error(fmt.Sprintf("[%s:%d] %v", host, port, err))
				return
			}
			defer client.Quit()

			if err := client.Ping(); err != nil {
				this.Ui.Error(fmt.Sprintf("[%s:%d] %v", host, port, err))
				return
			}

			latency := time.Since(t0)

			this.mu.Lock()
			this.topInfos = append(this.topInfos, redisTopInfo{
				host:    host,
				port:    port,
				t0:      t0,
				latency: latency,
			})
			this.mu.Unlock()
		}(&wg, host, nport)
	}
	wg.Wait()

	latency := metrics.NewRegisteredHistogram("redis.latency", metrics.DefaultRegistry, metrics.NewExpDecaySample(1028, 0.015))

	sortutil.AscByField(this.topInfos, "latency")
	lines := []string{"#|Host|Port|latency"}
	if this.debug {
		lines = []string{"#|Host|Port|StartedAt|latency"}
	}
	for i, info := range this.topInfos {
		latency.Update(info.latency.Nanoseconds() / 1e6)

		if this.debug {
			lines = append(lines, fmt.Sprintf("%4d|%s|%d|%s|%s",
				i+1, info.host, info.port, info.t0, info.latency))
		} else {
			lines = append(lines, fmt.Sprintf("%4d|%s|%d|%s",
				i+1, info.host, info.port, info.latency))
		}

	}
	this.Ui.Output(columnize.SimpleFormat(lines))

	// summary
	ps := latency.Percentiles([]float64{0.7, 0.90, 0.95, 0.99, 0.999})
	this.Ui.Info(fmt.Sprintf("N:%d Min:%dms Max:%dms Mean:%.1fms 70%%:%1.fms 90%%:%.1fms 95%%:%.1fms 99%%:%.1fms",
		latency.Count(), latency.Min(), latency.Max(), latency.Mean(), ps[0], ps[1], ps[2], ps[3]))
}
Пример #2
0
func (this *Redis) runTop(zkzone *zk.ZkZone, interval time.Duration) {
	termui.Init()
	this.mainScreen = true
	this.w, this.h = termbox.Size()
	this.rows = this.h - 3 // head,max/total
	if this.batchMode {
		termbox.Close()
	} else {
		defer termui.Close()

		termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse)
		eventChan := make(chan termbox.Event, 16)
		go this.handleEvents(eventChan)
		go func() {
			for {
				ev := termbox.PollEvent()
				eventChan <- ev
			}
		}()

		this.drawSplash()
	}

	this.topInfos = make([]redisTopInfo, 0, 100)
	this.topInfos1 = make([]redisTopInfo, 0, 100)
	for {
		var wg sync.WaitGroup

		this.mu.Lock()
		this.topInfos1 = this.topInfos1[:0]
		freezedPorts := make(map[string]struct{})

		// clone freezedPorts to avoid concurrent map access
		if len(this.freezedPorts) > 0 {
			for port, _ := range this.freezedPorts {
				freezedPorts[port] = struct{}{}
			}
		}
		this.mu.Unlock()

		for _, hostPort := range zkzone.AllRedis() {
			host, port, err := net.SplitHostPort(hostPort)
			if err != nil {
				log.Error("invalid redis instance: %s", hostPort)
				continue
			}

			if len(this.ports) > 0 {
				if _, present := this.ports[port]; !present {
					continue
				}
			}
			if len(freezedPorts) > 0 {
				if _, present := freezedPorts[port]; !present {
					continue
				}
			}

			nport, err := strconv.Atoi(port)
			if err != nil || nport < 0 {
				log.Error("invalid redis instance: %s", hostPort)
				continue
			}

			wg.Add(1)
			go this.updateRedisInfo(&wg, host, nport) // update happens on topInfos1
		}
		wg.Wait()

		this.mu.Lock()
		this.topInfos1, this.topInfos = this.topInfos, this.topInfos1
		this.mu.Unlock()

		if this.mainScreen {
			this.render()
		}

		select {
		case <-time.After(interval):

		case <-this.quit:
			return
		}
	}
}