Merge lp:~kissiel/checkbox/touch-logging into lp:checkbox

Proposed by Maciej Kisielewski
Status: Merged
Approved by: Zygmunt Krynicki
Approved revision: 3571
Merged at revision: 3572
Proposed branch: lp:~kissiel/checkbox/touch-logging
Merge into: lp:checkbox
Diff against target: 141 lines (+116/-0)
3 files modified
checkbox-touch/components/PythonLogger.qml (+98/-0)
checkbox-touch/main.qml (+14/-0)
checkbox-touch/py/checkbox_touch.py (+4/-0)
To merge this branch: bzr merge lp:~kissiel/checkbox/touch-logging
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Approve
Review via email: mp+249036@code.launchpad.net

Description of the change

This MR brings new logging to Checkbox-Touch. This makes logging more robust and easier to manage.

536d2ef checkbox-touch: add python logger
PythonLogger component is defined that uses pyotherside to forward logging events to python logging module.

fb7207c checkbox-touch: export checkbox.touch.qml logger to qml

9ce6636 checkbox-touch: use PythonLogger in checkbox-touch
Second, PythonLogger is used in Checkbox-Touch, overriding console.log and console.error, making them send events to python logging.

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

This looks good, +1, some typos below

review: Needs Fixing
lp:~kissiel/checkbox/touch-logging updated
3569. By Maciej Kisielewski

checkbox-touch: add python logger

This patch introduces PythonLogger component that handles logging by sending it
through pyotherside to python, which in turn uses logging module to properly
record events. When this logger is created it overrides default behaviour of
console.log and console.error with python counterparts.

Signed-off-by: Maciej Kisielewski <email address hidden>

3570. By Maciej Kisielewski

checkbox-touch: export checkbox.touch.qml logger to qml

This patch makes checkbox.touch.qml logger available to QML as object compliant
to PythonObjectHandle component.

Signed-off-by: Maciej Kisielewski <email address hidden>

3571. By Maciej Kisielewski

checkbox-touch: use PythonLogger in checkbox-touch

This patch adds PythonLogger object to checkbox-touch. As console.log are now
pushed as logging.DEBUG and the logging level used is INFO, many messages
previously seen when using checkbox-touch are now silenced.

Signed-off-by: Maciej Kisielewski <email address hidden>

Revision history for this message
Maciej Kisielewski (kissiel) wrote :

> This looks good, +1, some typos below

Typos fixed. Repushed.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'checkbox-touch/components/PythonLogger.qml'
2--- checkbox-touch/components/PythonLogger.qml 1970-01-01 00:00:00 +0000
3+++ checkbox-touch/components/PythonLogger.qml 2015-02-09 14:20:04 +0000
4@@ -0,0 +1,98 @@
5+/*
6+ * This file is part of Checkbox
7+ *
8+ * Copyright 2015 Canonical Ltd.
9+ *
10+ * Authors:
11+ * - Maciej Kisielewski <maciej.kisielewski@canonical.com>
12+ *
13+ * This program is free software; you can redistribute it and/or modify
14+ * it under the terms of the GNU General Public License as published by
15+ * the Free Software Foundation; version 3.
16+ *
17+ * This program is distributed in the hope that it will be useful,
18+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+ * GNU General Public License for more details.
21+ *
22+ * You should have received a copy of the GNU General Public License
23+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24+ */
25+
26+/*! \brief Python-driven logger
27+ \inherits PythonObjectHandle
28+
29+ This component uses pyotherside to forward logging events to python.
30+ It monkey-patches console.log and console.error to capture their calls
31+ and forward those calls to python logger.
32+*/
33+import QtQuick 2.0
34+
35+PythonObjectHandle {
36+
37+ function debug(msg) {
38+ invoke('debug', [msg], function() {});
39+ }
40+
41+ function info(msg) {
42+ invoke('info', [msg], function() {});
43+ }
44+
45+ function warning(msg) {
46+ invoke('warning', [msg], function() {});
47+ }
48+
49+ function error(msg) {
50+ invoke('error', [msg + "\nStacktrace:\n" + getStackTrace()], function() {});
51+ }
52+
53+ function critical(msg) {
54+ invoke('critical', [msg + "\nStacktrace:\n" + getStackTrace()], function() {});
55+ }
56+ /** get string containing pretty-formatted stack trace */
57+ function getStackTrace() {
58+ var stackTrace = "";
59+ var callers = ((new Error).stack).split("\n");
60+ callers.shift(); // remove current frame from ST (getStackTrace)
61+ callers.shift(); // remove logging method frame from ST
62+ for (var lvl in callers) {
63+ stackTrace += "#" + lvl + " " + callers[lvl] + "\n";
64+ }
65+ return stackTrace;
66+ }
67+
68+ /** Overridden invoke that doesn't log invoke calls */
69+ function invoke(func, args, callback) {
70+ if (py !== null && handle > 0) {
71+ py.call("py_invoke", [handle, func, args], function(response) {
72+ callback(response);
73+ });
74+ } else {
75+ _original_console_error("unable to py_invoke: " + handle + ", " + func + ", " + JSON.stringify(args));
76+ throw "py_invoke called without ready py and handle";
77+ }
78+ }
79+
80+ Component.onCompleted: {
81+ /* save original logging facilities */
82+ _original_console_log = console.log;
83+ _original_console_error = console.error;
84+ }
85+
86+ onHandleReady: {
87+ /* monkey-patch console.log and console.error */
88+ console.log = function() { debug(_argsToString(arguments)); };
89+ console.error = function() { error(_argsToString(arguments)); };
90+ debug("Python logger ready");
91+ }
92+
93+ /** get string containing unpacked values from arguments object separated by spaces*/
94+ function _argsToString(argsObj) {
95+ var args = [];
96+ for(var i = 0; i < argsObj.length; i++) args.push(argsObj[i]);
97+ return args.join(" ");
98+ }
99+
100+ property var _original_console_log
101+ property var _original_console_error
102+}
103
104=== modified file 'checkbox-touch/main.qml'
105--- checkbox-touch/main.qml 2015-01-29 14:58:11 +0000
106+++ checkbox-touch/main.qml 2015-02-09 14:20:04 +0000
107@@ -122,6 +122,20 @@
108 }
109 }
110
111+ PythonLogger {
112+ id: logger
113+ py: py
114+ Component.onCompleted: {
115+ py.Component.onCompleted.connect(function() {
116+ py.importModule("checkbox_touch", function() {
117+ py.call("checkbox_touch.get_qml_logger", [], function(handle) {
118+ logger.handle = handle;
119+ });
120+ });
121+ });
122+ }
123+ }
124+
125 PageStack {
126 id: pageStack
127 Component.onCompleted: push(welcomePage)
128
129=== modified file 'checkbox-touch/py/checkbox_touch.py'
130--- checkbox-touch/py/checkbox_touch.py 2015-02-06 15:51:40 +0000
131+++ checkbox-touch/py/checkbox_touch.py 2015-02-09 14:20:04 +0000
132@@ -799,5 +799,9 @@
133 return manager
134
135
136+def get_qml_logger():
137+ return _manager.ref(logging.getLogger('checkbox.touch.qml'))
138+
139+
140 create_app_object = CheckboxTouchApplication.create_and_get_handle
141 _manager = bootstrap()

Subscribers

People subscribed via source and target branches