Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prometheus metrics exporter #73

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

Ranhiru
Copy link

@Ranhiru Ranhiru commented Jul 31, 2022

Update web server to export configurable Prometheus metrics using Prometheus Python Client

Labels are following the Metric and Label naming guide

The metrics output looks like below.

# HELP inverter_device_type_code_info Device Type Code
# TYPE inverter_device_type_code_info gauge
inverter_device_type_code_info{device_type_code="SG5K-D"} 1.0
# HELP inverter_run_state Run State
# TYPE inverter_run_state gauge
inverter_run_state{inverter_run_state="ON"} 1.0
inverter_run_state{inverter_run_state="OFF"} 0.0
# HELP inverter_daily_power_yield_watt_hours Daily Power Yields
# TYPE inverter_daily_power_yield_watt_hours gauge
inverter_daily_power_yield_watt_hours 17200.0
# HELP inverter_total_power_yield_watt_hours Total Power Yields
# TYPE inverter_total_power_yield_watt_hours gauge
inverter_total_power_yield_watt_hours 326800.0
# HELP inverter_internal_temperature_celsius Internal Temperature
# TYPE inverter_internal_temperature_celsius gauge
inverter_internal_temperature_celsius 30.1
# HELP inverter_phase_a_voltage_volts Phase A Voltage
# TYPE inverter_phase_a_voltage_volts gauge
inverter_phase_a_voltage_volts 233.2
# HELP inverter_total_active_power_watts Total Active Power
# TYPE inverter_total_active_power_watts gauge
inverter_total_active_power_watts 0.0
# HELP inverter_work_state_info Work State
# TYPE inverter_work_state_info gauge
inverter_work_state_info{work_state="Initial Standby"} 1.0
# HELP inverter_meter_power_watts Meter Power
# TYPE inverter_meter_power_watts gauge
inverter_meter_power_watts 268.0
# HELP inverter_load_power_watts Load Power
# TYPE inverter_load_power_watts gauge
inverter_load_power_watts 268.0
# HELP inverter_daily_export_energy_watts Daily Export Energy
# TYPE inverter_daily_export_energy_watts gauge
inverter_daily_export_energy_watts 14000.0
# HELP inverter_total_export_energy_watts Total Export Energy
# TYPE inverter_total_export_energy_watts gauge
inverter_total_export_energy_watts 248000.0
# HELP inverter_daily_import_energy_watts Daily Import Energy
# TYPE inverter_daily_import_energy_watts gauge
inverter_daily_import_energy_watts 5700.0
# HELP inverter_total_import_energy_watts Total Import Energy
# TYPE inverter_total_import_energy_watts gauge
inverter_total_import_energy_watts 198400.0
# HELP inverter_daily_direct_energy_consumption_watt_hours Daily Direct Energy Consumption
# TYPE inverter_daily_direct_energy_consumption_watt_hours gauge
inverter_daily_direct_energy_consumption_watt_hours 3200.0
# HELP inverter_total_direct_energy_consumption_watt_hours Total Direct Energy Consumption
# TYPE inverter_total_direct_energy_consumption_watt_hours gauge
inverter_total_direct_energy_consumption_watt_hours 78800.0
# HELP inverter_daily_running_time_minutes Daily Running Time
# TYPE inverter_daily_running_time_minutes gauge
inverter_daily_running_time_minutes 1335.0
# HELP inverter_start_stop Start/Stop
# TYPE inverter_start_stop gauge
inverter_start_stop{inverter_start_stop="Start"} 1.0
inverter_start_stop{inverter_start_stop="Stop"} 0.0
# HELP inverter_export_to_grid_watts Export to Grid
# TYPE inverter_export_to_grid_watts gauge
inverter_export_to_grid_watts 0.0
# HELP inverter_import_from_grid_watts Import from Grid
# TYPE inverter_import_from_grid_watts gauge
inverter_import_from_grid_watts 268.0

@michbeck100
Copy link
Collaborator

Thanks for your efforts, but there is already a /metrics endpoint in the webserver exporter (bca665a). Maybe you could extend this one? I don’t think we need an extra exporter.

@Ranhiru
Copy link
Author

Ranhiru commented Jul 31, 2022

Hey @michbeck100. Thank you for your input.

Hopefully I can convince you to have a separate Prometheus exporter 🙂

  1. The existing /metrics endpoint is currently not working. This is due to it incorrectly exporting multiple string values (inverter name, work state) that's not supported
  2. The naming convention for the currently exported metrics does not follow naming best practices
  3. The values that are exported are not in their base units
  4. There's no ability currently to configure which metrics are exported
  5. I believe the current metrics are exported incorrectly in regards to the use of labels (Please allow me to say that I'm very new Prometheus, so it's very possible I'm wrong on this one)

For example one of the currently exported metrics is shown below

daily_power_yields{address="5003", unit="kWh"} 17.6

The use of address and unit as labels I believe is incorrect as labels are used to create additional dimensions for the same metric. Please see below an example I've copied from this web page

# Request counter for the User Directory service
http_requests_total{service="users-directory"}

# Request counter for the Billing History Service
http_requests_total{service="billing-history"}

The address (5003) or unit (kWh) is not going to change for the life time of the metrics gathering.
6. Finally and most importantly I've created a new export so as to not disrupt the current usage of the /metrics endpoint.
7. Also, by using the official python client library, we get additional metadata (HELP, TYPE)

@michbeck100
Copy link
Collaborator

I still don’t see the need for a dedicated exporter. You can reuse and change/fix the current /metrics endpoint. It makes no sense to have two endpoints for prometheus. I like all the other things you pointed out. I’ve implemented the endpoint in the webserver exporter because it’s just a different format not worth a whole exporter.

@bohdan-s
Copy link
Owner

It looks like we could add this to the existing /metrics endpoint with a few extra settings in the config file? Would there a be use case for both styles to run at the same time though?

@Ranhiru
Copy link
Author

Ranhiru commented Jul 31, 2022

There would be no need to have two exporters, that I fully agree with. However I'm sure there's active usage of the current /metrics endpoint by others and didn't want to disrupt that. My idea was to run things side by side and deprecate the old endpoint

@michbeck100
Copy link
Collaborator

@Ranhiru just extend/replace the existing one. I think the endpoint should still be /metrics. Since it will be a new release version we can replace it and people can switch to the new version once they adopted to the new format.

@Ranhiru
Copy link
Author

Ranhiru commented Aug 7, 2022

Hey @michbeck100, apologies for not getting back to you sooner, it's been a busy week.

I'm still hoping I can convince you or @bohdan-s to make metrics its own exporter. I'd say that if anything, the HTML and JSON content should have been served through the same exporter with different Content-Type.

Although Prometheus style of metrics is different from HTML or JSON, I understand that it's still plain text served through a web endpoint. (/metrics) I'll see what's the best way to get the metrics integrated to the web exporter instead of creating a new exporter.

I have a question around the current configuration I've added here. I've added configuration for each of the fields that's returned from my inverter but I'm assuming not all inverters will support all the fields. Do I add some example configuration and leave it up to the user to fill in the rest ?

@Ranhiru Ranhiru marked this pull request as ready for review August 7, 2022 13:00
@Ranhiru
Copy link
Author

Ranhiru commented Aug 15, 2022

Not the nicest looking dashboard but I could get this working in Grafana Cloud

Screen Shot 2022-08-15 at 4 39 22 pm

metric_name = metric_config['metric_name']
metric_type = metric_config['type']

logging.info(f"Prometheus: Initialising metric {metric_name} as type {metric_type}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rather logging.debug?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'll change that

@michbeck100
Copy link
Collaborator

Do I add some example configuration and leave it up to the user to fill in the rest ?

I think that's ok for now. But for the future we should try to implement an automatism that exports all registers without extra config.

@Ranhiru Ranhiru requested a review from michbeck100 August 19, 2022 12:28
@michbeck100
Copy link
Collaborator

Basically I like the implementation. What I don't like is the rather complex configuration. That's what I like about the current implementation which just exports all registers. Would be great to have this ability, too. Maybe decide by datatype which metric type to use and create the description from register name. And reuse the unit.

What do you think?

@Ranhiru
Copy link
Author

Ranhiru commented Aug 19, 2022

@michbeck100 Fair enough. The configuration is definitely complex.

How about instead of having all of the current configuration in the config.yaml, we leave only the most commonly used metrics that the influx db exporter currently exports, and move the rest as examples to the README or a Wiki ?

In that way, we let the end user decide how complex they want the configuration to be

@Ranhiru
Copy link
Author

Ranhiru commented Sep 18, 2022

Anything else that needs to be done to merge this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants