mirror of
https://github.com/wgh136/nysoure.git
synced 2025-12-16 07:51:14 +00:00
feat: prometheus
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"nysoure/server/middleware"
|
||||
"nysoure/server/model"
|
||||
"nysoure/server/service"
|
||||
"nysoure/server/stat"
|
||||
"nysoure/server/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -240,6 +241,7 @@ func downloadFile(c fiber.Ctx) error {
|
||||
}
|
||||
q.Set("token", token)
|
||||
uri.RawQuery = q.Encode()
|
||||
stat.RecordDownload()
|
||||
return c.Redirect().Status(fiber.StatusFound).To(uri.String())
|
||||
}
|
||||
data := map[string]string{
|
||||
@@ -251,6 +253,7 @@ func downloadFile(c fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return model.NewInternalServerError("Failed to generate download token")
|
||||
}
|
||||
stat.RecordDownload()
|
||||
return c.Redirect().Status(fiber.StatusFound).To(fmt.Sprintf("%s/api/files/download/local?token=%s", c.BaseURL(), token))
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"nysoure/server/middleware"
|
||||
"nysoure/server/model"
|
||||
"nysoure/server/service"
|
||||
"nysoure/server/stat"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -24,6 +25,7 @@ func handleUserRegister(c fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stat.RecordRegister()
|
||||
return c.Status(fiber.StatusOK).JSON(model.Response[model.UserViewWithToken]{
|
||||
Success: true,
|
||||
Data: user,
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"nysoure/server/model"
|
||||
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
@@ -13,73 +12,22 @@ import (
|
||||
func ErrorHandler(c fiber.Ctx) error {
|
||||
err := c.Next()
|
||||
if err != nil {
|
||||
var requestErr *model.RequestError
|
||||
var unauthorizedErr *model.UnAuthorizedError
|
||||
var notFoundErr *model.NotFoundError
|
||||
var fiberErr *fiber.Error
|
||||
if errors.As(err, &requestErr) {
|
||||
log.Error("Request Error: ", err)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: requestErr.Error(),
|
||||
})
|
||||
} else if errors.As(err, &unauthorizedErr) {
|
||||
log.Error("Unauthorized Error: ", err)
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: unauthorizedErr.Error(),
|
||||
})
|
||||
} else if errors.As(err, ¬FoundErr) {
|
||||
log.Error("Not Found Error: ", err)
|
||||
return c.Status(fiber.StatusNotFound).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: notFoundErr.Error(),
|
||||
})
|
||||
} else if errors.Is(err, fiber.ErrNotFound) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Not found",
|
||||
})
|
||||
} else if errors.Is(err, fiber.ErrMethodNotAllowed) {
|
||||
return c.Status(fiber.StatusMethodNotAllowed).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Method not allowed",
|
||||
})
|
||||
} else if errors.As(err, &fiberErr) && fiberErr.Message != "" {
|
||||
return c.Status(fiberErr.Code).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: fiberErr.Message,
|
||||
})
|
||||
} else if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Not found",
|
||||
})
|
||||
} else {
|
||||
var fiberErr *fiber.Error
|
||||
if errors.As(err, &fiberErr) {
|
||||
if fiberErr.Code == fiber.StatusNotFound {
|
||||
return c.Status(fiber.StatusNotFound).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Not found",
|
||||
})
|
||||
}
|
||||
if errors.As(err, &fiberErr) {
|
||||
if fiberErr.Code != fiber.StatusInternalServerError {
|
||||
return c.Status(fiberErr.Code).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: fiberErr.Message,
|
||||
})
|
||||
}
|
||||
log.Error("Internal Server Error: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Internal server error",
|
||||
})
|
||||
}
|
||||
log.Error("Internal Server Error: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(model.Response[any]{
|
||||
Success: false,
|
||||
Data: nil,
|
||||
Message: "Internal server error",
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ func FrontendMiddleware(c fiber.Ctx) error {
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
if strings.HasPrefix(c.Path(), "/metrics") {
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
path := c.Path()
|
||||
file := "static" + path
|
||||
|
||||
|
||||
21
server/middleware/stat_middleware.go
Normal file
21
server/middleware/stat_middleware.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"nysoure/server/stat"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
func StatMiddleware(c fiber.Ctx) error {
|
||||
err := c.Next()
|
||||
status := "200"
|
||||
if err != nil {
|
||||
if e, ok := err.(*fiber.Error); ok {
|
||||
status = string(rune(e.Code))
|
||||
} else {
|
||||
status = "500"
|
||||
}
|
||||
}
|
||||
stat.RecordRequest(c.Method(), c.Path(), status)
|
||||
return err
|
||||
}
|
||||
@@ -2,78 +2,31 @@ package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
type RequestError struct {
|
||||
Message string `json:"message"`
|
||||
func NewRequestError(message string) error {
|
||||
return fiber.NewError(400, message)
|
||||
}
|
||||
|
||||
func (e *RequestError) Error() string {
|
||||
return e.Message
|
||||
func NewUnAuthorizedError(message string) error {
|
||||
return fiber.NewError(403, message)
|
||||
}
|
||||
|
||||
func NewRequestError(message string) *RequestError {
|
||||
return &RequestError{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
func IsRequestError(err error) bool {
|
||||
var requestError *RequestError
|
||||
ok := errors.As(err, &requestError)
|
||||
return ok
|
||||
}
|
||||
|
||||
type UnAuthorizedError struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *UnAuthorizedError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func NewUnAuthorizedError(message string) *UnAuthorizedError {
|
||||
return &UnAuthorizedError{
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
func IsUnAuthorizedError(err error) bool {
|
||||
var unAuthorizedError *UnAuthorizedError
|
||||
ok := errors.As(err, &unAuthorizedError)
|
||||
return ok
|
||||
}
|
||||
|
||||
type NotFoundError struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *NotFoundError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func NewNotFoundError(message string) *NotFoundError {
|
||||
return &NotFoundError{
|
||||
Message: message,
|
||||
}
|
||||
func NewNotFoundError(message string) error {
|
||||
return fiber.NewError(404, message)
|
||||
}
|
||||
|
||||
func IsNotFoundError(err error) bool {
|
||||
var notFoundError *NotFoundError
|
||||
ok := errors.As(err, ¬FoundError)
|
||||
return ok
|
||||
}
|
||||
|
||||
type InternalServerError struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (e *InternalServerError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func NewInternalServerError(message string) *InternalServerError {
|
||||
return &InternalServerError{
|
||||
Message: message,
|
||||
var fiberError *fiber.Error
|
||||
ok := errors.As(err, &fiberError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return fiberError.Code == 404
|
||||
}
|
||||
|
||||
func NewInternalServerError(message string) error {
|
||||
return fiber.NewError(500, message)
|
||||
}
|
||||
|
||||
52
server/stat/stat.go
Normal file
52
server/stat/stat.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package stat
|
||||
|
||||
import (
|
||||
prom "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
RequestCount = prom.NewCounterVec(
|
||||
prom.CounterOpts{
|
||||
Name: "http_requests_total",
|
||||
Help: "Total number of HTTP requests",
|
||||
},
|
||||
[]string{"path", "status"},
|
||||
)
|
||||
RegisterCount = prom.NewCounterVec(
|
||||
prom.CounterOpts{
|
||||
Name: "register_requests_total",
|
||||
Help: "Total number of registration requests",
|
||||
},
|
||||
[]string{},
|
||||
)
|
||||
DownloadCount = prom.NewCounterVec(
|
||||
prom.CounterOpts{
|
||||
Name: "download_requests_total",
|
||||
Help: "Total number of download requests",
|
||||
},
|
||||
[]string{},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
prom.MustRegister(RequestCount)
|
||||
prom.MustRegister(RegisterCount)
|
||||
prom.MustRegister(DownloadCount)
|
||||
}
|
||||
|
||||
func RecordRequest(method, path string, status string) {
|
||||
if status == "404" {
|
||||
// Aggregate all 404s under a single label
|
||||
path = "NOT_FOUND"
|
||||
}
|
||||
path = method + " " + path
|
||||
RequestCount.WithLabelValues(path, status).Inc()
|
||||
}
|
||||
|
||||
func RecordRegister() {
|
||||
RegisterCount.WithLabelValues().Inc()
|
||||
}
|
||||
|
||||
func RecordDownload() {
|
||||
DownloadCount.WithLabelValues().Inc()
|
||||
}
|
||||
Reference in New Issue
Block a user