123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- #include "debugfs_plugin.h"
- struct zone_t {
- char *zone_chart_id;
- char *subzone_chart_id;
- char *name;
- char *path;
- unsigned long long max_energy_range_uj;
- unsigned long long energy_uj;
- struct zone_t *subzones;
- struct zone_t *prev, *next;
- };
- static struct zone_t *rapl_zones = NULL;
- static bool get_measurement(const char *path, unsigned long long *energy_uj) {
- return read_single_number_file(path, energy_uj) == 0;
- }
- static struct zone_t *get_rapl_zone(const char *control_type __maybe_unused, struct zone_t *parent __maybe_unused, const char *dirname) {
- char temp[FILENAME_MAX + 1];
- snprintfz(temp, FILENAME_MAX, "%s/%s", dirname, "name");
- char name[FILENAME_MAX + 1] = "";
- if (read_file(temp, name, sizeof(name) - 1) != 0)
- return NULL;
- char *trimmed = trim(name);
- if (unlikely(trimmed == NULL || trimmed[0] == 0))
- return NULL;
- snprintfz(temp, FILENAME_MAX, "%s/%s", dirname, "max_energy_range_uj");
- unsigned long long max_energy_range_uj = 0;
- if (unlikely(read_single_number_file(temp, &max_energy_range_uj) != 0)) {
- collector_error("Cannot read %s", temp);
- return NULL;
- }
- snprintfz(temp, FILENAME_MAX, "%s/%s", dirname, "energy_uj");
- unsigned long long energy_uj;
- if (unlikely(!get_measurement(temp, &energy_uj))) {
- collector_info("%s: Cannot read %s", trimmed, temp);
- return NULL;
- }
- struct zone_t *zone = callocz(1, sizeof(*zone));
- zone->name = strdupz(trimmed);
- zone->path = strdupz(temp);
- zone->max_energy_range_uj = max_energy_range_uj;
- zone->energy_uj = energy_uj;
- collector_info("Found zone: \"%s\"", zone->name);
- return zone;
- }
- static struct zone_t *look_for_rapl_zones(const char *control_type, struct zone_t *parent, const char *path, int depth) {
- if(depth > 2)
- return NULL;
- struct zone_t *base = NULL;
- DIR *dir = opendir(path);
- if (unlikely(dir == NULL))
- return NULL;
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if (de->d_type != DT_DIR || de->d_name[0] == '.')
- continue;
- if(strncmp(de->d_name, "intel-rapl:", 11) != 0)
- continue;
- char zone_path[FILENAME_MAX + 1];
- snprintfz(zone_path, FILENAME_MAX, "%s/%s", path, de->d_name);
- struct zone_t *zone = get_rapl_zone(control_type, parent, zone_path);
- if(zone) {
- DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(base, zone, prev, next);
- if(!parent)
- zone->subzones = look_for_rapl_zones(control_type, zone, zone_path, depth + 1);
- }
- }
- closedir(dir);
- return base;
- }
- static struct zone_t *get_main_rapl_zones(void) {
- struct zone_t *base = NULL;
- char dirname[FILENAME_MAX + 1];
- snprintfz(dirname, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/powercap");
- DIR *dir = opendir(dirname);
- if (unlikely(dir == NULL))
- return 0;
- struct dirent *de = NULL;
- while ((de = readdir(dir))) {
- if (de->d_type != DT_DIR || de->d_name[0] == '.')
- continue;
- if(strncmp(de->d_name, "intel-rapl", 10) != 0)
- continue;
- char control_type_path[FILENAME_MAX + 1];
- snprintfz(control_type_path, FILENAME_MAX, "%s/%s", dirname, de->d_name);
- collector_info("Looking at control type \"%s\"", de->d_name);
- struct zone_t *zone = look_for_rapl_zones(de->d_name, NULL, control_type_path, 0);
- if(zone)
- DOUBLE_LINKED_LIST_APPEND_LIST_UNSAFE(base, zone, prev, next);
- }
- closedir(dir);
- return base;
- }
- int do_sys_devices_virtual_powercap(int update_every, const char *name __maybe_unused) {
- if (unlikely(!rapl_zones)) {
- rapl_zones = get_main_rapl_zones();
- if (unlikely(!rapl_zones)) {
- collector_info("Failed to find powercap zones.");
- return 1;
- }
- }
- for(struct zone_t *zone = rapl_zones; zone ; zone = zone->next) {
- if(!zone->zone_chart_id) {
- char id[1000 + 1];
- snprintf(id, 1000, "cpu.powercap_intel_rapl_zone_%s", zone->name);
- zone->zone_chart_id = strdupz(id);
- fprintf(stdout,
- "CHART '%s' '' 'Intel RAPL Zone Power Consumption' 'Watts' 'powercap' '%s' '%s' %d %d '' 'debugfs.plugin' 'intel_rapl'\n",
- zone->zone_chart_id,
- "cpu.powercap_intel_rapl_zone",
- debugfs_rrdset_type_name(RRDSET_TYPE_LINE),
- NETDATA_CHART_PRIO_POWERCAP,
- update_every);
- fprintf(stdout,
- "CLABEL 'zone' '%s' 0\n"
- "CLABEL_COMMIT\n",
- zone->name);
- fprintf(stdout,
- "DIMENSION 'power' '' %s 1 1000000 ''\n",
- debugfs_rrd_algorithm_name(RRD_ALGORITHM_INCREMENTAL));
- // for the sub-zones
- snprintf(id, 1000, "cpu.powercap_intel_rapl_subzones_%s", zone->name);
- zone->subzone_chart_id = strdupz(id);
- fprintf(stdout,
- "CHART '%s' '' 'Intel RAPL Subzones Power Consumption' 'Watts' 'powercap' '%s' '%s' %d %d '' 'debugfs.plugin' 'intel_rapl'\n",
- zone->subzone_chart_id,
- "cpu.powercap_intel_rapl_subzones",
- debugfs_rrdset_type_name(RRDSET_TYPE_LINE),
- NETDATA_CHART_PRIO_POWERCAP + 1,
- update_every);
- fprintf(stdout,
- "CLABEL 'zone' '%s' 0\n"
- "CLABEL_COMMIT\n",
- zone->name);
- for(struct zone_t *subzone = zone->subzones; subzone ; subzone = subzone->next) {
- fprintf(stdout,
- "DIMENSION '%s' '' %s 1 1000000 ''\n",
- subzone->name,
- debugfs_rrd_algorithm_name(RRD_ALGORITHM_INCREMENTAL));
- }
- }
- if(get_measurement(zone->path, &zone->energy_uj)) {
- fprintf(stdout,
- "BEGIN '%s'\n"
- "SET power = %llu\n"
- "END\n"
- , zone->zone_chart_id
- , zone->energy_uj);
- }
- if(zone->subzones) {
- fprintf(stdout,
- "BEGIN '%s'\n",
- zone->subzone_chart_id);
- for (struct zone_t *subzone = zone->subzones; subzone; subzone = subzone->next) {
- if(get_measurement(subzone->path, &subzone->energy_uj)) {
- fprintf(stdout,
- "SET '%s' = %llu\n",
- subzone->name,
- subzone->energy_uj);
- }
- }
- fprintf(stdout, "END\n");
- }
- }
- fflush(stdout);
- return 0;
- }
|