aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--application_router.go10
-rw-r--r--caronte.go6
-rw-r--r--go.mod3
-rw-r--r--go.sum12
-rw-r--r--resources_controller.go91
-rw-r--r--utils.go8
7 files changed, 129 insertions, 3 deletions
diff --git a/VERSION b/VERSION
index ce609ca..bc1f22f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.8 \ No newline at end of file
+v0.20.10 \ No newline at end of file
diff --git a/application_router.go b/application_router.go
index 334e9f3..da71538 100644
--- a/application_router.go
+++ b/application_router.go
@@ -14,7 +14,7 @@ import (
)
func CreateApplicationRouter(applicationContext *ApplicationContext,
- notificationController *NotificationController) *gin.Engine {
+ notificationController *NotificationController, resourcesController *ResourcesController) *gin.Engine {
router := gin.New()
router.Use(gin.Logger())
router.Use(gin.Recovery())
@@ -342,6 +342,14 @@ func CreateApplicationRouter(applicationContext *ApplicationContext,
success(c, applicationContext.StatisticsController.GetStatistics(c, filter))
})
+
+ api.GET("/resources/system", func(c *gin.Context) {
+ success(c, resourcesController.GetSystemStats(c))
+ })
+
+ api.GET("/resources/process", func(c *gin.Context) {
+ success(c, resourcesController.GetProcessStats(c))
+ })
}
return router
diff --git a/caronte.go b/caronte.go
index 288563c..d999724 100644
--- a/caronte.go
+++ b/caronte.go
@@ -35,7 +35,11 @@ func main() {
notificationController := NewNotificationController(applicationContext)
go notificationController.Run()
- applicationRouter := CreateApplicationRouter(applicationContext, notificationController)
+
+ resourcesController := NewResourcesController(notificationController)
+ go resourcesController.Run()
+
+ applicationRouter := CreateApplicationRouter(applicationContext, notificationController, resourcesController)
if applicationRouter.Run(fmt.Sprintf("%s:%v", *bindAddress, *bindPort)) != nil {
log.WithError(err).WithFields(logFields).Fatal("failed to create the server")
}
diff --git a/go.mod b/go.mod
index 404f64c..7834dbe 100644
--- a/go.mod
+++ b/go.mod
@@ -3,15 +3,18 @@ module github.com/eciavatta/caronte
go 1.14
require (
+ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/flier/gohs v1.0.0
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607
github.com/gin-gonic/gin v1.6.2
+ github.com/go-ole/go-ole v1.2.4 // indirect
github.com/go-playground/validator/v10 v10.2.0
github.com/golang/protobuf v1.3.5 // indirect
github.com/google/gopacket v1.1.17
github.com/gorilla/websocket v1.4.2
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
+ github.com/shirou/gopsutil v2.20.9+incompatible
github.com/sirupsen/logrus v1.4.2
github.com/smartystreets/assertions v1.0.0 // indirect
github.com/stretchr/testify v1.4.0
diff --git a/go.sum b/go.sum
index d29e0cb..b507337 100644
--- a/go.sum
+++ b/go.sum
@@ -1,4 +1,6 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
+github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -10,6 +12,8 @@ github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 h1:MrIm8EEPue08J
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg=
github.com/gin-gonic/gin v1.6.2 h1:88crIK23zO6TqlQBt+f9FrPJNKm9ZEr7qjp9vl/d5TM=
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
+github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -52,6 +56,7 @@ github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.14/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw=
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
@@ -104,9 +109,13 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
+github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ=
+github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
@@ -152,6 +161,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -161,6 +172,7 @@ golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 h1:T5DasATyLQfmbTpfEXx/IOL9vfjzW6up+ZDkmHvIf2s=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200406155108-e3b113bbe6a4 h1:c1Sgqkh8v6ZxafNGG64r8C8UisIW2TKMJN8P86tKjr0=
diff --git a/resources_controller.go b/resources_controller.go
new file mode 100644
index 0000000..050157a
--- /dev/null
+++ b/resources_controller.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "context"
+ "github.com/gin-gonic/gin"
+ "github.com/shirou/gopsutil/cpu"
+ "github.com/shirou/gopsutil/disk"
+ "github.com/shirou/gopsutil/mem"
+ log "github.com/sirupsen/logrus"
+ "sync"
+ "time"
+)
+
+const (
+ averageCPUPercentAlertThreshold = 90.0
+ averageCPUPercentAlertMinInterval = 120.0
+)
+
+type SystemStats struct {
+ VirtualMemory *mem.VirtualMemoryStat `json:"virtual_memory"`
+ CPUTimes []cpu.TimesStat `json:"cpu_times"`
+ CPUPercents []float64 `json:"cpu_percents"`
+ DiskUsage *disk.UsageStat `json:"disk_usage"`
+}
+
+type ResourcesController struct {
+ notificationController *NotificationController
+ lastCPUPercent []float64
+ mutex sync.Mutex
+}
+
+func NewResourcesController(notificationController *NotificationController) *ResourcesController {
+ return &ResourcesController{
+ notificationController: notificationController,
+ }
+}
+
+func (csc *ResourcesController) GetProcessStats(c context.Context) interface{} {
+ return nil
+}
+
+func (csc *ResourcesController) GetSystemStats(c context.Context) SystemStats {
+ virtualMemory, err := mem.VirtualMemoryWithContext(c)
+ if err != nil {
+ log.WithError(err).Panic("failed to retrieve virtual memory")
+ }
+ cpuTimes, err := cpu.TimesWithContext(c, true)
+ if err != nil {
+ log.WithError(err).Panic("failed to retrieve cpu times")
+ }
+ diskUsage, err := disk.UsageWithContext(c, "/")
+ if err != nil {
+ log.WithError(err).Panic("failed to retrieve disk usage")
+ }
+
+ defer csc.mutex.Unlock()
+ csc.mutex.Lock()
+
+ return SystemStats{
+ VirtualMemory: virtualMemory,
+ CPUTimes: cpuTimes,
+ DiskUsage: diskUsage,
+ CPUPercents: csc.lastCPUPercent,
+ }
+}
+
+func (csc *ResourcesController) Run() {
+ interval, _ := time.ParseDuration("3s")
+ var lastAlertTime time.Time
+
+ for {
+ cpuPercent, err := cpu.Percent(interval, true)
+ if err != nil {
+ log.WithError(err).Error("failed to retrieve cpu percent")
+ return
+ }
+
+ csc.mutex.Lock()
+ csc.lastCPUPercent = cpuPercent
+ csc.mutex.Unlock()
+
+ avg := Average(cpuPercent)
+ if avg > averageCPUPercentAlertThreshold && time.Now().Sub(lastAlertTime).Seconds() > averageCPUPercentAlertMinInterval {
+ csc.notificationController.Notify("resources.cpu_alert", "alert", gin.H{
+ "cpu_percent": cpuPercent,
+ })
+ log.WithField("cpu_percent", cpuPercent).Warn("cpu percent usage has exceeded the limit threshold")
+ lastAlertTime = time.Now()
+ }
+ }
+}
diff --git a/utils.go b/utils.go
index a14fdca..ec5a807 100644
--- a/utils.go
+++ b/utils.go
@@ -151,3 +151,11 @@ func ParseIPNet(address string) *net.IPNet {
return network
}
+
+func Average(array []float64) float64 {
+ var sum float64
+ for _, f := range array {
+ sum += f
+ }
+ return sum / float64(len(array))
+}