diff --git a/etcdmain/grpc_proxy.go b/etcdmain/grpc_proxy.go index b2cc25c3a220..50519da294b6 100644 --- a/etcdmain/grpc_proxy.go +++ b/etcdmain/grpc_proxy.go @@ -19,6 +19,7 @@ import ( "fmt" "net" "net/http" + "net/url" "os" "time" @@ -40,6 +41,7 @@ import ( var ( grpcProxyListenAddr string + grpcProxyMetricsListenAddr string grpcProxyEndpoints []string grpcProxyDNSCluster string grpcProxyInsecureDiscovery bool @@ -79,7 +81,7 @@ func newGRPCProxyStartCommand() *cobra.Command { } cmd.Flags().StringVar(&grpcProxyListenAddr, "listen-addr", "127.0.0.1:23790", "listen address") - cmd.Flags().StringVar(&grpcProxyDNSCluster, "discovery-srv", "", "DNS domain used to bootstrap initial cluster") + cmd.Flags().StringVar(&grpcProxyMetricsListenAddr, "metrics-addr", "", "listen for /metrics requests on an additional interface") cmd.Flags().BoolVar(&grpcProxyInsecureDiscovery, "insecure-discovery", false, "accept insecure SRV records") cmd.Flags().StringSliceVar(&grpcProxyEndpoints, "endpoints", []string{"127.0.0.1:2379"}, "comma separated etcd cluster endpoints") cmd.Flags().StringVar(&grpcProxyCert, "cert", "", "identify secure connections with etcd servers using this TLS certificate file") @@ -129,7 +131,7 @@ func startGRPCProxy(cmd *cobra.Command, args []string) { }() m := cmux.New(l) - cfg, err := newClientCfg() + cfg, cfgtls, err := newClientCfg() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -202,6 +204,31 @@ func startGRPCProxy(cmd *cobra.Command, args []string) { go func() { errc <- m.Serve() }() + if len(grpcProxyMetricsListenAddr) > 0 { + murl, err := url.Parse(grpcProxyMetricsListenAddr) + if err != nil { + fmt.Fprintf(os.Stderr, "cannot parse %q", grpcProxyMetricsListenAddr) + os.Exit(1) + } + if murl.Scheme == "https" { + murl.Scheme = "http" + plog.Warningf("grpc-proxy: serving non-secured '/metrics' for %s", murl.String()) + } + ml, err := transport.NewListener(murl.Host, murl.Scheme, nil) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + mux := http.NewServeMux() + mux.Handle("/metrics", prometheus.Handler()) + + go func() { + plog.Info("grpc-proxy: listening for metrics on ", murl.String()) + plog.Fatal(http.Serve(ml, mux)) + }() + } + // grpc-proxy is initialized, ready to serve notifySystemd() @@ -209,7 +236,7 @@ func startGRPCProxy(cmd *cobra.Command, args []string) { os.Exit(1) } -func newClientCfg() (*clientv3.Config, error) { +func newClientCfg() (*clientv3.Config, *transport.TLSInfo, error) { // set tls if any one tls option set var cfgtls *transport.TLSInfo tlsinfo := transport.TLSInfo{} @@ -235,12 +262,12 @@ func newClientCfg() (*clientv3.Config, error) { if cfgtls != nil { clientTLS, err := cfgtls.ClientConfig() if err != nil { - return nil, err + return nil, nil, err } cfg.TLS = clientTLS } // TODO: support insecure tls - return &cfg, nil + return &cfg, cfgtls, nil }