wip refactoring: better logging and error systems

This commit is contained in:
Julien Neuhart
2019-07-07 17:45:07 +02:00
parent a4aa8dafac
commit c8f7ea934c
36 changed files with 1346 additions and 1096 deletions

View File

@@ -0,0 +1,38 @@
package middleware
import (
"github.com/labstack/echo/v4"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/context"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/resource"
"github.com/thecodingmachine/gotenberg/internal/pkg/standarderror"
)
// Cleanup helps removing a resource at the end of a request.
func Cleanup() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
const op = "middleware.Cleanup"
err := next(c)
ctx := context.MustCastFromEchoContext(c)
r := ctx.Resource()
if r == nil {
return err
}
// if a webhook URL has been given,
// do not remove the resource here because
// we don't know if the result file has been
// generated or sent.
if r.Has(resource.WebhookURLFormField) {
return err
}
// a resource is associated with our custom context.
if resourceErr := r.Close(); resourceErr != nil {
ctx.StandardLogger().ErrorOp(op, &standarderror.Error{
Op: op,
Err: resourceErr,
})
}
return err
}
}
}

View File

@@ -0,0 +1,41 @@
package middleware
import (
"github.com/labstack/echo/v4"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/context"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/handler"
"github.com/thecodingmachine/gotenberg/internal/pkg/config"
"github.com/thecodingmachine/gotenberg/internal/pkg/logger"
"github.com/thecodingmachine/gotenberg/internal/pkg/random"
)
// Context helps extending the default echo.Context with
// our custom context.
func Context(config *config.Config) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// generate a unique identifier for the request.
trace := random.Get()
// create the logger for this request using
// the previous identifier as trace.
logger := logger.New(config.LogLevel(), trace)
// extend the current echo context with our custom
// context.
ctx := context.New(c, logger, config)
// if its an healthcheck request, there
// is no resource associated to it.
if ctx.Path() == handler.PingEndpoint {
return next(ctx)
}
// if the endpoint is not for healthcheck, associate a
// resource to our custom context.
if err := ctx.WithResource(trace); err != nil {
// required to have a correct status code
// in the logs.
ctx.Error(err)
return ctx.LogRequestResult(err, false)
}
return next(ctx)
}
}
}

View File

@@ -0,0 +1,3 @@
// Package middleware contains the
// middleware of the API.
package middleware

View File

@@ -0,0 +1,43 @@
package middleware
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/context"
"github.com/thecodingmachine/gotenberg/internal/pkg/standarderror"
)
// Error helps handling errors (if any).
func Error() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
ctx := context.MustCastFromEchoContext(c)
err := next(ctx)
if err == nil {
// so far so good!
return nil
}
// we log the initial error before returning
// the HTTP error.
logger := ctx.StandardLogger()
logger.Error(err.Error())
// handle our custom HTTP error.
var httpErr error
errCode := standarderror.Code(err)
errMessage := standarderror.Message(err)
switch errCode {
case standarderror.Invalid:
httpErr = echo.NewHTTPError(http.StatusBadRequest, errMessage)
case standarderror.Timeout:
httpErr = echo.NewHTTPError(http.StatusRequestTimeout, errMessage)
default:
httpErr = echo.NewHTTPError(http.StatusInternalServerError, errMessage)
}
// required to have a correct status code
// in the logs.
ctx.Error(httpErr)
return httpErr
}
}
}

View File

@@ -0,0 +1,21 @@
package middleware
import (
"github.com/labstack/echo/v4"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/context"
"github.com/thecodingmachine/gotenberg/internal/app/api/pkg/handler"
)
// Logger helps logging the result of a request.
func Logger() echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
ctx := context.MustCastFromEchoContext(c)
err := next(ctx)
// we do not want to log healthcheck requests if
// log level is not set to DEBUG.
isDebug := ctx.Path() == handler.PingEndpoint
return ctx.LogRequestResult(err, isDebug)
}
}
}