From dd2876a186ee4f08f832509b9ca3b95f93fd7685 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 4 Apr 2022 15:50:54 +0200 Subject: [PATCH] Added --debug-file flag to gRPC daemon debug mode --- cli/daemon/daemon.go | 19 +++++++++++++++++++ cli/daemon/interceptors.go | 17 ++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/cli/daemon/daemon.go b/cli/daemon/daemon.go index b5152103140..2ca7370ff2a 100644 --- a/cli/daemon/daemon.go +++ b/cli/daemon/daemon.go @@ -36,6 +36,7 @@ import ( srv_debug "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/debug/v1" srv_monitor "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/monitor/v1" srv_settings "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/settings/v1" + "github.com/arduino/go-paths-helper" "github.com/segmentio/stats/v4" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -47,6 +48,7 @@ var ( ip string daemonize bool debug bool + debugFile string debugFilters []string ) @@ -65,6 +67,7 @@ func NewCommand() *cobra.Command { configuration.Settings.BindPFlag("daemon.port", daemonCommand.PersistentFlags().Lookup("port")) daemonCommand.Flags().BoolVar(&daemonize, "daemonize", false, tr("Do not terminate daemon process if the parent process dies")) daemonCommand.Flags().BoolVar(&debug, "debug", false, tr("Enable debug logging of gRPC calls")) + daemonCommand.Flags().StringVar(&debugFile, "debug-file", "", tr("Append debug logging to the specified file")) daemonCommand.Flags().StringSliceVar(&debugFilters, "debug-filter", []string{}, tr("Display only the provided gRPC calls")) return daemonCommand } @@ -79,7 +82,23 @@ func runDaemonCommand(cmd *cobra.Command, args []string) { } port := configuration.Settings.GetString("daemon.port") gRPCOptions := []grpc.ServerOption{} + if debugFile != "" { + if !debug { + feedback.Error(tr("The flag --debug-file must be used with --debug.")) + os.Exit(errorcodes.ErrBadArgument) + } + } if debug { + if debugFile != "" { + outFile := paths.New(debugFile) + f, err := outFile.Append() + if err != nil { + feedback.Error(tr("Error opening debug logging file: %s", err)) + os.Exit(errorcodes.ErrBadCall) + } + debugStdOut = f + defer f.Close() + } gRPCOptions = append(gRPCOptions, grpc.UnaryInterceptor(unaryLoggerInterceptor), grpc.StreamInterceptor(streamLoggerInterceptor), diff --git a/cli/daemon/interceptors.go b/cli/daemon/interceptors.go index e2321515404..a3383d7527d 100644 --- a/cli/daemon/interceptors.go +++ b/cli/daemon/interceptors.go @@ -19,20 +19,23 @@ import ( "context" "encoding/json" "fmt" + "os" "strings" "google.golang.org/grpc" ) +var debugStdOut = os.Stdout + func log(isRequest bool, msg interface{}) { j, _ := json.MarshalIndent(msg, "| ", " ") inOut := map[bool]string{true: "REQ: ", false: "RESP: "} - fmt.Println("| " + inOut[isRequest] + string(j)) + fmt.Fprintln(debugStdOut, "| "+inOut[isRequest]+string(j)) } func logError(err error) { if err != nil { - fmt.Println("| ERROR: ", err) + fmt.Fprintln(debugStdOut, "| ERROR: ", err) } } @@ -52,12 +55,12 @@ func unaryLoggerInterceptor(ctx context.Context, req interface{}, info *grpc.Una if !logSelector(info.FullMethod) { return handler(ctx, req) } - fmt.Println("CALLED:", info.FullMethod) + fmt.Fprintln(debugStdOut, "CALLED:", info.FullMethod) log(true, req) resp, err := handler(ctx, req) logError(err) log(false, resp) - fmt.Println() + fmt.Fprintln(debugStdOut) return resp, err } @@ -72,11 +75,11 @@ func streamLoggerInterceptor(srv interface{}, stream grpc.ServerStream, info *gr if info.IsServerStream { streamReq += "STREAM_RESP" } - fmt.Println("CALLED:", info.FullMethod, streamReq) + fmt.Fprintln(debugStdOut, "CALLED:", info.FullMethod, streamReq) err := handler(srv, &loggingServerStream{ServerStream: stream}) logError(err) - fmt.Println("STREAM CLOSED") - fmt.Println() + fmt.Fprintln(debugStdOut, "STREAM CLOSED") + fmt.Fprintln(debugStdOut) return err }