Simplify the memory thresholds

This commit is contained in:
Benedikt Heine 2018-04-16 18:18:50 +02:00 committed by Felix Buehler
parent 7839e93c9b
commit cba8f55938
5 changed files with 92 additions and 73 deletions

View File

@ -423,13 +423,10 @@ int main(int argc, char *argv[]) {
cfg_opt_t memory_opts[] = {
CFG_STR("format", "%used %free %available", CFGF_NONE),
CFG_STR("degraded_format_below_threshold", NULL, CFGF_NONE),
CFG_STR("degraded_threshold_type", "percentage_avail", CFGF_NONE),
CFG_FLOAT("degraded_low_threshold", 0, CFGF_NONE),
CFG_STR("critical_format_below_threshold", NULL, CFGF_NONE),
CFG_STR("critical_threshold_type", "percentage_avail", CFGF_NONE),
CFG_FLOAT("critical_low_threshold", 0, CFGF_NONE),
CFG_BOOL("use_available_memory", true, CFGF_NONE),
CFG_STR("format_degraded", NULL, CFGF_NONE),
CFG_STR("threshold_degraded", NULL, CFGF_NONE),
CFG_STR("threshold_critical", NULL, CFGF_NONE),
CFG_STR("memory_used_method", "classical", CFGF_NONE),
CFG_CUSTOM_ALIGN_OPT,
CFG_CUSTOM_COLOR_OPTS,
CFG_CUSTOM_MIN_WIDTH_OPT,
@ -743,7 +740,7 @@ int main(int argc, char *argv[]) {
CASE_SEC("memory") {
SEC_OPEN_MAP("memory");
print_memory(json_gen, buffer, cfg_getstr(sec, "format"), cfg_getstr(sec, "degraded_format_below_threshold"), cfg_getstr(sec, "degraded_threshold_type"), cfg_getfloat(sec, "degraded_low_threshold"), cfg_getstr(sec, "critical_format_below_threshold"), cfg_getstr(sec, "critical_threshold_type"), cfg_getfloat(sec, "critical_low_threshold"), cfg_getbool(sec, "use_available_memory"));
print_memory(json_gen, buffer, cfg_getstr(sec, "format"), cfg_getstr(sec, "format_degraded"), cfg_getstr(sec, "threshold_degraded"), cfg_getstr(sec, "threshold_critical"), cfg_getstr(sec, "memory_used_method"));
SEC_CLOSE_MAP;
}

View File

@ -17,6 +17,7 @@ order += "wireless _first_"
order += "ethernet _first_"
order += "battery all"
order += "load"
order += "memory"
order += "tztime local"
wireless _first_ {
@ -42,6 +43,12 @@ load {
format = "%1min"
}
memory {
format = "%used | %available"
threshold_degraded = "1G"
format_degraded = "MEMORY < %available"
}
disk "/" {
format = "%avail"
}

View File

@ -223,7 +223,7 @@ void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const
void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format, const char *format_above_threshold, const char *format_above_degraded_threshold, const char *path, const float max_threshold, const float degraded_threshold);
void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
void print_load(yajl_gen json_gen, char *buffer, const char *format, const char *format_above_threshold, const float max_threshold);
void print_memory(yajl_gen json_gen, char *buffer, const char *format, const char *degraded_format_below_threshold, const char *degraded_threshold_type, const float degraded_low_threshold, const char *critical_format_below_threshold, const char *critical_threshold_type, const float critical_low_threshold, const bool use_available_memory);
void print_memory(yajl_gen json_gen, char *buffer, const char *format, const char *format_degraded, const char *threshold_degraded, const char *threshold_critical, const char *memory_used_method);
void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_muted, const char *device, const char *mixer, int mixer_idx);
bool process_runs(const char *path);
int volume_pulseaudio(uint32_t sink_idx, const char *sink_name);

View File

@ -116,6 +116,8 @@ cpu_temperature 0 {
memory {
format = "%used"
threshold_degraded = "10%"
format_degraded = "MEMORY: %free"
}
disk "/" {
@ -197,6 +199,7 @@ double-quote (""") characters need to be replaced with "`&amp;`", "`&lt;`",
for generated content (e.g. wireless ESSID, time).
*Example configuration*:
-------------------------------------------------------------
general {
output_format = "xmobar"
@ -431,46 +434,42 @@ starting from %cpu0. This feature is currently not supported in FreeBSD.
=== Memory
Gets the memory usage from system.
On Linux, the information is taken from +/proc/meminfo+.
Gets the memory usage from system on a Linux system from +/proc/meminfo+. Other
systems are currently not supported.
These values can also be expressed in percentages with the +percentage_used+,
+percentage_free+ and +percentage_shared+ formats.
As format placeholders, +total+, +used+, +free+, +available+ and +shared+ are
available. These will print human readable values. It's also possible to prefix
the placeholders with +percentage_+ to get a value in percent.
If a +critical_low_threshold+ is defined, the output will be colored using
+color_bad+. The unit of this threshold is defined by the unit given in
+critical_threshold_type+, which can be one of "bytes_free", "bytes_avail",
"percentage_free" and "percentage_avail". Additionally, the former two can be
prefixed with one of "k", "m", "g" or "t" to change the exact unit.
For example, setting critical_low_threshold to 2 and threshold_type to "gbytes_avail"
causes available memory below 2 GiB to be colored with +color_bad+. The
defaults are "percentage_avail" with a threshold of 0.
Furthermore, the format used when the threshold is reached can be customized
using the option +critical_format_below_threshold+.
Same applies to +degraded_low_threshold+, +degraded_threshold_type+ and
+degraded_format_below_threshold+ using +color_degraded+.
It's possible to define a +threshold_degraded+ and a +threshold_critical+ to
color the status bar output in yellow or red, if the available memory falls
below the given threshold. Possible values of the threshold can be any integer,
suffixed with an iec symbol (+T+, +G+, +M+, +K+). Alternatively, the integer
can be suffixed by a percent sign, which then rets evaluated relatively to
total memory.
The most common one is:
"used memory" = "total memory" - "free memory" - "buffers" - "cache"
This is the default in i3status. Some other programs use
"used memory" = "total memory" - "available memory"
You can disable this behavior using +use_available_memory+.
If the +format_degraded+ parameter is given and either the critical or the
degraded threshold applies, +format_degraded+ will get used as format string.
It acts equivalently to +format+.
As Linux' meminfo doesn't expose the overall memory in use, there are multiple
methods to distinguish the actually used memory.
*Example used_memory_method*: +memavailable+ ("total memory" - "MemAvailable", matches gnome system monitor)
*Example used_memory_method*: +classical+ ("total memory" - "free" - "buffers" - "cache", matches gnome system monitor)
*Example order*: +memory+
*Example format*: +%free %available (%used)/ %total+
*Example format*: +%free %available (%used) / %total+
*Example format*: +used %percentage_used , free %percentage_free, shared %percentage_shared+
*Example format*: +%percentage_used used, %percentage_free free, %percentage_shared shared+
*Example degraded_low_threshold*: +10+
*Example threshold_degraded*: +10%+
*Example degraded_threshold_type*: +percentage_free+
*Example threshold_critical*: +5%+
*Example critical_low_threshold*: +5+
*Example critical_format_below_threshold*: +Warning: %percentage_free+
*Example use_available_memory: +false+
*Example format_degraded*: +Memory LOW: %free+
=== Load

View File

@ -29,49 +29,57 @@ static int print_bytes_human(char *outwalk, uint64_t bytes) {
}
/*
* Determines whether remaining bytes are below given threshold.
* Convert a string to its absolute representation based on the total
* memory of `mem_total`.
*
* The string can contain any percentage values, which then return a
* the value of `size` in relation to `mem_total`.
* Alternatively an absolute value can be given, suffixed with an iec
* symbol.
*
*/
static bool below_threshold(const long ram_total, const long ram_used, const char *threshold_type, const long low_threshold) {
// empty is available or free, based on "use_available_memory"
long empty = ram_total - ram_used;
if (BEGINS_WITH(threshold_type, "percentage_")) {
return 100.0 * empty / ram_total < low_threshold;
} else if (strcasecmp(threshold_type, "bytes_free") == 0) {
return empty < low_threshold;
} else if (threshold_type[0] != '\0' && strncasecmp(threshold_type + 1, "bytes_", strlen("bytes_")) == 0) {
static long memory_absolute(const long mem_total, const char *size) {
long mem_absolute = -1;
char *endptr = NULL;
long factor = 1;
mem_absolute = strtol(size, &endptr, 10);
switch (threshold_type[0]) {
if (endptr) {
while (endptr[0] != '\0' && isspace(endptr[0]))
endptr++;
switch (endptr[0]) {
case 'T':
case 't':
factor *= BINARY_BASE;
mem_absolute *= BINARY_BASE;
case 'G':
case 'g':
factor *= BINARY_BASE;
mem_absolute *= BINARY_BASE;
case 'M':
case 'm':
factor *= BINARY_BASE;
mem_absolute *= BINARY_BASE;
case 'K':
case 'k':
factor *= BINARY_BASE;
mem_absolute *= BINARY_BASE;
break;
case '%':
mem_absolute = mem_total * mem_absolute / 100;
break;
default:
return false;
break;
}
return empty < low_threshold * factor;
}
return false;
return mem_absolute;
}
void print_memory(yajl_gen json_gen, char *buffer, const char *format, const char *degraded_format_below_threshold, const char *degraded_threshold_type, const float degraded_low_threshold, const char *critical_format_below_threshold, const char *critical_threshold_type, const float critical_low_threshold, const bool use_available_memory) {
void print_memory(yajl_gen json_gen, char *buffer, const char *format, const char *format_degraded, const char *threshold_degraded, const char *threshold_critical, const char *memory_used_method) {
char *outwalk = buffer;
#if defined(linux)
const char *selected_format = format;
const char *walk;
bool colorful_output = false;
const char *output_color = NULL;
long ram_total = -1;
long ram_free = -1;
@ -121,26 +129,34 @@ void print_memory(yajl_gen json_gen, char *buffer, const char *format, const cha
ram_buffers = ram_buffers * BINARY_BASE;
ram_cached = ram_cached * BINARY_BASE;
ram_shared = ram_shared * BINARY_BASE;
if (use_available_memory) {
if (BEGINS_WITH(memory_used_method, "memavailable")) {
ram_used = ram_total - ram_available;
} else {
} else if (BEGINS_WITH(memory_used_method, "classical")) {
ram_used = ram_total - ram_free - ram_buffers - ram_cached;
}
if (degraded_low_threshold > 0 && below_threshold(ram_total, ram_used, degraded_threshold_type, degraded_low_threshold)) {
if (critical_low_threshold > 0 && below_threshold(ram_total, ram_used, critical_threshold_type, critical_low_threshold)) {
START_COLOR("color_bad");
colorful_output = true;
if (critical_format_below_threshold != NULL)
selected_format = critical_format_below_threshold;
} else {
START_COLOR("color_degraded");
colorful_output = true;
if (degraded_format_below_threshold != NULL)
selected_format = degraded_format_below_threshold;
if (threshold_degraded) {
long abs = memory_absolute(ram_total, threshold_degraded);
if (ram_available < abs) {
output_color = "color_degraded";
}
}
if (threshold_critical) {
long abs = memory_absolute(ram_total, threshold_critical);
if (ram_available < abs) {
output_color = "color_bad";
}
}
if (output_color) {
START_COLOR(output_color);
if (format_degraded)
selected_format = format_degraded;
}
for (walk = selected_format; *walk != '\0'; walk++) {
if (*walk != '%') {
*(outwalk++) = *walk;
@ -192,7 +208,7 @@ void print_memory(yajl_gen json_gen, char *buffer, const char *format, const cha
}
}
if (colorful_output)
if (output_color)
END_COLOR;
*outwalk = '\0';