|
|
// Copyright 2019 The Prometheus Authors |
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
// you may not use this file except in compliance with the License. |
|
|
// You may obtain a copy of the License at |
|
|
// |
|
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
|
// |
|
|
// Unless required by applicable law or agreed to in writing, software |
|
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
|
// See the License for the specific language governing permissions and |
|
|
// limitations under the License. |
|
|
|
|
|
//go:build !nopowersupplyclass |
|
|
// +build !nopowersupplyclass |
|
|
|
|
|
package collector |
|
|
|
|
|
import ( |
|
|
"errors" |
|
|
"fmt" |
|
|
"os" |
|
|
"regexp" |
|
|
"strings" |
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus" |
|
|
"github.com/prometheus/procfs/sysfs" |
|
|
) |
|
|
|
|
|
func (c *powerSupplyClassCollector) Update(ch chan<- prometheus.Metric) error { |
|
|
powerSupplyClass, err := getPowerSupplyClassInfo(c.ignoredPattern) |
|
|
if err != nil { |
|
|
if errors.Is(err, os.ErrNotExist) { |
|
|
return ErrNoData |
|
|
} |
|
|
return fmt.Errorf("could not get power_supply class info: %w", err) |
|
|
} |
|
|
for _, powerSupply := range powerSupplyClass { |
|
|
|
|
|
for name, value := range map[string]*int64{ |
|
|
"authentic": powerSupply.Authentic, |
|
|
"calibrate": powerSupply.Calibrate, |
|
|
"capacity": powerSupply.Capacity, |
|
|
"capacity_alert_max": powerSupply.CapacityAlertMax, |
|
|
"capacity_alert_min": powerSupply.CapacityAlertMin, |
|
|
"cyclecount": powerSupply.CycleCount, |
|
|
"online": powerSupply.Online, |
|
|
"present": powerSupply.Present, |
|
|
"time_to_empty_seconds": powerSupply.TimeToEmptyNow, |
|
|
"time_to_full_seconds": powerSupply.TimeToFullNow, |
|
|
} { |
|
|
if value != nil { |
|
|
pushPowerSupplyMetric(ch, c.subsystem, name, float64(*value), powerSupply.Name, prometheus.GaugeValue) |
|
|
} |
|
|
} |
|
|
|
|
|
for name, value := range map[string]*int64{ |
|
|
"current_boot": powerSupply.CurrentBoot, |
|
|
"current_max": powerSupply.CurrentMax, |
|
|
"current_ampere": powerSupply.CurrentNow, |
|
|
"energy_empty": powerSupply.EnergyEmpty, |
|
|
"energy_empty_design": powerSupply.EnergyEmptyDesign, |
|
|
"energy_full": powerSupply.EnergyFull, |
|
|
"energy_full_design": powerSupply.EnergyFullDesign, |
|
|
"energy_watthour": powerSupply.EnergyNow, |
|
|
"voltage_boot": powerSupply.VoltageBoot, |
|
|
"voltage_max": powerSupply.VoltageMax, |
|
|
"voltage_max_design": powerSupply.VoltageMaxDesign, |
|
|
"voltage_min": powerSupply.VoltageMin, |
|
|
"voltage_min_design": powerSupply.VoltageMinDesign, |
|
|
"voltage_volt": powerSupply.VoltageNow, |
|
|
"voltage_ocv": powerSupply.VoltageOCV, |
|
|
"charge_control_limit": powerSupply.ChargeControlLimit, |
|
|
"charge_control_limit_max": powerSupply.ChargeControlLimitMax, |
|
|
"charge_counter": powerSupply.ChargeCounter, |
|
|
"charge_empty": powerSupply.ChargeEmpty, |
|
|
"charge_empty_design": powerSupply.ChargeEmptyDesign, |
|
|
"charge_full": powerSupply.ChargeFull, |
|
|
"charge_full_design": powerSupply.ChargeFullDesign, |
|
|
"charge_ampere": powerSupply.ChargeNow, |
|
|
"charge_term_current": powerSupply.ChargeTermCurrent, |
|
|
"constant_charge_current": powerSupply.ConstantChargeCurrent, |
|
|
"constant_charge_current_max": powerSupply.ConstantChargeCurrentMax, |
|
|
"constant_charge_voltage": powerSupply.ConstantChargeVoltage, |
|
|
"constant_charge_voltage_max": powerSupply.ConstantChargeVoltageMax, |
|
|
"precharge_current": powerSupply.PrechargeCurrent, |
|
|
"input_current_limit": powerSupply.InputCurrentLimit, |
|
|
"power_watt": powerSupply.PowerNow, |
|
|
} { |
|
|
if value != nil { |
|
|
pushPowerSupplyMetric(ch, c.subsystem, name, float64(*value)/1e6, powerSupply.Name, prometheus.GaugeValue) |
|
|
} |
|
|
} |
|
|
|
|
|
for name, value := range map[string]*int64{ |
|
|
"temp_celsius": powerSupply.Temp, |
|
|
"temp_alert_max_celsius": powerSupply.TempAlertMax, |
|
|
"temp_alert_min_celsius": powerSupply.TempAlertMin, |
|
|
"temp_ambient_celsius": powerSupply.TempAmbient, |
|
|
"temp_ambient_max_celsius": powerSupply.TempAmbientMax, |
|
|
"temp_ambient_min_celsius": powerSupply.TempAmbientMin, |
|
|
"temp_max_celsius": powerSupply.TempMax, |
|
|
"temp_min_celsius": powerSupply.TempMin, |
|
|
} { |
|
|
if value != nil { |
|
|
pushPowerSupplyMetric(ch, c.subsystem, name, float64(*value)/10.0, powerSupply.Name, prometheus.GaugeValue) |
|
|
} |
|
|
} |
|
|
|
|
|
var ( |
|
|
keys []string |
|
|
values []string |
|
|
) |
|
|
for name, value := range map[string]string{ |
|
|
"power_supply": powerSupply.Name, |
|
|
"capacity_level": powerSupply.CapacityLevel, |
|
|
"charge_type": powerSupply.ChargeType, |
|
|
"health": powerSupply.Health, |
|
|
"manufacturer": powerSupply.Manufacturer, |
|
|
"model_name": powerSupply.ModelName, |
|
|
"serial_number": powerSupply.SerialNumber, |
|
|
"status": powerSupply.Status, |
|
|
"technology": powerSupply.Technology, |
|
|
"type": powerSupply.Type, |
|
|
"usb_type": powerSupply.UsbType, |
|
|
"scope": powerSupply.Scope, |
|
|
} { |
|
|
if value != "" { |
|
|
keys = append(keys, name) |
|
|
values = append(values, strings.ToValidUTF8(value, "<EFBFBD>")) |
|
|
} |
|
|
} |
|
|
|
|
|
fieldDesc := prometheus.NewDesc( |
|
|
prometheus.BuildFQName(namespace, c.subsystem, "info"), |
|
|
"info of /sys/class/power_supply/<power_supply>.", |
|
|
keys, |
|
|
nil, |
|
|
) |
|
|
ch <- prometheus.MustNewConstMetric(fieldDesc, prometheus.GaugeValue, 1.0, values...) |
|
|
|
|
|
} |
|
|
|
|
|
return nil |
|
|
} |
|
|
|
|
|
func pushPowerSupplyMetric(ch chan<- prometheus.Metric, subsystem string, name string, value float64, powerSupplyName string, valueType prometheus.ValueType) { |
|
|
fieldDesc := prometheus.NewDesc( |
|
|
prometheus.BuildFQName(namespace, subsystem, name), |
|
|
fmt.Sprintf("%s value of /sys/class/power_supply/<power_supply>.", name), |
|
|
[]string{"power_supply"}, |
|
|
nil, |
|
|
) |
|
|
|
|
|
ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, value, powerSupplyName) |
|
|
} |
|
|
|
|
|
func getPowerSupplyClassInfo(ignore *regexp.Regexp) (sysfs.PowerSupplyClass, error) { |
|
|
fs, err := sysfs.NewFS(*sysPath) |
|
|
if err != nil { |
|
|
return nil, err |
|
|
} |
|
|
powerSupplyClass, err := fs.PowerSupplyClass() |
|
|
|
|
|
if err != nil { |
|
|
return powerSupplyClass, fmt.Errorf("error obtaining power_supply class info: %w", err) |
|
|
} |
|
|
|
|
|
for device := range powerSupplyClass { |
|
|
if ignore.MatchString(device) { |
|
|
delete(powerSupplyClass, device) |
|
|
} |
|
|
} |
|
|
|
|
|
return powerSupplyClass, nil |
|
|
}
|
|
|
|