#! /usr/bin/env ruby # frozen_string_literal: true require 'json' class MacOSBatteryExporter def export puts metrics end def metrics <<~METRICS # HELP node_battery_charge_percent Battery charge percent # TYPE node_battery_charge_percent gauge node_battery_charge_percent{serial="#{battery_serial_number}"} #{charge_percentage} # HELP node_battery_charge_ampere Battery charge ampere # TYPE node_battery_charge_ampere gauge node_battery_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_current_capacity'] / 1000.0} # HELP node_battery_full_charge_ampere Battery full charge capacity # TYPE node_battery_full_charge_ampere gauge node_battery_full_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_max_capacity'] / 1000.0} # HELP node_battery_current_flow_ampere Current flow of ampere in (+) or out (-) of battery # TYPE node_battery_current_flow_ampere gauge node_battery_current_flow_ampere{serial="#{battery_serial_number}"} #{battery_info['sppower_current_amperage'] / 1000.0} # HELP node_battery_charger_connected Is charger connected? # TYPE node_battery_charger_connected gauge node_battery_charger_connected{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_charger_connected'] == 'TRUE' ? 1.0 : 0.0} # HELP node_battery_is_charging Is charger connected? # TYPE node_battery_is_charging gauge node_battery_is_charging{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_is_charging'] == 'TRUE' ? 1.0 : 0.0} # HELP node_battery_charger_watts Watts provided by charger # TYPE node_battery_charger_watts gauge node_battery_charger_watts{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_ac_charger_watts'].to_f} # HELP node_battery_fully_charged Is battery fully charged? # TYPE node_battery_fully_charged gauge node_battery_fully_charged{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_fully_charged'] == 'TRUE' ? 1.0 : 0.0} # HELP node_battery_cycle_count Battery cycle count # TYPE node_battery_cycle_count counter node_battery_cycle_count{serial="#{battery_serial_number}"} #{health_info['sppower_battery_cycle_count']} METRICS end def charge_percentage @charge_percentage ||= `pmset -g batt | grep -Eo '\\d+%' | cut -d% -f1`.strip end def battery_serial_number battery_info.dig( 'sppower_battery_model_info', 'sppower_battery_serial_number' ) end def charge_info @charge_info ||= battery_info['sppower_battery_charge_info'] end def health_info @health_info ||= battery_info['sppower_battery_health_info'] end def battery_info @battery_info ||= power_data&.find do |v| v['_name'] == 'spbattery_information' end end def ac_charger_info @ac_charger_info ||= power_data&.find do |v| v['_name'] == 'sppower_ac_charger_information' end end def power_data @power_data ||= JSON.parse(`system_profiler SPPowerDataType -json`) &.[]('SPPowerDataType') end end MacOSBatteryExporter.new.export if __FILE__ == $PROGRAM_NAME