138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
// FILE: lixenwraith/log/heartbeat.go
|
|
package log
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"time"
|
|
)
|
|
|
|
// handleHeartbeat processes a heartbeat timer tick
|
|
func (l *Logger) handleHeartbeat() {
|
|
c := l.getConfig()
|
|
heartbeatLevel := c.HeartbeatLevel
|
|
|
|
if heartbeatLevel >= 1 {
|
|
l.logProcHeartbeat()
|
|
}
|
|
|
|
if heartbeatLevel >= 2 {
|
|
l.logDiskHeartbeat()
|
|
}
|
|
|
|
if heartbeatLevel >= 3 {
|
|
l.logSysHeartbeat()
|
|
}
|
|
}
|
|
|
|
// logProcHeartbeat logs process/logger statistics heartbeat
|
|
func (l *Logger) logProcHeartbeat() {
|
|
processed := l.state.TotalLogsProcessed.Load()
|
|
dropped := l.state.DroppedLogs.Load()
|
|
sequence := l.state.HeartbeatSequence.Add(1)
|
|
|
|
startTimeVal := l.state.LoggerStartTime.Load()
|
|
var uptimeHours float64 = 0
|
|
if startTime, ok := startTimeVal.(time.Time); ok && !startTime.IsZero() {
|
|
uptime := time.Since(startTime)
|
|
uptimeHours = uptime.Hours()
|
|
}
|
|
|
|
procArgs := []any{
|
|
"type", "proc",
|
|
"sequence", sequence,
|
|
"uptime_hours", fmt.Sprintf("%.2f", uptimeHours),
|
|
"processed_logs", processed,
|
|
"dropped_logs", dropped,
|
|
}
|
|
|
|
l.writeHeartbeatRecord(LevelProc, procArgs)
|
|
}
|
|
|
|
// logDiskHeartbeat logs disk/file statistics heartbeat
|
|
func (l *Logger) logDiskHeartbeat() {
|
|
sequence := l.state.HeartbeatSequence.Load()
|
|
rotations := l.state.TotalRotations.Load()
|
|
deletions := l.state.TotalDeletions.Load()
|
|
|
|
c := l.getConfig()
|
|
dir := c.Directory
|
|
ext := c.Extension
|
|
currentSizeMB := float64(l.state.CurrentSize.Load()) / (1024 * 1024) // Current file size
|
|
totalSizeMB := float64(-1.0) // Default error value
|
|
fileCount := -1 // Default error value
|
|
|
|
dirSize, err := l.getLogDirSize(dir, ext)
|
|
if err == nil {
|
|
totalSizeMB = float64(dirSize) / (1024 * 1024)
|
|
} else {
|
|
l.internalLog("warning - heartbeat failed to get dir size: %v\n", err)
|
|
}
|
|
|
|
count, err := l.getLogFileCount(dir, ext)
|
|
if err == nil {
|
|
fileCount = count
|
|
} else {
|
|
l.internalLog("warning - heartbeat failed to get file count: %v\n", err)
|
|
}
|
|
|
|
diskArgs := []any{
|
|
"type", "disk",
|
|
"sequence", sequence,
|
|
"rotated_files", rotations,
|
|
"deleted_files", deletions,
|
|
"total_log_size_mb", fmt.Sprintf("%.2f", totalSizeMB),
|
|
"log_file_count", fileCount,
|
|
"current_file_size_mb", fmt.Sprintf("%.2f", currentSizeMB),
|
|
"disk_status_ok", l.state.DiskStatusOK.Load(),
|
|
}
|
|
|
|
// Add disk free space if we can get it
|
|
freeSpace, err := l.getDiskFreeSpace(dir)
|
|
if err == nil {
|
|
freeSpaceMB := float64(freeSpace) / (1024 * 1024)
|
|
diskArgs = append(diskArgs, "disk_free_mb", fmt.Sprintf("%.2f", freeSpaceMB))
|
|
}
|
|
|
|
l.writeHeartbeatRecord(LevelDisk, diskArgs)
|
|
}
|
|
|
|
// logSysHeartbeat logs system/runtime statistics heartbeat
|
|
func (l *Logger) logSysHeartbeat() {
|
|
sequence := l.state.HeartbeatSequence.Load()
|
|
|
|
var memStats runtime.MemStats
|
|
runtime.ReadMemStats(&memStats)
|
|
|
|
sysArgs := []any{
|
|
"type", "sys",
|
|
"sequence", sequence,
|
|
"alloc_mb", fmt.Sprintf("%.2f", float64(memStats.Alloc)/(1000*1000)),
|
|
"sys_mb", fmt.Sprintf("%.2f", float64(memStats.Sys)/(1000*1000)),
|
|
"num_gc", memStats.NumGC,
|
|
"num_goroutine", runtime.NumGoroutine(),
|
|
}
|
|
|
|
// Write the heartbeat record
|
|
l.writeHeartbeatRecord(LevelSys, sysArgs)
|
|
}
|
|
|
|
// writeHeartbeatRecord creates and sends a heartbeat log record through the main processing channel
|
|
func (l *Logger) writeHeartbeatRecord(level int64, args []any) {
|
|
if l.state.LoggerDisabled.Load() || l.state.ShutdownCalled.Load() {
|
|
return
|
|
}
|
|
|
|
// Create heartbeat record with appropriate flags
|
|
record := logRecord{
|
|
Flags: FlagDefault | FlagShowLevel,
|
|
TimeStamp: time.Now(),
|
|
Level: level,
|
|
Trace: "",
|
|
Args: args,
|
|
unreportedDrops: 0,
|
|
}
|
|
|
|
// Send through the main processing channel
|
|
l.sendLogRecord(record)
|
|
} |