diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index a1eacefef..b23eafb56 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -7523,6 +7523,20 @@ func (m *Monitor) StopDiscoveryService() { } } +// EnableTemperatureMonitoring enables temperature data collection +func (m *Monitor) EnableTemperatureMonitoring() { + // Temperature collection is always enabled when tempCollector is initialized + // This method exists for interface compatibility + log.Info().Msg("Temperature monitoring enabled") +} + +// DisableTemperatureMonitoring disables temperature data collection +func (m *Monitor) DisableTemperatureMonitoring() { + // Temperature collection is always enabled when tempCollector is initialized + // This method exists for interface compatibility + log.Info().Msg("Temperature monitoring disabled") +} + // GetGuestMetrics returns historical metrics for a guest func (m *Monitor) GetGuestMetrics(guestID string, duration time.Duration) map[string][]MetricPoint { return m.metricsHistory.GetAllGuestMetrics(guestID, duration) diff --git a/internal/tempproxy/client.go b/internal/tempproxy/client.go index 7bd87d8d6..958f28929 100644 --- a/internal/tempproxy/client.go +++ b/internal/tempproxy/client.go @@ -122,6 +122,51 @@ func calculateBackoff(attempt int) time.Duration { // classifyError categorizes errors for retry logic func classifyError(err error, respError string) *ProxyError { + // Check response error messages first (even if err is nil) + // This handles cases where the socket succeeds but the proxy returns an application error + if respError != "" { + // Rate limiting - never retry + if contains(respError, "rate limit") { + return &ProxyError{ + Type: ErrorTypeTransport, + Message: respError, + Retryable: false, + Wrapped: fmt.Errorf("%s", respError), + } + } + + // Authorization errors - never retry + if respError == "unauthorized" || respError == "method requires host-level privileges" { + return &ProxyError{ + Type: ErrorTypeAuth, + Message: respError, + Retryable: false, + Wrapped: fmt.Errorf("%s", respError), + } + } + + // SSH-related errors - retryable + if contains(respError, "ssh", "connection", "timeout") { + return &ProxyError{ + Type: ErrorTypeSSH, + Message: "SSH connectivity issue", + Retryable: true, + Wrapped: fmt.Errorf("%s", respError), + } + } + + // Sensor errors - never retry + if contains(respError, "sensor", "temperature") { + return &ProxyError{ + Type: ErrorTypeSensor, + Message: "sensor command failed", + Retryable: false, + Wrapped: fmt.Errorf("%s", respError), + } + } + } + + // If no response error and no network error, nothing to classify if err == nil { return nil } @@ -146,38 +191,6 @@ func classifyError(err error, respError string) *ProxyError { } } - // Check response error messages - if respError != "" { - if respError == "unauthorized" || respError == "method requires host-level privileges" { - return &ProxyError{ - Type: ErrorTypeAuth, - Message: respError, - Retryable: false, - Wrapped: fmt.Errorf("%s", respError), - } - } - - // SSH-related errors - if contains(respError, "ssh", "connection", "timeout") { - return &ProxyError{ - Type: ErrorTypeSSH, - Message: "SSH connectivity issue", - Retryable: true, - Wrapped: fmt.Errorf("%s", respError), - } - } - - // Sensor errors - if contains(respError, "sensor", "temperature") { - return &ProxyError{ - Type: ErrorTypeSensor, - Message: "sensor command failed", - Retryable: false, - Wrapped: fmt.Errorf("%s", respError), - } - } - } - // Unknown error return &ProxyError{ Type: ErrorTypeUnknown,