get.porter.sh/porter@v1.3.0/pkg/grpc/server.go (about)

     1  package grpc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"net/http"
     8  	"os"
     9  
    10  	pGRPCv1alpha1 "get.porter.sh/porter/gen/proto/go/porterapis/porter/v1alpha1"
    11  	"get.porter.sh/porter/pkg/config"
    12  	pserver "get.porter.sh/porter/pkg/grpc/portergrpc"
    13  	"get.porter.sh/porter/pkg/porter"
    14  	"get.porter.sh/porter/pkg/tracing"
    15  
    16  	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
    17  	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
    18  	"github.com/prometheus/client_golang/prometheus"
    19  	"github.com/prometheus/client_golang/prometheus/promhttp"
    20  	"google.golang.org/grpc"
    21  	"google.golang.org/grpc/health"
    22  	"google.golang.org/grpc/health/grpc_health_v1"
    23  	"google.golang.org/grpc/reflection"
    24  )
    25  
    26  var (
    27  	reg = prometheus.NewRegistry()
    28  	// Create some standard server metrics.
    29  	grpcMetrics = grpc_prometheus.NewServerMetrics()
    30  
    31  	// Create a customized counter metric.
    32  	customizedCounterMetric = prometheus.NewCounterVec(prometheus.CounterOpts{
    33  		Name: "demo_server_say_hello_method_handle_count",
    34  		Help: "Total number of RPCs handled on the server.",
    35  	}, []string{"name"})
    36  )
    37  
    38  func init() {
    39  	reg.MustRegister(grpcMetrics, customizedCounterMetric)
    40  	customizedCounterMetric.WithLabelValues("Test")
    41  }
    42  
    43  type PorterGRPCService struct {
    44  	PorterConfig *config.Config
    45  	opts         *porter.ServiceOptions
    46  	ctx          context.Context
    47  }
    48  
    49  func NewServer(ctx context.Context, opts *porter.ServiceOptions) (*PorterGRPCService, error) {
    50  	pCfg := config.New()
    51  	srv := &PorterGRPCService{
    52  		PorterConfig: pCfg,
    53  		opts:         opts,
    54  		ctx:          ctx,
    55  	}
    56  	return srv, nil
    57  }
    58  
    59  func (s *PorterGRPCService) ListenAndServe() (*grpc.Server, error) {
    60  	_, log := tracing.StartSpan(s.ctx)
    61  	defer log.EndSpan()
    62  	log.Infof("Starting gRPC on %v", s.opts.Port)
    63  	listener, err := net.Listen("tcp", fmt.Sprintf(":%v", s.opts.Port))
    64  	if err != nil {
    65  		return nil, fmt.Errorf("failed to listen on %d: %s", s.opts.Port, err)
    66  	}
    67  	httpServer := &http.Server{Handler: promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), Addr: fmt.Sprintf("0.0.0.0:%d", 9092)}
    68  
    69  	healthServer := health.NewServer()
    70  	psrv, err := pserver.NewPorterServer(s.PorterConfig)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	srv := grpc.NewServer(
    75  		grpc.StreamInterceptor(grpcMetrics.StreamServerInterceptor()),
    76  		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
    77  			grpcMetrics.UnaryServerInterceptor(),
    78  			psrv.NewConnectionInterceptor),
    79  		),
    80  	)
    81  	reflection.Register(srv)
    82  
    83  	pGRPCv1alpha1.RegisterPorterServer(srv, psrv)
    84  	healthServer.SetServingStatus(s.opts.ServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
    85  	grpc_prometheus.Register(srv)
    86  
    87  	srvErrCh := make(chan error, 1)
    88  	go func() {
    89  		if err := srv.Serve(listener); err != nil {
    90  			srvErrCh <- err
    91  		}
    92  	}()
    93  
    94  	select {
    95  	case err := <-srvErrCh:
    96  		if err != nil {
    97  			_ = log.Errorf("failed to serve GRPC listener: %w", err)
    98  			os.Exit(1)
    99  		}
   100  	default:
   101  		// Continue if no error is received yet
   102  	}
   103  
   104  	http.Handle("/metrics", promhttp.Handler())
   105  
   106  	// Start your http server for prometheus.
   107  	go func() {
   108  		if err := httpServer.ListenAndServe(); err != nil {
   109  			srvErrCh <- err
   110  		}
   111  	}()
   112  	select {
   113  	case err := <-srvErrCh:
   114  		if err != nil {
   115  			_ = log.Errorf("Unable to start a http server. %w", err)
   116  			os.Exit(1)
   117  		}
   118  	default:
   119  		// Continue if no error is received yet
   120  	}
   121  
   122  	grpcMetrics.InitializeMetrics(srv)
   123  	return srv, nil
   124  }