forked from htop-dev/htop
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce the DynamicMeter class for runtime extension
This commit is based on exploratory work by Sohaib Mohamed. The end goal is two-fold - to support addition of Meters we build via configuration files for both the PCP platform and for scripts ( htop-dev#526 ) Here, we focus on generic code and the PCP support. A new class DynamicMeter is introduced - its use the special case 'param' field handling that previously was used only by the CPUMeter, such that every runtime-configured Meter is given a unique identifier. Unlike with the CPUMeter this is used internally only. When reading/writing to htoprc instead of CPU(N) - where N is an integer param (CPU number) - we use the string name for each meter. For example, if we have a configuration for a DynamicMeter for some Redis metrics, we might read and write "Dynamic(redis)". This identifier is subsequently matched (back) up to the configuration file so we're able to re-create arbitrary user configurations. The PCP platform configuration file format is fairly simple. We expand configs from several directories, including the users homedir alongside htoprc (below htop/meters/) and also /etc/pcp/htop/meters. The format will be described via a new pcp-htop(5) man page, but its basically ini-style and each Meter has one or more metric expressions associated, as well as specifications for labels, color and so on via a dot separated notation for individual metrics within the Meter. A few initial sample configuration files are provided below ./pcp/meters that give the general idea. The PCP "derived" metric specification - see pmRegisterDerived(3) - is used as the syntax for specifying metrics in PCP DynamicMeters.
- Loading branch information
Showing
22 changed files
with
792 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
htop - DynamicMeter.c | ||
(C) 2021 htop dev team | ||
(C) 2021 Red Hat, Inc. All Rights Reserved. | ||
Released under the GNU GPLv2, see the COPYING file | ||
in the source distribution for its full text. | ||
*/ | ||
#include "config.h" // IWYU pragma: keep | ||
|
||
#include "DynamicMeter.h" | ||
|
||
#include "CRT.h" | ||
#include "Object.h" | ||
#include "Platform.h" | ||
#include "ProcessList.h" | ||
#include "RichString.h" | ||
#include "XUtils.h" | ||
|
||
static const int DynamicMeter_attributes[] = { | ||
DYNAMIC_GRAY, | ||
DYNAMIC_RED, | ||
DYNAMIC_GREEN, | ||
DYNAMIC_BLUE, | ||
DYNAMIC_CYAN, | ||
DYNAMIC_MAGENTA, | ||
DYNAMIC_YELLOW, | ||
DYNAMIC_WHITE | ||
}; | ||
|
||
Hashtable* DynamicMeters_new(void) { | ||
return Platform_dynamicMeters(); | ||
} | ||
|
||
typedef struct { | ||
unsigned int key; | ||
const char* name; | ||
} DynamicIterator; | ||
|
||
static void DynamicMeter_compare(ht_key_t key, void* value, void* data) { | ||
const DynamicMeter* meter = (const DynamicMeter*)value; | ||
DynamicIterator* iter = (DynamicIterator*)data; | ||
if (String_eq(iter->name, meter->name)) | ||
iter->key = key; | ||
} | ||
|
||
unsigned int DynamicMeter_search(const ProcessList* pl, const char* name) { | ||
DynamicIterator iter = { .key = 0, .name = name }; | ||
Hashtable_foreach(pl->dynamicMeters, DynamicMeter_compare, &iter); | ||
return iter.key; | ||
} | ||
|
||
const char* DynamicMeter_lookup(const ProcessList* pl, unsigned int key) { | ||
const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, key); | ||
return meter->name; | ||
} | ||
|
||
static void DynamicMeter_init(Meter* meter) { | ||
Platform_dynamicMeterInit(meter); | ||
} | ||
|
||
static void DynamicMeter_updateValues(Meter* meter) { | ||
Platform_dynamicMeterUpdateValues(meter); | ||
} | ||
|
||
static void DynamicMeter_display(const Object* cast, RichString* out) { | ||
const Meter* meter = (const Meter*)cast; | ||
Platform_dynamicMeterDisplay(meter, out); | ||
} | ||
|
||
static void DynamicMeter_getUiName(const Meter* this, char* name, size_t length) { | ||
const ProcessList* pl = this->pl; | ||
const DynamicMeter* meter = Hashtable_get(pl->dynamicMeters, this->param); | ||
xSnprintf(name, length, "%s", meter->name); | ||
} | ||
|
||
const MeterClass DynamicMeter_class = { | ||
.super = { | ||
.extends = Class(Meter), | ||
.delete = Meter_delete, | ||
.display = DynamicMeter_display | ||
}, | ||
.init = DynamicMeter_init, | ||
.updateValues = DynamicMeter_updateValues, | ||
.getUiName = DynamicMeter_getUiName, | ||
.defaultMode = TEXT_METERMODE, | ||
.maxItems = 0, | ||
.total = 100.0, | ||
.attributes = DynamicMeter_attributes, | ||
.name = "Dynamic", | ||
.uiName = "Dynamic", | ||
.caption = "", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifndef HEADER_DynamicMeter | ||
#define HEADER_DynamicMeter | ||
|
||
#include "Meter.h" | ||
|
||
|
||
typedef struct DynamicMeter_ { | ||
char name[32]; /* unique name, cannot contain spaces */ | ||
char* label; | ||
char* caption; | ||
char* description; | ||
unsigned int type; | ||
double maximum; | ||
|
||
void* dynamicData; /* platform-specific meter data */ | ||
} DynamicMeter; | ||
|
||
Hashtable* DynamicMeters_new(void); | ||
|
||
const char* DynamicMeter_lookup(const ProcessList* pl, unsigned int); | ||
|
||
unsigned int DynamicMeter_search(const ProcessList* pl, const char* name); | ||
|
||
extern const MeterClass DynamicMeter_class; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.