added metrics, fix charsets

This commit is contained in:
Sergey Chubaryan 2024-08-25 16:45:27 +03:00
parent 99b75a731b
commit 3e999f8b60
7 changed files with 102 additions and 7 deletions

View File

@ -25,7 +25,7 @@ func GetCharset(charsetType CharsetType) Charset {
case CharsetTypeLettersLower: case CharsetTypeLettersLower:
return charsetLettersLower return charsetLettersLower
case CharsetTypeLettersUpper: case CharsetTypeLettersUpper:
return charsetLettersLower return charsetLettersUpper
case CharsetTypeLetters: case CharsetTypeLetters:
return charsetLetters return charsetLetters
case CharsetTypeAll: case CharsetTypeAll:

View File

@ -58,7 +58,7 @@ func (u *userService) CreateUser(ctx context.Context, params UserCreateParams) (
} }
if err := u.deps.Password.Validate(params.Password); err != nil { if err := u.deps.Password.Validate(params.Password); err != nil {
return nil, ErrUserBadPassword return nil, err
} }
secret, err := u.deps.Password.Hash(params.Password) secret, err := u.deps.Password.Hash(params.Password)

View File

@ -0,0 +1,79 @@
package integrations
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type Prometheus struct {
reg *prometheus.Registry
rpsGauge prometheus.Gauge
avgReqTimeHist prometheus.Histogram
panicsHist prometheus.Histogram
}
func NewPrometheus() *Prometheus {
reg := prometheus.NewRegistry()
// Add go runtime metrics and process collectors.
reg.MustRegister(
collectors.NewGoCollector(),
collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
)
// errorsCounter := prometheus.NewCounter(
// prometheus.CounterOpts{
// Name: "backend_errors_count",
// Help: "Summary errors count",
// },
// )
rpsGauge := prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "backend_requests_per_second",
Help: "Requests per second metric",
},
)
avgReqTimeHist := prometheus.NewHistogram(
prometheus.HistogramOpts{
Name: "backend_requests_average_time",
Help: "Average time of requests",
},
)
panicsHist := prometheus.NewHistogram(
prometheus.HistogramOpts{
Name: "backend_panics",
Help: "Panics histogram metric",
},
)
reg.MustRegister(rpsGauge, avgReqTimeHist, panicsHist)
return &Prometheus{
panicsHist: panicsHist,
avgReqTimeHist: avgReqTimeHist,
rpsGauge: rpsGauge,
reg: reg,
}
}
func (p *Prometheus) GetRequestHandler() http.Handler {
return promhttp.HandlerFor(p.reg, promhttp.HandlerOpts{Registry: p.reg})
}
func (p *Prometheus) RequestInc() {
p.rpsGauge.Inc()
}
func (p *Prometheus) RequestDec() {
p.rpsGauge.Dec()
}
func (p *Prometheus) AddRequestTime(reqTime float64) {
p.avgReqTimeHist.Observe(reqTime)
}
func (p *Prometheus) AddPanic() {
p.panicsHist.Observe(1)
}

View File

@ -26,5 +26,8 @@ func (b *bufioWrapper) Flush() error {
} }
func (b *bufioWrapper) Close() error { func (b *bufioWrapper) Close() error {
return b.Flush() b.m.Lock()
defer b.m.Unlock()
return b.Writer.Flush()
} }

View File

@ -3,6 +3,7 @@ package middleware
// Modified recovery from gin, use own logger // Modified recovery from gin, use own logger
import ( import (
"backend/src/integrations"
"backend/src/logger" "backend/src/logger"
"bytes" "bytes"
"errors" "errors"
@ -29,11 +30,13 @@ var (
slash = []byte("/") slash = []byte("/")
) )
func NewRecoveryMiddleware(logger logger.Logger, debugMode bool) gin.HandlerFunc { func NewRecoveryMiddleware(logger logger.Logger, prometheus *integrations.Prometheus, debugMode bool) gin.HandlerFunc {
handle := defaultHandleRecovery handle := defaultHandleRecovery
return func(c *gin.Context) { return func(c *gin.Context) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
prometheus.AddPanic()
// Check for a broken connection, as it is not really a // Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace. // condition that warrants a panic stack trace.
var brokenPipe bool var brokenPipe bool

View File

@ -1,6 +1,7 @@
package middleware package middleware
import ( import (
"backend/src/integrations"
log "backend/src/logger" log "backend/src/logger"
"time" "time"
@ -8,8 +9,11 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
func NewRequestLogMiddleware(logger log.Logger) gin.HandlerFunc { func NewRequestLogMiddleware(logger log.Logger, prometheus *integrations.Prometheus) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
prometheus.RequestInc()
defer prometheus.RequestDec()
requestId := c.GetHeader("X-Request-Id") requestId := c.GetHeader("X-Request-Id")
if requestId == "" { if requestId == "" {
requestId = uuid.New().String() requestId = uuid.New().String()
@ -26,6 +30,8 @@ func NewRequestLogMiddleware(logger log.Logger) gin.HandlerFunc {
c.Next() c.Next()
latency := time.Since(start) latency := time.Since(start)
prometheus.AddRequestTime(float64(latency))
method := c.Request.Method method := c.Request.Method
statusCode := c.Writer.Status() statusCode := c.Writer.Status()
clientIP := c.ClientIP() clientIP := c.ClientIP()

View File

@ -3,6 +3,7 @@ package server
import ( import (
"backend/src/client_notifier" "backend/src/client_notifier"
"backend/src/core/services" "backend/src/core/services"
"backend/src/integrations"
"backend/src/logger" "backend/src/logger"
"backend/src/server/handlers" "backend/src/server/handlers"
"backend/src/server/middleware" "backend/src/server/middleware"
@ -35,8 +36,11 @@ func New(opts NewServerOpts) *Server {
r.Static("/webapp", "./webapp") r.Static("/webapp", "./webapp")
r.GET("/health", handlers.NewDummyHandler()) r.GET("/health", handlers.NewDummyHandler())
r.Use(middleware.NewRequestLogMiddleware(opts.Logger)) prometheus := integrations.NewPrometheus()
r.Use(middleware.NewRecoveryMiddleware(opts.Logger, opts.DebugMode)) r.Any("/metrics", gin.WrapH(prometheus.GetRequestHandler()))
r.Use(middleware.NewRequestLogMiddleware(opts.Logger, prometheus))
r.Use(middleware.NewRecoveryMiddleware(opts.Logger, prometheus, opts.DebugMode))
r.GET("/pooling", handlers.NewLongPoolingHandler(opts.Logger, opts.Notifier)) r.GET("/pooling", handlers.NewLongPoolingHandler(opts.Logger, opts.Notifier))