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 }