Browse Source

darwin powersupply collector (#1777)

* Extract powersupply linux code from collector common file.
* Add Darwin powersupply collector.

Signed-off-by: Alessio Caiazza <nolith@abisso.org>
pull/2182/head
Alessio Caiazza 3 years ago committed by GitHub
parent
commit
6523fdfc4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 158
      collector/powersupplyclass.go
  2. 418
      collector/powersupplyclass_darwin.go
  3. 176
      collector/powersupplyclass_linux.go

158
collector/powersupplyclass.go

@ -11,21 +11,17 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//go:build !nopowersupplyclass && linux //go:build !nopowersupplyclass && (linux || darwin)
// +build !nopowersupplyclass,linux // +build !nopowersupplyclass
// +build linux darwin
package collector package collector
import ( import (
"errors"
"fmt"
"os"
"regexp" "regexp"
"strings"
"github.com/go-kit/log" "github.com/go-kit/log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs/sysfs"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
) )
@ -53,151 +49,3 @@ func NewPowerSupplyClassCollector(logger log.Logger) (Collector, error) {
logger: logger, logger: logger,
}, nil }, nil
} }
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
}

418
collector/powersupplyclass_darwin.go

@ -0,0 +1,418 @@
// 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
/*
#cgo LDFLAGS: -framework IOKit -framework CoreFoundation
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
#include <CoreFoundation/CFArray.h>
// values collected from IOKit Power Source APIs
// Functions documentation available at
// https://developer.apple.com/documentation/iokit/iopowersources_h
// CFDictionary keys definition
// https://developer.apple.com/documentation/iokit/iopskeys_h/defines
struct macos_powersupply {
char *Name;
char *PowerSourceState;
char *Type;
char *TransportType;
char *BatteryHealth;
char *HardwareSerialNumber;
int *PowerSourceID;
int *CurrentCapacity;
int *MaxCapacity;
int *DesignCapacity;
int *NominalCapacity;
int *TimeToEmpty;
int *TimeToFullCharge;
int *Voltage;
int *Current;
int *Temperature;
// boolean values
int *IsCharged;
int *IsCharging;
int *InternalFailure;
int *IsPresent;
};
int *CFDictionaryGetInt(CFDictionaryRef theDict, const void *key) {
CFNumberRef tmp;
int *value;
tmp = CFDictionaryGetValue(theDict, key);
if (tmp == NULL)
return NULL;
value = (int*)malloc(sizeof(int));
if (CFNumberGetValue(tmp, kCFNumberIntType, value)) {
return value;
}
free(value);
return NULL;
}
int *CFDictionaryGetBoolean(CFDictionaryRef theDict, const void *key) {
CFBooleanRef tmp;
int *value;
tmp = CFDictionaryGetValue(theDict, key);
if (tmp == NULL)
return NULL;
value = (int*)malloc(sizeof(int));
if (CFBooleanGetValue(tmp)) {
*value = 1;
} else {
*value = 0;
}
return value;
}
char *CFDictionaryGetSring(CFDictionaryRef theDict, const void *key) {
CFStringRef tmp;
CFIndex size;
char *value;
tmp = CFDictionaryGetValue(theDict, key);
if (tmp == NULL)
return NULL;
size = CFStringGetLength(tmp) + 1;
value = (char*)malloc(size);
if(CFStringGetCString(tmp, value, size, kCFStringEncodingUTF8)) {
return value;
}
free(value);
return NULL;
}
struct macos_powersupply* getPowerSupplyInfo(CFDictionaryRef powerSourceInformation) {
struct macos_powersupply *ret;
if (powerSourceInformation == NULL)
return NULL;
ret = (struct macos_powersupply*)malloc(sizeof(struct macos_powersupply));
ret->PowerSourceID = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSPowerSourceIDKey));
ret->CurrentCapacity = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSCurrentCapacityKey));
ret->MaxCapacity = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSMaxCapacityKey));
ret->DesignCapacity = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSDesignCapacityKey));
ret->NominalCapacity = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSNominalCapacityKey));
ret->TimeToEmpty = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSTimeToEmptyKey));
ret->TimeToFullCharge = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSTimeToFullChargeKey));
ret->Voltage = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSVoltageKey));
ret->Current = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSCurrentKey));
ret->Temperature = CFDictionaryGetInt(powerSourceInformation, CFSTR(kIOPSTemperatureKey));
ret->Name = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSNameKey));
ret->PowerSourceState = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSPowerSourceStateKey));
ret->Type = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSTypeKey));
ret->TransportType = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSTransportTypeKey));
ret->BatteryHealth = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSBatteryHealthKey));
ret->HardwareSerialNumber = CFDictionaryGetSring(powerSourceInformation, CFSTR(kIOPSHardwareSerialNumberKey));
ret->IsCharged = CFDictionaryGetBoolean(powerSourceInformation, CFSTR(kIOPSIsChargedKey));
ret->IsCharging = CFDictionaryGetBoolean(powerSourceInformation, CFSTR(kIOPSIsChargingKey));
ret->InternalFailure = CFDictionaryGetBoolean(powerSourceInformation, CFSTR(kIOPSInternalFailureKey));
ret->IsPresent = CFDictionaryGetBoolean(powerSourceInformation, CFSTR(kIOPSIsPresentKey));
return ret;
}
void releasePowerSupply(struct macos_powersupply *ps) {
free(ps->Name);
free(ps->PowerSourceState);
free(ps->Type);
free(ps->TransportType);
free(ps->BatteryHealth);
free(ps->HardwareSerialNumber);
free(ps->PowerSourceID);
free(ps->CurrentCapacity);
free(ps->MaxCapacity);
free(ps->DesignCapacity);
free(ps->NominalCapacity);
free(ps->TimeToEmpty);
free(ps->TimeToFullCharge);
free(ps->Voltage);
free(ps->Current);
free(ps->Temperature);
free(ps->IsCharged);
free(ps->IsCharging);
free(ps->InternalFailure);
free(ps->IsPresent);
free(ps);
}
*/
import "C"
import (
"fmt"
"strconv"
"github.com/prometheus/client_golang/prometheus"
)
func (c *powerSupplyClassCollector) Update(ch chan<- prometheus.Metric) error {
psList, err := getPowerSourceList()
if err != nil {
return fmt.Errorf("couldn't get IOPPowerSourcesList: %w", err)
}
for _, info := range psList {
labels := getPowerSourceDescriptorLabels(info)
powerSupplyName := labels["power_supply"]
if c.ignoredPattern.MatchString(powerSupplyName) {
continue
}
for name, value := range getPowerSourceDescriptorMap(info) {
if value == nil {
continue
}
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, c.subsystem, name),
fmt.Sprintf("IOKit Power Source information field %s for <power_supply>.", name),
[]string{"power_supply"}, nil,
),
prometheus.GaugeValue, *value, powerSupplyName,
)
}
pushEnumMetric(
ch,
getPowerSourceDescriptorState(info),
"power_source_state",
c.subsystem,
powerSupplyName,
)
pushEnumMetric(
ch,
getPowerSourceDescriptorBatteryHealth(info),
"battery_health",
c.subsystem,
powerSupplyName,
)
var (
keys []string
values []string
)
for name, value := range labels {
if value != "" {
keys = append(keys, name)
values = append(values, value)
}
}
fieldDesc := prometheus.NewDesc(
prometheus.BuildFQName(namespace, c.subsystem, "info"),
"IOKit Power Source information for <power_supply>.",
keys,
nil,
)
ch <- prometheus.MustNewConstMetric(fieldDesc, prometheus.GaugeValue, 1.0, values...)
C.releasePowerSupply(info)
}
return nil
}
// getPowerSourceList fetches information from IOKit APIs
//
// Data is provided as opaque CoreFoundation references
// C.getPowerSupplyInfo will convert those objects in something
// easily manageable in Go.
// https://developer.apple.com/documentation/iokit/iopowersources_h
func getPowerSourceList() ([]*C.struct_macos_powersupply, error) {
infos, err := C.IOPSCopyPowerSourcesInfo()
if err != nil {
return nil, err
}
defer C.CFRelease(infos)
psList, err := C.IOPSCopyPowerSourcesList(infos)
if err != nil {
return nil, err
}
if psList == C.CFArrayRef(0) {
return nil, nil
}
defer C.CFRelease(C.CFTypeRef(psList))
size, err := C.CFArrayGetCount(psList)
if err != nil {
return nil, err
}
ret := make([]*C.struct_macos_powersupply, size)
for i := C.CFIndex(0); i < size; i++ {
ps, err := C.CFArrayGetValueAtIndex(psList, i)
if err != nil {
return nil, err
}
dict, err := C.IOPSGetPowerSourceDescription(infos, (C.CFTypeRef)(ps))
if err != nil {
return nil, err
}
info, err := C.getPowerSupplyInfo(dict)
if err != nil {
return nil, err
}
ret[int(i)] = info
}
return ret, nil
}
func getPowerSourceDescriptorMap(info *C.struct_macos_powersupply) map[string]*float64 {
return map[string]*float64{
"current_capacity": convertValue(info.CurrentCapacity),
"max_capacity": convertValue(info.MaxCapacity),
"design_capacity": convertValue(info.DesignCapacity),
"nominal_capacity": convertValue(info.NominalCapacity),
"time_to_empty_seconds": minutesToSeconds(info.TimeToEmpty),
"time_to_full_seconds": minutesToSeconds(info.TimeToFullCharge),
"voltage_volt": scaleValue(info.Voltage, 1e3),
"current_ampere": scaleValue(info.Current, 1e3),
"temp_celsius": convertValue(info.Temperature),
"present": convertValue(info.IsPresent),
"charging": convertValue(info.IsCharging),
"charged": convertValue(info.IsCharged),
"internal_failure": convertValue(info.InternalFailure),
}
}
func getPowerSourceDescriptorLabels(info *C.struct_macos_powersupply) map[string]string {
return map[string]string{
"id": strconv.FormatInt(int64(*info.PowerSourceID), 10),
"power_supply": C.GoString(info.Name),
"type": C.GoString(info.Type),
"transport_type": C.GoString(info.TransportType),
"serial_number": C.GoString(info.HardwareSerialNumber),
}
}
func getPowerSourceDescriptorState(info *C.struct_macos_powersupply) map[string]float64 {
stateMap := map[string]float64{
"Off Line": 0,
"AC Power": 0,
"Battery Power": 0,
}
// This field is always present
// https://developer.apple.com/documentation/iokit/kiopspowersourcestatekey
stateMap[C.GoString(info.PowerSourceState)] = 1
return stateMap
}
func getPowerSourceDescriptorBatteryHealth(info *C.struct_macos_powersupply) map[string]float64 {
// This field is optional
// https://developer.apple.com/documentation/iokit/kiopsBatteryHealthkey
if info.BatteryHealth == nil {
return nil
}
stateMap := map[string]float64{
"Good": 0,
"Fair": 0,
"Poor": 0,
}
stateMap[C.GoString(info.BatteryHealth)] = 1
return stateMap
}
func convertValue(value *C.int) *float64 {
if value == nil {
return nil
}
ret := new(float64)
*ret = (float64)(*value)
return ret
}
func scaleValue(value *C.int, scale float64) *float64 {
ret := convertValue(value)
if ret == nil {
return nil
}
*ret /= scale
return ret
}
// minutesToSeconds converts *C.int minutes into *float64 seconds.
//
// Only positive values will be scaled to seconds, because negative ones
// have special meanings. I.e. -1 indicates "Still Calculating the Time"
func minutesToSeconds(minutes *C.int) *float64 {
ret := convertValue(minutes)
if ret == nil {
return nil
}
if *ret > 0 {
*ret *= 60
}
return ret
}
func pushEnumMetric(ch chan<- prometheus.Metric, values map[string]float64, name, subsystem, powerSupply string) {
for state, value := range values {
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, name),
fmt.Sprintf("IOKit Power Source information field %s for <power_supply>.", name),
[]string{"power_supply", "state"}, nil,
),
prometheus.GaugeValue, value, powerSupply, state,
)
}
}

176
collector/powersupplyclass_linux.go

@ -0,0 +1,176 @@
// 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
}
Loading…
Cancel
Save