func main()

in Elastiflix/go-favorite-elastic-manual/main.go [55:210]


func main() {
	delayTime, _ := strconv.Atoi(os.Getenv("TOGGLE_SERVICE_DELAY"))

	logrus.AddHook(&apmlogrus.Hook{})

	redisHost := os.Getenv("REDIS_HOST")
	if redisHost == "" {
		redisHost = "localhost"
	}

	redisPort := os.Getenv("REDIS_PORT")
	if redisPort == "" {
		redisPort = "6379"
	}

	applicationPort := os.Getenv("APPLICATION_PORT")
	if applicationPort == "" {
		applicationPort = "5000"
	}

	serviceName := os.Getenv("ELASTIC_APM_SERVICE_NAME")
	if serviceName == "" {
		serviceName = "python-favorite-elastic-manual"
	}

	secretToken := os.Getenv("ELASTIC_APM_SECRET_TOKEN")
	if secretToken == "" {
		log.Fatal("ELASTIC_APM_SECRET_TOKEN environment variable not set")
	}

	serverURL := os.Getenv("ELASTIC_APM_SERVER_URL")
	if serverURL == "" {
		log.Fatal("ELASTIC_APM_SERVER_URL environment variable not set")
	}

	// Initialize Redis client
	rdb := redis.NewClient(&redis.Options{
		Addr:     redisHost + ":" + redisPort,
		Password: "",
		DB:       0,
	})

	rdb.AddHook(apmgoredis.NewHook())

	// Initialize router
	r := gin.New()
	r.Use(apmgin.Middleware(r))
	r.Use(logrusMiddleware)

	
	// Define routes
	r.GET("/", func(c *gin.Context) {
		contextLogger(c).Infof("Main request successful")
		c.String(http.StatusOK, "Hello World!")
	})

	r.GET("/favorites", func(c *gin.Context) {
		// artificial sleep for delayTime
		time.Sleep(time.Duration(rand.NormFloat64()*float64(delayTime / 10)+float64(delayTime))* time.Millisecond)

		userID := c.Query("user_id")

		contextLogger(c).Infof("Getting favorites for user %q", userID)

		favorites, err := rdb.SMembers(c.Request.Context(), userID).Result()
		if err != nil {
			contextLogger(c).Error("Failed to get favorites for user %q", userID)
			c.String(http.StatusInternalServerError, "Failed to get favorites")
			return
		}

		contextLogger(c).Infof("User %q has favorites %q", userID, favorites)

		c.JSON(http.StatusOK, gin.H{
			"favorites": favorites,
		})
	})

	r.POST("/favorites", func(c *gin.Context) {
		// artificial sleep for delayTime
		time.Sleep(time.Duration(rand.NormFloat64()*float64(delayTime / 10)+float64(delayTime))* time.Millisecond)
		
		userID := c.Query("user_id")

		contextLogger(c).Infof("Adding or removing favorites for user %q", userID)

		var data struct {
			ID int `json:"id"`
		}
		if err := c.BindJSON(&data); err != nil {
			contextLogger(c).Error("Failed to decode request body for user %q", userID)
			c.String(http.StatusBadRequest, "Failed to decode request body")
			return
		}

		redisResponse := rdb.SRem(c.Request.Context(), userID, data.ID)
		if redisResponse.Err() != nil {
			contextLogger(c).Error("Failed to remove movie from favorites for user %q", userID)
			c.String(http.StatusInternalServerError, "Failed to remove movie from favorites")
			return
		}

		if redisResponse.Val() == 0 {
			rdb.SAdd(c.Request.Context(), userID, data.ID)
		}

		favorites, err := rdb.SMembers(c.Request.Context(), userID).Result()
		contextLogger(c).Infof("Getting favorites for user")
		if err != nil {
			contextLogger(c).Error("Failed to get favorites for user %q", userID)
			c.String(http.StatusInternalServerError, "Failed to get favorites")
			return
		}

		contextLogger(c).Infof("User %q has favorites %q", userID, favorites)

		// if enabled, in 50% of the cases, sleep for 2 seconds
		sleepTimeStr := os.Getenv("TOGGLE_CANARY_DELAY")
		sleepTime := 0
		if sleepTimeStr != "" {
			sleepTime, _ = strconv.Atoi(sleepTimeStr)
		}

		if sleepTime > 0 && rand.Float64() < 0.5 {
			time.Sleep(time.Duration(rand.NormFloat64()*float64(sleepTime / 10)+float64(sleepTime))* time.Millisecond)
			// add label to transaction
			logger.Info("Canary enabled")
			tx := apm.TransactionFromContext(c.Request.Context())
			tx.Context.SetLabel("quiz_solution", "correlations")
			tx.Context.SetLabel("canary", "test-new-feature")

			// read env var TOGGLE_CANARY_FAILURE, which is a float between 0 and 1

			if toggleCanaryFailureStr := os.Getenv("TOGGLE_CANARY_FAILURE"); toggleCanaryFailureStr != "" {
				toggleCanaryFailure, err := strconv.ParseFloat(toggleCanaryFailureStr, 64)
				if err != nil {
					toggleCanaryFailure = 0
				}
				if rand.Float64() < toggleCanaryFailure {
					// throw an exception in 50% of the cases
					logger.Error("Something went wrong")
					panic("Something went wrong")
				}
			}
		}

		c.JSON(http.StatusOK, gin.H{
			"favorites": favorites,
		})
	})

	// Start server
	logger.Infof("App startup")
	log.Fatal(http.ListenAndServe(":"+applicationPort, r))
	logger.Infof("App stopped")
}