Skip to content

Commit

Permalink
metrics middleware skelly
Browse files Browse the repository at this point in the history
  • Loading branch information
kayra1 committed May 13, 2024
1 parent 463b3a3 commit 516e435
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 9 deletions.
31 changes: 22 additions & 9 deletions internal/api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,30 @@ func NewGoCertRouter(env *Environment) http.Handler {
router.Handle("/api/v1/", http.StripPrefix("/api/v1", apiV1Router))
router.Handle("/", frontendHandler)

return logging(router)
ctx := Context{}
middleware := createMiddlewareStack(
Metrics(&ctx),
Logging(&ctx),
)
return middleware(router)
}

// createMiddlewareStack chains given middleware for the server.
// Each middleware functions calls next.ServeHTTP in order to resume the chain of execution.
// The order these functions are given to createMiddlewareStack matters.
// The functions will run the code before next.ServeHTTP in order.
// The functions will run the code after next.ServeHTTP in reverse order.
func createMiddlewareStack(middleware ...Middleware) Middleware {
return func(next http.Handler) http.Handler {
for i := len(middleware) - 1; i >= 0; i-- {
mw := middleware[i]
next = mw(next)
}
return next
}
}

// newFrontendFileServer uses the embedded ui output files as the base for a file server
func newFrontendFileServer() http.Handler {
frontendFS, err := fs.Sub(ui.FrontendFS, "out")
if err != nil {
Expand Down Expand Up @@ -213,14 +234,6 @@ func DeleteCertificate(env *Environment) http.HandlerFunc {
}
}

// The logging middleware captures any http request coming through, and logs it
func logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
log.Println(r.Method, r.URL.Path)
})
}

// logErrorAndWriteResponse is a helper function that logs any error and writes it back as an http response
func logErrorAndWriteResponse(msg string, status int, w http.ResponseWriter) {
errMsg := fmt.Sprintf("error: %s", msg)
Expand Down
55 changes: 55 additions & 0 deletions internal/api/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package server

import (
"log"
"net/http"
)

type Middleware func(http.Handler) http.Handler

// The Context type helps middleware pass along information through the chain.
type Context struct {
responseStatusCode int
}

// The ResponseWriterCloner struct implements the http.ResponseWriter class, and copies the status
// code of the response for the middleware to be able to read the responses.
type ResponseWriterCloner struct {
http.ResponseWriter
statusCode int
}

// NewResponseWriter returns a new ResponseWriterCloner struct
func NewResponseWriter(w http.ResponseWriter) *ResponseWriterCloner {
return &ResponseWriterCloner{w, http.StatusOK}
}

// WriteHeader duplicates the status code into the cloner struct for reading
func (rwc *ResponseWriterCloner) WriteHeader(code int) {
rwc.statusCode = code
rwc.ResponseWriter.WriteHeader(code)
}

// The Metrics middleware captures any request relevant to a metric and records it for prometheus.
func Metrics(ctx *Context) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
if ctx.responseStatusCode != 200 {
return
}
})
}
}

// The logging middleware captures any http request coming through, and logs it.
func Logging(ctx *Context) Middleware {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
clonedWwriter := NewResponseWriter(w)
next.ServeHTTP(w, r)
log.Println(r.Method, r.URL.Path, clonedWwriter.statusCode, http.StatusText(clonedWwriter.statusCode))
ctx.responseStatusCode = clonedWwriter.statusCode
})
}
}
1 change: 1 addition & 0 deletions internal/api/middleware_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package server_test

0 comments on commit 516e435

Please sign in to comment.