Enable profiler and profile-guided builds
I used the chance to simplify the Makefile, as this is required for the file check to work correctly. Variables should not contain quotes, as these will be included in the value otherwise.
This commit is contained in:

committed by
Sebastian Serth

parent
00952ca212
commit
1a378ce640
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,9 @@
|
||||
# Project binary
|
||||
/poseidon
|
||||
|
||||
# CPU profiling information
|
||||
cmd/poseidon/default.pgo
|
||||
|
||||
# Configuration file
|
||||
configuration.yaml
|
||||
tests/e2e/configuration.yaml
|
||||
|
30
Makefile
30
Makefile
@ -1,19 +1,23 @@
|
||||
PROJECT_NAME := "poseidon"
|
||||
REPOSITORY_OWNER = "openHPI"
|
||||
PKG := "github.com/$(REPOSITORY_OWNER)/$(PROJECT_NAME)/cmd/$(PROJECT_NAME)"
|
||||
PROJECT_NAME = poseidon
|
||||
REPOSITORY_OWNER = openHPI
|
||||
PKG = github.com/$(REPOSITORY_OWNER)/$(PROJECT_NAME)/cmd/$(PROJECT_NAME)
|
||||
UNIT_TESTS = $(shell go list ./... | grep -v /e2e | grep -v /recovery)
|
||||
|
||||
DOCKER_TAG := "poseidon:latest"
|
||||
DOCKER_OPTS := -v $(shell pwd)/configuration.yaml:/configuration.yaml
|
||||
# Define the PGO file to be used for the build
|
||||
PGO_FILE = ./cmd/$(PROJECT_NAME)/default.pgo
|
||||
|
||||
# Docker options
|
||||
DOCKER_TAG = poseidon:latest
|
||||
DOCKER_OPTS = -v $(shell pwd)/configuration.yaml:/configuration.yaml
|
||||
LOWER_REPOSITORY_OWNER = $(shell echo $(REPOSITORY_OWNER) | tr A-Z a-z)
|
||||
|
||||
# Define image to be used in e2e tests. Requires `make` to be available.
|
||||
E2E_TEST_DOCKER_CONTAINER := co_execenv_java
|
||||
E2E_TEST_DOCKER_TAG := 17
|
||||
E2E_TEST_DOCKER_IMAGE = "$(LOWER_REPOSITORY_OWNER)/$(E2E_TEST_DOCKER_CONTAINER):$(E2E_TEST_DOCKER_TAG)"
|
||||
E2E_TEST_DOCKER_CONTAINER = co_execenv_java
|
||||
E2E_TEST_DOCKER_TAG = 17
|
||||
E2E_TEST_DOCKER_IMAGE = $(LOWER_REPOSITORY_OWNER)/$(E2E_TEST_DOCKER_CONTAINER):$(E2E_TEST_DOCKER_TAG)
|
||||
# The base image of the e2e test image. This is used to build the base image as well.
|
||||
E2E_TEST_BASE_CONTAINER := docker_exec_phusion
|
||||
E2E_TEST_BASE_IMAGE = "$(LOWER_REPOSITORY_OWNER)/$(E2E_TEST_BASE_CONTAINER)"
|
||||
E2E_TEST_BASE_IMAGE = $(LOWER_REPOSITORY_OWNER)/$(E2E_TEST_BASE_CONTAINER)
|
||||
|
||||
default: help
|
||||
|
||||
@ -45,7 +49,13 @@ git-hooks: .git/hooks/pre-commit ## Install the git-hooks
|
||||
|
||||
.PHONY: build
|
||||
build: deps ## Build the binary
|
||||
ifneq ("$(wildcard $(PGO_FILE))","")
|
||||
# PGO_FILE exists
|
||||
@go build -pgo=$(PGO_FILE) -ldflags "-X main.pgoEnabled=true" -o $(PROJECT_NAME) -v $(PKG)
|
||||
else
|
||||
# PGO_FILE does not exist
|
||||
@go build -o $(PROJECT_NAME) -v $(PKG)
|
||||
endif
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## Remove previous build
|
||||
@ -101,7 +111,7 @@ deploy/dockerfiles: ## Clone Dockerfiles repository
|
||||
|
||||
.PHONY: e2e-test-docker-image
|
||||
e2e-test-docker-image: deploy/dockerfiles ## Build Docker image that is used in e2e tests
|
||||
@docker build -t $(E2E_TEST_BASE_IMAGE) -f deploy/dockerfiles/$(E2E_TEST_BASE_CONTAINER)
|
||||
@docker build -t $(E2E_TEST_BASE_IMAGE) deploy/dockerfiles/$(E2E_TEST_BASE_CONTAINER)
|
||||
@docker build -t $(E2E_TEST_DOCKER_IMAGE) deploy/dockerfiles/$(E2E_TEST_DOCKER_CONTAINER)/$(E2E_TEST_DOCKER_TAG)
|
||||
|
||||
.PHONY: e2e-test
|
||||
|
@ -15,6 +15,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
@ -22,9 +24,21 @@ import (
|
||||
var (
|
||||
gracefulShutdownWait = 15 * time.Second
|
||||
log = logging.GetLogger("main")
|
||||
// If pgoEnabled is true, the binary was built with PGO enabled.
|
||||
// This is set during compilation with our Makefile as a STRING.
|
||||
pgoEnabled = "false"
|
||||
)
|
||||
|
||||
func initSentry(options *sentry.ClientOptions) {
|
||||
func initSentry(options *sentry.ClientOptions, profilingEnabled bool) {
|
||||
options.BeforeSendTransaction = func(event *sentry.Event, _ *sentry.EventHint) *sentry.Event {
|
||||
if event.Tags == nil {
|
||||
event.Tags = make(map[string]string)
|
||||
}
|
||||
event.Tags["go_pgo"] = pgoEnabled
|
||||
event.Tags["go_profiling"] = strconv.FormatBool(profilingEnabled)
|
||||
return event
|
||||
}
|
||||
|
||||
if err := sentry.Init(*options); err != nil {
|
||||
log.Errorf("sentry.Init: %s", err)
|
||||
}
|
||||
@ -37,6 +51,33 @@ func shutdownSentry() {
|
||||
}
|
||||
}
|
||||
|
||||
func initProfiling(options config.Profiling) (cancel func()) {
|
||||
if options.Enabled {
|
||||
profile, err := os.Create(options.File)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Error while opening the profile file")
|
||||
}
|
||||
|
||||
log.Debug("Starting CPU profiler")
|
||||
if err := pprof.StartCPUProfile(profile); err != nil {
|
||||
log.WithError(err).Error("Error while starting the CPU profiler!!")
|
||||
}
|
||||
|
||||
cancel = func() {
|
||||
if options.Enabled {
|
||||
log.Debug("Stopping CPU profiler")
|
||||
pprof.StopCPUProfile()
|
||||
if err := profile.Close(); err != nil {
|
||||
log.WithError(err).Error("Error while closing profile file")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cancel = func() {}
|
||||
}
|
||||
return cancel
|
||||
}
|
||||
|
||||
func runServer(server *http.Server) {
|
||||
log.WithField("address", server.Addr).Info("Starting server")
|
||||
var err error
|
||||
@ -139,9 +180,12 @@ func main() {
|
||||
log.WithError(err).Warn("Could not initialize configuration")
|
||||
}
|
||||
logging.InitializeLogging(config.Config.Logger.Level)
|
||||
initSentry(&config.Config.Sentry)
|
||||
initSentry(&config.Config.Sentry, config.Config.Profiling.Enabled)
|
||||
defer shutdownSentry()
|
||||
|
||||
stopProfiling := initProfiling(config.Config.Profiling)
|
||||
defer stopProfiling()
|
||||
|
||||
cancel := monitoring.InitializeInfluxDB(&config.Config.InfluxDB)
|
||||
defer cancel()
|
||||
|
||||
|
@ -61,6 +61,14 @@ logger:
|
||||
# Log level that is used after reading the config (INFO until then)
|
||||
level: DEBUG
|
||||
|
||||
# Configuration of the embedded profiler
|
||||
profiling:
|
||||
# Enables the runtime profiler
|
||||
enabled: false
|
||||
# The file to which the profile is written to.
|
||||
# The default location `cmd/poseidon/default.pgo` will be picked up during the build process to create a profile-guided build.
|
||||
file: cmd/poseidon/default.pgo
|
||||
|
||||
# Configuration of the sentry logging
|
||||
sentry:
|
||||
# The DSN of the sentry endpoint to use.
|
||||
|
@ -123,6 +123,12 @@ type logger struct {
|
||||
Level string
|
||||
}
|
||||
|
||||
// Profiling configures the usage of a runtime profiler to create optimized binaries.
|
||||
type Profiling struct {
|
||||
Enabled bool
|
||||
File string
|
||||
}
|
||||
|
||||
// InfluxDB configures the usage of an Influx db monitoring.
|
||||
type InfluxDB struct {
|
||||
URL string
|
||||
@ -138,6 +144,7 @@ type configuration struct {
|
||||
Nomad Nomad
|
||||
AWS AWS
|
||||
Logger logger
|
||||
Profiling Profiling
|
||||
Sentry sentry.ClientOptions
|
||||
InfluxDB InfluxDB
|
||||
}
|
||||
|
Reference in New Issue
Block a user