dokploy/apps/monitoring/main.go
Mauricio Siu 74a0f5e992
Feat/monitoring (#1267) Cloud Version
* feat: add start monitoring remote servers

* reafctor: update

* refactor: update

* refactor: update

* refactor: update

* refactor: update

* refactor: update

* refactor: update

* refactor:

* refactor: add metrics

* feat: add disk monitoring

* refactor: translate to english

* refacotor: add stats

* refactor: remove color

* feat: add log server metrics

* refactor: remove unused deps

* refactor: add origin

* refactor: add logs

* refactor: update

* feat: add series monitoring

* refactor: add system monitoring

* feat: add benchmark to optimize data

* refactor: update fn

* refactor: remove comments

* refactor: update

* refactor: exclude items

* feat: add refresh rate

* feat: add monitoring remote servers

* refactor: update

* refactor: remove unsued volumes

* refactor: update monitoring

* refactor: add more presets

* feat: add container metrics

* feat: add docker monitoring

* refactor: update conversion

* refactor: remove unused code

* refactor: update

* refactor: add docker compose logs

* refactor: add docker cli

* refactor: add install curl

* refactor: add get update

* refactor: add monitoring remote servers

* refactor: add containers config

* feat: add container specification

* refactor: update path

* refactor: add server filter

* refactor: simplify logic

* fix: verify if file exist before get stats

* refactor: update

* refactor: remove unused deps

* test: add test for containers

* refactor: update

* refactor add memory collector

* refactor: update

* refactor: update

* refactor: update

* refactor: remove

* refactor: add memory

* refactor: add server memory usage

* refactor: change memory

* refactor: update

* refactor: update

* refactor: add container metrics

* refactor: comment code

* refactor: mount proc bind

* refactor: change interval with node cron

* refactor: remove opening file

* refactor: use streams

* refactor: remove unused ws

* refactor: disable live when is all

* refactor: add sqlite

* refactor: update

* feat: add golang benchmark

* refactor: update go

* refactor: update dockerfile

* refactor: update db

* refactor: add env

* refactor: separate logic

* refactor: split logic

* refactor: update logs

* refactor: update dockerfile

* refactor: hide .env

* refactor: update

* chore: hide ,.ebnv

* refactor: add end angle

* refactor: update

* refactor: update

* refactor: update

* refactor: update

* refactor: update

* refactor: update monitoring

* refactor: add mount db

* refactor: add metrics and url callback

* refactor: add middleware

* refactor: add threshold property

* feat: add memory and cpu threshold notification

* feat: send notifications to the server

* feat: add metrics for dokploy server

* refactor: add dokploy server to monitoring

* refactor: update methods

* refactor: add admin to useeffect

* refactor: stop monitoring containers if elements are 0

* refactor: cancel request if appName is empty

* refactor: reuse methods

* chore; add feat monitoring

* refactor: set base url

* refactor: adjust monitoring

* refactor: delete migrations

* feat: add columns

* fix: add missing flag

* refactor: add free metrics

* refactor: add paid monitoring

* refactor: update methods

* feat: improve ui

* feat: add container stats

* refactor: add all container metrics

* refactor: add color primary

* refactor: change default rate limiting refresher

* refactor: update retention days

* refactor: use json instead of individual properties

* refactor: lint

* refactor: pass json env

* refactor: update

* refactor: delete

* refactor: update

* refactor: fix types

* refactor: add retention days

* chore: add license

* refactor: create db

* refactor: update path

* refactor: update setup

* refactor: update

* refactor: create files

* refactor: update

* refactor: delete

* refactor: update

* refactor: update token metrics

* fix: typechecks

* refactor: setup web server

* refactor: update error handling and add monitoring

* refactor: add local storage save

* refactor: add spacing

* refactor: update

* refactor: upgrade drizzle

* refactor: delete

* refactor: uppgrade drizzle kit

* refactor: update search with jsonB

* chore: upgrade drizzle

* chore: update packages

* refactor: add missing type

* refactor: add serverType

* refactor: update url

* refactor: update

* refactor: update

* refactor: hide monitoring on self hosted

* refactor: update server

* refactor: update

* refactor: update

* refactor: pin node version
2025-02-02 14:08:06 -06:00

165 lines
3.9 KiB
Go

package main
import (
"log"
"os"
"strconv"
"time"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/joho/godotenv"
"github.com/mauriciogm/dokploy/apps/monitoring/config"
"github.com/mauriciogm/dokploy/apps/monitoring/containers"
"github.com/mauriciogm/dokploy/apps/monitoring/database"
"github.com/mauriciogm/dokploy/apps/monitoring/middleware"
"github.com/mauriciogm/dokploy/apps/monitoring/monitoring"
)
func main() {
godotenv.Load()
// Get configuration
cfg := config.GetMetricsConfig()
token := cfg.Server.Token
METRICS_URL_CALLBACK := cfg.Server.UrlCallback
log.Printf("Environment variables:")
log.Printf("METRICS_CONFIG: %s", os.Getenv("METRICS_CONFIG"))
if token == "" || METRICS_URL_CALLBACK == "" {
log.Fatal("token and urlCallback are required in the configuration")
}
db, err := database.InitDB()
if err != nil {
log.Fatal(err)
}
// Iniciar el sistema de limpieza de métricas
cleanupCron, err := database.StartMetricsCleanup(db.DB, cfg.Server.RetentionDays, cfg.Server.CronJob)
if err != nil {
log.Fatalf("Error starting metrics cleanup system: %v", err)
}
defer cleanupCron.Stop()
app := fiber.New()
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowHeaders: "Origin, Content-Type, Accept, Authorization",
}))
app.Get("/health", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": "ok",
})
})
app.Use(func(c *fiber.Ctx) error {
if c.Path() == "/health" {
return c.Next()
}
return middleware.AuthMiddleware()(c)
})
app.Get("/metrics", func(c *fiber.Ctx) error {
limit := c.Query("limit", "50")
var metrics []monitoring.SystemMetrics
if limit == "all" {
dbMetrics, err := db.GetAllMetrics()
if err != nil {
return c.Status(500).JSON(fiber.Map{
"error": "Failed to fetch metrics",
})
}
for _, m := range dbMetrics {
metrics = append(metrics, monitoring.ConvertToSystemMetrics(m))
}
} else {
n, err := strconv.Atoi(limit)
if err != nil {
n = 50
}
dbMetrics, err := db.GetLastNMetrics(n)
if err != nil {
return c.Status(500).JSON(fiber.Map{
"error": "Failed to fetch metrics",
})
}
for _, m := range dbMetrics {
metrics = append(metrics, monitoring.ConvertToSystemMetrics(m))
}
}
return c.JSON(metrics)
})
containerMonitor, err := containers.NewContainerMonitor(db)
if err != nil {
log.Fatalf("Failed to create container monitor: %v", err)
}
if err := containerMonitor.Start(); err != nil {
log.Fatalf("Failed to start container monitor: %v", err)
}
defer containerMonitor.Stop()
app.Get("/metrics/containers", func(c *fiber.Ctx) error {
limit := c.Query("limit", "50")
appName := c.Query("appName", "")
if appName == "" {
return c.JSON([]database.ContainerMetric{})
}
var metrics []database.ContainerMetric
var err error
if limit == "all" {
metrics, err = db.GetAllMetricsContainer(appName)
} else {
limitNum, parseErr := strconv.Atoi(limit)
if parseErr != nil {
limitNum = 50
}
metrics, err = db.GetLastNContainerMetrics(appName, limitNum)
}
if err != nil {
return c.Status(500).JSON(fiber.Map{
"error": "Error getting container metrics: " + err.Error(),
})
}
return c.JSON(metrics)
})
go func() {
refreshRate := cfg.Server.RefreshRate
duration := time.Duration(refreshRate) * time.Second
log.Printf("Refreshing server metrics every %v", duration)
ticker := time.NewTicker(duration)
defer ticker.Stop()
for range ticker.C {
metrics := monitoring.GetServerMetrics()
if err := db.SaveMetric(metrics); err != nil {
log.Printf("Error saving metrics: %v", err)
}
if err := monitoring.CheckThresholds(metrics); err != nil {
log.Printf("Error checking thresholds: %v", err)
}
}
}()
port := cfg.Server.Port
if port == 0 {
port = 3001
}
log.Printf("Server starting on port %d", port)
log.Fatal(app.Listen(":" + strconv.Itoa(port)))
}