[gnome-talos] Initial attempt at generating HTML report
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-talos] Initial attempt at generating HTML report
- Date: Sun, 25 Sep 2011 23:08:20 +0000 (UTC)
commit 60bf12b7bcb6bc193513a6a9b0d536aaf2bb6919
Author: Colin Walters <walters verbum org>
Date: Sun Sep 25 18:24:57 2011 -0400
Initial attempt at generating HTML report
Makefile-src.am | 9 +++-
configure.ac | 23 +++++++
src/gnome-talos.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++------
src/report.html | 69 ++++++++++++++++++++
4 files changed, 257 insertions(+), 22 deletions(-)
---
diff --git a/Makefile-src.am b/Makefile-src.am
index 0477e82..9672d63 100644
--- a/Makefile-src.am
+++ b/Makefile-src.am
@@ -14,6 +14,13 @@ gnome_talos_SOURCES = src/gnome-talos.c \
src/gnome-talos-procinfo.h \
src/gnome-talos-meta.c \
src/gnome-talos-meta.h
-gnome_talos_CPPFLAGS = $(GNOME_TALOS_CFLAGS)
+gnome_talos_CPPFLAGS = $(GNOME_TALOS_CFLAGS) -I $(top_srcdir) -I $(top_builddir)
gnome_talos_LDADD = $(GNOME_TALOS_LIBS)
+report.html.h: src/report.html Makefile
+ echo -n "#define REPORT_HTML " > $ tmp && \
+ sed -e s,\\\\,\\\\\\\\,g < $< | sed -e s,\",\\\\\",g | sed -e s,^,\",g -e s,\$$,\\\\n\"\\\\,g >> $ tmp && \
+ echo "" >> $ tmp && mv $ tmp $@
+BUILT_SOURCES += report.html.h
+
+EXTRA_DIST += src/report.html
diff --git a/configure.ac b/configure.ac
index 8fb8ccd..6474c6c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,29 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_PROG_CC
AM_PROG_CC_C_O
+AC_ARG_WITH(jquery,
+ [AC_HELP_STRING([--with-jquery=@<:@path@:>@],
+ [path to jquery library])])
+if test x"$with_jquery" = x; then
+ if test -f "${srcdir}/jquery.js"; then
+ with_jquery=${srcdir}/jquery.js
+ else
+ AC_MSG_ERROR([--with-jquery must be specified])
+ fi
+fi
+AC_DEFINE_UNQUOTED([JQUERY_PATH], "$with_jquery", [Path to jquery])
+AC_ARG_WITH(jquery-flot,
+ [AC_HELP_STRING([--with-jquery-flot=@<:@path@:>@],
+ [path to jquery flot library])])
+if test x"$with_jquery_flot" = x; then
+ if test -f "${srcdir}/jquery.flot.js"; then
+ with_jquery_flot=${srcdir}/jquery.flot.js
+ else
+ AC_MSG_ERROR([--with-jquery-flot must be specified])
+ fi
+fi
+AC_DEFINE_UNQUOTED([JQUERY_FLOT_PATH], "$with_jquery_flot", [Path to jquery flot])
+
AC_PATH_PROG(GIT, [git])
GIT_VERSION=
if test x$GIT != x && test -d ${srcdir}/.git; then
diff --git a/src/gnome-talos.c b/src/gnome-talos.c
index c08168e..d3667a9 100644
--- a/src/gnome-talos.c
+++ b/src/gnome-talos.c
@@ -21,6 +21,7 @@
#include "config.h"
+#include <glib-unix.h>
#include <gio/gio.h>
#include <json-glib/json-glib.h>
@@ -29,8 +30,23 @@
#include "gnome-talos-procinfo.h"
#include "gnome-talos-meta.h"
+#include "report.html.h"
+
+static void
+fatal_gerror (GError **error) G_GNUC_NORETURN;
+
+static void
+fatal_gerror (GError **error)
+{
+ g_assert (*error != NULL);
+ g_printerr ("%s\n", (*error)->message);
+
+ exit (1);
+}
+
static gint timeout = 5;
-static char *log_file = NULL;
+static char *log_file_path = NULL;
+static char *to_html_file_path = NULL;
GVariant *
gather_snapshot (void)
@@ -94,7 +110,7 @@ write_variant (GVariant *variant,
}
typedef struct {
- GFile *out_path;
+ GFile *log_file;
GFileOutputStream *out;
GMainLoop *loop;
} GnomeTalosApp;
@@ -104,9 +120,11 @@ timeout_gather_data (gpointer user_data)
{
GnomeTalosApp *app = user_data;
GVariant *snapshot;
+ GError *error = NULL;
snapshot = gather_snapshot ();
- write_variant (snapshot, NULL, (GOutputStream*)app->out, NULL);
+ if (!write_variant (snapshot, NULL, (GOutputStream*)app->out, &error))
+ fatal_gerror (&error);
g_variant_unref (snapshot);
if (timeout > 0)
@@ -117,17 +135,145 @@ timeout_gather_data (gpointer user_data)
return FALSE;
}
+static gboolean
+on_interrupt_received (gpointer user_data)
+{
+ GnomeTalosApp *app = user_data;
+ GError *error = NULL;
+
+ if (!g_output_stream_write_all ((GOutputStream*)app->out,
+ "]", 1, NULL, NULL, &error))
+ fatal_gerror (&error);
+
+ if (!g_output_stream_close ((GOutputStream*)app->out, NULL, &error))
+ fatal_gerror (&error);
+
+ g_main_loop_quit (app->loop);
+}
+
+static void
+run_collection (GnomeTalosApp *app)
+{
+ GError *error = NULL;
+ GVariant *sysinfo;
+
+ g_unix_signal_add (SIGINT,
+ on_interrupt_received,
+ &app);
+ g_unix_signal_add (SIGTERM,
+ on_interrupt_received,
+ &app);
+
+ app->out = g_file_replace (app->log_file, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION,
+ NULL, &error);
+ if (app->out == NULL)
+ fatal_gerror (&error);
+
+ if (!g_output_stream_write_all ((GOutputStream*)app->out,
+ "[", 1, NULL, NULL, &error))
+ fatal_gerror (&error);
+
+ sysinfo = gnome_talos_acquire_meta ();
+ if (!write_variant (sysinfo, NULL, (GOutputStream*)app->out, &error))
+ fatal_gerror (&error);
+ g_variant_unref (sysinfo);
+
+ if (!g_output_stream_write_all ((GOutputStream*)app->out,
+ ",\n", 2, NULL, NULL, &error))
+ fatal_gerror (&error);
+
+ g_idle_add (timeout_gather_data, &app);
+}
+
+static char *
+replace_key (char *buf,
+ const char *key,
+ const char *value)
+{
+ GRegex *regex;
+ char *escaped_key;
+ char *key_regex;
+ char *new_buf;
+
+ escaped_key = g_regex_escape_string (key, -1);
+ key_regex = g_strconcat ("@", escaped_key, "@", NULL);
+ g_free (escaped_key);
+
+ regex = g_regex_new (key_regex, 0, 0, NULL);
+ g_assert (regex != NULL);
+
+ new_buf = g_regex_replace (regex, buf, -1, 0, value, 0, NULL);
+ g_free (buf);
+
+ g_regex_unref (regex);
+
+ return new_buf;
+}
+
+static void
+convert_to_html (GnomeTalosApp *app)
+{
+ GError *error = NULL;
+ JsonParser *parser;
+ JsonGenerator *generator;
+ JsonNode *root;
+ GFile *to_html_file;
+ GFileOutputStream *out;
+ char *data_string;
+ char *buf;
+ GRegex *regex;
+
+ parser = json_parser_new ();
+
+ if (!json_parser_load_from_file (parser, log_file_path, &error))
+ fatal_gerror (&error);
+
+ root = json_parser_get_root (parser);
+
+ to_html_file = g_file_new_for_path (to_html_file_path);
+
+ if ((out = g_file_replace (to_html_file, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION,
+ NULL, &error)) == NULL)
+ fatal_gerror (&error);
+
+ generator = json_generator_new ();
+ json_generator_set_pretty (generator, TRUE);
+ json_generator_set_root (generator, root);
+ data_string = json_generator_to_data (generator, NULL);
+ g_object_unref (generator);
+ json_node_free (root);
+
+ buf = g_strdup (REPORT_HTML);
+ buf = replace_key (buf, "SRC_FILE", log_file_path);
+ buf = replace_key (buf, "JQUERY_PATH", JQUERY_PATH);
+ buf = replace_key (buf, "JQUERY_FLOT_PATH", JQUERY_FLOT_PATH);
+ buf = replace_key (buf, "DATA", data_string);
+ g_free (data_string);
+
+ if (!g_output_stream_write_all ((GOutputStream*)out,
+ buf, strlen (buf), NULL, NULL, &error))
+ fatal_gerror (&error);
+ g_free (buf);
+
+ if (!g_output_stream_close ((GOutputStream*)out, NULL, &error))
+ fatal_gerror (&error);
+
+ g_idle_add ((GSourceFunc)g_main_loop_quit, app->loop);
+}
+
int
main (int argc,
char **argv)
{
GnomeTalosApp app;
- GVariant *sysinfo;
GError *error = NULL;
GOptionContext *context;
static const GOptionEntry options[] = {
{ "timeout", 0, 0, G_OPTION_ARG_INT, &timeout, "Time between data snapshots, in seconds (default=5)", "seconds" },
- { "log-file", 0, 0, G_OPTION_ARG_FILENAME, &log_file, "Log file path", "path" },
+ { "log-file", 0, 0, G_OPTION_ARG_FILENAME, &log_file_path, "Log file path", "path" },
+ { "to-html-file", 0, 0, G_OPTION_ARG_FILENAME, &to_html_file_path, "Convert log file to HTML", "path" },
{ NULL }
};
@@ -142,29 +288,19 @@ main (int argc,
g_printerr ("%s\n", error->message);
return 1;
}
- if (log_file == NULL)
+ if (log_file_path == NULL)
{
g_printerr ("--log-file is required\n");
return 1;
}
- app.out_path = g_file_new_for_path (log_file);
- app.out = g_file_replace (app.out_path, NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION,
- NULL, &error);
- if (app.out == NULL)
- {
- g_printerr ("%s\n", error->message);
- return 1;
- }
-
- sysinfo = gnome_talos_acquire_meta ();
- write_variant (sysinfo, NULL, (GOutputStream*)app.out, NULL);
- g_variant_unref (sysinfo);
-
app.loop = g_main_loop_new (NULL, TRUE);
+ app.log_file = g_file_new_for_path (log_file_path);
- g_idle_add (timeout_gather_data, &app);
+ if (to_html_file_path == NULL)
+ run_collection (&app);
+ else
+ convert_to_html (&app);
g_main_loop_run (app.loop);
diff --git a/src/report.html b/src/report.html
new file mode 100644
index 0000000..fe66885
--- /dev/null
+++ b/src/report.html
@@ -0,0 +1,69 @@
+<!-- -*- mode: HTML -*-; indent-tabs-mode: nil; tab-width: 2 -*- -->
+<!-- Copyright (C) 2011 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Author: Colin Walters <walters verbum org>
+-->
+
+<html>
+ <head>
+ <title>Report for @SRC_FILE@</title>
+ <script type="text/javascript" src="@JQUERY_PATH@"></script>
+ <script type="text/javascript" src="@JQUERY_FLOT_PATH@"></script>
+ <script type="text/javascript">
+ var data = @DATA@;
+
+ function getRSSForSnapshot(snapshot) {
+ var meta = snapshot[0];
+ var processes = snapshot[1].processes[0];
+ var system = 0;
+ var user = 0;
+
+ for (var pid in processes) {
+ var process = processes[pid];
+ var real_uid = process['real-uid'];
+ if (real_uid >= 500)
+ system += process['rss'];
+ else
+ user += process['rss'];
+ }
+
+ return [system, user];
+ }
+
+ $(document).ready(function () {
+ $("#system-uuid")[0].appendChild(document.createTextNode(data[0].uuid));
+ $("#system-ram")[0].appendChild(document.createTextNode(data[0].memtotal));
+
+ var systemRSS = [];
+ var userRSS = [];
+ for (var i = 1; i < data.length; i++) {
+ var rssData = getRSSForSnapshot(data[i]);
+ systemRSS.push([i, rssData[0]]);
+ userRSS.push([i, rssData[1]]);
+ }
+ $.plot($("#rss-graph"), [ systemRSS, userRSS ]);
+ });
+ </script>
+ </head>
+ <body>
+ <h1>Report for @SRC_FILE@:</h1>
+ <p><tt>System UUID: <span id="system-uuid"></span></tt></p>
+ <p><tt>System Total RAM: <span id="system-ram"></span></tt></p>
+ <div id="rss-graph" style="width:800px;height:500px;"></div>
+ </body>
+</html>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]