From 5f3a9c0a72e08f669e47b8109a2c815db5e50cb0 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 26 May 2019 12:57:41 -0700 Subject: [PATCH] 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(-) create mode 100644 src/libsysprof-ui/sysprof-logs-view.c create mode 100644 src/libsysprof-ui/sysprof-logs-view.h create mode 100644 src/libsysprof-ui/ui/sysprof-logs-view.ui diff --git a/src/libsysprof-ui/libsysprof-ui.gresource.xml b/src/libsysprof-ui/libsysprof-ui.gresource.xml index c3e80a0a..53f245c9 100644 --- a/src/libsysprof-ui/libsysprof-ui.gresource.xml +++ b/src/libsysprof-ui/libsysprof-ui.gresource.xml @@ -19,6 +19,7 @@ ui/sysprof-empty-state-view.ui ui/sysprof-environ-editor-row.ui ui/sysprof-failed-state-view.ui + ui/sysprof-logs-view.ui ui/sysprof-marks-view.ui ui/sysprof-process-model-row.ui ui/sysprof-profiler-assistant.ui diff --git a/src/libsysprof-ui/meson.build b/src/libsysprof-ui/meson.build index 5ec95baf..37d8663c 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 70332ffd..74ae83d6 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 3726f911..d5abfedf 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 +#include #include #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 cd8e8652..7edb25fa 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 00000000..23b3d006 --- /dev/null +++ b/src/libsysprof-ui/sysprof-logs-view.c @@ -0,0 +1,60 @@ +/* sysprof-logs-view.c + * + * Copyright 2019 Christian Hergert + * + * 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 . + * + * 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 00000000..11dec75d --- /dev/null +++ b/src/libsysprof-ui/sysprof-logs-view.h @@ -0,0 +1,36 @@ +/* sysprof-logs-view.h + * + * Copyright 2019 Christian Hergert + * + * 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +#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 8159cffd..ef0555bd 100644 --- a/src/libsysprof-ui/ui/sysprof-capture-view.ui +++ b/src/libsysprof-ui/ui/sysprof-capture-view.ui @@ -153,6 +153,16 @@ counters + + + true + + + + _Logs + logs + + true 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 00000000..837d3829 --- /dev/null +++ b/src/libsysprof-ui/ui/sysprof-logs-view.ui @@ -0,0 +1,74 @@ + + + +