From 33fe7c19a31505dbcdb1cc2e5b0c16aed9b93383 Mon Sep 17 00:00:00 2001 From: "Laurie T. Malau" Date: Tue, 26 Apr 2022 14:54:02 +0000 Subject: [PATCH] logging middleware --- components/public-api-server/main.go | 11 ++++-- .../public-api-server/middleware/logging.go | 34 +++++++++++++++++ .../middleware/logging_test.go | 37 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 components/public-api-server/middleware/logging.go create mode 100644 components/public-api-server/middleware/logging_test.go diff --git a/components/public-api-server/main.go b/components/public-api-server/main.go index 3485140a3dca43..65893513711bdf 100644 --- a/components/public-api-server/main.go +++ b/components/public-api-server/main.go @@ -7,6 +7,7 @@ package main import ( "github.com/gitpod-io/gitpod/common-go/baseserver" "github.com/gitpod-io/gitpod/common-go/log" + "github.com/gitpod-io/gitpod/public-api-server/middleware" "github.com/gitpod-io/gitpod/public-api-server/pkg/apiv1" v1 "github.com/gitpod-io/gitpod/public-api/v1" "net/http" @@ -33,12 +34,16 @@ func main() { } func register(srv *baseserver.Server) error { - srv.HTTPMux().HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { - _, _ = w.Write([]byte(`hello world`)) - }) + logger := log.New() + m := middleware.NewLoggingMiddleware(logger) + srv.HTTPMux().Handle("/", m(http.HandlerFunc(HelloWorldHandler))) v1.RegisterWorkspacesServiceServer(srv.GRPC(), apiv1.NewWorkspaceService()) v1.RegisterPrebuildsServiceServer(srv.GRPC(), v1.UnimplementedPrebuildsServiceServer{}) return nil } + +func HelloWorldHandler(w http.ResponseWriter, _ *http.Request) { + w.Write([]byte(`hello world`)) +} diff --git a/components/public-api-server/middleware/logging.go b/components/public-api-server/middleware/logging.go new file mode 100644 index 00000000000000..6d41c1de1d31e8 --- /dev/null +++ b/components/public-api-server/middleware/logging.go @@ -0,0 +1,34 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package middleware + +import ( + "github.com/sirupsen/logrus" + "net/http" + "time" +) + +type Middleware func(handler http.Handler) http.Handler + +func NewLoggingMiddleware(l *logrus.Entry) Middleware { + + return func(next http.Handler) http.Handler { + logging := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + uri := r.RequestURI + method := r.Method + duration := time.Since(start) + next.ServeHTTP(w, r) + + l.WithFields(logrus.Fields{ + "uri": uri, + "method": method, + "duration": duration, + }).Infof("Handled HTTP request %s %s", method, uri) + }) + + return logging + } +} diff --git a/components/public-api-server/middleware/logging_test.go b/components/public-api-server/middleware/logging_test.go new file mode 100644 index 00000000000000..ec0191b34de511 --- /dev/null +++ b/components/public-api-server/middleware/logging_test.go @@ -0,0 +1,37 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package middleware + +import ( + "bytes" + "github.com/sirupsen/logrus" + _ "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/require" + "net/http" + "net/http/httptest" + "testing" +) + +func TestLoggingMiddleware(t *testing.T) { + logInMemory := &bytes.Buffer{} + logger := logrus.New() + logger.SetOutput(logInMemory) + logger.SetFormatter(&logrus.JSONFormatter{}) + + expectedBody := `hello world` + + someHandler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Write([]byte(expectedBody)) + }) + req := httptest.NewRequest("GET", "/", nil) + rec := httptest.NewRecorder() // this records the response + + m := NewLoggingMiddleware(logrus.NewEntry(logger)) + wrappedHandler := m(someHandler) + wrappedHandler.ServeHTTP(rec, req) + + require.HTTPStatusCode(t, someHandler, http.MethodGet, "/", nil, http.StatusOK) + require.HTTPBodyContains(t, someHandler, http.MethodGet, "/", nil, "hello") +}