func()

in flw/flw.go [26:111]


func (c *Client) Srvr(server string) (*ServerStats, error) {
	// different parts of the regular expression that are required to parse the srvr output
	const (
		zrVer   = `^Zookeeper version: ([A-Za-z0-9\.\-]+), built on (\d\d/\d\d/\d\d\d\d \d\d:\d\d [A-Za-z0-9:\+\-]+)`
		zrLat   = `^Latency min/avg/max: (\d+)/([0-9.]+)/(\d+)`
		zrNet   = `^Received: (\d+).*\n^Sent: (\d+).*\n^Connections: (\d+).*\n^Outstanding: (\d+)`
		zrState = `^Zxid: (0x[A-Za-z0-9]+).*\n^Mode: (\w+).*\n^Node count: (\d+)`
	)

	// build the regex from the pieces above
	re, err := regexp.Compile(fmt.Sprintf(`(?m:\A%v.*\n%v.*\n%v.*\n%v)`, zrVer, zrLat, zrNet, zrState))
	if err != nil {
		return nil, fmt.Errorf("error compiling srvr response regex: %w", err)
	}

	response, err := fourLetterWord(server, "srvr", c.Timeout)

	if err != nil {
		return nil, fmt.Errorf("invalid srvr response: %w", err)
	}
	matches := re.FindAllStringSubmatch(string(response), -1)

	if matches == nil {
		return nil, fmt.Errorf("unable to parse fields from zookeeper response (no regex matches)")
	}

	match := matches[0][1:]

	// determine current server
	var srvrMode Mode
	switch match[10] {
	case "leader":
		srvrMode = ModeLeader
	case "follower":
		srvrMode = ModeFollower
	case "standalone":
		srvrMode = ModeStandalone
	default:
		srvrMode = ModeUnknown
	}

	buildTime, err := time.Parse("01/02/2006 15:04 MST", match[1])

	if err != nil {
		return nil, fmt.Errorf("error parsing srvr response: %w", err)
	}

	parsedInt, err := strconv.ParseInt(match[9], 0, 64)

	if err != nil {
		return nil, fmt.Errorf("error parsing srvr response: %w", err)
	}

	// the ZxID value is an int64 with two int32s packed inside
	// the high int32 is the epoch (i.e., number of leader elections)
	// the low int32 is the counter
	epoch := int32(parsedInt >> 32)
	counter := int32(parsedInt & 0xFFFFFFFF)

	// within the regex above, these values must be numerical
	// so we can avoid useless checking of the error return value
	minLatency, _ := strconv.ParseInt(match[2], 0, 64)
	avgLatency, _ := strconv.ParseFloat(match[3], 64)
	maxLatency, _ := strconv.ParseInt(match[4], 0, 64)
	recv, _ := strconv.ParseInt(match[5], 0, 64)
	sent, _ := strconv.ParseInt(match[6], 0, 64)
	cons, _ := strconv.ParseInt(match[7], 0, 64)
	outs, _ := strconv.ParseInt(match[8], 0, 64)
	ncnt, _ := strconv.ParseInt(match[11], 0, 64)

	return &ServerStats{
		Sent:        sent,
		Received:    recv,
		NodeCount:   ncnt,
		MinLatency:  minLatency,
		AvgLatency:  avgLatency,
		MaxLatency:  maxLatency,
		Connections: cons,
		Outstanding: outs,
		Epoch:       epoch,
		Counter:     counter,
		BuildTime:   buildTime,
		Mode:        srvrMode,
		Version:     match[0],
	}, nil
}