diff options
Diffstat (limited to '')
-rw-r--r-- | src/collectors/freeipmi.plugin/freeipmi_plugin.c (renamed from collectors/freeipmi.plugin/freeipmi_plugin.c) | 174 |
1 files changed, 98 insertions, 76 deletions
diff --git a/collectors/freeipmi.plugin/freeipmi_plugin.c b/src/collectors/freeipmi.plugin/freeipmi_plugin.c index 6ec9b698b..3b27c5d5a 100644 --- a/collectors/freeipmi.plugin/freeipmi_plugin.c +++ b/src/collectors/freeipmi.plugin/freeipmi_plugin.c @@ -23,7 +23,9 @@ #include "libnetdata/required_dummies.h" #define FREEIPMI_GLOBAL_FUNCTION_SENSORS() do { \ - fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"ipmi-sensors\" %d \"%s\"\n", 5, "Displays current sensor state and readings"); \ + fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " GLOBAL \"ipmi-sensors\" %d \"%s\" \"top\" "HTTP_ACCESS_FORMAT" %d\n", \ + 5, "Displays current sensor state and readings", \ + (HTTP_ACCESS_FORMAT_CAST)(HTTP_ACCESS_NONE), 100); \ } while(0) // component names, based on our patterns @@ -65,9 +67,8 @@ static void netdata_update_ipmi_sensor_reading( , int sensor_bitmask_type , int sensor_bitmask , char **sensor_bitmask_strings - , struct netdata_ipmi_state *state -); -static void netdata_update_ipmi_sel_events_count(struct netdata_ipmi_state *state, uint32_t events); + , struct netdata_ipmi_state *stt); +static void netdata_update_ipmi_sel_events_count(struct netdata_ipmi_state *stt, uint32_t events); // END NETDATA CODE // ---------------------------------------------------------------------------- @@ -905,7 +906,7 @@ const char *netdata_collect_type_to_string(IPMI_COLLECTION_TYPE type) { return "unknown"; } -static void netdata_sensor_set_value(struct sensor *sn, void *sensor_reading, struct netdata_ipmi_state *state __maybe_unused) { +static void netdata_sensor_set_value(struct sensor *sn, void *sensor_reading, struct netdata_ipmi_state *stt __maybe_unused) { switch(sn->sensor_reading_type) { case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL: sn->sensor_reading.bool_value = *((uint8_t *)sensor_reading); @@ -939,8 +940,7 @@ static void netdata_update_ipmi_sensor_reading( , int sensor_bitmask_type __maybe_unused , int sensor_bitmask __maybe_unused , char **sensor_bitmask_strings __maybe_unused - , struct netdata_ipmi_state *state -) { + , struct netdata_ipmi_state *stt) { if(unlikely(sensor_state == IPMI_MONITORING_STATE_UNKNOWN && sensor_type == IPMI_MONITORING_SENSOR_TYPE_UNKNOWN && sensor_units == IPMI_MONITORING_SENSOR_UNITS_UNKNOWN && @@ -952,38 +952,38 @@ static void netdata_update_ipmi_sensor_reading( if(unlikely(!sensor_name || !*sensor_name)) sensor_name = "UNNAMED"; - state->sensors.collected++; + stt->sensors.collected++; char key[SENSORS_DICT_KEY_SIZE + 1]; snprintfz(key, SENSORS_DICT_KEY_SIZE, "i%d_n%d_t%d_u%d_%s", record_id, sensor_number, sensor_reading_type, sensor_units, sensor_name); // find the sensor record - const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(state->sensors.dict, key); + const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(stt->sensors.dict, key); if(likely(item)) { // recurring collection - if(state->debug) + if(stt->debug) fprintf(stderr, "%s: reusing sensor record for sensor '%s', id %d, number %d, type %d, state %d, units %d, reading_type %d\n", program_name, sensor_name, record_id, sensor_number, sensor_type, sensor_state, sensor_units, sensor_reading_type); struct sensor *sn = dictionary_acquired_item_value(item); if(sensor_reading) { - netdata_sensor_set_value(sn, sensor_reading, state); - sn->last_collected_metric_ut = state->sensors.now_ut; + netdata_sensor_set_value(sn, sensor_reading, stt); + sn->last_collected_metric_ut = stt->sensors.now_ut; } sn->sensor_state = sensor_state; - sn->last_collected_state_ut = state->sensors.now_ut; + sn->last_collected_state_ut = stt->sensors.now_ut; - dictionary_acquired_item_release(state->sensors.dict, item); + dictionary_acquired_item_release(stt->sensors.dict, item); return; } - if(state->debug) + if(stt->debug) fprintf(stderr, "Allocating new sensor data record for sensor '%s', id %d, number %d, type %d, state %d, units %d, reading_type %d\n", sensor_name, record_id, sensor_number, sensor_type, sensor_state, sensor_units, sensor_reading_type); @@ -992,12 +992,12 @@ static void netdata_update_ipmi_sensor_reading( bool excluded_state = excluded_status_record_ids_check(record_id); if(excluded_metric) { - if(state->debug) + if(stt->debug) fprintf(stderr, "Sensor '%s' is excluded by excluded_record_ids_check()\n", sensor_name); } if(excluded_state) { - if(state->debug) + if(stt->debug) fprintf(stderr, "Sensor '%s' is excluded for status check, by excluded_status_record_ids_check()\n", sensor_name); } @@ -1022,7 +1022,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "Celsius"; t.family = "temperatures"; t.chart_type = "line"; - t.priority = state->sensors.priority + 10; + t.priority = stt->sensors.priority + 10; break; case IPMI_MONITORING_SENSOR_UNITS_FAHRENHEIT: @@ -1032,7 +1032,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "Fahrenheit"; t.family = "temperatures"; t.chart_type = "line"; - t.priority = state->sensors.priority + 20; + t.priority = stt->sensors.priority + 20; break; case IPMI_MONITORING_SENSOR_UNITS_VOLTS: @@ -1042,7 +1042,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "Volts"; t.family = "voltages"; t.chart_type = "line"; - t.priority = state->sensors.priority + 30; + t.priority = stt->sensors.priority + 30; break; case IPMI_MONITORING_SENSOR_UNITS_AMPS: @@ -1052,7 +1052,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "Amps"; t.family = "current"; t.chart_type = "line"; - t.priority = state->sensors.priority + 40; + t.priority = stt->sensors.priority + 40; break; case IPMI_MONITORING_SENSOR_UNITS_RPM: @@ -1062,7 +1062,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "RPM"; t.family = "fans"; t.chart_type = "line"; - t.priority = state->sensors.priority + 50; + t.priority = stt->sensors.priority + 50; break; case IPMI_MONITORING_SENSOR_UNITS_WATTS: @@ -1072,7 +1072,7 @@ static void netdata_update_ipmi_sensor_reading( t.units = "Watts"; t.family = "power"; t.chart_type = "line"; - t.priority = state->sensors.priority + 60; + t.priority = stt->sensors.priority + 60; break; case IPMI_MONITORING_SENSOR_UNITS_PERCENT: @@ -1082,11 +1082,11 @@ static void netdata_update_ipmi_sensor_reading( t.units = "%%"; t.family = "other"; t.chart_type = "line"; - t.priority = state->sensors.priority + 70; + t.priority = stt->sensors.priority + 70; break; default: - t.priority = state->sensors.priority + 80; + t.priority = stt->sensors.priority + 80; t.do_metric = false; break; } @@ -1107,57 +1107,57 @@ static void netdata_update_ipmi_sensor_reading( } if(sensor_reading) { - netdata_sensor_set_value(&t, sensor_reading, state); - t.last_collected_metric_ut = state->sensors.now_ut; + netdata_sensor_set_value(&t, sensor_reading, stt); + t.last_collected_metric_ut = stt->sensors.now_ut; } - t.last_collected_state_ut = state->sensors.now_ut; + t.last_collected_state_ut = stt->sensors.now_ut; - dictionary_set(state->sensors.dict, key, &t, sizeof(t)); + dictionary_set(stt->sensors.dict, key, &t, sizeof(t)); } -static void netdata_update_ipmi_sel_events_count(struct netdata_ipmi_state *state, uint32_t events) { - state->sel.events = events; +static void netdata_update_ipmi_sel_events_count(struct netdata_ipmi_state *stt, uint32_t events) { + stt->sel.events = events; } -int netdata_ipmi_collect_data(struct ipmi_monitoring_ipmi_config *ipmi_config, IPMI_COLLECTION_TYPE type, struct netdata_ipmi_state *state) { +int netdata_ipmi_collect_data(struct ipmi_monitoring_ipmi_config *ipmi_config, IPMI_COLLECTION_TYPE type, struct netdata_ipmi_state *stt) { errno = 0; if(type & IPMI_COLLECT_TYPE_SENSORS) { - state->sensors.collected = 0; - state->sensors.now_ut = now_monotonic_usec(); + stt->sensors.collected = 0; + stt->sensors.now_ut = now_monotonic_usec(); - if (netdata_read_ipmi_sensors(ipmi_config, state) < 0) return -1; + if (netdata_read_ipmi_sensors(ipmi_config, stt) < 0) return -1; } if(type & IPMI_COLLECT_TYPE_SEL) { - state->sel.events = 0; - state->sel.now_ut = now_monotonic_usec(); - if(netdata_get_ipmi_sel_events_count(ipmi_config, state) < 0) return -2; + stt->sel.events = 0; + stt->sel.now_ut = now_monotonic_usec(); + if(netdata_get_ipmi_sel_events_count(ipmi_config, stt) < 0) return -2; } return 0; } -int netdata_ipmi_detect_speed_secs(struct ipmi_monitoring_ipmi_config *ipmi_config, IPMI_COLLECTION_TYPE type, struct netdata_ipmi_state *state) { +int netdata_ipmi_detect_speed_secs(struct ipmi_monitoring_ipmi_config *ipmi_config, IPMI_COLLECTION_TYPE type, struct netdata_ipmi_state *stt) { int i, checks = SPEED_TEST_ITERATIONS, successful = 0; usec_t total = 0; for(i = 0 ; i < checks ; i++) { - if(unlikely(state->debug)) + if(unlikely(stt->debug)) fprintf(stderr, "%s: checking %s data collection speed iteration %d of %d\n", program_name, netdata_collect_type_to_string(type), i + 1, checks); // measure the time a data collection needs usec_t start = now_realtime_usec(); - if(netdata_ipmi_collect_data(ipmi_config, type, state) < 0) + if(netdata_ipmi_collect_data(ipmi_config, type, stt) < 0) continue; usec_t end = now_realtime_usec(); successful++; - if(unlikely(state->debug)) + if(unlikely(stt->debug)) fprintf(stderr, "%s: %s data collection speed was %"PRIu64" usec\n", program_name, netdata_collect_type_to_string(type), end - start); @@ -1297,31 +1297,32 @@ static inline bool is_sensor_updated(usec_t last_collected_ut, usec_t now_ut, us return (now_ut - last_collected_ut < freq * 2) ? true : false; } -static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *state) { - if(state->sensors.status != ICS_RUNNING) { - if(unlikely(state->debug)) +static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *stt) { + if(stt->sensors.status != ICS_RUNNING) { + if(unlikely(stt->debug)) fprintf(stderr, "%s: %s() sensors state is not RUNNING\n", program_name, __FUNCTION__ ); return 0; } size_t total_sensors_sent = 0; - int update_every = (int)(state->sensors.freq_ut / USEC_PER_SEC); + int update_every_s = (int)(stt->sensors.freq_ut / USEC_PER_SEC); struct sensor *sn; netdata_mutex_lock(&stdout_mutex); // generate the CHART/DIMENSION lines, if we have to - dfe_start_reentrant(state->sensors.dict, sn) { + dfe_start_reentrant(stt->sensors.dict, sn) { if(unlikely(!sn->do_metric && !sn->do_state)) continue; bool did_metric = false, did_state = false; if(likely(sn->do_metric)) { - if(unlikely(!is_sensor_updated(sn->last_collected_metric_ut, state->updates.now_ut, state->sensors.freq_ut))) { - if(unlikely(state->debug)) + if(unlikely(!is_sensor_updated(sn->last_collected_metric_ut, stt->updates.now_ut, stt->sensors.freq_ut))) { + if(unlikely(stt->debug)) fprintf(stderr, "%s: %s() sensor '%s' metric is not UPDATED (last updated %"PRIu64", now %"PRIu64", freq %"PRIu64"\n", - program_name, __FUNCTION__, sn->sensor_name, sn->last_collected_metric_ut, state->updates.now_ut, state->sensors.freq_ut); + program_name, __FUNCTION__, sn->sensor_name, sn->last_collected_metric_ut, + stt->updates.now_ut, stt->sensors.freq_ut); } else { if (unlikely(!sn->metric_chart_sent)) { @@ -1329,7 +1330,8 @@ static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *sta printf("CHART '%s_%s' '' '%s' '%s' '%s' '%s' '%s' %d %d '' '%s' '%s'\n", sn->context, sn_dfe.name, sn->title, sn->units, sn->family, sn->context, - sn->chart_type, sn->priority + 1, update_every, program_name, "sensors"); + sn->chart_type, sn->priority + 1, + update_every_s, program_name, "sensors"); printf("CLABEL 'sensor' '%s' 1\n", sn->sensor_name); printf("CLABEL 'type' '%s' 1\n", sn->type); @@ -1343,19 +1345,16 @@ static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *sta switch (sn->sensor_reading_type) { case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER32: - printf("SET '%s' = %u\n", sn->dimension, sn->sensor_reading.uint32_value - ); + printf("SET '%s' = %u\n", sn->dimension, sn->sensor_reading.uint32_value); break; case IPMI_MONITORING_SENSOR_READING_TYPE_DOUBLE: printf("SET '%s' = %lld\n", sn->dimension, - (long long int) (sn->sensor_reading.double_value * sn->multiplier) - ); + (long long int) (sn->sensor_reading.double_value * sn->multiplier)); break; case IPMI_MONITORING_SENSOR_READING_TYPE_UNSIGNED_INTEGER8_BOOL: - printf("SET '%s' = %u\n", sn->dimension, sn->sensor_reading.bool_value - ); + printf("SET '%s' = %u\n", sn->dimension, sn->sensor_reading.bool_value); break; default: @@ -1371,17 +1370,18 @@ static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *sta } if(likely(sn->do_state)) { - if(unlikely(!is_sensor_updated(sn->last_collected_state_ut, state->updates.now_ut, state->sensors.freq_ut))) { - if (unlikely(state->debug)) + if(unlikely(!is_sensor_updated(sn->last_collected_state_ut, stt->updates.now_ut, stt->sensors.freq_ut))) { + if (unlikely(stt->debug)) fprintf(stderr, "%s: %s() sensor '%s' state is not UPDATED (last updated %"PRIu64", now %"PRIu64", freq %"PRIu64"\n", - program_name, __FUNCTION__, sn->sensor_name, sn->last_collected_state_ut, state->updates.now_ut, state->sensors.freq_ut); + program_name, __FUNCTION__, sn->sensor_name, sn->last_collected_state_ut, + stt->updates.now_ut, stt->sensors.freq_ut); } else { if (unlikely(!sn->state_chart_sent)) { sn->state_chart_sent = true; printf("CHART 'ipmi.sensor_state_%s' '' 'IPMI Sensor State' 'state' 'states' 'ipmi.sensor_state' 'line' %d %d '' '%s' '%s'\n", - sn_dfe.name, sn->priority, update_every, program_name, "sensors"); + sn_dfe.name, sn->priority, update_every_s, program_name, "sensors"); printf("CLABEL 'sensor' '%s' 1\n", sn->sensor_name); printf("CLABEL 'type' '%s' 1\n", sn->type); @@ -1414,17 +1414,17 @@ static size_t send_ipmi_sensor_metrics_to_netdata(struct netdata_ipmi_state *sta return total_sensors_sent; } -static size_t send_ipmi_sel_metrics_to_netdata(struct netdata_ipmi_state *state) { +static size_t send_ipmi_sel_metrics_to_netdata(struct netdata_ipmi_state *stt) { static bool sel_chart_generated = false; netdata_mutex_lock(&stdout_mutex); - if(likely(state->sel.status == ICS_RUNNING)) { + if(likely(stt->sel.status == ICS_RUNNING)) { if(unlikely(!sel_chart_generated)) { sel_chart_generated = true; printf("CHART ipmi.events '' 'IPMI Events' 'events' 'events' ipmi.sel area %d %d '' '%s' '%s'\n" - , state->sel.priority + 2 - , (int)(state->sel.freq_ut / USEC_PER_SEC) + , stt->sel.priority + 2 + , (int)(stt->sel.freq_ut / USEC_PER_SEC) , program_name , "sel" ); @@ -1435,13 +1435,14 @@ static size_t send_ipmi_sel_metrics_to_netdata(struct netdata_ipmi_state *state) "BEGIN ipmi.events\n" "SET events = %zu\n" "END\n" - , state->sel.events + , + stt->sel.events ); } netdata_mutex_unlock(&stdout_mutex); - return state->sel.events; + return stt->sel.events; } // ---------------------------------------------------------------------------- @@ -1470,15 +1471,35 @@ static const char *get_sensor_function_priority(struct sensor *sn) { } } -static void freeimi_function_sensors(const char *transaction, char *function __maybe_unused, int timeout __maybe_unused, bool *cancelled __maybe_unused) { - time_t expires = now_realtime_sec() + update_every; +static void freeimi_function_sensors(const char *transaction, char *function __maybe_unused, + usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused, + BUFFER *payload __maybe_unused, HTTP_ACCESS access __maybe_unused, + const char *source __maybe_unused, void *data __maybe_unused) { + time_t now_s = now_realtime_sec(); - BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX, NULL); + BUFFER *wb = buffer_create(4096, NULL); buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS); buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK); buffer_json_member_add_string(wb, "type", "table"); buffer_json_member_add_time_t(wb, "update_every", update_every); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", "View IPMI sensor readings and its state"); + + char function_copy[strlen(function) + 1]; + memcpy(function_copy, function, sizeof(function_copy)); + char *words[1024]; + size_t num_words = quoted_strings_splitter_pluginsd(function_copy, words, 1024); + for(size_t i = 1; i < num_words ;i++) { + char *param = get_word(words, num_words, i); + if(strcmp(param, "info") == 0) { + buffer_json_member_add_array(wb, "accepted_params"); + buffer_json_array_close(wb); // accepted_params + buffer_json_member_add_array(wb, "required_params"); + buffer_json_array_close(wb); // required_params + goto close_and_send; + } + } + buffer_json_member_add_array(wb, "data"); struct sensor *sn; @@ -1604,10 +1625,11 @@ static void freeimi_function_sensors(const char *transaction, char *function __m } buffer_json_array_close(wb); - buffer_json_member_add_time_t(wb, "expires", now_realtime_sec() + 1); +close_and_send: + buffer_json_member_add_time_t(wb, "expires", now_s + update_every); buffer_json_finalize(wb); - pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires, wb); + pluginsd_function_result_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + update_every, wb); buffer_free(wb); } @@ -1615,7 +1637,7 @@ static void freeimi_function_sensors(const char *transaction, char *function __m // ---------------------------------------------------------------------------- // main, command line arguments parsing -static void plugin_exit(int code) { +static NORETURN void plugin_exit(int code) { fflush(stdout); function_plugin_should_exit = true; exit(code); @@ -1803,7 +1825,7 @@ int main (int argc, char **argv) { " options ipmi_si kipmid_max_busy_us=10\n" "\n" " For more information:\n" - " https://github.com/netdata/netdata/tree/master/collectors/freeipmi.plugin\n" + " https://github.com/netdata/netdata/tree/master/src/collectors/freeipmi.plugin\n" "\n" , program_name, VERSION , update_every @@ -1972,7 +1994,7 @@ int main (int argc, char **argv) { size_t iteration = 0; usec_t step = 100 * USEC_PER_MS; bool global_chart_created = false; - bool tty = isatty(fileno(stderr)) == 1; + bool tty = isatty(fileno(stdout)) == 1; heartbeat_t hb; heartbeat_init(&hb); @@ -2044,7 +2066,7 @@ int main (int argc, char **argv) { struct functions_evloop_globals *wg = functions_evloop_init(1, "FREEIPMI", &stdout_mutex, &function_plugin_should_exit); functions_evloop_add_function( - wg, "ipmi-sensors", freeimi_function_sensors, PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT); + wg, "ipmi-sensors", freeimi_function_sensors, PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT, NULL); FREEIPMI_GLOBAL_FUNCTION_SENSORS(); } |