func (mx *mux) serverStats(key engine.ServerKey) (*engine.RoundTripStats, error) {
	b, ok := mx.backends[key.BackendKey]
	if !ok {
		return nil, fmt.Errorf("%v not found", key.BackendKey)
	}
	srv, ok := b.findServer(key)
	if !ok {
		return nil, fmt.Errorf("%v not found", key)
	}

	u, err := url.Parse(srv.URL)
	if err != nil {
		return nil, err
	}

	m, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}
	for _, f := range mx.frontends {
		if f.backend.backend.Id != key.BackendKey.Id {
			continue
		}
		if err := f.watcher.collectServerMetrics(m, u); err != nil {
			return nil, err
		}
	}
	return engine.NewRoundTripStats(m)
}
func (rt *RTWatcher) upsertServer(u *url.URL) error {
	rt.mtx.Lock()
	defer rt.mtx.Unlock()

	m, err := memmetrics.NewRTMetrics()
	if err != nil {
		return err
	}
	rt.srvs[surl{scheme: u.Scheme, host: u.Host}] = m
	return nil
}
func newSval(s engine.Server) (*sval, error) {
	m, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}
	u, err := url.Parse(s.URL)
	if err != nil {
		return nil, err
	}
	return &sval{srv: &s, m: m, u: u}, nil
}
func NewWatcher(next http.Handler) (*RTWatcher, error) {
	m, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}

	return &RTWatcher{
		mtx:   &sync.Mutex{},
		m:     m,
		clock: &timetools.RealTime{},
		next:  next,
		srvs:  make(map[surl]*memmetrics.RTMetrics),
	}, nil
}
func (mx *mux) backendStats(key engine.BackendKey) (*engine.RoundTripStats, error) {
	m, err := memmetrics.NewRTMetrics()
	if err != nil {
		return nil, err
	}
	for _, f := range mx.frontends {
		if f.backend.backend.Id != key.Id {
			continue
		}
		if err := f.watcher.collectMetrics(m); err != nil {
			return nil, err
		}
	}
	return engine.NewRoundTripStats(m)
}