diff --git a/agent/client/client.go b/agent/client/client.go index ea20c065a8..be54e00b23 100644 --- a/agent/client/client.go +++ b/agent/client/client.go @@ -56,8 +56,10 @@ type Client struct { } func (c *Client) Start(ctx context.Context) error { + c.logger.Debug("Starting controlPlane client") err := c.startup(ctx) if err != nil { + c.logger.Error("Failed to start controlPlane client", zap.Error(err)) return err } @@ -65,6 +67,7 @@ func (c *Client) Start(ctx context.Context) error { ctx, cancel := context.WithCancel(ctx) go func() { <-c.done + c.logger.Debug("Stopping controlPlane client") // We cannot `defer cancel()` in this case because the start listener functions // start one goroutine each and don't block the execution of this function. // Thus, if we cancel the context, all those goroutines will fail. @@ -73,39 +76,48 @@ func (c *Client) Start(ctx context.Context) error { err = c.startStopListener(ctx) if err != nil { + c.logger.Error("Failed to start stop listener", zap.Error(err)) return err } err = c.startTriggerListener(ctx) if err != nil { + c.logger.Error("Failed to start trigger listener", zap.Error(err)) return err } err = c.startPollerListener(ctx) if err != nil { + c.logger.Error("Failed to start poller listener", zap.Error(err)) return err } err = c.startShutdownListener(ctx) if err != nil { + c.logger.Error("Failed to start shutdown listener", zap.Error(err)) return err } err = c.startDataStoreConnectionTestListener(ctx) if err != nil { + c.logger.Error("Failed to start data store connection test listener", zap.Error(err)) return err } err = c.startOTLPConnectionTestListener(ctx) if err != nil { + c.logger.Error("Failed to start OTLP connection test listener", zap.Error(err)) return err } err = c.startHeartBeat(ctx) if err != nil { + c.logger.Error("Failed to start heart beat", zap.Error(err)) return err } + c.logger.Debug("ControlPlane client started") + return nil } diff --git a/agent/client/workflow_listen_for_ds_connection_tests.go b/agent/client/workflow_listen_for_ds_connection_tests.go index 992d58c702..aea4d07e41 100644 --- a/agent/client/workflow_listen_for_ds_connection_tests.go +++ b/agent/client/workflow_listen_for_ds_connection_tests.go @@ -8,13 +8,18 @@ import ( "github.com/kubeshop/tracetest/agent/proto" "github.com/kubeshop/tracetest/server/telemetry" + "go.uber.org/zap" ) func (c *Client) startDataStoreConnectionTestListener(ctx context.Context) error { + logger := c.logger.Named("dataStoreConnectionTestListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterDataStoreConnectionTestAgent(ctx, c.sessionConfig.AgentIdentification) if err != nil { + logger.Error("could not open agent stream", zap.Error(err)) return fmt.Errorf("could not open agent stream: %w", err) } @@ -22,16 +27,22 @@ func (c *Client) startDataStoreConnectionTestListener(ctx context.Context) error for { req := proto.DataStoreConnectionTestRequest{} err := stream.RecvMsg(&req) + if err != nil { + logger.Error("could not get message from data store connection stream", zap.Error(err)) + } if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("data store connection stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to data store connection stream") return } if err != nil { + logger.Error("could not get message from data store connection stream", zap.Error(err)) log.Println("could not get message from data store connection stream: %w", err) time.Sleep(1 * time.Second) continue @@ -39,11 +50,13 @@ func (c *Client) startDataStoreConnectionTestListener(ctx context.Context) error ctx, err := telemetry.ExtractContextFromStream(stream) if err != nil { + logger.Error("could not extract context from stream", zap.Error(err)) log.Println("could not extract context from stream %w", err) } err = c.dataStoreConnectionListener(ctx, &req) if err != nil { + logger.Error("could not handle data store connection test request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_listen_for_otlp_connection_tests.go b/agent/client/workflow_listen_for_otlp_connection_tests.go index 18c9cce077..d80f6cdd50 100644 --- a/agent/client/workflow_listen_for_otlp_connection_tests.go +++ b/agent/client/workflow_listen_for_otlp_connection_tests.go @@ -8,13 +8,18 @@ import ( "github.com/kubeshop/tracetest/agent/proto" "github.com/kubeshop/tracetest/server/telemetry" + "go.uber.org/zap" ) func (c *Client) startOTLPConnectionTestListener(ctx context.Context) error { + logger := c.logger.Named("otlpConnectionTestListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterOTLPConnectionTestListener(ctx, c.sessionConfig.AgentIdentification) if err != nil { + logger.Error("could not open agent stream", zap.Error(err)) return fmt.Errorf("could not open agent stream: %w", err) } @@ -22,16 +27,22 @@ func (c *Client) startOTLPConnectionTestListener(ctx context.Context) error { for { req := proto.OTLPConnectionTestRequest{} err := stream.RecvMsg(&req) + if err != nil { + logger.Error("could not get message from otlp connection stream", zap.Error(err)) + } if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("otlp connection stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to otlp connection stream") return } if err != nil { + logger.Error("could not get message from otlp connection stream", zap.Error(err)) log.Println("could not get message from otlp connection stream: %w", err) time.Sleep(1 * time.Second) continue @@ -39,11 +50,13 @@ func (c *Client) startOTLPConnectionTestListener(ctx context.Context) error { ctx, err := telemetry.ExtractContextFromStream(stream) if err != nil { + logger.Error("could not extract context from stream", zap.Error(err)) log.Println("could not extract context from stream %w", err) } err = c.otlpConnectionTestListener(ctx, &req) if err != nil { + logger.Error("could not handle otlp connection test request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_listen_for_poll_requests.go b/agent/client/workflow_listen_for_poll_requests.go index 1e308a40f4..2bc5ce2e02 100644 --- a/agent/client/workflow_listen_for_poll_requests.go +++ b/agent/client/workflow_listen_for_poll_requests.go @@ -8,9 +8,13 @@ import ( "github.com/kubeshop/tracetest/agent/proto" "github.com/kubeshop/tracetest/server/telemetry" + "go.uber.org/zap" ) func (c *Client) startPollerListener(ctx context.Context) error { + logger := c.logger.Named("pollerListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterPollerAgent(ctx, c.sessionConfig.AgentIdentification) @@ -22,16 +26,22 @@ func (c *Client) startPollerListener(ctx context.Context) error { for { resp := proto.PollingRequest{} err := stream.RecvMsg(&resp) + if err != nil { + logger.Error("could not get message from poller stream", zap.Error(err)) + } if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("poller stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to poller stream") return } if err != nil { + logger.Error("could not get message from poller stream", zap.Error(err)) log.Println("could not get message from poller stream: %w", err) time.Sleep(1 * time.Second) continue @@ -39,11 +49,13 @@ func (c *Client) startPollerListener(ctx context.Context) error { ctx, err := telemetry.ExtractContextFromStream(stream) if err != nil { + logger.Error("could not extract context from stream", zap.Error(err)) log.Println("could not extract context from stream %w", err) } err = c.pollListener(ctx, &resp) if err != nil { + logger.Error("could not handle poll request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_listen_for_stop_requests.go b/agent/client/workflow_listen_for_stop_requests.go index 77928821b1..1192b4b572 100644 --- a/agent/client/workflow_listen_for_stop_requests.go +++ b/agent/client/workflow_listen_for_stop_requests.go @@ -7,14 +7,19 @@ import ( "time" "github.com/kubeshop/tracetest/agent/proto" + "go.uber.org/zap" ) // TODO: fix this and add test func (c *Client) startStopListener(ctx context.Context) error { + logger := c.logger.Named("stopListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterStopRequestAgent(ctx, c.sessionConfig.AgentIdentification) if err != nil { + logger.Error("could not open agent stream", zap.Error(err)) return fmt.Errorf("could not open agent stream: %w", err) } @@ -22,16 +27,22 @@ func (c *Client) startStopListener(ctx context.Context) error { for { resp := proto.StopRequest{} err := stream.RecvMsg(&resp) + if err != nil { + logger.Error("could not get message from stop stream", zap.Error(err)) + } if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("stop stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to stop stream") return } if err != nil { + logger.Error("could not get message from stop stream", zap.Error(err)) log.Println("could not get message from trigger stream: %w", err) time.Sleep(1 * time.Second) continue @@ -40,6 +51,7 @@ func (c *Client) startStopListener(ctx context.Context) error { // TODO: get context from request err = c.stopListener(context.Background(), &resp) if err != nil { + logger.Error("could not handle stop request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_listen_for_trigger_requests.go b/agent/client/workflow_listen_for_trigger_requests.go index 2d609a11aa..63cb7af32e 100644 --- a/agent/client/workflow_listen_for_trigger_requests.go +++ b/agent/client/workflow_listen_for_trigger_requests.go @@ -8,13 +8,18 @@ import ( "github.com/kubeshop/tracetest/agent/proto" "github.com/kubeshop/tracetest/server/telemetry" + "go.uber.org/zap" ) func (c *Client) startTriggerListener(ctx context.Context) error { + logger := c.logger.Named("triggerListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterTriggerAgent(ctx, c.sessionConfig.AgentIdentification) if err != nil { + logger.Error("could not open agent stream", zap.Error(err)) return fmt.Errorf("could not open agent stream: %w", err) } @@ -22,16 +27,22 @@ func (c *Client) startTriggerListener(ctx context.Context) error { for { resp := proto.TriggerRequest{} err := stream.RecvMsg(&resp) + if err != nil { + logger.Error("could not get message from stop stream", zap.Error(err)) + } if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("stop stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to stop stream") return } if err != nil { + logger.Error("could not get message from stop stream", zap.Error(err)) log.Println("could not get message from trigger stream: %w", err) time.Sleep(1 * time.Second) continue @@ -39,11 +50,13 @@ func (c *Client) startTriggerListener(ctx context.Context) error { ctx, err := telemetry.ExtractContextFromStream(stream) if err != nil { + logger.Error("could not extract context from stream", zap.Error(err)) log.Println("could not extract context from stream %w", err) } err = c.triggerListener(ctx, &resp) if err != nil { + logger.Error("could not handle trigger request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_ping.go b/agent/client/workflow_ping.go index 7794998011..6642fd44c0 100644 --- a/agent/client/workflow_ping.go +++ b/agent/client/workflow_ping.go @@ -6,25 +6,35 @@ import ( "time" "github.com/kubeshop/tracetest/agent/proto" + "go.uber.org/zap" ) func (c *Client) startHeartBeat(ctx context.Context) error { + logger := c.logger.Named("pingListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) ticker := time.NewTicker(c.config.PingPeriod) go func() { for range ticker.C { _, err := client.Ping(ctx, c.sessionConfig.AgentIdentification) + if err != nil { + log.Println("could not send ping: %w", err) + } if isEndOfFileError(err) || isCancelledError(err) { + log.Println("ping stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + log.Println("reconnected to ping stream") return } if err != nil { + logger.Error("could not get message from ping stream", zap.Error(err)) log.Println("could not get message from ping stream: %w", err) time.Sleep(1 * time.Second) continue diff --git a/agent/client/workflow_shutdown.go b/agent/client/workflow_shutdown.go index a25c6d39e2..75051c6417 100644 --- a/agent/client/workflow_shutdown.go +++ b/agent/client/workflow_shutdown.go @@ -7,13 +7,18 @@ import ( "time" "github.com/kubeshop/tracetest/agent/proto" + "go.uber.org/zap" ) func (c *Client) startShutdownListener(ctx context.Context) error { + logger := c.logger.Named("shutdownListener") + logger.Debug("Starting") + client := proto.NewOrchestratorClient(c.conn) stream, err := client.RegisterShutdownListener(ctx, c.sessionConfig.AgentIdentification) if err != nil { + logger.Error("could not open agent stream", zap.Error(err)) return fmt.Errorf("could not open agent stream: %w", err) } @@ -22,16 +27,23 @@ func (c *Client) startShutdownListener(ctx context.Context) error { resp := proto.ShutdownRequest{} err := stream.RecvMsg(&resp) + if err != nil { + logger.Error("could not get message from shutdown stream", zap.Error(err)) + } + if isEndOfFileError(err) || isCancelledError(err) { + logger.Debug("shutdown stream closed") return } reconnected, err := c.handleDisconnectionError(err) if reconnected { + logger.Warn("reconnected to shutdown stream") return } if err != nil { + logger.Error("could not get message from shutdown stream", zap.Error(err)) log.Println("could not get message from shutdown stream: %w", err) time.Sleep(1 * time.Second) continue @@ -40,6 +52,7 @@ func (c *Client) startShutdownListener(ctx context.Context) error { // TODO: get context from request err = c.shutdownListener(context.Background(), &resp) if err != nil { + logger.Error("could not handle shutdown request", zap.Error(err)) fmt.Println(err.Error()) } } diff --git a/agent/client/workflow_startup.go b/agent/client/workflow_startup.go index d3e78cbbe4..4a38f16a3f 100644 --- a/agent/client/workflow_startup.go +++ b/agent/client/workflow_startup.go @@ -6,6 +6,7 @@ import ( "time" "github.com/kubeshop/tracetest/agent/proto" + "go.uber.org/zap" ) // The startup workflow consists in exchanging information about the server @@ -14,15 +15,20 @@ import ( // Agent sends information about authentication and identification, server responds with // a configuration object that must be used when connected to that server. func (c *Client) startup(ctx context.Context) error { + logger := c.logger.Named("startup") + logger.Debug("Starting") + orchestratorClient := proto.NewOrchestratorClient(c.conn) request, err := c.getConnectionRequest() if err != nil { + logger.Error("could not get connection request", zap.Error(err)) return err } response, err := orchestratorClient.Connect(ctx, request) if err != nil { + logger.Error("could not send request to server", zap.Error(err)) return fmt.Errorf("could not send request to server: %w", err) } @@ -31,5 +37,7 @@ func (c *Client) startup(ctx context.Context) error { AgentIdentification: response.Identification, } + logger.Debug("Received configuration from server", zap.Any("config", c.sessionConfig)) + return nil } diff --git a/agent/runner/runner.go b/agent/runner/runner.go index b04e60b5de..8a3e2a258f 100644 --- a/agent/runner/runner.go +++ b/agent/runner/runner.go @@ -12,6 +12,7 @@ import ( "github.com/kubeshop/tracetest/agent/ui" "github.com/kubeshop/tracetest/cli/config" + "github.com/kubeshop/tracetest/cli/pkg/oauth" "github.com/kubeshop/tracetest/cli/pkg/resourcemanager" "go.uber.org/zap" @@ -38,7 +39,7 @@ func NewRunner(configurator config.Configurator, resources *resourcemanager.Regi } } -func (s *Runner) Run(ctx context.Context, cfg config.Config, flags agentConfig.Flags) error { +func (s *Runner) Run(ctx context.Context, cfg config.Config, flags agentConfig.Flags, verbose bool) error { s.ui.Banner(config.Version) s.ui.Println(`Tracetest start launches a lightweight agent. It enables you to run tests and collect traces with Tracetest. Once started, Tracetest Agent exposes OTLP ports 4317 and 4318 to ingest traces via gRCP and HTTP.`) @@ -56,6 +57,10 @@ Once started, Tracetest Agent exposes OTLP ports 4317 and 4318 to ingest traces if enableLogging(flags.LogLevel) { var err error atom := zap.NewAtomicLevel() + if verbose { + atom.SetLevel(zapcore.DebugLevel) + } + logger, err = zap.NewDevelopment() if err != nil { return fmt.Errorf("could not create logger: %w", err) @@ -73,6 +78,10 @@ Once started, Tracetest Agent exposes OTLP ports 4317 and 4318 to ingest traces } s.logger = logger + s.configurator = s.configurator.WithLogger(logger) + oauth.SetLogger(logger) + + s.logger.Debug("Starting agent with flags", zap.Any("flags", flags)) return s.configurator.Start(ctx, &cfg, flags) } @@ -105,22 +114,30 @@ func (s *Runner) onStartAgent(ctx context.Context, cfg config.Config) { func (s *Runner) StartAgent(ctx context.Context, endpoint, agentApiKey, uiEndpoint string) error { cfg, err := agentConfig.LoadConfig() + s.logger.Debug("Loaded agent config", zap.Any("config", cfg)) if err != nil { + s.logger.Error("Could not load agent config", zap.Error(err)) return err } if endpoint != "" { + s.logger.Debug("Overriding agent endpoint", zap.String("endpoint", endpoint)) cfg.ServerURL = endpoint } + s.logger.Debug("Agent endpoint", zap.String("endpoint", cfg.ServerURL)) if agentApiKey != "" { + s.logger.Debug("Overriding agent api key", zap.String("apiKey", agentApiKey)) cfg.APIKey = agentApiKey } + s.logger.Debug("Agent api key", zap.String("apiKey", cfg.APIKey)) if s.mode == agentConfig.Mode_Desktop { + s.logger.Debug("Starting agent in desktop mode") return s.RunDesktopStrategy(ctx, cfg, uiEndpoint) } + s.logger.Debug("Starting agent in verbose mode") return s.RunVerboseStrategy(ctx, cfg) } diff --git a/agent/runner/session.go b/agent/runner/session.go index db3e40c1a1..c5957dcb60 100644 --- a/agent/runner/session.go +++ b/agent/runner/session.go @@ -36,10 +36,12 @@ func (s *Session) WaitUntilDisconnected() { // Start the agent session with given configuration func StartSession(ctx context.Context, cfg config.Config, observer event.Observer, logger *zap.Logger) (*Session, error) { + logger.Debug("Starting agent session") observer = event.WrapObserver(observer) tracer, err := telemetry.GetTracer(ctx, cfg.CollectorEndpoint, cfg.Name) if err != nil { + logger.Error("Failed to create tracer", zap.Error(err)) observer.Error(err) return nil, err } diff --git a/cli/cmd/start_cmd.go b/cli/cmd/start_cmd.go index 05fa9313d3..a2d60d602d 100644 --- a/cli/cmd/start_cmd.go +++ b/cli/cmd/start_cmd.go @@ -70,7 +70,7 @@ var startCmd = &cobra.Command{ flags.Mode = agentConfig.Mode(cfg.Mode) } - err = agentRunner.Run(ctx, cliConfig, flags) + err = agentRunner.Run(ctx, cliConfig, flags, verbose) return "", err })), PostRun: teardownCommand, diff --git a/cli/config/configurator.go b/cli/config/configurator.go index c1bc14b4ce..73f637db30 100644 --- a/cli/config/configurator.go +++ b/cli/config/configurator.go @@ -13,11 +13,13 @@ import ( "github.com/kubeshop/tracetest/cli/pkg/oauth" "github.com/kubeshop/tracetest/cli/pkg/resourcemanager" cliUI "github.com/kubeshop/tracetest/cli/ui" + "go.uber.org/zap" ) type onFinishFn func(context.Context, Config) type Configurator struct { + logger *zap.Logger resources *resourcemanager.Registry ui cliUI.UI onFinish onFinishFn @@ -30,6 +32,7 @@ func NewConfigurator(resources *resourcemanager.Registry) Configurator { ui := cliUI.DefaultUI return Configurator{ + logger: zap.NewNop(), resources: resources, ui: ui, onFinish: func(_ context.Context, _ Config) { @@ -43,6 +46,11 @@ func NewConfigurator(resources *resourcemanager.Registry) Configurator { } } +func (c Configurator) WithLogger(logger *zap.Logger) Configurator { + c.logger = logger + return c +} + func (c Configurator) WithOnFinish(onFinish onFinishFn) Configurator { c.onFinish = onFinish return c @@ -59,34 +67,44 @@ func (c Configurator) Start(ctx context.Context, prev *Config, flags agentConfig c.flags = &flags var serverURL string + c.logger.Debug("Starting configurator", zap.Any("flags", flags), zap.Any("prev", prev), zap.String("serverURL", serverURL)) + if c.flags.AutomatedEnvironmentCanBeInferred() { + c.logger.Debug("Automated environment detected, skipping prompts") // avoid prompts on automated or non-interactive environments serverURL = c.lastUsedURL(prev) } else { + c.logger.Debug("Interactive environment detected, prompting for server URL") var err error serverURL, err = c.getServerURL(prev) if err != nil { + c.logger.Error("Invalid server URL", zap.Error(err)) return err } } c.finalServerURL = serverURL + c.logger.Debug("Final server URL", zap.String("serverURL", serverURL)) cfg, err := c.createConfig(serverURL) if err != nil { + c.logger.Error("Could not create config", zap.Error(err)) return err } cfg, err, isOSS := c.populateConfigWithVersionInfo(ctx, cfg) if err != nil { + c.logger.Error("Could not populate config with version info", zap.Error(err)) return err } if isOSS { + c.logger.Debug("OSS server detected, skipping OAuth") // we don't need anything else for OSS return nil } if c.flags.CI { + c.logger.Debug("CI environment detected, skipping OAuth") _, err = Save(ctx, cfg) if err != nil { return err @@ -96,9 +114,12 @@ func (c Configurator) Start(ctx context.Context, prev *Config, flags agentConfig _, err = c.handleOAuth(ctx, cfg, prev) if err != nil { + c.logger.Error("Could not handle OAuth", zap.Error(err)) return err } + c.logger.Debug("Successfully configured OAuth") + return nil } @@ -229,31 +250,39 @@ func (c Configurator) populateConfigWithVersionInfo(ctx context.Context, cfg Con func (c Configurator) handleOAuth(ctx context.Context, cfg Config, prev *Config) (Config, error) { if prev != nil && cfg.UIEndpoint == prev.UIEndpoint { + c.logger.Debug("Using previous UI endpoint", zap.String("uiEndpoint", cfg.UIEndpoint)) if prev != nil && prev.Jwt != "" { + c.logger.Debug("Using previous JWT") cfg.Jwt = prev.Jwt cfg.Token = prev.Token } } if c.flags.Token != "" { + c.logger.Debug("Using token from flag") var err error cfg, err = c.exchangeToken(cfg, c.flags.Token) if err != nil { + c.logger.Error("Could not exchange token", zap.Error(err)) return Config{}, err } } if c.flags.AgentApiKey != "" { + c.logger.Debug("Using agent API key from flag") cfg.AgentApiKey = c.flags.AgentApiKey c.showOrganizationSelector(ctx, prev, cfg) return cfg, nil } if cfg.Jwt != "" { + c.logger.Debug("Using JWT from config") c.showOrganizationSelector(ctx, prev, cfg) return cfg, nil } + c.logger.Debug("No JWT found, executing user login") + return c.ExecuteUserLogin(ctx, cfg, prev) } @@ -270,8 +299,10 @@ func (c Configurator) ExecuteUserLogin(ctx context.Context, cfg Config, prev *Co } func (c Configurator) exchangeToken(cfg Config, token string) (Config, error) { + c.logger.Debug("Exchanging token", zap.String("token", token)) jwt, err := oauth.ExchangeToken(cfg.OAuthEndpoint(), token) if err != nil { + c.logger.Error("Could not exchange token", zap.Error(err)) return Config{}, err } @@ -280,6 +311,7 @@ func (c Configurator) exchangeToken(cfg Config, token string) (Config, error) { claims, err := GetTokenClaims(jwt) if err != nil { + c.logger.Error("Could not get token claims", zap.Error(err)) return Config{}, err } @@ -287,9 +319,11 @@ func (c Configurator) exchangeToken(cfg Config, token string) (Config, error) { environmentId := claims["environment_id"].(string) if organizationId != "" { + c.logger.Debug("Using organization ID from token", zap.String("organizationID", organizationId)) c.flags.OrganizationID = organizationId } if environmentId != "" { + c.logger.Debug("Using environment ID from token", zap.String("environmentID", environmentId)) c.flags.EnvironmentID = environmentId } @@ -308,6 +342,7 @@ func getFirstNonEmptyString(values []string) string { func (c Configurator) onOAuthSuccess(ctx context.Context, cfg Config, prev *Config) func(token, jwt string) { return func(token, jwt string) { + c.logger.Debug("OAuth success") cfg.Jwt = jwt cfg.Token = token @@ -320,10 +355,13 @@ func (c Configurator) onOAuthFailure(err error) { } func (c Configurator) showOrganizationSelector(ctx context.Context, prev *Config, cfg Config) { + c.logger.Debug("Showing organization selector", zap.String("organizationID", cfg.OrganizationID), zap.String("environmentID", cfg.EnvironmentID)) cfg.OrganizationID = c.flags.OrganizationID if cfg.OrganizationID == "" && c.flags.AgentApiKey == "" { + c.logger.Debug("Organization ID not found, prompting for organization") orgID, err := c.organizationSelector(ctx, cfg, prev) if err != nil { + c.logger.Error("Could not select organization", zap.Error(err)) c.errorHandlerFn(ctx, err) return } @@ -333,6 +371,7 @@ func (c Configurator) showOrganizationSelector(ctx context.Context, prev *Config cfg.EnvironmentID = c.flags.EnvironmentID if cfg.EnvironmentID == "" && c.flags.AgentApiKey == "" { + c.logger.Debug("Environment ID not found, prompting for environment") envID, err := c.environmentSelector(ctx, cfg, prev) if err != nil { c.errorHandlerFn(ctx, err) @@ -344,6 +383,7 @@ func (c Configurator) showOrganizationSelector(ctx context.Context, prev *Config ctx, err := Save(ctx, cfg) if err != nil { + c.logger.Error("Could not save configuration", zap.Error(err)) c.errorHandlerFn(ctx, err) return } diff --git a/cli/pkg/oauth/oauth.go b/cli/pkg/oauth/oauth.go index 0db69d8373..afb148a82f 100644 --- a/cli/pkg/oauth/oauth.go +++ b/cli/pkg/oauth/oauth.go @@ -9,6 +9,7 @@ import ( "sync" "github.com/kubeshop/tracetest/cli/ui" + "go.uber.org/zap" ) type OnAuthSuccess func(token string, jwt string) @@ -72,33 +73,47 @@ type JWTResponse struct { Jwt string `json:"jwt"` } +var logger = zap.NewNop() + +func SetLogger(l *zap.Logger) { + logger = l +} + func ExchangeToken(endpoint string, token string) (string, error) { + logger.Debug("Exchanging token", zap.String("endpoint", endpoint), zap.String("token", token)) req, err := http.NewRequest("GET", fmt.Sprintf("%s/tokens/%s/exchange", endpoint, token), nil) if err != nil { + logger.Debug("Failed to create request", zap.Error(err)) return "", fmt.Errorf("failed to create request: %w", err) } res, err := http.DefaultClient.Do(req) if err != nil { + logger.Debug("Failed to exchange token", zap.Error(err)) return "", fmt.Errorf("failed to exchange token: %w", err) } if res.StatusCode != http.StatusCreated { + logger.Debug("Failed to exchange token", zap.String("status", res.Status)) return "", fmt.Errorf("failed to exchange token: %s", res.Status) } defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { + logger.Debug("Failed to read response body", zap.Error(err)) return "", fmt.Errorf("failed to read response body: %w", err) } var jwtResponse JWTResponse err = json.Unmarshal(body, &jwtResponse) if err != nil { + logger.Debug("Failed to unmarshal response body", zap.Error(err)) return "", fmt.Errorf("failed to unmarshal response body: %w", err) } + logger.Debug("Token exchanged") + return jwtResponse.Jwt, nil }