[sysprof/wip/chergert/sysprof-3] libsysprof-ui: add log view



commit ab31662843025c7bea45dece63f2b2f72b736ef3
Author: Christian Hergert <chergert redhat com>
Date:   Sun May 26 12:57:41 2019 -0700

    libsysprof-ui: add log view

 src/libsysprof-ui/libsysprof-ui.gresource.xml |  1 +
 src/libsysprof-ui/meson.build                 |  1 +
 src/libsysprof-ui/sysprof-capture-view.c      | 54 +++++++++++++++++++
 src/libsysprof-ui/sysprof-log-model.c         | 52 +++++++++++++++++--
 src/libsysprof-ui/sysprof-log-model.h         |  1 +
 src/libsysprof-ui/sysprof-logs-view.c         | 60 ++++++++++++++++++++++
 src/libsysprof-ui/sysprof-logs-view.h         | 36 +++++++++++++
 src/libsysprof-ui/ui/sysprof-capture-view.ui  | 10 ++++
 src/libsysprof-ui/ui/sysprof-logs-view.ui     | 74 +++++++++++++++++++++++++++
 9 files changed, 285 insertions(+), 4 deletions(-)
---
diff --git a/src/libsysprof-ui/libsysprof-ui.gresource.xml b/src/libsysprof-ui/libsysprof-ui.gresource.xml
index c3e80a0..53f245c 100644
--- a/src/libsysprof-ui/libsysprof-ui.gresource.xml
+++ b/src/libsysprof-ui/libsysprof-ui.gresource.xml
@@ -19,6 +19,7 @@
     <file preprocess="xml-stripblanks">ui/sysprof-empty-state-view.ui</file>
     <file preprocess="xml-stripblanks">ui/sysprof-environ-editor-row.ui</file>
     <file preprocess="xml-stripblanks">ui/sysprof-failed-state-view.ui</file>
+    <file preprocess="xml-stripblanks">ui/sysprof-logs-view.ui</file>
     <file preprocess="xml-stripblanks">ui/sysprof-marks-view.ui</file>
     <file preprocess="xml-stripblanks">ui/sysprof-process-model-row.ui</file>
     <file preprocess="xml-stripblanks">ui/sysprof-profiler-assistant.ui</file>
diff --git a/src/libsysprof-ui/meson.build b/src/libsysprof-ui/meson.build
index 5ec95ba..37d8663 100644
--- a/src/libsysprof-ui/meson.build
+++ b/src/libsysprof-ui/meson.build
@@ -42,6 +42,7 @@ libsysprof_ui_private_sources = [
   'sysprof-environ-variable.c',
   'sysprof-environ.c',
   'sysprof-log-model.c',
+  'sysprof-logs-view.c',
   'sysprof-tab.c',
   'sysprof-time-label.c',
   'sysprof-theme-manager.c',
diff --git a/src/libsysprof-ui/sysprof-capture-view.c b/src/libsysprof-ui/sysprof-capture-view.c
index 70332ff..74ae83d 100644
--- a/src/libsysprof-ui/sysprof-capture-view.c
+++ b/src/libsysprof-ui/sysprof-capture-view.c
@@ -28,6 +28,7 @@
 #include "sysprof-callgraph-view.h"
 #include "sysprof-capture-view.h"
 #include "sysprof-details-view.h"
+#include "sysprof-logs-view.h"
 #include "sysprof-marks-view.h"
 #include "sysprof-ui-private.h"
 #include "sysprof-visualizer-view.h"
@@ -41,6 +42,7 @@ typedef struct
   guint has_samples : 1;
   guint has_counters : 1;
   guint has_forks : 1;
+  guint has_logs : 1;
   guint has_marks : 1;
   guint can_replay : 1;
 } SysprofCaptureFeatures;
@@ -58,6 +60,7 @@ typedef struct
   GtkStack               *stack;
   SysprofCallgraphView   *callgraph_view;
   SysprofDetailsView     *details_view;
+  SysprofLogsView        *logs_view;
   SysprofMarksView       *counters_view;
   SysprofMarksView       *marks_view;
   SysprofVisualizerView  *visualizer_view;
@@ -387,6 +390,11 @@ sysprof_capture_view_scan_worker (GTask        *task,
           features.has_counters = TRUE;
           sysprof_capture_reader_skip (reader);
         }
+      else if (frame.type == SYSPROF_CAPTURE_FRAME_LOG)
+        {
+          features.has_logs = TRUE;
+          sysprof_capture_reader_skip (reader);
+        }
       else if (frame.type == SYSPROF_CAPTURE_FRAME_SAMPLE)
         {
           features.has_samples = TRUE;
@@ -567,6 +575,38 @@ sysprof_capture_view_load_callgraph_cb (GObject      *object,
     g_task_return_boolean (task, TRUE);
 }
 
+static void
+sysprof_capture_view_load_logs_cb (GObject      *object,
+                                   GAsyncResult *result,
+                                   gpointer      user_data)
+{
+  g_autoptr(SysprofLogModel) model = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autoptr(GTask) task = user_data;
+  LoadAsync *state;
+
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  state = g_task_get_task_data (task);
+  g_assert (state != NULL);
+  g_assert (state->reader != NULL);
+  g_assert (state->n_active > 0);
+
+  if ((model = sysprof_log_model_new_finish (result, &error)))
+    {
+      SysprofCaptureView *self = g_task_get_source_object (task);
+      SysprofCaptureViewPrivate *priv = sysprof_capture_view_get_instance_private (self);
+
+      sysprof_logs_view_set_model (priv->logs_view, model);
+    }
+
+  state->n_active--;
+
+  if (state->n_active == 0)
+    g_task_return_boolean (task, TRUE);
+}
+
 static void
 sysprof_capture_view_load_scan_cb (GObject      *object,
                                    GAsyncResult *result,
@@ -603,6 +643,16 @@ sysprof_capture_view_load_scan_cb (GObject      *object,
                                                      g_object_ref (task));
     }
 
+  if (priv->features.has_logs)
+    {
+      state->n_active++;
+      sysprof_log_model_new_async (state->reader,
+                                   state->selection,
+                                   g_task_get_cancellable (task),
+                                   sysprof_capture_view_load_logs_cb,
+                                   g_object_ref (task));
+    }
+
   sysprof_visualizer_view_set_reader (priv->visualizer_view, state->reader);
 
   if (priv->features.has_counters)
@@ -815,6 +865,7 @@ sysprof_capture_view_class_init (SysprofCaptureViewClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, callgraph_view);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, details_view);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, counters_view);
+  gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, logs_view);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, marks_view);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, stack);
   gtk_widget_class_bind_template_child_private (widget_class, SysprofCaptureView, stack_switcher);
@@ -833,6 +884,9 @@ sysprof_capture_view_class_init (SysprofCaptureViewClass *klass)
 
   g_type_ensure (DZL_TYPE_MULTI_PANED);
   g_type_ensure (SYSPROF_TYPE_DETAILS_VIEW);
+  g_type_ensure (SYSPROF_TYPE_LOGS_VIEW);
+  g_type_ensure (SYSPROF_TYPE_MARKS_VIEW);
+  g_type_ensure (SYSPROF_TYPE_CALLGRAPH_VIEW);
 }
 
 static void
diff --git a/src/libsysprof-ui/sysprof-log-model.c b/src/libsysprof-ui/sysprof-log-model.c
index 3726f91..d5abfed 100644
--- a/src/libsysprof-ui/sysprof-log-model.c
+++ b/src/libsysprof-ui/sysprof-log-model.c
@@ -23,15 +23,19 @@
 #include "config.h"
 
 #include <gtk/gtk.h>
+#include <glib/gi18n.h>
 #include <string.h>
 
 #include "sysprof-log-model.h"
 
+#define NSEC_PER_SEC (G_USEC_PER_SEC * 1000L)
+
 struct _SysprofLogModel
 {
   GObject       parent_instance;
   GStringChunk *chunks;
   GArray       *items;
+  gint64        begin_time;
 };
 
 typedef struct
@@ -58,10 +62,9 @@ sysprof_log_model_get_column_type (GtkTreeModel *model,
       return G_TYPE_INT64;
 
     case SYSPROF_LOG_MODEL_COLUMN_SEVERITY:
-      return G_TYPE_UINT;
-
     case SYSPROF_LOG_MODEL_COLUMN_DOMAIN:
     case SYSPROF_LOG_MODEL_COLUMN_MESSAGE:
+    case SYSPROF_LOG_MODEL_COLUMN_TIME_STRING:
       return G_TYPE_STRING;
 
     default:
@@ -183,14 +186,50 @@ sysprof_log_model_get_value (GtkTreeModel *model,
 
   switch (column)
     {
+    case SYSPROF_LOG_MODEL_COLUMN_TIME_STRING:
+      {
+        gint64 offset = item->time - self->begin_time;
+        gint min = offset / (NSEC_PER_SEC * 60L);
+        gint seconds = (offset - (min * NSEC_PER_SEC)) / NSEC_PER_SEC;
+        gint msec = (offset % NSEC_PER_SEC) / (NSEC_PER_SEC / 1000L);
+
+        g_value_init (value, G_TYPE_STRING);
+        g_value_take_string (value,
+                             g_strdup_printf ("%02d:%02d.%03d", min, seconds, msec));
+      }
+      break;
+
     case SYSPROF_LOG_MODEL_COLUMN_TIME:
       g_value_init (value, G_TYPE_INT64);
       g_value_set_int64 (value, item->time);
       break;
 
     case SYSPROF_LOG_MODEL_COLUMN_SEVERITY:
-      g_value_init (value, G_TYPE_UINT);
-      g_value_set_uint (value, item->severity);
+      g_value_init (value, G_TYPE_STRING);
+      switch (item->severity)
+        {
+        case G_LOG_LEVEL_MESSAGE:
+          g_value_set_static_string (value, _("Message"));
+          break;
+        case G_LOG_LEVEL_INFO:
+          g_value_set_static_string (value, _("Info"));
+          break;
+        case G_LOG_LEVEL_CRITICAL:
+          g_value_set_static_string (value, _("Critical"));
+          break;
+        case G_LOG_LEVEL_ERROR:
+          g_value_set_static_string (value, _("Error"));
+          break;
+        case G_LOG_LEVEL_DEBUG:
+          g_value_set_static_string (value, _("Debug"));
+          break;
+        case G_LOG_LEVEL_WARNING:
+          g_value_set_static_string (value, _("Warning"));
+          break;
+        default:
+          g_value_set_static_string (value, "");
+          break;
+        }
       break;
 
     case SYSPROF_LOG_MODEL_COLUMN_DOMAIN:
@@ -296,11 +335,16 @@ sysprof_log_model_new_worker (GTask        *task,
 {
   g_autoptr(SysprofLogModel) self = NULL;
   SysprofCaptureCursor *cursor = task_data;
+  SysprofCaptureReader *reader;
 
   g_assert (G_IS_TASK (task));
   g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
 
   self = g_object_new (SYSPROF_TYPE_LOG_MODEL, NULL);
+
+  reader = sysprof_capture_cursor_get_reader (cursor);
+  self->begin_time = sysprof_capture_reader_get_start_time (reader);
+
   sysprof_capture_cursor_foreach (cursor, cursor_foreach_cb, self);
   g_array_sort (self->items, item_compare);
 
diff --git a/src/libsysprof-ui/sysprof-log-model.h b/src/libsysprof-ui/sysprof-log-model.h
index cd8e865..7edb25f 100644
--- a/src/libsysprof-ui/sysprof-log-model.h
+++ b/src/libsysprof-ui/sysprof-log-model.h
@@ -30,6 +30,7 @@ typedef enum
   SYSPROF_LOG_MODEL_COLUMN_SEVERITY,
   SYSPROF_LOG_MODEL_COLUMN_DOMAIN,
   SYSPROF_LOG_MODEL_COLUMN_MESSAGE,
+  SYSPROF_LOG_MODEL_COLUMN_TIME_STRING,
   SYSPROF_LOG_MODEL_COLUMN_LAST
 } SysprofLogModelColumn;
 
diff --git a/src/libsysprof-ui/sysprof-logs-view.c b/src/libsysprof-ui/sysprof-logs-view.c
new file mode 100644
index 0000000..23b3d00
--- /dev/null
+++ b/src/libsysprof-ui/sysprof-logs-view.c
@@ -0,0 +1,60 @@
+/* sysprof-logs-view.c
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "sysprof-logs-view"
+
+#include "config.h"
+
+#include "sysprof-log-model.h"
+#include "sysprof-logs-view.h"
+
+struct _SysprofLogsView
+{
+  GtkBin parent_instance;
+
+  GtkTreeView *tree_view;
+};
+
+G_DEFINE_TYPE (SysprofLogsView, sysprof_logs_view, GTK_TYPE_BIN)
+
+static void
+sysprof_logs_view_class_init (SysprofLogsViewClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/ui/sysprof-logs-view.ui");
+  gtk_widget_class_bind_template_child (widget_class, SysprofLogsView, tree_view);
+}
+
+static void
+sysprof_logs_view_init (SysprofLogsView *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+void
+sysprof_logs_view_set_model (SysprofLogsView *self,
+                             SysprofLogModel *model)
+{
+  g_return_if_fail (SYSPROF_IS_LOGS_VIEW (self));
+  g_return_if_fail (!model || SYSPROF_IS_LOG_MODEL (model));
+
+  gtk_tree_view_set_model (GTK_TREE_VIEW (self->tree_view), GTK_TREE_MODEL (model));
+} 
diff --git a/src/libsysprof-ui/sysprof-logs-view.h b/src/libsysprof-ui/sysprof-logs-view.h
new file mode 100644
index 0000000..11dec75
--- /dev/null
+++ b/src/libsysprof-ui/sysprof-logs-view.h
@@ -0,0 +1,36 @@
+/* sysprof-logs-view.h
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "sysprof-log-model.h"
+
+G_BEGIN_DECLS
+
+#define SYSPROF_TYPE_LOGS_VIEW (sysprof_logs_view_get_type())
+
+G_DECLARE_FINAL_TYPE (SysprofLogsView, sysprof_logs_view, SYSPROF, LOGS_VIEW, GtkBin)
+
+void sysprof_logs_view_set_model (SysprofLogsView *self,
+                                  SysprofLogModel *model);
+
+G_END_DECLS
diff --git a/src/libsysprof-ui/ui/sysprof-capture-view.ui b/src/libsysprof-ui/ui/sysprof-capture-view.ui
index 8159cff..ef0555b 100644
--- a/src/libsysprof-ui/ui/sysprof-capture-view.ui
+++ b/src/libsysprof-ui/ui/sysprof-capture-view.ui
@@ -153,6 +153,16 @@
                     <property name="name">counters</property>
                   </packing>
                 </child>
+                <child>
+                  <object class="SysprofLogsView" id="logs_view">
+                    <property name="visible">true</property>
+                  </object>
+                  <packing>
+                    <!-- translators: the _ is used to denote the accelerator key -->
+                    <property name="title" translatable="yes">_Logs</property>
+                    <property name="name">logs</property>
+                  </packing>
+                </child>
                 <child>
                   <object class="SysprofDetailsView" id="details_view">
                     <property name="visible">true</property>
diff --git a/src/libsysprof-ui/ui/sysprof-logs-view.ui b/src/libsysprof-ui/ui/sysprof-logs-view.ui
new file mode 100644
index 0000000..837d382
--- /dev/null
+++ b/src/libsysprof-ui/ui/sysprof-logs-view.ui
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="SysprofLogsView" parent="GtkBin">
+    <child>
+      <object class="GtkScrolledWindow">
+        <property name="visible">true</property>
+        <child>
+          <object class="GtkTreeView" id="tree_view">
+            <property name="headers-visible">true</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkTreeViewColumn">
+                <property name="expand">false</property>
+                <property name="title" translatable="yes">Offset</property>
+                <child>
+                  <object class="GtkCellRendererText">
+                    <property name="xalign">0.0</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">4</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn">
+                <property name="expand">false</property>
+                <property name="title" translatable="yes">Severity</property>
+                <child>
+                  <object class="GtkCellRendererText">
+                    <property name="xalign">0.0</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">1</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn">
+                <property name="expand">false</property>
+                <property name="resizable">true</property>
+                <property name="title" translatable="yes">Domain</property>
+                <child>
+                  <object class="GtkCellRendererText">
+                    <property name="xalign">0.0</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">2</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn">
+                <property name="expand">true</property>
+                <property name="title" translatable="yes">Message</property>
+                <child>
+                  <object class="GtkCellRendererText">
+                    <property name="ellipsize">end</property>
+                    <property name="xalign">0.0</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">3</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]