@@ -9,12 +9,14 @@ import (
99 "strings"
1010 "sync"
1111 "syscall"
12+ "time"
1213
1314 "github.com/google/uuid"
1415 "github.com/rs/zerolog"
1516 "github.com/savsgio/gotils/strconv"
1617 "github.com/valyala/fasthttp"
1718
19+ "github.com/wallarm/api-firewall/internal/platform/metrics"
1820 "github.com/wallarm/api-firewall/internal/platform/router"
1921 "github.com/wallarm/api-firewall/internal/platform/storage"
2022 "github.com/wallarm/api-firewall/internal/platform/web"
3234type App struct {
3335 Routers map [int ]* router.Mux
3436 Log zerolog.Logger
37+ Metrics metrics.Metrics
3538 passOPTIONS bool
3639 maxErrorsInResponse int
3740 shutdown chan os.Signal
@@ -41,7 +44,7 @@ type App struct {
4144}
4245
4346// NewApp creates an App value that handle a set of routes for the set of application.
44- func NewApp (lock * sync.RWMutex , passOPTIONS bool , maxErrorsInResponse int , storedSpecs storage.DBOpenAPILoader , shutdown chan os.Signal , logger zerolog.Logger , mw ... web.Middleware ) * App {
47+ func NewApp (lock * sync.RWMutex , passOPTIONS bool , maxErrorsInResponse int , storedSpecs storage.DBOpenAPILoader , shutdown chan os.Signal , logger zerolog.Logger , pMetrics metrics. Metrics , mw ... web.Middleware ) * App {
4548
4649 schemaIDs := storedSpecs .SchemaIDs ()
4750
@@ -56,6 +59,7 @@ func NewApp(lock *sync.RWMutex, passOPTIONS bool, maxErrorsInResponse int, store
5659 shutdown : shutdown ,
5760 mw : mw ,
5861 Log : logger ,
62+ Metrics : pMetrics ,
5963 storedSpecs : storedSpecs ,
6064 lock : lock ,
6165 passOPTIONS : passOPTIONS ,
@@ -138,6 +142,9 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
138142 // handle panic
139143 defer func () {
140144 if r := recover (); r != nil {
145+
146+ a .Metrics .IncErrorTypeCounter ("request processing error" , 0 )
147+
141148 a .Log .Error ().Msgf ("panic: %v" , r )
142149
143150 // Log the Go stack trace for this panic'd goroutine.
@@ -149,10 +156,15 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
149156 // Add request ID
150157 ctx .SetUserValue (web .RequestID , uuid .NewString ())
151158
159+ // Request handling start time
160+ start := time .Now ()
161+
152162 schemaIDs , notFoundSchemaIDs , err := getWallarmSchemaID (ctx , a .storedSpecs )
153163 if err != nil {
154164 defer web .LogRequestResponseAtTraceLevel (ctx , a .Log )
155165
166+ a .Metrics .IncErrorTypeCounter ("schema not found" , 0 )
167+
156168 a .Log .Error ().
157169 Err (err ).
158170 Bytes ("host" , ctx .Request .Header .Host ()).
@@ -161,6 +173,8 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
161173 Interface ("request_id" , ctx .UserValue (web .RequestID )).
162174 Msg ("error while getting schema ID" )
163175
176+ a .Metrics .IncHTTPRequestTotalCountOnly (0 , fasthttp .StatusInternalServerError )
177+
164178 if err := web .RespondError (ctx , fasthttp .StatusInternalServerError , "" ); err != nil {
165179 a .Log .Error ().
166180 Err (err ).
@@ -256,6 +270,8 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
256270 continue
257271 }
258272
273+ a .Metrics .IncErrorTypeCounter ("request processing error" , schemaIDs [i ])
274+
259275 // Didn't receive the response code. It means that the router respond to the request because it was not valid.
260276 // The API Firewall should respond by 500 status code in this case.
261277 ctx .Response .Header .Reset ()
@@ -274,6 +290,8 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
274290
275291 // Add schema IDs that were not found in the DB to the response
276292 for i := 0 ; i < len (notFoundSchemaIDs ); i ++ {
293+ a .Metrics .IncErrorTypeCounter ("schema not found" , notFoundSchemaIDs [i ])
294+ a .Metrics .IncHTTPRequestTotalCountOnly (notFoundSchemaIDs [i ], fasthttp .StatusOK )
277295 responseSummary = append (responseSummary , & validator.ValidationResponseSummary {
278296 SchemaID : & notFoundSchemaIDs [i ],
279297 StatusCode : & statusInternalError ,
@@ -288,6 +306,11 @@ func (a *App) APIModeMainHandler(ctx *fasthttp.RequestCtx) {
288306 ctx .Request .Header .SetMethod (fasthttp .MethodGet )
289307 }
290308
309+ // save http request count for each schema ID
310+ for _ , schemaID := range schemaIDs {
311+ a .Metrics .IncHTTPRequestStat (start , schemaID , fasthttp .StatusOK )
312+ }
313+
291314 // limit amount of errors to reduce the total size of the response
292315 limitedResponseErrors := validator .SampleSlice (responseErrors , a .maxErrorsInResponse )
293316
0 commit comments