2020-08-27 09:37:32 +02:00
|
|
|
package metrics
|
|
|
|
|
|
|
|
import (
|
2022-03-18 02:07:55 +01:00
|
|
|
"sync"
|
2020-08-27 09:37:32 +02:00
|
|
|
"time"
|
2022-03-07 02:26:52 +01:00
|
|
|
|
|
|
|
"github.com/owncast/owncast/config"
|
|
|
|
"github.com/owncast/owncast/core/data"
|
|
|
|
"github.com/owncast/owncast/models"
|
2020-08-27 09:37:32 +02:00
|
|
|
)
|
|
|
|
|
2020-11-13 00:14:59 +01:00
|
|
|
// How often we poll for updates.
|
2022-03-25 22:20:51 +01:00
|
|
|
const hardwareMetricsPollingInterval = 2 * time.Minute
|
|
|
|
const playbackMetricsPollingInterval = 2 * time.Minute
|
2022-03-17 01:34:44 +01:00
|
|
|
|
|
|
|
const (
|
|
|
|
// How often we poll for updates.
|
|
|
|
viewerMetricsPollingInterval = 2 * time.Minute
|
|
|
|
activeChatClientCountKey = "chat_client_count"
|
|
|
|
activeViewerCountKey = "viewer_count"
|
|
|
|
)
|
2020-08-27 09:37:32 +02:00
|
|
|
|
2020-11-13 00:14:59 +01:00
|
|
|
// CollectedMetrics stores different collected + timestamped values.
|
2020-10-02 21:18:08 +02:00
|
|
|
type CollectedMetrics struct {
|
2022-03-18 02:07:55 +01:00
|
|
|
m sync.Mutex `json:"-"`
|
|
|
|
|
2022-03-17 06:49:27 +01:00
|
|
|
CPUUtilizations []TimestampedValue `json:"cpu"`
|
|
|
|
RAMUtilizations []TimestampedValue `json:"memory"`
|
|
|
|
DiskUtilizations []TimestampedValue `json:"disk"`
|
|
|
|
|
|
|
|
errorCount []TimestampedValue `json:"-"`
|
|
|
|
lowestBitrate []TimestampedValue `json:"-"`
|
|
|
|
medianBitrate []TimestampedValue `json:"-"`
|
|
|
|
highestBitrate []TimestampedValue `json:"-"`
|
|
|
|
|
|
|
|
medianSegmentDownloadSeconds []TimestampedValue `json:"-"`
|
|
|
|
maximumSegmentDownloadSeconds []TimestampedValue `json:"-"`
|
|
|
|
minimumSegmentDownloadSeconds []TimestampedValue `json:"-"`
|
|
|
|
|
|
|
|
minimumLatency []TimestampedValue `json:"-"`
|
|
|
|
maximumLatency []TimestampedValue `json:"-"`
|
|
|
|
medianLatency []TimestampedValue `json:"-"`
|
|
|
|
|
|
|
|
qualityVariantChanges []TimestampedValue `json:"-"`
|
2022-03-25 07:06:47 +01:00
|
|
|
|
|
|
|
streamHealthOverview *models.StreamHealthOverview
|
2020-08-27 09:37:32 +02:00
|
|
|
}
|
|
|
|
|
2020-11-13 00:14:59 +01:00
|
|
|
// Metrics is the shared Metrics instance.
|
2022-03-17 01:34:44 +01:00
|
|
|
var metrics *CollectedMetrics
|
2020-08-27 09:37:32 +02:00
|
|
|
|
2022-03-25 07:06:47 +01:00
|
|
|
var _getStatus func() models.Status
|
|
|
|
|
2020-11-13 00:14:59 +01:00
|
|
|
// Start will begin the metrics collection and alerting.
|
2022-03-07 02:26:52 +01:00
|
|
|
func Start(getStatus func() models.Status) {
|
2022-03-25 07:06:47 +01:00
|
|
|
_getStatus = getStatus
|
2022-03-07 02:26:52 +01:00
|
|
|
host := data.GetServerURL()
|
|
|
|
if host == "" {
|
|
|
|
host = "unknown"
|
|
|
|
}
|
|
|
|
labels = map[string]string{
|
|
|
|
"version": config.VersionNumber,
|
|
|
|
"host": host,
|
|
|
|
}
|
|
|
|
|
2022-03-17 01:34:44 +01:00
|
|
|
setupPrometheusCollectors()
|
2022-03-07 02:26:52 +01:00
|
|
|
|
2022-03-17 01:34:44 +01:00
|
|
|
metrics = new(CollectedMetrics)
|
2020-10-02 21:18:08 +02:00
|
|
|
go startViewerCollectionMetrics()
|
2020-08-27 09:37:32 +02:00
|
|
|
|
2022-03-25 07:06:47 +01:00
|
|
|
go func() {
|
|
|
|
for range time.Tick(hardwareMetricsPollingInterval) {
|
|
|
|
handlePolling()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for range time.Tick(playbackMetricsPollingInterval) {
|
|
|
|
handlePlaybackPolling()
|
|
|
|
}
|
|
|
|
}()
|
2020-08-27 09:37:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func handlePolling() {
|
2022-03-18 02:07:55 +01:00
|
|
|
metrics.m.Lock()
|
|
|
|
defer metrics.m.Unlock()
|
|
|
|
|
2020-08-27 09:37:32 +02:00
|
|
|
// Collect hardware stats
|
|
|
|
collectCPUUtilization()
|
|
|
|
collectRAMUtilization()
|
2020-10-02 21:18:08 +02:00
|
|
|
collectDiskUtilization()
|
2020-08-27 09:37:32 +02:00
|
|
|
|
|
|
|
// Alerting
|
|
|
|
handleAlerting()
|
|
|
|
}
|
2022-03-17 01:34:44 +01:00
|
|
|
|
|
|
|
// GetMetrics will return the collected metrics.
|
|
|
|
func GetMetrics() *CollectedMetrics {
|
|
|
|
return metrics
|
|
|
|
}
|