diff --git a/cmd/deploy/service.go b/cmd/deploy/service.go index 9b51ed4a..7c057a90 100644 --- a/cmd/deploy/service.go +++ b/cmd/deploy/service.go @@ -53,29 +53,20 @@ func init() { func execute(cmd *cobra.Command) { env = config.EnsureEnvPresent(env) ctx := cmd.Context() - traceID := util.GenerateTraceID() - contextWithTrace := context.WithValue(ctx, constant.TraceIDKey, traceID) - verboseEnabled, err := cmd.Flags().GetBool(constant.VerboseFlag) - if err != nil { - log.Fatal(err) - } - contextWithTrace = context.WithValue(contextWithTrace, constant.VerboseEnabledKey, verboseEnabled) - - if isStrictEnvironment(contextWithTrace, env) { + if isStrictEnvironment(ctx, env) { consentMessage := fmt.Sprintf(constant.ConsentMessageTemplate, env) util.AskForConfirmation(env, consentMessage) } - if (serviceName == "" && serviceVersion == "" && labels == "") && (definitionFile != "" && provisioningFile != "") { - deployUsingFiles(contextWithTrace) + deployUsingFiles(ctx) } else if (serviceName != "" && serviceVersion != "" && labels == "") && (definitionFile == "" && provisioningFile == "") { - deployUsingServiceNameAndVersion(contextWithTrace) + deployUsingServiceNameAndVersion(ctx) } else if (serviceName != "" && labels != "" && serviceVersion == "") && (definitionFile == "" && provisioningFile == "") { if err := validateLabels(labels); err != nil { log.Fatal("Invalid labels format: ", err) } - deployUsingServiceNameAndLabels(contextWithTrace) + deployUsingServiceNameAndLabels(ctx) } else { log.Fatal("Invalid combination of flags. Use either (service name and version) or (definitionFile and provisioningFile).") } diff --git a/internal/service/client.go b/internal/service/client.go index ec857b5f..d616b6a7 100644 --- a/internal/service/client.go +++ b/internal/service/client.go @@ -9,8 +9,6 @@ import ( "time" "github.com/dream11/odin/pkg/config" - "github.com/dream11/odin/pkg/constant" - "github.com/dream11/odin/pkg/util" log "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -23,14 +21,8 @@ func getTLSOpts(appConfig *configuration.Configuration) grpc.DialOption { tlsConf := tls.Config{ ServerName: strings.Split(appConfig.BackendAddress, ":")[0], } - if appConfig.Plaintext { - // Disable TLS - return grpc.WithTransportCredentials(insecure.NewCredentials()) - } - if appConfig.Insecure { - // Perform TLS handshake but skip certificate verification - tlsConf.InsecureSkipVerify = true - } + // Disable TLS + return grpc.WithTransportCredentials(insecure.NewCredentials()) return grpc.WithTransportCredentials(credentials.NewTLS(&tlsConf)) @@ -38,19 +30,11 @@ func getTLSOpts(appConfig *configuration.Configuration) grpc.DialOption { func grpcClient(ctx *context.Context) (*grpc.ClientConn, *context.Context, error) { appConfig := config.GetConfig() - var traceID string - var contextWithTrace context.Context - if (*ctx).Value(constant.TraceIDKey) == nil { - traceID = util.GenerateTraceID() - contextWithTrace = context.WithValue(*ctx, constant.TraceIDKey, traceID) - } else { - traceID = (*ctx).Value(constant.TraceIDKey).(string) - contextWithTrace = *ctx - } if appConfig.BackendAddress == "" { log.Fatal("Cannot create grpc client: Backend address is empty in config! Run `odin configure` to set backend address") } + opts := []grpc.DialOption{ grpc.WithKeepaliveParams( keepalive.ClientParameters{ @@ -61,11 +45,11 @@ func grpcClient(ctx *context.Context) (*grpc.ClientConn, *context.Context, error getTLSOpts(appConfig), } conn, err := grpc.NewClient(appConfig.BackendAddress, opts...) - if err != nil { return nil, nil, err } - // Enrich context with authorisation metadata - requestCtx := metadata.AppendToOutgoingContext(contextWithTrace, "Authorization", fmt.Sprintf("Bearer %s", appConfig.AccessToken), string(constant.TraceIDKey), traceID) + + // Enrich context with authorization metadata only + requestCtx := metadata.AppendToOutgoingContext(*ctx, "Authorization", fmt.Sprintf("Bearer %s", appConfig.AccessToken)) return conn, &requestCtx, nil } diff --git a/internal/service/component.go b/internal/service/component.go index 5a606009..35cf8d06 100644 --- a/internal/service/component.go +++ b/internal/service/component.go @@ -24,7 +24,7 @@ func (e *Component) OperateComponent(ctx *context.Context, request *serviceProto defer cancelFunction() // Start log streaming in background - go streamLogs(streamCtx, ctx, request.GetServiceName()) + go streamLogs(streamCtx, ctx, request.GetServiceName(), request.GetEnvName()) // Attempt operation with retries return retry.Do( @@ -52,8 +52,11 @@ func (e *Component) OperateComponent(ctx *context.Context, request *serviceProto return response.GetServiceResponse().GetServiceStatus().GetServiceStatus(), response.GetServiceResponse().GetServiceStatus().GetServiceAction() } + getTraceId := func(response *serviceProto.OperateServiceResponse) string { + return response.GetTraceId() + } - return handleResponse(stream, cancelFunction, getMessage, getStatus) + return handleResponse(stream, cancelFunction, getMessage, getStatus, getTraceId) }, retry.Delay(constant.Delay), retry.RetryIf(isRetryableError), diff --git a/internal/service/environment.go b/internal/service/environment.go index b3fa41bf..8c4eea64 100644 --- a/internal/service/environment.go +++ b/internal/service/environment.go @@ -51,6 +51,7 @@ func (e *Environment) CreateEnvironment(ctx *context.Context, request *environme return err } var message string + var traceID string for { response, err := stream.Recv() spinnerInstance.Stop() @@ -61,6 +62,12 @@ func (e *Environment) CreateEnvironment(ctx *context.Context, request *environme return err } if response != nil { + // Print Trace ID only once, when it first arrives + if traceID == "" && response.TraceId != "" { + traceID = response.TraceId + log.Infof("Generated Trace Id for env creation: %s", traceID) + } + message = response.Message spinnerInstance.Prefix = fmt.Sprintf(" %s ", response.Message) spinnerInstance.Start() @@ -91,6 +98,7 @@ func (e *Environment) DeleteEnvironment(ctx *context.Context, request *environme return err } var message string + var traceID string for { response, err := stream.Recv() spinnerInstance.Stop() @@ -101,6 +109,11 @@ func (e *Environment) DeleteEnvironment(ctx *context.Context, request *environme return err } if response != nil { + // Print Trace ID only once, when it first arrives + if traceID == "" && response.TraceId != "" { + traceID = response.TraceId + log.Infof("Generated Trace Id for env creation: %s", traceID) + } message = response.Message spinnerInstance.Prefix = fmt.Sprintf(" %s ", response.Message) spinnerInstance.Start() diff --git a/internal/service/service.go b/internal/service/service.go index a99e3158..b4146c64 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -48,6 +48,8 @@ type getStatus[R any] func(response R) (serviceAction, serviceStatus string) type getMessage[R any] func(response R) string +type getTraceId[R any] func(response R) string + // DeployService deploys service func (e *Service) DeployService(ctx *context.Context, request *serviceProto.DeployServiceRequest) error { log.Info("Deploying Service...") @@ -57,7 +59,7 @@ func (e *Service) DeployService(ctx *context.Context, request *serviceProto.Depl defer cancelFunction() // Start log streaming in background - go streamLogs(streamCtx, ctx, request.GetServiceDefinition().GetName()) + go streamLogs(streamCtx, ctx, request.GetServiceDefinition().GetName(), request.GetEnvName()) // Attempt deployment with retries return retry.Do( @@ -86,7 +88,11 @@ func (e *Service) DeployService(ctx *context.Context, request *serviceProto.Depl response.GetServiceResponse().GetServiceStatus().GetServiceAction() } - return handleResponse(stream, cancelFunction, getMessage, getStatus) + getTraceId := func(response *serviceProto.DeployServiceResponse) string { + return response.GetTraceId() + } + + return handleResponse(stream, cancelFunction, getMessage, getStatus, getTraceId) }, retry.Delay(constant.Delay), retry.RetryIf(isRetryableError), @@ -162,7 +168,7 @@ func (e *Service) DeployReleasedService(ctx *context.Context, request *servicePr defer cancelFunction() // Start log streaming in background - go streamLogs(streamCtx, ctx, request.GetServiceIdentifier().GetServiceName()) + go streamLogs(streamCtx, ctx, request.GetServiceIdentifier().GetServiceName(), request.GetEnvName()) // Attempt deployment with retries return retry.Do( @@ -192,7 +198,11 @@ func (e *Service) DeployReleasedService(ctx *context.Context, request *servicePr response.GetServiceResponse().GetServiceStatus().GetServiceAction() } - return handleResponse(stream, cancelFunction, getMessage, getStatus) + getTraceId := func(response *serviceProto.DeployReleasedServiceResponse) string { + return response.GetTraceId() + } + + return handleResponse(stream, cancelFunction, getMessage, getStatus, getTraceId) }, retry.Delay(constant.Delay), retry.RetryIf(isRetryableError), @@ -210,7 +220,7 @@ func (e *Service) UndeployService(ctx *context.Context, request *serviceProto.Un defer cancelFunction() // Start log streaming in background - go streamLogs(streamCtx, &contextWithTrace, request.GetServiceName()) + go streamLogs(streamCtx, &contextWithTrace, request.GetServiceName(), request.GetEnvName()) conn, requestCtx, err := grpcClient(&contextWithTrace) if err != nil { @@ -261,7 +271,7 @@ func (e *Service) OperateService(ctx *context.Context, request *serviceProto.Ope defer cancelFunction() // Start log streaming in background - go streamLogs(streamCtx, ctx, request.GetServiceName()) + go streamLogs(streamCtx, ctx, request.GetServiceName(), request.GetEnvName()) // Attempt operation with retries return retry.Do( @@ -290,7 +300,11 @@ func (e *Service) OperateService(ctx *context.Context, request *serviceProto.Ope response.GetServiceResponse().GetServiceStatus().GetServiceAction() } - return handleResponse(stream, cancelFunction, getMessage, getStatus) + getTraceId := func(response *serviceProto.OperateServiceResponse) string { + return response.GetTraceId() + } + + return handleResponse(stream, cancelFunction, getMessage, getStatus, getTraceId) }, retry.Delay(constant.Delay), retry.RetryIf(isRetryableError), @@ -403,26 +417,26 @@ func (e *Service) GetConflictingServices(ctx *context.Context, request *serviceP } // streamLogs streams logs for a service -func streamLogs(streamCtx context.Context, ctx *context.Context, serviceName string) { +func streamLogs(streamCtx context.Context, ctx *context.Context, serviceName string, envName string) { var err error lastLogTime := int64(0) - traceID := (*ctx).Value(constant.TraceIDKey).(string) + //traceID := (*ctx).Value(constant.TraceIDKey).(string) follow := true // Start the spinner in a background goroutine - go func() { - spinnerInstance := spinner.New(spinner.CharSets[constant.SpinnerType], constant.SpinnerDelay) - err = spinnerInstance.Color(constant.SpinnerColor, constant.SpinnerStyle) - if err != nil { - spinnerInstance.Stop() - } - spinnerInstance.Prefix = fmt.Sprintf("Fetching live logs for service: %s ", serviceName) - spinnerInstance.Suffix = "\n" - spinnerInstance.Start() - time.Sleep(30 * time.Second) - spinnerInstance.Stop() - fmt.Printf("Fetching live logs for service: %s \n", serviceName) - }() - + //go func() { + //spinnerInstance := spinner.New(spinner.CharSets[constant.SpinnerType], constant.SpinnerDelay) + //err = spinnerInstance.Color(constant.SpinnerColor, constant.SpinnerStyle) + //if err != nil { + // spinnerInstance.Stop() + //} + //spinnerInstance.Prefix = fmt.Sprintf("Fetching live logs for service: %s ", serviceName) + //spinnerInstance.Suffix = "\n" + //spinnerInstance.Start() + //time.Sleep(30 * time.Second) + //spinnerInstance.Stop() + + //}() + fmt.Printf("Fetching live logs for service: %s \n", serviceName) for { select { case <-streamCtx.Done(): @@ -430,10 +444,10 @@ func streamLogs(streamCtx context.Context, ctx *context.Context, serviceName str default: // Get logs with retry on error lastLogTime, err = logsClient.GetLogs(ctx, &logs.GetLogsRequest{ - TraceId: &traceID, Follow: &follow, ServiceName: &serviceName, StartTime: &lastLogTime, + EnvName: &envName, }) if err != nil { @@ -445,10 +459,20 @@ func streamLogs(streamCtx context.Context, ctx *context.Context, serviceName str } // handleResponse streams the service deploy response and call cancel on action termination -func handleResponse[S StreamReceiverInterface[R], R any](stream S, cancelFunc context.CancelFunc, getMessage getMessage[R], getStatus getStatus[R]) error { +func handleResponse[S StreamReceiverInterface[R], R any](stream S, cancelFunc context.CancelFunc, getMessage getMessage[R], getStatus getStatus[R], getTraceId getTraceId[R]) error { var serviceAction, serviceStatus string + var traceID string + traceIdLogged := false for { response, err := stream.Recv() + traceID = getTraceId(response) + if !traceIdLogged { + if traceID != "" { + log.Info("Generated Trace Id for deploy service: ", traceID) + traceIdLogged = true + } + } + if err != nil { if isActionCompleted(serviceAction, serviceStatus) { cancelFunc() diff --git a/proto/dream11/od/environment/v1/environment.proto b/proto/dream11/od/environment/v1/environment.proto index d137a9b7..f2a0acca 100644 --- a/proto/dream11/od/environment/v1/environment.proto +++ b/proto/dream11/od/environment/v1/environment.proto @@ -69,18 +69,25 @@ message CreateEnvironmentRequest { string env_name = 1; repeated string accounts = 2; string provisioning_type = 3; + optional string trace_id = 4; + } message CreateEnvironmentResponse { string message = 1; + string trace_id = 2; + } message DeleteEnvironmentRequest { string env_name = 1; + optional string trace_id = 2; } message DeleteEnvironmentResponse { string message = 1; + string trace_id = 2; + } message IsStrictEnvironmentRequest { diff --git a/proto/dream11/od/logs/v1/logs.proto b/proto/dream11/od/logs/v1/logs.proto index a3a5f212..bec0377a 100644 --- a/proto/dream11/od/logs/v1/logs.proto +++ b/proto/dream11/od/logs/v1/logs.proto @@ -8,11 +8,11 @@ service LogsService { } message GetLogsRequest { - string trace_id = 1; optional bool follow = 2; optional string service_name = 3; optional string component_name = 4; - optional int64 start_time = 5; + optional string env_name = 5; + optional int64 start_time = 6; } message GetLogsResponse { diff --git a/proto/dream11/od/service/v1/service.proto b/proto/dream11/od/service/v1/service.proto index ecf14f09..148f3613 100644 --- a/proto/dream11/od/service/v1/service.proto +++ b/proto/dream11/od/service/v1/service.proto @@ -23,6 +23,7 @@ message DeployServiceRequest { string env_name = 1; dto.v1.ServiceDefinition service_definition = 2; dto.v1.ProvisioningConfig provisioning_config = 3; + optional string trace_id = 4; } message ServiceResponse { @@ -35,6 +36,7 @@ message ServiceResponse { message DeployReleasedServiceResponse { ServiceResponse service_response = 1; + string trace_id = 2; } message ServiceIdentifier { @@ -47,6 +49,7 @@ message ServiceIdentifier { message DeployReleasedServiceRequest { ServiceIdentifier service_identifier = 1; string env_name = 3; + optional string trace_id = 4; } message DeployServiceSetRequest { @@ -66,6 +69,7 @@ message DeployServiceSetServiceResponse { message DeployServiceResponse { ServiceResponse service_response = 1; + string trace_id = 2; } message ServiceStatus { @@ -100,10 +104,12 @@ message OperateServiceRequest { bool is_component_operation = 4; string operation = 5; optional google.protobuf.Struct config = 6; + optional string trace_id = 7; } message OperateServiceResponse { ServiceResponse service_response = 1; + string trace_id = 2; } message UndeployServiceRequest {