@@ -22,10 +22,14 @@ import (
2222 "net"
2323 "net/http"
2424 "reflect"
25+ "time"
2526
2627 "github.com/improbable-eng/grpc-web/go/grpcweb"
2728 "github.com/soheilhy/cmux"
2829
30+ "log"
31+ "os"
32+
2933 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
3034 "github.com/kubeapps/kubeapps/cmd/kubeapps-apis/core"
3135 packagesv1alpha1 "github.com/kubeapps/kubeapps/cmd/kubeapps-apis/core/packages/v1alpha1"
@@ -34,16 +38,40 @@ import (
3438 pluginsGRPCv1alpha1 "github.com/kubeapps/kubeapps/cmd/kubeapps-apis/gen/core/plugins/v1alpha1"
3539 "google.golang.org/grpc"
3640 "google.golang.org/grpc/reflection"
41+ "google.golang.org/grpc/status"
3742 "google.golang.org/protobuf/encoding/protojson"
38- log "k8s.io/klog/v2"
43+ klogv2 "k8s.io/klog/v2"
3944)
4045
46+ // LogRequest is a gRPC UnaryServerInterceptor that will log the API call
47+ func CreateRequestLogger () func (ctx context.Context , req interface {}, info * grpc.UnaryServerInfo , handler grpc.UnaryHandler ) (response interface {}, err error ) {
48+
49+ // Include micro seconds in timestamp
50+ logger := log .New (os .Stderr , "" , log .Ldate | log .Ltime | log .Lmicroseconds )
51+
52+ return func (ctx context.Context , req interface {}, info * grpc.UnaryServerInfo , handler grpc.UnaryHandler ) (response interface {}, err error ) {
53+
54+ start := time .Now ()
55+ res , err := handler (ctx , req )
56+
57+ // Format string : [timestamp] [status code] [duration] [full path]
58+ // 2021-11-29 15:10:21.642313 OK 97.752µs /kubeappsapis.core.packages.v1alpha1.PackagesService/GetAvailablePackageSummaries
59+ logger .Printf ("%v %s %s\n " ,
60+ status .Code (err ),
61+ time .Since (start ),
62+ info .FullMethod )
63+
64+ return res , err
65+ }
66+ }
67+
4168// Serve is the root command that is run when no other sub-commands are present.
4269// It runs the gRPC service, registering the configured plugins.
4370func Serve (serveOpts core.ServeOptions ) error {
4471 // Create the grpc server and register the reflection server (for now, useful for discovery
4572 // using grpcurl) or similar.
46- grpcSrv := grpc .NewServer ()
73+ logRequest := CreateRequestLogger ()
74+ grpcSrv := grpc .NewServer (grpc .ChainUnaryInterceptor (logRequest ))
4775 reflection .Register (grpcSrv )
4876
4977 // Create the http server, register our core service followed by any plugins.
@@ -124,27 +152,27 @@ func Serve(serveOpts core.ServeOptions) error {
124152 go func () {
125153 err := grpcSrv .Serve (grpcLis )
126154 if err != nil {
127- log .Fatalf ("failed to serve: %v" , err )
155+ klogv2 .Fatalf ("failed to serve: %v" , err )
128156 }
129157 }()
130158 go func () {
131159 err := grpcSrv .Serve (grpcwebLis )
132160 if err != nil {
133- log .Fatalf ("failed to serve: %v" , err )
161+ klogv2 .Fatalf ("failed to serve: %v" , err )
134162 }
135163 }()
136164 go func () {
137165 err := httpSrv .Serve (httpLis )
138166 if err != nil {
139- log .Fatalf ("failed to serve: %v" , err )
167+ klogv2 .Fatalf ("failed to serve: %v" , err )
140168 }
141169 }()
142170
143171 if serveOpts .UnsafeLocalDevKubeconfig {
144- log .Warning ("Using the local Kubeconfig file instead of the actual in-cluster's config. This is not recommended except for development purposes." )
172+ klogv2 .Warning ("Using the local Kubeconfig file instead of the actual in-cluster's config. This is not recommended except for development purposes." )
145173 }
146174
147- log .Infof ("Starting server on :%d" , serveOpts .Port )
175+ klogv2 .Infof ("Starting server on :%d" , serveOpts .Port )
148176 if err := mux .Serve (); err != nil {
149177 return fmt .Errorf ("failed to serve: %v" , err )
150178 }
0 commit comments