func ShortenGUIDString(s string) string {
	return guidRegex.ReplaceAllString(s, "$1")
}
ShortenGUIDString takes a string with one or more GUIDs and elides them to make it more human readable. It turns
"354754bd-b73e-4d20-8021-ab93a3d145c0:67af70c5-f45e-4b3d-9d20-6758195e2ff4:3:2" into "354754bd:67af70c5:3:2"
package common
import (
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math"
	"math/rand"
	"net"
	"net/http"
	"os"
	"os/signal"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	log "github.com/sirupsen/logrus"
	"github.com/uber-common/bark"
	"github.com/uber/cherami-server/common/configure"
	"github.com/uber/cherami-server/common/metrics"
	"github.com/uber/cherami-thrift/.generated/go/admin"
	"github.com/uber/cherami-thrift/.generated/go/cherami"
	"github.com/uber/cherami-thrift/.generated/go/shared"
	"github.com/uber/ringpop-go"
	"github.com/uber/ringpop-go/discovery/statichosts"
	"github.com/uber/ringpop-go/swim"
	"github.com/uber/tchannel-go"
	"github.com/uber/tchannel-go/hyperbahn"
	"github.com/uber/tchannel-go/thrift"
)
var rpMutex sync.RWMutex  
var ringpopBootstrapFile string
const hyperbahnPort int16 = 21300
const rpAppNamePrefix string = "cherami"
const maxRpJoinTimeout = 30 * time.Second
const maxRateExtrapolationTime = 120.0
const MaxDuration time.Duration = 1<<62 - 1
var ports = []int{4240, 4253, 4254, 5425, 4922}
const (
	inputHostAdminChannelName  = "inputhost-admin-client"
	outputHostAdminChannelName = "outputhost-admin-client"
	storeHostClientChannelName = "storehost-client"
)
type HandleSignalFunc func(sig os.Signal, hostport string, endpoint string, timeout time.Duration)
func buildRingpopHosts(ipaddr string, port int) []string {
	var ringpopHosts []string
	ringpopHosts = append(ringpopHosts, fmt.Sprintf("%s:%d", ipaddr, port))
	for _, indPort := range ports {
		if indPort != port {
			log.Infof("appending port: %v", indPort)
			ringpopHosts = append(ringpopHosts, fmt.Sprintf("%s:%d", ipaddr, indPort))
		}
	}
	return ringpopHosts
}
func CreateRingpop(service string, ch *tchannel.Channel, ipaddr string, port int) *(ringpop.Ringpop) {
	rp, _ := ringpop.New(fmt.Sprintf("%s", rpAppNamePrefix), ringpop.Channel(ch), ringpop.Address(fmt.Sprintf("%s:%d", ipaddr, port)))
	return rp
}
func GetDefaultLogger() bark.Logger {
	return bark.NewLoggerFromLogrus(log.StandardLogger())
}
func BootstrapRingpop(rp *ringpop.Ringpop, ipaddr string, port int, cfg configure.CommonServiceConfig) error {
	lcLg := GetDefaultLogger()
	if rp == nil {
		lcLg.WithField(TagHostIP, FmtHostIP(ipaddr)).Error("no ringpop to bootstrap")
		return errors.New("cannot bootstrap a nil ringpop")
	}
	var rpHosts []string
	if len(cfg.GetRingHosts()) > 0 {
		for _, host := range strings.Split(cfg.GetRingHosts(), ",") {
			hostTrimed := strings.TrimSpace(host)
			if len(hostTrimed) > 0 {
				rpHosts = append(rpHosts, hostTrimed)
			}
		}
	}
	if len(rpHosts) == 0 {
		rpHosts = buildRingpopHosts(ipaddr, port)
	}
	lcLg.WithFields(bark.Fields{TagHostIP: FmtHostIP(ipaddr), `RingHosts`: rpHosts}).
		Debug("RingHosts")
	bOptions := new(swim.BootstrapOptions)
	bOptions.DiscoverProvider = statichosts.New(rpHosts...)
	bOptions.MaxJoinDuration = maxRpJoinTimeout
	bOptions.JoinSize = 1  
	_, err := rp.Bootstrap(bOptions)
	return err
}
func getHyperbahnInitialNodes(bootstrapFile string) []string {
	ip, _ := tchannel.ListenIP()
	ret := []string{fmt.Sprintf("%s:%d", ip.String(), hyperbahnPort)}
	if len(bootstrapFile) < 1 {
		return ret
	}
	blob, err := ioutil.ReadFile(bootstrapFile)
	if err != nil {
		return ret
	}
	err = json.Unmarshal(blob, &ret)
	if err != nil {
		return ret
	}
	return ret
}
func isPersistentService(name string) bool {
	return (strings.Compare(name, StoreServiceName) == 0)
}
func SetupServerConfig(configurator configure.Configure) configure.CommonAppConfig {
	return configurator.SetupServerConfig()
}
func CreateHyperbahnClient(ch *tchannel.Channel, bootstrapFile string) *hyperbahn.Client {
	initialNodes := getHyperbahnInitialNodes(bootstrapFile)
	config := hyperbahn.Configuration{InitialNodes: initialNodes}
	if len(config.InitialNodes) == 0 {
		log.Fatal("No Hyperbahn nodes to connect to.")
	}
	hClient, _ := hyperbahn.NewClient(ch, config, nil)
	return hClient
}
func GetHTTPListenAddress(cfgListenAddress net.IP) string {
	listenAddress := `127.0.0.1`
	if cfgListenAddress.IsLoopback() {  
		listenAddress = cfgListenAddress.String()
	}
	return listenAddress
}
func ServiceLoop(port int, cfg configure.CommonAppConfig, service SCommon) {
	httpHandlers := NewHTTPHandler(cfg, service)
	mux := http.NewServeMux()
	httpHandlers.Register(mux)
	listenAddress := GetHTTPListenAddress(service.GetConfig().GetListenAddress())
	log.Info(fmt.Sprintf("Diagnostic http endpoint listening on %s:%d", listenAddress, port))
	log.Panic(http.ListenAndServe(fmt.Sprintf("%s:%d", listenAddress, port), mux))
}
func WSStart(listenAddress string, port int, wsservice WSService) {
	mux := wsservice.RegisterWSHandler()
	go func() {
		log.Info(fmt.Sprintf("WebSocket listening %s:%d", listenAddress, port))
		log.Panic(http.ListenAndServe(fmt.Sprintf("%v:%d", listenAddress, port), mux))
	}()
}
func SplitHostPort(hostPort string) (string, int, error) {
	if len(hostPort) == 0 {
		return "", 0, nil
	}
	parts := strings.Split(hostPort, ":")
	port, err := strconv.Atoi(parts[1])
	return parts[0], port, err
}
var guidRegex = regexp.MustCompile(`([[:xdigit:]]{8})-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}`)