<commit_before>package main

import (
	"net/http"
	"os"

	"github.com/gitpods/gitpod/handler"
	"github.com/gitpods/gitpod/store"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/gobuffalo/packr"
	"github.com/urfave/cli"
)

func ActionWeb(c *cli.Context) error {
	addr := c.String("addr")
	env := c.String("env")

	// Create the logger based on the environment: production/development/test
	logger := newLogger(env)

	// Create FileServer handler with buffalo's packr to serve file from disk or from within the binary.
	// The path is relative to this file.
	box := packr.NewBox("../../public")

	// Create a simple store running in memory for example purposes
	userStore := store.NewUserInMemory()

	// Create the http router and return it for use
	r := handler.NewRouter(logger, box, userStore)

	level.Info(logger).Log("msg", "starting gitpod", "addr", addr)
	return http.ListenAndServe(addr, r)
}

func newLogger(env string) log.Logger {
	var logger log.Logger
	if env == DefaultEnv {
		logger = log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
		logger = level.NewFilter(logger, level.AllowInfo())
	} else {
		logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
		logger = level.NewFilter(logger, level.AllowAll())
	}

	return log.With(logger, "ts", log.DefaultTimestampUTC)
}<commit_msg>Add a first try to implement http server graceful shutdown<commit_after>package main

import (
	"context"
	"net/http"
	"os"
	"time"

	"github.com/gitpods/gitpod/handler"
	"github.com/gitpods/gitpod/store"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/gobuffalo/packr"
	"github.com/oklog/oklog/pkg/group"
	"github.com/urfave/cli"
)

func ActionWeb(c *cli.Context) error {
	addr := c.String("addr")
	env := c.String("env")

	// Create the logger based on the environment: production/development/test
	logger := newLogger(env)

	var server *http.Server

	var gr group.Group
	gr.Add(func() error {
		// Create FileServer handler with buffalo's packr to serve file from disk or from within the binary.
		// The path is relative to this file.
		box := packr.NewBox("../../public")

		// Create a simple store running in memory for example purposes
		userStore := store.NewUserInMemory()

		// Create the http router and return it for use
		r := handler.NewRouter(logger, box, userStore)

		level.Info(logger).Log("msg", "starting gitpod", "addr", addr)

		server := &http.Server{Addr: addr, Handler: r}
		return server.ListenAndServe()
	}, func(err error) {
		ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
		server.Shutdown(ctx)
		level.Info(logger).Log(
			"msg", "http server shutdown gracefully",
			"err", err,
		)
	})

	return gr.Run()
}

func newLogger(env string) log.Logger {
	var logger log.Logger
	if env == DefaultEnv {
		logger = log.NewJSONLogger(log.NewSyncWriter(os.Stdout))
		logger = level.NewFilter(logger, level.AllowInfo())
	} else {
		logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stdout))
		logger = level.NewFilter(logger, level.AllowAll())
	}

	return log.With(logger, "ts", log.DefaultTimestampUTC)
}
{'fraction_non_alphanumeric': 0.1399548532731377, 'fraction_numerical': 0.0003224766204450177, 'mean_word_length': 4.152823920265781, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3576721', 'n_tokens_mistral': 1108, 'n_tokens_neox': 1052, 'n_words': 264}