web/web.go
func (h *Handler) Run(ctx context.Context) error {
	level.Info(h.logger).Log("msg", "Start listening for connections", "address", h.options.ListenAddress)

	listener, err := net.Listen("tcp", h.options.ListenAddress)
	if err != nil {
		return err
	}
	listener = netutil.LimitListener(listener, h.options.MaxConnections)

	// Monitor incoming connections with conntrack.
	listener = conntrack.NewListener(listener,
		conntrack.TrackWithName("http"),
		conntrack.TrackWithTracing())

	var (
		m = cmux.New(listener)
		// See https://github.com/grpc/grpc-go/issues/2636 for why we need to use MatchWithWriters().
		grpcl   = m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
		httpl   = m.Match(cmux.HTTP1Fast())
		grpcSrv = grpc.NewServer()
	)
	av2 := api_v2.New(
		h.options.TSDB,
		h.options.EnableAdminAPI,
	)
	av2.RegisterGRPC(grpcSrv)

	hh, err := av2.HTTPHandler(ctx, h.options.ListenAddress)
	if err != nil {
		return err
	}

	hhFunc := h.testReadyHandler(hh)

	operationName := nethttp.OperationNameFunc(func(r *http.Request) string {
		return fmt.Sprintf("%s %s", r.Method, r.URL.Path)
	})
	mux := http.NewServeMux()
	mux.Handle("/", h.router)

	av1 := route.New().WithInstrumentation(instrumentHandlerWithPrefix("/api/v1"))
	h.apiV1.Register(av1)
	apiPath := "/api"
	if h.options.RoutePrefix != "/" {
		apiPath = h.options.RoutePrefix + apiPath
		level.Info(h.logger).Log("msg", "router prefix", "prefix", h.options.RoutePrefix)
	}

	mux.Handle(apiPath+"/v1/", http.StripPrefix(apiPath+"/v1", av1))

	mux.Handle(apiPath+"/", http.StripPrefix(apiPath,
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			httputil.SetCORS(w, h.options.CORSOrigin, r)
			hhFunc(w, r)
		}),
	))

	errlog := stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0)

	httpSrv := &http.Server{
		Handler:     withStackTracer(nethttp.Middleware(opentracing.GlobalTracer(), mux, operationName), h.logger),
		ErrorLog:    errlog,
		ReadTimeout: h.options.ReadTimeout,
	}

	errCh := make(chan error)
	go func() {
		errCh <- httpSrv.Serve(httpl)
	}()
	go func() {
		errCh <- grpcSrv.Serve(grpcl)
	}()
	go func() {
		errCh <- m.Serve()
	}()

	select {
	case e := <-errCh:
		return e
	case <-ctx.Done():
		httpSrv.Shutdown(ctx)
		grpcSrv.GracefulStop()
		return nil
	}
}
func (h *Handler) Run(ctx context.Context) error {
	level.Info(h.logger).Log("msg", "Start listening for connections", "address", h.options.ListenAddress)

	listener, err := net.Listen("tcp", h.options.ListenAddress)
	if err != nil {
		return err
	}
	listener = netutil.LimitListener(listener, h.options.MaxConnections)

	// Monitor incoming connections with conntrack.
	listener = conntrack.NewListener(listener,
		conntrack.TrackWithName("http"),
		conntrack.TrackWithTracing())

	var (
		m = cmux.New(listener)
		// See https://github.com/grpc/grpc-go/issues/2636 for why we need to use MatchWithWriters().
		grpcl   = m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
		httpl   = m.Match(cmux.HTTP1Fast())
		grpcSrv = grpc.NewServer()
	)
	av2 := api_v2.New(
		h.options.TSDB,
		h.options.EnableAdminAPI,
	)
	av2.RegisterGRPC(grpcSrv)

	hh, err := av2.HTTPHandler(ctx, h.options.ListenAddress)
	if err != nil {
		return err
	}

	hhFunc := h.testReadyHandler(hh)

	operationName := nethttp.OperationNameFunc(func(r *http.Request) string {
		return fmt.Sprintf("%s %s", r.Method, r.URL.Path)
	})
	mux := http.NewServeMux()
	mux.Handle("/", h.router)

	av1 := route.New().WithInstrumentation(instrumentHandlerWithPrefix("/api/v1"))
	h.apiV1.Register(av1)
	apiPath := "/api"
	if h.options.RoutePrefix != "/" {
		apiPath = h.options.RoutePrefix + apiPath
		level.Info(h.logger).Log("msg", "router prefix", "prefix", h.options.RoutePrefix)
	}

	mux.Handle(apiPath+"/v1/", http.StripPrefix(apiPath+"/v1", av1))

	mux.Handle(apiPath+"/", http.StripPrefix(apiPath,
		http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			httputil.SetCORS(w, h.options.CORSOrigin, r)
			hhFunc(w, r)
		}),
	))

	errlog := stdlog.New(log.NewStdlibAdapter(level.Error(h.logger)), "", 0)

	httpSrv := &http.Server{
		Handler:     withStackTracer(nethttp.Middleware(opentracing.GlobalTracer(), mux, operationName), h.logger),
		ErrorLog:    errlog,
		ReadTimeout: h.options.ReadTimeout,
	}

	errCh := make(chan error)
	go func() {
		errCh <- httpSrv.Serve(httpl)
	}()
	go func() {
		errCh <- grpcSrv.Serve(grpcl)
	}()
	go func() {
		errCh <- m.Serve()
	}()

	select {
	case e := <-errCh:
		return e
	case <-ctx.Done():
		httpSrv.Shutdown(ctx)
		grpcSrv.GracefulStop()
		return nil
	}
}
// Run serves the HTTP endpoints.