feat: add metrics system, move webhook feature to dedicated module (#372)

This commit is contained in:
Julien Neuhart
2021-10-19 18:35:24 +02:00
committed by GitHub
parent b839069af1
commit d4c47cecf2
39 changed files with 3359 additions and 1309 deletions

View File

@@ -8,6 +8,7 @@ import (
"os"
"regexp"
"strings"
"sync"
"time"
"github.com/chromedp/cdproto/fetch"
@@ -236,19 +237,35 @@ func (mod Chromium) Validate() error {
return nil
}
// Metrics returns the metrics.
func (mod Chromium) Metrics() ([]gotenberg.Metric, error) {
return []gotenberg.Metric{
{
Name: "chromium_active_instances_count",
Description: "Current number of active Chromium instances.",
Read: func() float64 {
activeInstancesCountMu.RLock()
defer activeInstancesCountMu.RUnlock()
return activeInstancesCount
},
},
}, nil
}
// Chromium returns an API for interacting with Chromium for converting HTML
// documents to PDF.
func (mod Chromium) Chromium() (API, error) {
return mod, nil
}
// Routes returns the API routes.
func (mod Chromium) Routes() ([]api.MultipartFormDataRoute, error) {
// Routes returns the HTTP routes.
func (mod Chromium) Routes() ([]api.Route, error) {
if mod.disableRoutes {
return nil, nil
}
return []api.MultipartFormDataRoute{
return []api.Route{
convertURLRoute(mod, mod.engine),
convertHTMLRoute(mod, mod.engine),
convertMarkdownRoute(mod, mod.engine),
@@ -475,9 +492,17 @@ func (mod Chromium) PDF(ctx context.Context, logger *zap.Logger, URL, outputPath
}
}
activeInstancesCountMu.Lock()
activeInstancesCount += 1
activeInstancesCountMu.Unlock()
var buffer []byte
err := chromedp.Run(taskCtx, printToPDF(URL, options, &buffer))
activeInstancesCountMu.Lock()
activeInstancesCount -= 1
activeInstancesCountMu.Unlock()
// Always remove the user profile directory created by Chromium.
go func() {
logger.Debug(fmt.Sprintf("remove user profile directory '%s'", userProfileDirPath))
@@ -514,12 +539,18 @@ func (mod Chromium) PDF(ctx context.Context, logger *zap.Logger, URL, outputPath
return nil
}
var (
activeInstancesCount float64
activeInstancesCountMu sync.RWMutex
)
// Interface guards.
var (
_ gotenberg.Module = (*Chromium)(nil)
_ gotenberg.Provisioner = (*Chromium)(nil)
_ gotenberg.Validator = (*Chromium)(nil)
_ api.MultipartFormDataRouter = (*Chromium)(nil)
_ API = (*Chromium)(nil)
_ Provider = (*Chromium)(nil)
_ gotenberg.Module = (*Chromium)(nil)
_ gotenberg.Provisioner = (*Chromium)(nil)
_ gotenberg.Validator = (*Chromium)(nil)
_ gotenberg.MetricsProvider = (*Chromium)(nil)
_ api.Router = (*Chromium)(nil)
_ API = (*Chromium)(nil)
_ Provider = (*Chromium)(nil)
)

View File

@@ -173,6 +173,22 @@ func TestChromium_Validate(t *testing.T) {
}
}
func TestChromium_Metrics(t *testing.T) {
metrics, err := new(Chromium).Metrics()
if err != nil {
t.Errorf("expected no error but got: %v", err)
}
if len(metrics) != 1 {
t.Errorf("expected %d metrics, but got %d", 1, len(metrics))
}
actual := metrics[0].Read()
if actual != 0 {
t.Errorf("expected %d Chromium instances, but got %f", 0, actual)
}
}
func TestChromium_Chromium(t *testing.T) {
mod := new(Chromium)

View File

@@ -14,6 +14,7 @@ import (
"github.com/gotenberg/gotenberg/v7/pkg/gotenberg"
"github.com/gotenberg/gotenberg/v7/pkg/modules/api"
"github.com/labstack/echo/v4"
"github.com/microcosm-cc/bluemonday"
"github.com/russross/blackfriday/v2"
"go.uber.org/multierr"
@@ -89,12 +90,14 @@ func FormDataChromiumPDFOptions(ctx *api.Context) (*api.FormData, Options) {
return form, options
}
// convertURLRoute returns an api.MultipartFormDataRoute route which can
// convert a URL to PDF.
func convertURLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute {
return api.MultipartFormDataRoute{
Path: "/chromium/convert/url",
Handler: func(ctx *api.Context) error {
// convertURLRoute returns an api.Route which can convert a URL to PDF.
func convertURLRoute(chromium API, engine gotenberg.PDFEngine) api.Route {
return api.Route{
Method: http.MethodPost,
Path: "/forms/chromium/convert/url",
IsMultipart: true,
Handler: func(c echo.Context) error {
ctx := c.Get("context").(*api.Context)
form, options := FormDataChromiumPDFOptions(ctx)
var (
@@ -121,12 +124,14 @@ func convertURLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartForm
}
}
// convertHTMLRoute returns an api.MultipartFormDataRoute route which can
// convert an HTML file to PDF.
func convertHTMLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute {
return api.MultipartFormDataRoute{
Path: "/chromium/convert/html",
Handler: func(ctx *api.Context) error {
// convertHTMLRoute returns an api.Route which can convert an HTML file to PDF.
func convertHTMLRoute(chromium API, engine gotenberg.PDFEngine) api.Route {
return api.Route{
Method: http.MethodPost,
Path: "/forms/chromium/convert/html",
IsMultipart: true,
Handler: func(c echo.Context) error {
ctx := c.Get("context").(*api.Context)
form, options := FormDataChromiumPDFOptions(ctx)
var (
@@ -155,12 +160,15 @@ func convertHTMLRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFor
}
}
// convertMarkdownRoute returns an api.MultipartFormDataRoute route which can
// convert markdown files to PDF.
func convertMarkdownRoute(chromium API, engine gotenberg.PDFEngine) api.MultipartFormDataRoute {
return api.MultipartFormDataRoute{
Path: "/chromium/convert/markdown",
Handler: func(ctx *api.Context) error {
// convertMarkdownRoute returns an api.Route which can convert markdown files
// to PDF.
func convertMarkdownRoute(chromium API, engine gotenberg.PDFEngine) api.Route {
return api.Route{
Method: http.MethodPost,
Path: "/forms/chromium/convert/markdown",
IsMultipart: true,
Handler: func(c echo.Context) error {
ctx := c.Get("context").(*api.Context)
form, options := FormDataChromiumPDFOptions(ctx)
var (

View File

@@ -3,13 +3,14 @@ package chromium
import (
"context"
"errors"
"github.com/gotenberg/gotenberg/v7/pkg/gotenberg"
"net/http"
"os"
"reflect"
"testing"
"github.com/gotenberg/gotenberg/v7/pkg/gotenberg"
"github.com/gotenberg/gotenberg/v7/pkg/modules/api"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
)
@@ -137,7 +138,10 @@ func TestConvertURLHandler(t *testing.T) {
expectOutputPathsCount: 1,
},
} {
err := convertURLRoute(tc.api, nil).Handler(tc.ctx.Context)
c := echo.New().NewContext(nil, nil)
c.Set("context", tc.ctx.Context)
err := convertURLRoute(tc.api, nil).Handler(c)
if tc.expectErr && err == nil {
t.Errorf("test %d: expected error but got: %v", i, err)
@@ -238,7 +242,10 @@ func TestConvertHTMLHandler(t *testing.T) {
expectOutputPathsCount: 1,
},
} {
err := convertHTMLRoute(tc.api, nil).Handler(tc.ctx.Context)
c := echo.New().NewContext(nil, nil)
c.Set("context", tc.ctx.Context)
err := convertHTMLRoute(tc.api, nil).Handler(c)
if tc.expectErr && err == nil {
t.Errorf("test %d: expected error but got: %v", i, err)
@@ -472,7 +479,10 @@ func TestConvertMarkdownHandler(t *testing.T) {
}()
}
err := convertMarkdownRoute(tc.api, nil).Handler(tc.ctx.Context)
c := echo.New().NewContext(nil, nil)
c.Set("context", tc.ctx.Context)
err := convertMarkdownRoute(tc.api, nil).Handler(c)
if tc.expectErr && err == nil {
t.Errorf("test %d: expected error but got: %v", i, err)