Compare commits

...

4 Commits

Author SHA1 Message Date
Ben Kochie 780120f501
Merge 315c1c9f57 into bde0a086ab 2025-07-03 20:02:54 +02:00
Siyuan Miao bde0a086ab chore: bump to 0.4.7 2025-07-03 19:03:46 +02:00
Aveline 9c9335da31
chore: typo 'supression' should be 'suppression' (#671) 2025-07-03 17:28:00 +02:00
SuperQ 315c1c9f57
Add more metrics
* Configuration load success/timestamp.
* Wake-on-Lan packets/errors.

Signed-off-by: SuperQ <superq@gmail.com>
2025-06-12 09:14:25 +02:00
7 changed files with 53 additions and 8 deletions

View File

@ -2,8 +2,8 @@ BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
BUILDDATE ?= $(shell date -u +%FT%T%z) BUILDDATE ?= $(shell date -u +%FT%T%z)
BUILDTS ?= $(shell date -u +%s) BUILDTS ?= $(shell date -u +%s)
REVISION ?= $(shell git rev-parse HEAD) REVISION ?= $(shell git rev-parse HEAD)
VERSION_DEV ?= 0.4.6-dev$(shell date +%Y%m%d%H%M) VERSION_DEV ?= 0.4.7-dev$(shell date +%Y%m%d%H%M)
VERSION ?= 0.4.5 VERSION ?= 0.4.6
PROMETHEUS_TAG := github.com/prometheus/common/version PROMETHEUS_TAG := github.com/prometheus/common/version
KVM_PKG_NAME := github.com/jetkvm/kvm KVM_PKG_NAME := github.com/jetkvm/kvm

View File

@ -9,6 +9,8 @@ import (
"github.com/jetkvm/kvm/internal/logging" "github.com/jetkvm/kvm/internal/logging"
"github.com/jetkvm/kvm/internal/network" "github.com/jetkvm/kvm/internal/network"
"github.com/jetkvm/kvm/internal/usbgadget" "github.com/jetkvm/kvm/internal/usbgadget"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
) )
type WakeOnLanDevice struct { type WakeOnLanDevice struct {
@ -138,6 +140,21 @@ var (
configLock = &sync.Mutex{} configLock = &sync.Mutex{}
) )
var (
configSuccess = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "jetkvm_config_last_reload_successful",
Help: "The last configuration load succeeded",
},
)
configSuccessTime = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "jetkvm_config_last_reload_success_timestamp_seconds",
Help: "Timestamp of last successful config load",
},
)
)
func LoadConfig() { func LoadConfig() {
configLock.Lock() configLock.Lock()
defer configLock.Unlock() defer configLock.Unlock()
@ -153,6 +170,8 @@ func LoadConfig() {
file, err := os.Open(configPath) file, err := os.Open(configPath)
if err != nil { if err != nil {
logger.Debug().Msg("default config file doesn't exist, using default") logger.Debug().Msg("default config file doesn't exist, using default")
configSuccess.Set(1.0)
configSuccessTime.SetToCurrentTime()
return return
} }
defer file.Close() defer file.Close()
@ -161,6 +180,7 @@ func LoadConfig() {
loadedConfig := *defaultConfig loadedConfig := *defaultConfig
if err := json.NewDecoder(file).Decode(&loadedConfig); err != nil { if err := json.NewDecoder(file).Decode(&loadedConfig); err != nil {
logger.Warn().Err(err).Msg("config file JSON parsing failed") logger.Warn().Err(err).Msg("config file JSON parsing failed")
configSuccess.Set(0.0)
return return
} }
@ -181,6 +201,9 @@ func LoadConfig() {
logging.GetRootLogger().UpdateLogLevel(config.DefaultLogLevel) logging.GetRootLogger().UpdateLogLevel(config.DefaultLogLevel)
configSuccess.Set(1.0)
configSuccessTime.SetToCurrentTime()
logger.Info().Str("path", configPath).Msg("config loaded") logger.Info().Str("path", configPath).Msg("config loaded")
} }

View File

@ -143,7 +143,7 @@ func (u *UsbGadget) listenKeyboardEvents() {
default: default:
l.Trace().Msg("reading from keyboard") l.Trace().Msg("reading from keyboard")
if u.keyboardHidFile == nil { if u.keyboardHidFile == nil {
u.logWithSupression("keyboardHidFileNil", 100, &l, nil, "keyboardHidFile is nil") u.logWithSuppression("keyboardHidFileNil", 100, &l, nil, "keyboardHidFile is nil")
// show the error every 100 times to avoid spamming the logs // show the error every 100 times to avoid spamming the logs
time.Sleep(time.Second) time.Sleep(time.Second)
continue continue
@ -153,7 +153,7 @@ func (u *UsbGadget) listenKeyboardEvents() {
n, err := u.keyboardHidFile.Read(buf) n, err := u.keyboardHidFile.Read(buf)
if err != nil { if err != nil {
u.logWithSupression("keyboardHidFileRead", 100, &l, err, "failed to read") u.logWithSuppression("keyboardHidFileRead", 100, &l, err, "failed to read")
continue continue
} }
u.resetLogSuppressionCounter("keyboardHidFileRead") u.resetLogSuppressionCounter("keyboardHidFileRead")
@ -201,7 +201,7 @@ func (u *UsbGadget) keyboardWriteHidFile(data []byte) error {
_, err := u.keyboardHidFile.Write(data) _, err := u.keyboardHidFile.Write(data)
if err != nil { if err != nil {
u.logWithSupression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0") u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0")
u.keyboardHidFile.Close() u.keyboardHidFile.Close()
u.keyboardHidFile = nil u.keyboardHidFile = nil
return err return err

View File

@ -75,7 +75,7 @@ func (u *UsbGadget) absMouseWriteHidFile(data []byte) error {
_, err := u.absMouseHidFile.Write(data) _, err := u.absMouseHidFile.Write(data)
if err != nil { if err != nil {
u.logWithSupression("absMouseWriteHidFile", 100, u.log, err, "failed to write to hidg1") u.logWithSuppression("absMouseWriteHidFile", 100, u.log, err, "failed to write to hidg1")
u.absMouseHidFile.Close() u.absMouseHidFile.Close()
u.absMouseHidFile = nil u.absMouseHidFile = nil
return err return err

View File

@ -65,7 +65,7 @@ func (u *UsbGadget) relMouseWriteHidFile(data []byte) error {
_, err := u.relMouseHidFile.Write(data) _, err := u.relMouseHidFile.Write(data)
if err != nil { if err != nil {
u.logWithSupression("relMouseWriteHidFile", 100, u.log, err, "failed to write to hidg2") u.logWithSuppression("relMouseWriteHidFile", 100, u.log, err, "failed to write to hidg2")
u.relMouseHidFile.Close() u.relMouseHidFile.Close()
u.relMouseHidFile = nil u.relMouseHidFile = nil
return err return err

View File

@ -81,7 +81,7 @@ func compareFileContent(oldContent []byte, newContent []byte, looserMatch bool)
return false return false
} }
func (u *UsbGadget) logWithSupression(counterName string, every int, logger *zerolog.Logger, err error, msg string, args ...interface{}) { func (u *UsbGadget) logWithSuppression(counterName string, every int, logger *zerolog.Logger, err error, msg string, args ...interface{}) {
u.logSuppressionLock.Lock() u.logSuppressionLock.Lock()
defer u.logSuppressionLock.Unlock() defer u.logSuppressionLock.Unlock()

22
wol.go
View File

@ -4,6 +4,24 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"net" "net"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
wolPackets = promauto.NewCounter(
prometheus.CounterOpts{
Name: "jetkvm_wol_sent_packets_total",
Help: "Total number of Wake-on-LAN magic packets sent.",
},
)
wolErrors = promauto.NewCounter(
prometheus.CounterOpts{
Name: "jetkvm_wol_sent_packet_errors_total",
Help: "Total number of Wake-on-LAN magic packets errors.",
},
)
) )
// SendWOLMagicPacket sends a Wake-on-LAN magic packet to the specified MAC address // SendWOLMagicPacket sends a Wake-on-LAN magic packet to the specified MAC address
@ -11,6 +29,7 @@ func rpcSendWOLMagicPacket(macAddress string) error {
// Parse the MAC address // Parse the MAC address
mac, err := net.ParseMAC(macAddress) mac, err := net.ParseMAC(macAddress)
if err != nil { if err != nil {
wolErrors.Inc()
return ErrorfL(wolLogger, "invalid MAC address", err) return ErrorfL(wolLogger, "invalid MAC address", err)
} }
@ -20,6 +39,7 @@ func rpcSendWOLMagicPacket(macAddress string) error {
// Set up UDP connection // Set up UDP connection
conn, err := net.Dial("udp", "255.255.255.255:9") conn, err := net.Dial("udp", "255.255.255.255:9")
if err != nil { if err != nil {
wolErrors.Inc()
return ErrorfL(wolLogger, "failed to establish UDP connection", err) return ErrorfL(wolLogger, "failed to establish UDP connection", err)
} }
defer conn.Close() defer conn.Close()
@ -27,10 +47,12 @@ func rpcSendWOLMagicPacket(macAddress string) error {
// Send the packet // Send the packet
_, err = conn.Write(packet) _, err = conn.Write(packet)
if err != nil { if err != nil {
wolErrors.Inc()
return ErrorfL(wolLogger, "failed to send WOL packet", err) return ErrorfL(wolLogger, "failed to send WOL packet", err)
} }
wolLogger.Info().Str("mac", macAddress).Msg("WOL packet sent") wolLogger.Info().Str("mac", macAddress).Msg("WOL packet sent")
wolPackets.Inc()
return nil return nil
} }