mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
feat: add database size metric
This commit is contained in:
4
main.go
4
main.go
@ -58,6 +58,7 @@ var (
|
|||||||
summaryRepository repositories.ISummaryRepository
|
summaryRepository repositories.ISummaryRepository
|
||||||
keyValueRepository repositories.IKeyValueRepository
|
keyValueRepository repositories.IKeyValueRepository
|
||||||
diagnosticsRepository repositories.IDiagnosticsRepository
|
diagnosticsRepository repositories.IDiagnosticsRepository
|
||||||
|
metricsRepository *repositories.MetricsRepository
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -149,6 +150,7 @@ func main() {
|
|||||||
summaryRepository = repositories.NewSummaryRepository(db)
|
summaryRepository = repositories.NewSummaryRepository(db)
|
||||||
keyValueRepository = repositories.NewKeyValueRepository(db)
|
keyValueRepository = repositories.NewKeyValueRepository(db)
|
||||||
diagnosticsRepository = repositories.NewDiagnosticsRepository(db)
|
diagnosticsRepository = repositories.NewDiagnosticsRepository(db)
|
||||||
|
metricsRepository = repositories.NewMetricsRepository(db)
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
mailService = mail.NewMailService()
|
mailService = mail.NewMailService()
|
||||||
@ -178,7 +180,7 @@ func main() {
|
|||||||
healthApiHandler := api.NewHealthApiHandler(db)
|
healthApiHandler := api.NewHealthApiHandler(db)
|
||||||
heartbeatApiHandler := api.NewHeartbeatApiHandler(userService, heartbeatService, languageMappingService)
|
heartbeatApiHandler := api.NewHeartbeatApiHandler(userService, heartbeatService, languageMappingService)
|
||||||
summaryApiHandler := api.NewSummaryApiHandler(userService, summaryService)
|
summaryApiHandler := api.NewSummaryApiHandler(userService, summaryService)
|
||||||
metricsHandler := api.NewMetricsHandler(userService, summaryService, heartbeatService, keyValueService)
|
metricsHandler := api.NewMetricsHandler(userService, summaryService, heartbeatService, keyValueService, metricsRepository)
|
||||||
diagnosticsHandler := api.NewDiagnosticsApiHandler(userService, diagnosticsService)
|
diagnosticsHandler := api.NewDiagnosticsApiHandler(userService, diagnosticsService)
|
||||||
avatarHandler := api.NewAvatarHandler()
|
avatarHandler := api.NewAvatarHandler()
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import "fmt"
|
|||||||
|
|
||||||
type CounterMetric struct {
|
type CounterMetric struct {
|
||||||
Name string
|
Name string
|
||||||
Value int
|
Value int64
|
||||||
Desc string
|
Desc string
|
||||||
Labels Labels
|
Labels Labels
|
||||||
}
|
}
|
||||||
|
43
repositories/metrics.go
Normal file
43
repositories/metrics.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/muety/wakapi/config"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricsRepository struct {
|
||||||
|
config *config.Config
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
const sizeTplMysql = `
|
||||||
|
SELECT SUM(data_length + index_length)
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema = ?
|
||||||
|
GROUP BY table_schema`
|
||||||
|
|
||||||
|
const sizeTplPostgres = `SELECT pg_database_size('%s');`
|
||||||
|
|
||||||
|
const sizeTplSqlite = `
|
||||||
|
SELECT page_count * page_size as size
|
||||||
|
FROM pragma_page_count(), pragma_page_size();`
|
||||||
|
|
||||||
|
func NewMetricsRepository(db *gorm.DB) *MetricsRepository {
|
||||||
|
return &MetricsRepository{config: config.Get(), db: db}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *MetricsRepository) GetDatabaseSize() (size int64, err error) {
|
||||||
|
cfg := srv.config.Db
|
||||||
|
|
||||||
|
query := srv.db.Raw("SELECT 0")
|
||||||
|
if cfg.IsMySQL() {
|
||||||
|
query = srv.db.Raw(sizeTplMysql, cfg.Name)
|
||||||
|
} else if cfg.IsPostgres() {
|
||||||
|
query = srv.db.Raw(sizeTplPostgres, cfg.Name)
|
||||||
|
} else if cfg.IsSQLite() {
|
||||||
|
query = srv.db.Raw(sizeTplSqlite)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = query.Scan(&size).Error
|
||||||
|
return size, err
|
||||||
|
}
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
v1 "github.com/muety/wakapi/models/compat/wakatime/v1"
|
v1 "github.com/muety/wakapi/models/compat/wakatime/v1"
|
||||||
mm "github.com/muety/wakapi/models/metrics"
|
mm "github.com/muety/wakapi/models/metrics"
|
||||||
|
"github.com/muety/wakapi/repositories"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
"github.com/muety/wakapi/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -39,6 +40,7 @@ const (
|
|||||||
DescMemAllocTotal = "Total number of bytes allocated for heap"
|
DescMemAllocTotal = "Total number of bytes allocated for heap"
|
||||||
DescMemSysTotal = "Total number of bytes obtained from the OS"
|
DescMemSysTotal = "Total number of bytes obtained from the OS"
|
||||||
DescGoroutines = "Total number of running goroutines"
|
DescGoroutines = "Total number of running goroutines"
|
||||||
|
DescDatabaseSize = "Total database size in bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MetricsHandler struct {
|
type MetricsHandler struct {
|
||||||
@ -47,14 +49,16 @@ type MetricsHandler struct {
|
|||||||
summarySrvc services.ISummaryService
|
summarySrvc services.ISummaryService
|
||||||
heartbeatSrvc services.IHeartbeatService
|
heartbeatSrvc services.IHeartbeatService
|
||||||
keyValueSrvc services.IKeyValueService
|
keyValueSrvc services.IKeyValueService
|
||||||
|
metricsRepo *repositories.MetricsRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMetricsHandler(userService services.IUserService, summaryService services.ISummaryService, heartbeatService services.IHeartbeatService, keyValueService services.IKeyValueService) *MetricsHandler {
|
func NewMetricsHandler(userService services.IUserService, summaryService services.ISummaryService, heartbeatService services.IHeartbeatService, keyValueService services.IKeyValueService, metricsRepo *repositories.MetricsRepository) *MetricsHandler {
|
||||||
return &MetricsHandler{
|
return &MetricsHandler{
|
||||||
userSrvc: userService,
|
userSrvc: userService,
|
||||||
summarySrvc: summaryService,
|
summarySrvc: summaryService,
|
||||||
heartbeatSrvc: heartbeatService,
|
heartbeatSrvc: heartbeatService,
|
||||||
keyValueSrvc: keyValueService,
|
keyValueSrvc: keyValueService,
|
||||||
|
metricsRepo: metricsRepo,
|
||||||
config: conf.Get(),
|
config: conf.Get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,21 +145,21 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_cumulative_seconds_total",
|
Name: MetricsPrefix + "_cumulative_seconds_total",
|
||||||
Desc: DescAllTime,
|
Desc: DescAllTime,
|
||||||
Value: int(v1.NewAllTimeFrom(summaryAllTime).Data.TotalSeconds),
|
Value: int64(v1.NewAllTimeFrom(summaryAllTime).Data.TotalSeconds),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_seconds_total",
|
Name: MetricsPrefix + "_seconds_total",
|
||||||
Desc: DescTotal,
|
Desc: DescTotal,
|
||||||
Value: int(summaryToday.TotalTime().Seconds()),
|
Value: int64(summaryToday.TotalTime().Seconds()),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_heartbeats_total",
|
Name: MetricsPrefix + "_heartbeats_total",
|
||||||
Desc: DescHeartbeats,
|
Desc: DescHeartbeats,
|
||||||
Value: int(heartbeatCount),
|
Value: int64(heartbeatCount),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -163,7 +167,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_project_seconds_total",
|
Name: MetricsPrefix + "_project_seconds_total",
|
||||||
Desc: DescProjects,
|
Desc: DescProjects,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryProject, p.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryProject, p.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: p.Key}},
|
Labels: []mm.Label{{Key: "name", Value: p.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -172,7 +176,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_language_seconds_total",
|
Name: MetricsPrefix + "_language_seconds_total",
|
||||||
Desc: DescLanguages,
|
Desc: DescLanguages,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryLanguage, l.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryLanguage, l.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: l.Key}},
|
Labels: []mm.Label{{Key: "name", Value: l.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -181,7 +185,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_editor_seconds_total",
|
Name: MetricsPrefix + "_editor_seconds_total",
|
||||||
Desc: DescEditors,
|
Desc: DescEditors,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryEditor, e.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryEditor, e.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: e.Key}},
|
Labels: []mm.Label{{Key: "name", Value: e.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -190,7 +194,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_operating_system_seconds_total",
|
Name: MetricsPrefix + "_operating_system_seconds_total",
|
||||||
Desc: DescOperatingSystems,
|
Desc: DescOperatingSystems,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryOS, o.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryOS, o.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: o.Key}},
|
Labels: []mm.Label{{Key: "name", Value: o.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -199,7 +203,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_machine_seconds_total",
|
Name: MetricsPrefix + "_machine_seconds_total",
|
||||||
Desc: DescMachines,
|
Desc: DescMachines,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryMachine, m.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryMachine, m.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: m.Key}},
|
Labels: []mm.Label{{Key: "name", Value: m.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -208,7 +212,7 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_label_seconds_total",
|
Name: MetricsPrefix + "_label_seconds_total",
|
||||||
Desc: DescLabels,
|
Desc: DescLabels,
|
||||||
Value: int(summaryToday.TotalTimeByKey(models.SummaryLabel, m.Key).Seconds()),
|
Value: int64(summaryToday.TotalTimeByKey(models.SummaryLabel, m.Key).Seconds()),
|
||||||
Labels: []mm.Label{{Key: "name", Value: m.Key}},
|
Labels: []mm.Label{{Key: "name", Value: m.Key}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -220,21 +224,34 @@ func (h *MetricsHandler) getUserMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_goroutines_total",
|
Name: MetricsPrefix + "_goroutines_total",
|
||||||
Desc: DescGoroutines,
|
Desc: DescGoroutines,
|
||||||
Value: runtime.NumGoroutine(),
|
Value: int64(runtime.NumGoroutine()),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_mem_alloc_total",
|
Name: MetricsPrefix + "_mem_alloc_total",
|
||||||
Desc: DescMemAllocTotal,
|
Desc: DescMemAllocTotal,
|
||||||
Value: int(memStats.Alloc),
|
Value: int64(memStats.Alloc),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_mem_sys_total",
|
Name: MetricsPrefix + "_mem_sys_total",
|
||||||
Desc: DescMemSysTotal,
|
Desc: DescMemSysTotal,
|
||||||
Value: int(memStats.Sys),
|
Value: int64(memStats.Sys),
|
||||||
|
Labels: []mm.Label{},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Database metrics
|
||||||
|
dbSize, err := h.metricsRepo.GetDatabaseSize()
|
||||||
|
if err != nil {
|
||||||
|
logbuch.Warn("failed to get database size (%v)", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
|
Name: MetricsPrefix + "_db_total_bytes",
|
||||||
|
Desc: DescDatabaseSize,
|
||||||
|
Value: dbSize,
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -267,28 +284,28 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_admin_seconds_total",
|
Name: MetricsPrefix + "_admin_seconds_total",
|
||||||
Desc: DescAdminTotalTime,
|
Desc: DescAdminTotalTime,
|
||||||
Value: totalSeconds,
|
Value: int64(totalSeconds),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_admin_heartbeats_total",
|
Name: MetricsPrefix + "_admin_heartbeats_total",
|
||||||
Desc: DescAdminTotalHeartbeats,
|
Desc: DescAdminTotalHeartbeats,
|
||||||
Value: int(totalHeartbeats),
|
Value: totalHeartbeats,
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_admin_users_total",
|
Name: MetricsPrefix + "_admin_users_total",
|
||||||
Desc: DescAdminTotalUsers,
|
Desc: DescAdminTotalUsers,
|
||||||
Value: int(totalUsers),
|
Value: totalUsers,
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_admin_users_active_total",
|
Name: MetricsPrefix + "_admin_users_active_total",
|
||||||
Desc: DescAdminActiveUsers,
|
Desc: DescAdminActiveUsers,
|
||||||
Value: len(activeUsers),
|
Value: int64(len(activeUsers)),
|
||||||
Labels: []mm.Label{},
|
Labels: []mm.Label{},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -304,7 +321,7 @@ func (h *MetricsHandler) getAdminMetrics(user *models.User) (*mm.Metrics, error)
|
|||||||
metrics = append(metrics, &mm.CounterMetric{
|
metrics = append(metrics, &mm.CounterMetric{
|
||||||
Name: MetricsPrefix + "_admin_user_heartbeats_total",
|
Name: MetricsPrefix + "_admin_user_heartbeats_total",
|
||||||
Desc: DescAdminUserHeartbeats,
|
Desc: DescAdminUserHeartbeats,
|
||||||
Value: int(uc.Count),
|
Value: uc.Count,
|
||||||
Labels: []mm.Label{{Key: "user", Value: uc.User}},
|
Labels: []mm.Label{{Key: "user", Value: uc.User}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user