diff --git a/internal/api/api.go b/internal/api/api.go index 229c4fd..4882d4c 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -47,8 +47,8 @@ func configureV1Router(router *mux.Router, w.WriteHeader(http.StatusNotFound) }) v1 := router.PathPrefix(BasePath).Subrouter() - v1.HandleFunc(HealthPath, Health).Methods(http.MethodGet) - v1.HandleFunc(VersionPath, Version).Methods(http.MethodGet) + v1.HandleFunc(HealthPath, Health).Methods(http.MethodGet).Name(HealthPath) + v1.HandleFunc(VersionPath, Version).Methods(http.MethodGet).Name(VersionPath) runnerController := &RunnerController{manager: runnerManager} environmentController := &EnvironmentController{manager: environmentManager} @@ -59,7 +59,8 @@ func configureV1Router(router *mux.Router, // May add a statistics controller if another route joins statisticsRouter := router.PathPrefix(StatisticsPath).Subrouter() statisticsRouter. - HandleFunc(EnvironmentsPath, StatisticsExecutionEnvironments(environmentManager)).Methods(http.MethodGet) + HandleFunc(EnvironmentsPath, StatisticsExecutionEnvironments(environmentManager)). + Methods(http.MethodGet).Name(EnvironmentsPath) } if auth.InitializeAuthentication() { diff --git a/internal/api/runners.go b/internal/api/runners.go index d1e0f48..d9ec81b 100644 --- a/internal/api/runners.go +++ b/internal/api/runners.go @@ -51,7 +51,6 @@ func (r *RunnerController) provide(writer http.ResponseWriter, request *http.Req return } environmentID := dto.EnvironmentID(runnerRequest.ExecutionEnvironmentID) - logging.AddEnvironmentID(request, environmentID) nextRunner, err := r.manager.Claim(environmentID, runnerRequest.InactivityTimeout) if err != nil { @@ -66,7 +65,7 @@ func (r *RunnerController) provide(writer http.ResponseWriter, request *http.Req } return } - logging.AddRunnerID(request, nextRunner.ID()) + addMonitoringData(request, nextRunner) sendJSON(writer, &dto.RunnerResponse{ID: nextRunner.ID(), MappedPorts: nextRunner.MappedPorts()}, http.StatusOK) } @@ -80,7 +79,7 @@ func (r *RunnerController) updateFileSystem(writer http.ResponseWriter, request } targetRunner, _ := runner.FromContext(request.Context()) - logging.AddRunnerID(request, targetRunner.ID()) + addMonitoringData(request, targetRunner) if err := targetRunner.UpdateFileSystem(fileCopyRequest); err != nil { log.WithError(err).Error("Could not perform the requested updateFileSystem.") writeInternalServerError(writer, err, dto.ErrorUnknown) @@ -106,7 +105,7 @@ func (r *RunnerController) execute(writer http.ResponseWriter, request *http.Req scheme = "ws" } targetRunner, _ := runner.FromContext(request.Context()) - logging.AddRunnerID(request, targetRunner.ID()) + addMonitoringData(request, targetRunner) path, err := r.runnerRouter.Get(WebsocketPath).URL(RunnerIDKey, targetRunner.ID()) if err != nil { @@ -158,7 +157,7 @@ func (r *RunnerController) findRunnerMiddleware(next http.Handler) http.Handler // It destroys the given runner on the executor and removes it from the used runners list. func (r *RunnerController) delete(writer http.ResponseWriter, request *http.Request) { targetRunner, _ := runner.FromContext(request.Context()) - logging.AddRunnerID(request, targetRunner.ID()) + addMonitoringData(request, targetRunner) err := r.manager.Return(targetRunner) if err != nil { @@ -172,3 +171,9 @@ func (r *RunnerController) delete(writer http.ResponseWriter, request *http.Requ writer.WriteHeader(http.StatusNoContent) } + +// addMonitoringData adds the data of the runner and environment we want to monitor. +func addMonitoringData(request *http.Request, r runner.Runner) { + logging.AddRunnerID(request, r.ID()) + logging.AddEnvironmentID(request, r.Environment()) +} diff --git a/internal/api/runners_test.go b/internal/api/runners_test.go index f7836de..6891ca8 100644 --- a/internal/api/runners_test.go +++ b/internal/api/runners_test.go @@ -254,6 +254,7 @@ func (s *UpdateFileSystemRouteTestSuite) SetupTest() { s.path = routeURL.String() s.runnerMock = &runner.RunnerMock{} s.runnerMock.On("ID").Return(tests.DefaultMockID) + s.runnerMock.On("Environment").Return(dto.EnvironmentID(tests.DefaultEnvironmentIDAsInteger)) s.runnerManager.On("Get", tests.DefaultMockID).Return(s.runnerMock, nil) s.recorder = httptest.NewRecorder() } diff --git a/internal/api/websocket.go b/internal/api/websocket.go index a99ff87..b2939b5 100644 --- a/internal/api/websocket.go +++ b/internal/api/websocket.go @@ -8,7 +8,6 @@ import ( "github.com/gorilla/websocket" "github.com/openHPI/poseidon/internal/runner" "github.com/openHPI/poseidon/pkg/dto" - "github.com/openHPI/poseidon/pkg/logging" "io" "net/http" "sync" @@ -337,7 +336,8 @@ func (wp *webSocketProxy) writeMessage(messageType int, data []byte) error { // connectToRunner is the endpoint for websocket connections. func (r *RunnerController) connectToRunner(writer http.ResponseWriter, request *http.Request) { targetRunner, _ := runner.FromContext(request.Context()) - logging.AddRunnerID(request, targetRunner.ID()) + addMonitoringData(request, targetRunner) + executionID := request.URL.Query().Get(ExecutionIDKey) if !targetRunner.ExecutionExists(executionID) { writeNotFound(writer, ErrUnknownExecutionID) diff --git a/internal/runner/execution_environment.go b/internal/runner/execution_environment.go new file mode 100644 index 0000000..3223c8f --- /dev/null +++ b/internal/runner/execution_environment.go @@ -0,0 +1,49 @@ +package runner + +import ( + "encoding/json" + "github.com/openHPI/poseidon/pkg/dto" +) + +// ExecutionEnvironment are groups of runner that share the configuration stored in the environment. +type ExecutionEnvironment interface { + json.Marshaler + + // ID returns the id of the environment. + ID() dto.EnvironmentID + SetID(id dto.EnvironmentID) + // PrewarmingPoolSize sets the number of idle runner of this environment that should be prewarmed. + PrewarmingPoolSize() uint + SetPrewarmingPoolSize(count uint) + // ApplyPrewarmingPoolSize creates idle runners according to the PrewarmingPoolSize. + ApplyPrewarmingPoolSize() error + // CPULimit sets the share of cpu that a runner should receive at minimum. + CPULimit() uint + SetCPULimit(limit uint) + // MemoryLimit sets the amount of memory that should be available for each runner. + MemoryLimit() uint + SetMemoryLimit(limit uint) + // Image sets the image of the runner, e.g. Docker image. + Image() string + SetImage(image string) + // NetworkAccess sets if a runner should have network access and if ports should be mapped. + NetworkAccess() (bool, []uint16) + SetNetworkAccess(allow bool, ports []uint16) + // SetConfigFrom copies all above attributes from the passed environment to the object itself. + SetConfigFrom(environment ExecutionEnvironment) + + // Register saves this environment at the executor. + Register() error + // Delete removes this environment and all it's runner from the executor and Poseidon itself. + Delete() error + + // Sample returns and removes an arbitrary available runner. + // ok is true iff a runner was returned. + Sample() (r Runner, ok bool) + // AddRunner adds an existing runner to the idle runners of the environment. + AddRunner(r Runner) + // DeleteRunner removes an idle runner from the environment. + DeleteRunner(id string) + // IdleRunnerCount returns the number of idle runners of the environment. + IdleRunnerCount() int +} diff --git a/internal/runner/manager.go b/internal/runner/manager.go index 2e34e45..1bfa880 100644 --- a/internal/runner/manager.go +++ b/internal/runner/manager.go @@ -1,52 +1,6 @@ package runner -import ( - "encoding/json" - "github.com/openHPI/poseidon/pkg/dto" -) - -// ExecutionEnvironment are groups of runner that share the configuration stored in the environment. -type ExecutionEnvironment interface { - json.Marshaler - - // ID returns the id of the environment. - ID() dto.EnvironmentID - SetID(id dto.EnvironmentID) - // PrewarmingPoolSize sets the number of idle runner of this environment that should be prewarmed. - PrewarmingPoolSize() uint - SetPrewarmingPoolSize(count uint) - // ApplyPrewarmingPoolSize creates idle runners according to the PrewarmingPoolSize. - ApplyPrewarmingPoolSize() error - // CPULimit sets the share of cpu that a runner should receive at minimum. - CPULimit() uint - SetCPULimit(limit uint) - // MemoryLimit sets the amount of memory that should be available for each runner. - MemoryLimit() uint - SetMemoryLimit(limit uint) - // Image sets the image of the runner, e.g. Docker image. - Image() string - SetImage(image string) - // NetworkAccess sets if a runner should have network access and if ports should be mapped. - NetworkAccess() (bool, []uint16) - SetNetworkAccess(allow bool, ports []uint16) - // SetConfigFrom copies all above attributes from the passed environment to the object itself. - SetConfigFrom(environment ExecutionEnvironment) - - // Register saves this environment at the executor. - Register() error - // Delete removes this environment and all it's runner from the executor and Poseidon itself. - Delete() error - - // Sample returns and removes an arbitrary available runner. - // ok is true iff a runner was returned. - Sample() (r Runner, ok bool) - // AddRunner adds an existing runner to the idle runners of the environment. - AddRunner(r Runner) - // DeleteRunner removes an idle runner from the environment. - DeleteRunner(id string) - // IdleRunnerCount returns the number of idle runners of the environment. - IdleRunnerCount() int -} +import "github.com/openHPI/poseidon/pkg/dto" // Manager keeps track of the used and unused runners of all execution environments in order to provide unused // runners to new clients and ensure no runner is used twice. diff --git a/pkg/logging/influxdb2_middleware.go b/pkg/logging/influxdb2_middleware.go index 3f921b4..074f927 100644 --- a/pkg/logging/influxdb2_middleware.go +++ b/pkg/logging/influxdb2_middleware.go @@ -50,12 +50,30 @@ func AddEnvironmentID(r *http.Request, id dto.EnvironmentID) { p.AddTag("environment_id", strconv.Itoa(int(id))) } +// AddEnvironmentType adds the type of the used environment to the influxdb data point. +func AddEnvironmentType(r *http.Request, t string) { + p := pointFromContext(r.Context()) + p.AddTag("environment_type", t) +} + // AddRunnerID adds the runner id to the influx data point for the current request. func AddRunnerID(r *http.Request, id string) { p := pointFromContext(r.Context()) p.AddTag("runner_id", id) } +// AddIdleRunner adds the count of idle runners of the used environment to the influxdb data point. +func AddIdleRunner(r *http.Request, count int) { + p := pointFromContext(r.Context()) + p.AddField("idle_runner", strconv.Itoa(count)) +} + +// AddPrewarmingPoolSize adds the prewarming pool size of the used environment to the influxdb data point. +func AddPrewarmingPoolSize(r *http.Request, count uint) { + p := pointFromContext(r.Context()) + p.AddField("prewarming_pool_size", strconv.Itoa(int(count))) +} + // AddRequestSize adds the size of the request body to the influx data point for the current request. func AddRequestSize(r *http.Request) { body, err := io.ReadAll(r.Body)