diff options
author | Costa Tsaousis <costa@netdata.cloud> | 2024-02-02 22:44:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-02 20:44:20 +0000 |
commit | de75ef2f6dccfa1d357d14b86179b8174c3745a5 (patch) | |
tree | cb261f2fc0c74e3580123e0d24ee8222a05ae154 | |
parent | bb8dfac31270375229e843f3ac143f77830718dc (diff) |
add support for the info parameter to all external plugin functions (#16915)
* add support for the info parameter to all functions
* add SO_CLOEXEC to inbound connections
* network-connections aggregated view for servers with dozens of thousands of connections
* optimized /proc/net files parsing; aggregated view of network-connections returns sorted sockets to avoid dancing visualization
* local-sockets is now using aral
* lower the payload returned by network-connections
20 files changed, 760 insertions, 391 deletions
diff --git a/collectors/apps.plugin/apps_plugin.c b/collectors/apps.plugin/apps_plugin.c index 4144787edc..7e0758f69f 100644 --- a/collectors/apps.plugin/apps_plugin.c +++ b/collectors/apps.plugin/apps_plugin.c @@ -4399,10 +4399,11 @@ static void apps_plugin_function_processes_help(const char *transaction) { buffer_json_add_array_item_double(wb, _tmp); \ } while(0) -static void function_processes(const char *transaction, char *function __maybe_unused, +static void function_processes(const char *transaction, char *function, usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused, BUFFER *payload __maybe_unused, HTTP_ACCESS access, const char *source __maybe_unused, void *data __maybe_unused) { + time_t now_s = now_realtime_sec(); struct pid_stat *p; bool show_cmdline = http_access_user_has_enough_access_level_for_endpoint( @@ -4418,6 +4419,7 @@ static void function_processes(const char *transaction, char *function __maybe_u pid_t pid = 0; uid_t uid = 0; gid_t gid = 0; + bool info = false; bool filter_pid = false, filter_uid = false, filter_gid = false; @@ -4468,16 +4470,11 @@ static void function_processes(const char *transaction, char *function __maybe_u apps_plugin_function_processes_help(transaction); return; } - else { - char msg[1024]; - snprintfz(msg, sizeof(msg), "Invalid parameter '%s'", keyword); - pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST, msg); - return; + else if(strcmp(keyword, "info") == 0) { + info = true; } } - time_t expires = now_realtime_sec() + update_every; - unsigned int cpu_divisor = time_factor * RATES_DETAIL / 100; unsigned int memory_divisor = 1024; unsigned int io_divisor = 1024 * RATES_DETAIL; @@ -4487,9 +4484,13 @@ static void function_processes(const char *transaction, char *function __maybe_u 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", APPS_PLUGIN_PROCESSES_FUNCTION_DESCRIPTION); buffer_json_member_add_array(wb, "data"); + if(info) + goto close_and_send; + NETDATA_DOUBLE UserCPU_max = 0.0 , SysCPU_max = 0.0 @@ -5251,10 +5252,11 @@ static void function_processes(const char *transaction, char *function __maybe_u } buffer_json_object_close(wb); // group_by - buffer_json_member_add_time_t(wb, "expires", expires); +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); } diff --git a/collectors/cgroups.plugin/cgroup-top.c b/collectors/cgroups.plugin/cgroup-top.c index 7593aae3e5..aa413dad11 100644 --- a/collectors/cgroups.plugin/cgroup-top.c +++ b/collectors/cgroups.plugin/cgroup-top.c @@ -107,6 +107,7 @@ int cgroup_function_cgroup_top(BUFFER *wb, const char *function __maybe_unused) 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", 1); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_CGTOP_HELP); buffer_json_member_add_array(wb, "data"); @@ -349,6 +350,7 @@ int cgroup_function_systemd_top(BUFFER *wb, const char *function __maybe_unused) 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", 1); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_CGTOP_HELP); buffer_json_member_add_array(wb, "data"); diff --git a/collectors/diskspace.plugin/plugin_diskspace.c b/collectors/diskspace.plugin/plugin_diskspace.c index 38b5ab42de..d93e743ae5 100644 --- a/collectors/diskspace.plugin/plugin_diskspace.c +++ b/collectors/diskspace.plugin/plugin_diskspace.c @@ -645,6 +645,7 @@ int diskspace_function_mount_points(BUFFER *wb, const char *function __maybe_unu 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", 1); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", RRDFUNCTIONS_DISKSPACE_HELP); buffer_json_member_add_array(wb, "data"); diff --git a/collectors/ebpf.plugin/ebpf_functions.c b/collectors/ebpf.plugin/ebpf_functions.c index feb4caf302..7876c9b945 100644 --- a/collectors/ebpf.plugin/ebpf_functions.c +++ b/collectors/ebpf.plugin/ebpf_functions.c @@ -292,6 +292,9 @@ static void ebpf_function_socket_manipulation(const char *transaction, rw_spinlock_write_lock(&ebpf_judy_pid.index.rw_spinlock); network_viewer_opt.enabled = CONFIG_BOOLEAN_YES; uint32_t previous; + bool info = false; + time_t now_s = now_realtime_sec(); + static const char *socket_help = { "ebpf.plugin / socket\n" "\n" @@ -413,7 +416,8 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) { ebpf_function_help(transaction, socket_help); rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock); return; - } + } else if (strncmp(keyword, "info", 4) == 0) + info = true; } rw_spinlock_write_unlock(&ebpf_judy_pid.index.rw_spinlock); @@ -443,8 +447,12 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) { 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", em->update_every); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", EBPF_PLUGIN_SOCKET_FUNCTION_DESCRIPTION); + if(info) + goto close_and_send; + // Collect data buffer_json_member_add_array(wb, "data"); ebpf_socket_read_open_connections(wb, em); @@ -652,12 +660,12 @@ for (int i = 1; i < PLUGINSD_MAX_WORDS; i++) { } buffer_json_object_close(wb); // group_by - time_t expires = now_realtime_sec() + em->update_every; - buffer_json_member_add_time_t(wb, "expires", expires); +close_and_send: + buffer_json_member_add_time_t(wb, "expires", now_s + em->update_every); buffer_json_finalize(wb); // Lock necessary to avoid race condition - pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires); + pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", now_s + em->update_every); fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout); diff --git a/collectors/freeipmi.plugin/freeipmi_plugin.c b/collectors/freeipmi.plugin/freeipmi_plugin.c index b94d365c7b..2ef223c306 100644 --- a/collectors/freeipmi.plugin/freeipmi_plugin.c +++ b/collectors/freeipmi.plugin/freeipmi_plugin.c @@ -1475,14 +1475,31 @@ static void freeimi_function_sensors(const char *transaction, char *function __m 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 expires = now_realtime_sec() + update_every; + time_t now_s = now_realtime_sec(); 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; @@ -1608,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); } diff --git a/collectors/network-viewer.plugin/network-connections-chart.html b/collectors/network-viewer.plugin/network-connections-chart.html index 385e715ff6..dd66b9a005 100644 --- a/collectors/network-viewer.plugin/network-connections-chart.html +++ b/collectors/network-viewer.plugin/network-connections-chart.html @@ -557,15 +557,39 @@ const app = updateApps(svg, data, w, h, borderPadding, theme); + app.transition().duration(5000) + simulation = d3.forceSimulation(data) //.force('center', d3.forceCenter(cw, ch).strength(1)) - .force("x", d3.forceX(d => d.d3.x).strength(0.05)) - .force("y", d3.forceY(d => d.d3.y).strength(0.05)) + .force("x", d3.forceX(d => d.d3.x).strength(d => { + if(d.counts.listen === d.counts.total) + return 0.5 + else + return 0.05 + })) + .force("y", d3.forceY(d => d.d3.y).strength(d => { + if(d.counts.listen === d.counts.total) + return 0.5 + else + return 0.05 + })) //.force("charge", d3.forceManyBody().strength(-0.05)) .force("collide", d3.forceCollide(d => d.d3.size * 1.1 + 15).strength(1)) .on('tick', ticked); function ticked() { + data.forEach(d => { + if(d.x > w - d.d3.size) + d.x = w - d.d3.size; + else if(d.x < 0) + d.x = 0; + + if(d.y > h - d.d3.size) + d.y = h - d.d3.size; + else if(d.y < 0) + d.y = 0; + }); + app.attr('transform', d => `translate(${d.x}, ${d.y})`); } diff --git a/collectors/network-viewer.plugin/network-viewer.c b/collectors/network-viewer.plugin/network-viewer.c index 130e56d715..8d9a451f34 100644 --- a/collectors/network-viewer.plugin/network-viewer.c +++ b/collectors/network-viewer.plugin/network-viewer.c @@ -3,12 +3,23 @@ #include "collectors/all.h" #include "libnetdata/libnetdata.h" #include "libnetdata/required_dummies.h" + +#define LOCAL_SOCKETS_EXTENDED_MEMBERS struct { \ + size_t count; \ + const char *local_address_space; \ + const char *remote_address_space; \ + } network_viewer; + #include "libnetdata/maps/local-sockets.h" #include "libnetdata/maps/system-users.h" #define NETWORK_CONNECTIONS_VIEWER_FUNCTION "network-connections" #define NETWORK_CONNECTIONS_VIEWER_HELP "Network connections explorer" +#define SIMPLE_HASHTABLE_VALUE_TYPE LOCAL_SOCKET +#define SIMPLE_HASHTABLE_NAME _AGGREGATED_SOCKETS +#include "libnetdata/simple_hashtable.h" + netdata_mutex_t stdout_mutex = NETDATA_MUTEX_INITIALIZER; static bool plugin_should_exit = false; static USERNAMES_CACHE *uc; @@ -44,10 +55,7 @@ ENUM_STR_MAP_DEFINE(TCP_STATE) = { }; ENUM_STR_DEFINE_FUNCTIONS(TCP_STATE, 0, "unknown"); - -static void local_socket_to_array(struct local_socket_state *ls, struct local_socket *n, void *data) { - BUFFER *wb = data; - +static void local_socket_to_json_array(BUFFER *wb, LOCAL_SOCKET *n, uint64_t proc_self_net_ns_inode, bool aggregated) { char local_address[INET6_ADDRSTRLEN]; char remote_address[INET6_ADDRSTRLEN]; char *protocol; @@ -66,7 +74,7 @@ static void local_socket_to_array(struct local_socket_state *ls, struct local_so return; const char *type; - if(n->net_ns_inode == ls->proc_self_net_ns_inode) + if(n->net_ns_inode == proc_self_net_ns_inode) type = "system"; else if(n->net_ns_inode == 0) type = "[unknown]"; @@ -90,55 +98,141 @@ static void local_socket_to_array(struct local_socket_state *ls, struct local_so else buffer_json_add_array_item_string(wb, n->comm); - buffer_json_add_array_item_string(wb, n->cmdline); + // buffer_json_add_array_item_string(wb, string2str(n->cmdline)); if(n->uid == UID_UNSET) { - buffer_json_add_array_item_uint64(wb, n->uid); + // buffer_json_add_array_item_uint64(wb, n->uid); buffer_json_add_array_item_string(wb, "[unknown]"); } else { - buffer_json_add_array_item_uint64(wb, n->uid); + // buffer_json_add_array_item_uint64(wb, n->uid); STRING *u = system_usernames_cache_lookup_uid(uc, n->uid); buffer_json_add_array_item_string(wb, string2str(u)); string_freez(u); } - buffer_json_add_array_item_string(wb, local_address); - buffer_json_add_array_item_uint64(wb, n->local.port); - buffer_json_add_array_item_string(wb, local_sockets_address_space(&n->local)); - buffer_json_add_array_item_string(wb, remote_address); - buffer_json_add_array_item_uint64(wb, n->remote.port); - buffer_json_add_array_item_string(wb, local_sockets_address_space(&n->remote)); + if(!aggregated) { + buffer_json_add_array_item_string(wb, local_address); + buffer_json_add_array_item_uint64(wb, n->local.port); + } + buffer_json_add_array_item_string(wb, n->network_viewer.local_address_space); + + if(!aggregated) { + buffer_json_add_array_item_string(wb, remote_address); + buffer_json_add_array_item_uint64(wb, n->remote.port); + } + buffer_json_add_array_item_string(wb, n->network_viewer.remote_address_space); uint16_t server_port; - switch(n->direction) { + const char *server_address; + const char *client_address_space; + const char *server_address_space; + switch (n->direction) { case SOCKET_DIRECTION_LISTEN: case SOCKET_DIRECTION_INBOUND: case SOCKET_DIRECTION_LOCAL_INBOUND: server_port = n->local.port; + server_address = local_address; + server_address_space = n->network_viewer.local_address_space; + client_address_space = n->network_viewer.remote_address_space; break; case SOCKET_DIRECTION_OUTBOUND: case SOCKET_DIRECTION_LOCAL_OUTBOUND: server_port = n->remote.port; + server_address = remote_address; + server_address_space = n->network_viewer.remote_address_space; + client_address_space = n->network_viewer.local_address_space; break; case SOCKET_DIRECTION_NONE: break; } + if(aggregated) + buffer_json_add_array_item_string(wb, server_address); + buffer_json_add_array_item_uint64(wb, server_port); - buffer_json_add_array_item_uint64(wb, n->inode); - buffer_json_add_array_item_uint64(wb, n->net_ns_inode); - buffer_json_add_array_item_uint64(wb, 1); // count + if(aggregated) { + buffer_json_add_array_item_string(wb, client_address_space); + buffer_json_add_array_item_string(wb, server_address_space); + } + + // buffer_json_add_array_item_uint64(wb, n->inode); + // buffer_json_add_array_item_uint64(wb, n->net_ns_inode); + buffer_json_add_array_item_uint64(wb, n->network_viewer.count); } buffer_json_array_close(wb); } +static void local_sockets_cb_to_json(LS_STATE *ls, LOCAL_SOCKET *n, void *data) { + n->network_viewer.count = 1; + n->network_viewer.local_address_space = local_sockets_address_space(&n->local); + n->network_viewer.remote_address_space = local_sockets_address_space(&n->remote); + local_socket_to_json_array(data, n, ls->proc_self_net_ns_inode, false); +} + +static void local_sockets_cb_to_aggregation(LS_STATE *ls __maybe_unused, LOCAL_SOCKET *n, void *data) { + SIMPLE_HASHTABLE_AGGREGATED_SOCKETS *ht = data; + n->network_viewer.count = 1; + n->network_viewer.local_address_space = local_sockets_address_space(&n->local); + n->network_viewer.remote_address_space = local_sockets_address_space(&n->remote); + + switch(n->direction) { + case SOCKET_DIRECTION_INBOUND: + case SOCKET_DIRECTION_LOCAL_INBOUND: + case SOCKET_DIRECTION_LISTEN: + memset(&n->remote.ip, 0, sizeof(n->remote.ip)); + n->remote.port = 0; + break; + + case SOCKET_DIRECTION_OUTBOUND: + case SOCKET_DIRECTION_LOCAL_OUTBOUND: + memset(&n->local.ip, 0, sizeof(n->remote.ip)); + n->local.port = 0; + break; + + case SOCKET_DIRECTION_NONE: + return; + } + + n->inode = 0; + n->local_ip_hash = 0; + n->remote_ip_hash = 0; + n->local_port_hash = 0; + n->timer = 0; + n->retransmits = 0; + n->expires = 0; + n->rqueue = 0; + n->wqueue = 0; + memset(&n->local_port_key, 0, sizeof(n->local_port_key)); + + XXH64_hash_t hash = XXH3_64bits(n, sizeof(*n)); + SIMPLE_HASHTABLE_SLOT_AGGREGATED_SOCKETS *sl = simple_hashtable_get_slot_AGGREGATED_SOCKETS(ht, hash, n, true); + LOCAL_SOCKET *t = SIMPLE_HASHTABLE_SLOT_DATA(sl); + if(t) { + t->network_viewer.count++; + } + else { + t = mallocz(sizeof(*t)); + memcpy(t, n, sizeof(*t)); + t->cmdline = string_dup(t->cmdline); + simple_hashtable_set_slot_AGGREGATED_SOCKETS(ht, sl, hash, t); + } +} + +static int local_sockets_compar(const void *a, const void *b) { + LOCAL_SOCKET *n1 = *(LOCAL_SOCKET **)a, *n2 = *(LOCAL_SOCKET **)b; + return strcmp(n1->comm, n2->comm); +} + void network_viewer_function(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(); + bool aggregated = false; + CLEAN_BUFFER *wb = buffer_create(0, NULL); buffer_flush(wb); wb->content_type = CT_APPLICATION_JSON; @@ -147,360 +241,483 @@ void network_viewer_function(const char *transaction, char *function __maybe_unu 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", 5); + buffer_json_member_add_boolean(wb, "has_history", false); buffer_json_member_add_string(wb, "help", NETWORK_CONNECTIONS_VIEWER_HELP); - buffer_json_member_add_array(wb, "data"); - - LS_STATE ls = { - .config = { - .listening = true, - .inbound = true, - .outbound = true, - .local = true, - .tcp4 = true, - .tcp6 = true, - .udp4 = true, - .udp6 = true, - .pid = true, - .uid = true, - .cmdline = true, - .comm = true, - .namespaces = true, - - .max_errors = 10, - - .cb = local_socket_to_array, - .data = wb, - }, - .stats = { 0 }, - .sockets_hashtable = { 0 }, - .local_ips_hashtable = { 0 }, - .listening_ports_hashtable = { 0 }, - }; - - local_sockets_process(&ls); - buffer_json_array_close(wb); - buffer_json_member_add_object(wb, "columns"); +#ifdef ENABLE_DETAILED_VIEW + buffer_json_member_add_array(wb, "accepted_params"); { - size_t field_id = 0; - - // Direction - buffer_rrdf_table_add_field(wb, field_id++, "Direction", "Socket Direction", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Protocol - buffer_rrdf_table_add_field(wb, field_id++, "Protocol", "Socket Protocol", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Type - buffer_rrdf_table_add_field(wb, field_id++, "Namespace", "Namespace", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // State - buffer_rrdf_table_add_field(wb, field_id++, "State", "Socket State", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Pid - buffer_rrdf_table_add_field(wb, field_id++, "PID", "Process ID", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Comm - buffer_rrdf_table_add_field(wb, field_id++, "Process", "Process Name", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH, - NULL); - - // Cmdline - buffer_rrdf_table_add_field(wb, field_id++, "CommandLine", "Command Line", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_NONE|RRDF_FIELD_OPTS_FULL_WIDTH, - NULL); - - // Uid - buffer_rrdf_table_add_field(wb, field_id++, "UID", "User ID", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_NONE, - NULL); - - // Username - buffer_rrdf_table_add_field(wb, field_id++, "User", "Username", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Local Address - buffer_rrdf_table_add_field(wb, field_id++, "LocalIP", "Local IP Address", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH, - NULL); - - // Local Port - buffer_rrdf_table_add_field(wb, field_id++, "LocalPort", "Local Port", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Local Address Space - buffer_rrdf_table_add_field(wb, field_id++, "LocalAddressSpace", "Local IP Address Space", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_NONE, - NULL); - - // Remote Address - buffer_rrdf_table_add_field(wb, field_id++, "RemoteIP", "Remote IP Address", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_VISIBLE|RRDF_FIELD_OPTS_FULL_WIDTH, - NULL); - - // Remote Port - buffer_rrdf_table_add_field(wb, field_id++, "RemotePort", "Remote Port", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_VISIBLE, - NULL); - - // Remote Address Space - buffer_rrdf_table_add_field(wb, field_id++, "RemoteAddressSpace", "Remote IP Address Space", - RRDF_FIELD_TYPE_STRING, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_NONE, - NULL); - - // Server Port - buffer_rrdf_table_add_field(wb, field_id++, "ServerPort", "Server Port", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_MULTISELECT, - RRDF_FIELD_OPTS_NONE, - NULL); - - // inode - buffer_rrdf_table_add_field(wb, field_id++, "Inode", "Socket Inode", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_NONE, - NULL); - - // Namespace inode - buffer_rrdf_table_add_field(wb, field_id++, "Namespace Inode", "Namespace Inode", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_NONE, - NULL); - - // Count - buffer_rrdf_table_add_field(wb, field_id++, "Count", "Count", - RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, - 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, - RRDF_FIELD_SUMMARY_COUNT, RRDF_FIELD_FILTER_NONE, - RRDF_FIELD_OPTS_NONE, - NULL); + buffer_json_add_array_item_string(wb, "sockets"); } - buffer_json_object_close(wb); // columns - buffer_json_member_add_string(wb, "default_sort_column", "Direction"); - - buffer_json_member_add_object(wb, "custom_charts"); + buffer_json_array_close(wb); // accepted_params + buffer_json_member_add_array(wb, "required_params"); { - buffer_json_member_add_object(wb, "Network Map"); + buffer_json_add_array_item_object(wb); { - buffer_json_member_ad |