[mod_status] Add status.show_runtime action
parent
8a0665aa53
commit
f0d5c9e789
|
@ -11,16 +11,21 @@
|
|||
* status.css <name|url> - set the stylesheet to use
|
||||
* type: string; values: "default", "blue" or a url to an external css file
|
||||
* Actions:
|
||||
* status.page - returns the status page to the client
|
||||
* status.show - returns the status page to the client
|
||||
* status.show_runtime - returns the runtime info page to the client
|
||||
*
|
||||
* Example config:
|
||||
* req.path == "/status" {
|
||||
* req.path == "/srv-status" {
|
||||
* status.css = "http://mydomain/status.css";
|
||||
* status.page;
|
||||
* if req.query == "runtime" {
|
||||
* status.show_runtime;
|
||||
* } else {
|
||||
* status.show;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Todo:
|
||||
* - handle race condition when connection is gone while collecting data (needs per connection plugin data)
|
||||
* - add querystring parameters like refresh=X and format=plain
|
||||
*
|
||||
* Author:
|
||||
* Copyright (c) 2008 Thomas Porzelt
|
||||
|
@ -112,6 +117,56 @@ static const gchar html_connections_row[] =
|
|||
" <td>%s</td>\n"
|
||||
" </tr>\n";
|
||||
|
||||
|
||||
static const gchar html_server_info[] =
|
||||
" <table cellspacing=\"0\">\n"
|
||||
" <tr>\n"
|
||||
" <td class=\"left\" style=\"width: 100px;\">Hostname</td>\n"
|
||||
" <td class=\"left\">%s</td>\n"
|
||||
" </tr>\n"
|
||||
" <tr>\n"
|
||||
" <td class=\"left\">User</td>\n"
|
||||
" <td class=\"left\">%s (%u)</td>\n"
|
||||
" </tr>\n"
|
||||
" <td class=\"left\">Event handler</td>\n"
|
||||
" <td class=\"left\">%s</td>\n"
|
||||
" </table>\n";
|
||||
static const gchar html_libinfo_th[] =
|
||||
" <table cellspacing=\"0\">\n"
|
||||
" <tr>\n"
|
||||
" <th style=\"width: 100px;\"></th>\n"
|
||||
" <th style=\"width: 100px;\">linked</th>\n"
|
||||
" <th style=\"width: 100px;\">headers</th>\n"
|
||||
" </tr>\n";
|
||||
static const gchar html_libinfo_row[] =
|
||||
" <tr>\n"
|
||||
" <td class=\"left\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" </tr>\n";
|
||||
static const gchar html_libev_th[] =
|
||||
" <table cellspacing=\"0\">\n"
|
||||
" <tr>\n"
|
||||
" <th style=\"width: 100px;\"></th>\n"
|
||||
" <th style=\"width: 100px;\">select</th>\n"
|
||||
" <th style=\"width: 100px;\">poll</th>\n"
|
||||
" <th style=\"width: 100px;\">epoll</th>\n"
|
||||
" <th style=\"width: 100px;\">kqueue</th>\n"
|
||||
" <th style=\"width: 100px;\">/dev/poll</th>\n"
|
||||
" <th style=\"width: 125px;\">solaris event port</th>\n"
|
||||
" </tr>\n";
|
||||
static const gchar html_libev_row[] =
|
||||
" <tr>\n"
|
||||
" <td class=\"left\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" <td style=\"text-align: center;\">%s</td>\n"
|
||||
" </tr>\n";
|
||||
|
||||
|
||||
static const gchar css_default[] =
|
||||
" <style type=\"text/css\">\n"
|
||||
" body { margin: 0; padding: 0; font-family: \"lucida grande\",tahoma,verdana,arial,sans-serif; font-size: 12px; }\n"
|
||||
|
@ -554,7 +609,7 @@ static void status_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *result
|
|||
}
|
||||
}
|
||||
|
||||
static liHandlerResult status_page_handle(liVRequest *vr, gpointer param, gpointer *context) {
|
||||
static liHandlerResult status_show(liVRequest *vr, gpointer param, gpointer *context) {
|
||||
if (li_vrequest_handle_direct(vr)) {
|
||||
liCollectInfo *ci;
|
||||
mod_status_job *j = g_slice_new(mod_status_job);
|
||||
|
@ -571,7 +626,7 @@ static liHandlerResult status_page_handle(liVRequest *vr, gpointer param, gpoint
|
|||
return (*context) ? LI_HANDLER_WAIT_FOR_EVENT : LI_HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
static liHandlerResult status_page_cleanup(liVRequest *vr, gpointer param, gpointer context) {
|
||||
static liHandlerResult status_show_cleanup(liVRequest *vr, gpointer param, gpointer context) {
|
||||
liCollectInfo *ci = (liCollectInfo*) context;
|
||||
|
||||
UNUSED(vr);
|
||||
|
@ -582,11 +637,210 @@ static liHandlerResult status_page_cleanup(liVRequest *vr, gpointer param, gpoin
|
|||
return LI_HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
static liAction* status_page(liServer *srv, liPlugin* p, liValue *val) {
|
||||
static liAction* status_show_create(liServer *srv, liPlugin* p, liValue *val) {
|
||||
UNUSED(srv);
|
||||
UNUSED(val);
|
||||
|
||||
return li_action_new_function(status_page_handle, status_page_cleanup, NULL, p);
|
||||
return li_action_new_function(status_show, status_show_cleanup, NULL, p);
|
||||
}
|
||||
|
||||
static gint str_comp(gconstpointer a, gconstpointer b) {
|
||||
return strcmp(*(const gchar**)a, *(const gchar**)b);
|
||||
}
|
||||
|
||||
static liHandlerResult status_show_runtime(liVRequest *vr, gpointer param, gpointer *context) {
|
||||
GString *html;
|
||||
liPlugin* p = param;
|
||||
GString* css = _OPTION(vr, p, 0).string;
|
||||
|
||||
UNUSED(context);
|
||||
|
||||
if (!li_vrequest_handle_direct(vr))
|
||||
return LI_HANDLER_ERROR;
|
||||
|
||||
html = g_string_sized_new(2047);
|
||||
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(header));
|
||||
|
||||
if (!css || !css->len) /* default css */
|
||||
g_string_append_len(html, CONST_STR_LEN(css_default));
|
||||
else if (g_str_equal(css->str, "blue")) /* blue css */
|
||||
g_string_append_len(html, CONST_STR_LEN(css_blue));
|
||||
else /* external css */
|
||||
g_string_append_printf(html, " <link rel=\"stylesheet\" rev=\"stylesheet\" href=\"%s\" media=\"screen\" />\n", css->str);
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
));
|
||||
|
||||
li_counter_format((guint64)(CUR_TS(vr->wrk) - vr->wrk->srv->started), COUNTER_TIME, vr->wrk->tmp_str);
|
||||
g_string_append_printf(html, html_top,
|
||||
vr->request.uri.host->str,
|
||||
vr->wrk->tmp_str->str,
|
||||
vr->wrk->srv->started_str->str
|
||||
);
|
||||
|
||||
|
||||
/* general info */
|
||||
{
|
||||
g_string_append_len(html, CONST_STR_LEN(" <div class=\"title\"><strong>Server info</strong></div>\n"));
|
||||
g_string_append_printf(html, html_server_info,
|
||||
g_get_host_name(), g_get_user_name(), getuid(), li_ev_backend_string(ev_backend(vr->wrk->loop))
|
||||
);
|
||||
}
|
||||
|
||||
/* library info */
|
||||
{
|
||||
GString *tmp_str = g_string_sized_new(31);
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" <div class=\"title\"><strong>Libraries</strong></div>\n"));
|
||||
g_string_append_len(html, CONST_STR_LEN(html_libinfo_th));
|
||||
|
||||
g_string_truncate(tmp_str, 0);
|
||||
g_string_append_printf(tmp_str, "%u.%u.%u", glib_major_version, glib_minor_version, glib_micro_version);
|
||||
g_string_truncate(vr->wrk->tmp_str, 0);
|
||||
g_string_append_printf(vr->wrk->tmp_str, "%u.%u.%u", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
|
||||
|
||||
g_string_append_printf(html, html_libinfo_row, "GLib",
|
||||
tmp_str->str,
|
||||
vr->wrk->tmp_str->str
|
||||
);
|
||||
|
||||
g_string_truncate(tmp_str, 0);
|
||||
g_string_append_printf(tmp_str, "%u.%u", ev_version_major(), ev_version_minor());
|
||||
g_string_truncate(vr->wrk->tmp_str, 0);
|
||||
g_string_append_printf(vr->wrk->tmp_str, "%u.%u", EV_VERSION_MAJOR, EV_VERSION_MINOR);
|
||||
|
||||
g_string_append_printf(html, html_libinfo_row, "libev",
|
||||
tmp_str->str,
|
||||
vr->wrk->tmp_str->str
|
||||
);
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" </table>\n"));
|
||||
g_string_free(tmp_str, TRUE);
|
||||
}
|
||||
|
||||
/* libev info */
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" <div class=\"title\"><strong>libev backends</strong></div>\n"));
|
||||
g_string_append_len(html, CONST_STR_LEN(html_libev_th));
|
||||
|
||||
/* supported backend, aka compiled in */
|
||||
i = ev_supported_backends();
|
||||
g_string_append_printf(html, html_libev_row, "supported",
|
||||
i & EVBACKEND_SELECT ? "yes" : "no",
|
||||
i & EVBACKEND_POLL ? "yes" : "no",
|
||||
i & EVBACKEND_EPOLL ? "yes" : "no",
|
||||
i & EVBACKEND_KQUEUE ? "yes" : "no",
|
||||
i & EVBACKEND_DEVPOLL ? "yes" : "no",
|
||||
i & EVBACKEND_PORT ? "yes" : "no"
|
||||
);
|
||||
|
||||
/* recommended backends */
|
||||
i = ev_recommended_backends();
|
||||
g_string_append_printf(html, html_libev_row, "recommended",
|
||||
i & EVBACKEND_SELECT ? "yes" : "no",
|
||||
i & EVBACKEND_POLL ? "yes" : "no",
|
||||
i & EVBACKEND_EPOLL ? "yes" : "no",
|
||||
i & EVBACKEND_KQUEUE ? "yes" : "no",
|
||||
i & EVBACKEND_DEVPOLL ? "yes" : "no",
|
||||
i & EVBACKEND_PORT ? "yes" : "no"
|
||||
);
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" </table>\n"));
|
||||
}
|
||||
|
||||
/* list modules */
|
||||
{
|
||||
guint i, col;
|
||||
gpointer k, v;
|
||||
GHashTableIter iter;
|
||||
GArray *list = g_array_sized_new(FALSE, FALSE, sizeof(gchar*), g_hash_table_size(vr->wrk->srv->plugins));
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" <div class=\"title\"><strong>Loaded modules</strong></div>\n"));
|
||||
g_string_append_len(html, CONST_STR_LEN(" <table cellspacing=\"0\">\n"));
|
||||
|
||||
g_hash_table_iter_init(&iter, vr->wrk->srv->plugins);
|
||||
|
||||
while (g_hash_table_iter_next(&iter, &k, &v))
|
||||
g_array_append_val(list, k);
|
||||
|
||||
g_array_sort(list, str_comp);
|
||||
|
||||
col = 0;
|
||||
|
||||
for (i = 1; i < list->len; i++) {
|
||||
if (col == 0) {
|
||||
g_string_append_len(html, CONST_STR_LEN(" <tr>\n"));
|
||||
col++;
|
||||
}
|
||||
else if (col == 5) {
|
||||
g_string_append_len(html, CONST_STR_LEN(" </tr>\n"));
|
||||
col = 0;
|
||||
continue;
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
|
||||
g_string_append_printf(html, " <td class=\"left\">%s</td>\n", g_array_index(list, gchar*, i));
|
||||
}
|
||||
|
||||
if (col) {
|
||||
for (i = 5 - col; i; i--)
|
||||
g_string_append_len(html, CONST_STR_LEN(" <td></td>\n"));
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" </tr>\n"));
|
||||
}
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" </table>\n"));
|
||||
|
||||
g_array_free(list, TRUE);
|
||||
}
|
||||
|
||||
/* list environment vars */
|
||||
{
|
||||
gchar **e;
|
||||
gchar **env = g_listenv();
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" <div class=\"title\"><strong>Process environment</strong></div>\n"));
|
||||
g_string_append_len(html, CONST_STR_LEN(" <table cellspacing=\"0\">\n"));
|
||||
|
||||
for (e = env; *e; e++) {
|
||||
g_string_append_printf(html, " <tr><td class=\"left\">%s</td><td class=\"left\">%s</td></tr>\n", *e, getenv(*e));
|
||||
}
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(" </table>\n"));
|
||||
|
||||
g_strfreev(env);
|
||||
}
|
||||
|
||||
g_string_append_len(html, CONST_STR_LEN(
|
||||
" </body>\n"
|
||||
"</html>\n"
|
||||
));
|
||||
|
||||
li_chunkqueue_append_string(vr->out, html);
|
||||
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
|
||||
|
||||
vr->response.http_status = 200;
|
||||
|
||||
return LI_HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
static liAction* status_show_runtime_create(liServer *srv, liPlugin* p, liValue *val) {
|
||||
|
||||
UNUSED(srv);
|
||||
|
||||
if (val) {
|
||||
ERROR(srv, "%s", "status.show_runtime expects no parameter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return li_action_new_function(status_show_runtime, NULL, NULL, p);
|
||||
}
|
||||
|
||||
|
||||
|
@ -598,7 +852,8 @@ static const liPluginOption options[] = {
|
|||
};
|
||||
|
||||
static const liPluginAction actions[] = {
|
||||
{ "status.page", status_page },
|
||||
{ "status.show", status_show_create },
|
||||
{ "status.show_runtime", status_show_runtime_create },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue