#include "vici_builder.h"
#include <inttypes.h>
+#include <time.h>
#ifndef WIN32
#include <sys/utsname.h>
#endif
+#ifdef HAVE_MALLINFO
+#include <malloc.h>
+#endif
#include <daemon.h>
* Dispatcher
*/
vici_dispatcher_t *dispatcher;
+
+ /**
+ * Daemon startup timestamp
+ */
+ time_t uptime;
};
/**
return b->finalize(b);
}
+/**
+ * Callback function for memusage summary
+ */
+CALLBACK(sum_usage, void,
+ vici_builder_t *b, int count, size_t bytes, int whitelisted)
+{
+ b->begin_section(b, "mem");
+ b->add_kv(b, "total", "%zu", bytes);
+ b->add_kv(b, "allocs", "%d", count);
+ b->end_section(b);
+}
+
+CALLBACK(stats, vici_message_t*,
+ private_vici_query_t *this, char *name, u_int id, vici_message_t *request)
+{
+ vici_builder_t *b;
+ enumerator_t *enumerator;
+ plugin_t *plugin;
+ time_t since, now;
+ int i;
+
+ b = vici_builder_create();
+
+ now = time_monotonic(NULL);
+ since = time(NULL) - (now - this->uptime);
+
+ b->begin_section(b, "uptime");
+ b->add_kv(b, "running", "%V", &now, &this->uptime);
+ b->add_kv(b, "since", "%T", &since, FALSE);
+ b->end_section(b);
+
+ b->begin_section(b, "workers");
+ b->add_kv(b, "total", "%d",
+ lib->processor->get_total_threads(lib->processor));
+ b->add_kv(b, "idle", "%d",
+ lib->processor->get_idle_threads(lib->processor));
+ b->begin_section(b, "active");
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+ lib->processor->get_working_threads(lib->processor, i));
+ }
+ b->end_section(b);
+ b->end_section(b);
+
+ b->begin_section(b, "queues");
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ b->add_kv(b, enum_to_name(job_priority_names, i), "%d",
+ lib->processor->get_job_load(lib->processor, i));
+ }
+ b->end_section(b);
+
+ b->add_kv(b, "scheduled", "%d",
+ lib->scheduler->get_job_load(lib->scheduler));
+
+ b->begin_section(b, "ikesas");
+ b->add_kv(b, "total", "%u",
+ charon->ike_sa_manager->get_count(charon->ike_sa_manager));
+ b->add_kv(b, "half-open", "%u",
+ charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
+ NULL));
+ b->end_section(b);
+
+ b->begin_list(b, "plugins");
+ enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+ while (enumerator->enumerate(enumerator, &plugin, NULL))
+ {
+ b->add_li(b, "%s", plugin->get_name(plugin));
+ }
+ enumerator->destroy(enumerator);
+ b->end_list(b);
+
+ if (lib->leak_detective)
+ {
+ lib->leak_detective->usage(lib->leak_detective, NULL, sum_usage, b);
+ }
+#ifdef HAVE_MALLINFO
+ {
+ struct mallinfo mi = mallinfo();
+
+ b->begin_section(b, "mallinfo");
+ b->add_kv(b, "sbrk", "%d", mi.arena);
+ b->add_kv(b, "mmap", "%d", mi.hblkhd);
+ b->add_kv(b, "used", "%d", mi.uordblks);
+ b->add_kv(b, "free", "%d", mi.fordblks);
+ b->end_section(b);
+ }
+#endif /* HAVE_MALLINFO */
+
+ return b->finalize(b);
+}
+
static void manage_command(private_vici_query_t *this,
char *name, vici_command_cb_t cb, bool reg)
{
manage_command(this, "list-conns", list_conns, reg);
manage_command(this, "list-certs", list_certs, reg);
manage_command(this, "version", version, reg);
+ manage_command(this, "stats", stats, reg);
}
METHOD(vici_query_t, destroy, void,
.destroy = _destroy,
},
.dispatcher = dispatcher,
+ .uptime = time_monotonic(NULL),
);
manage_commands(this, TRUE);