Merge lp:~jamesh/bindwood/log-to-file into lp:bindwood

Proposed by James Henstridge
Status: Merged
Approved by: James Henstridge
Approved revision: 42
Merged at revision: 42
Proposed branch: lp:~jamesh/bindwood/log-to-file
Merge into: lp:bindwood
Diff against target: 247 lines (+99/-19)
2 files modified
modules/logging.jsm (+70/-14)
modules/sync.jsm (+29/-5)
To merge this branch: bzr merge lp:~jamesh/bindwood/log-to-file
Reviewer Review Type Date Requested Status
Samuele Pedroni Approve
Eric Casteleijn (community) Approve
Review via email: mp+52977@code.launchpad.net

Commit message

Add support for logging errors and debug messages to a file specified by the BINDWOOD_LOGFILE environment variable.

Description of the change

Currently we log errors to the Firefox error console, with the option to log debug messages if the "bindwood.debug" preference is set to true.

This is inconvenient because the log messages will be mixed with other messages (e.g. CSS errors in pages being visited), and messages may be lost if too many are generated.

This branch adds support for logging Bindwood messages to a file. It is activated by setting the BINDWOOD_LOGFILE environment variable to a file to store the messages to. This will capture both debug messages and errors, irrespective of the "bindwood.debug" preference (I figure that if you want to log to an external file you want everything).

I've also added a few extra logging calls to the synchroniser to help track down bugs.

To post a comment you must log in.
Revision history for this message
Eric Casteleijn (thisfred) :
review: Approve
Revision history for this message
Samuele Pedroni (pedronis) wrote :

looks good, tests pass

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/logging.jsm'
2--- modules/logging.jsm 2011-02-21 04:28:04 +0000
3+++ modules/logging.jsm 2011-03-11 07:44:33 +0000
4@@ -17,37 +17,93 @@
5
6 const EXPORTED_SYMBOLS = ["Log"];
7
8-
9 const Cc = Components.classes;
10 const Ci = Components.interfaces;
11
12+var envService = Cc["@mozilla.org/process/environment;1"]
13+ .getService(Ci.nsIEnvironment);
14 var consoleService = Cc["@mozilla.org/consoleservice;1"]
15 .getService(Ci.nsIConsoleService);
16 var prefsBranch = Cc["@mozilla.org/preferences-service;1"]
17 .getService(Ci.nsIPrefService).getBranch("bindwood.");
18
19
20+const PR_WRONLY = 0x02;
21+const PR_CREATE_FILE = 0x08;
22+const PR_APPEND = 0x10;
23+
24+
25+const LEVEL_DEBUG = 0;
26+const LEVEL_INFO = 1;
27+const LEVEL_WARNING = 2;
28+const LEVEL_ERROR = 3;
29+
30+const LEVEL_NAMES = ["DEBUG", "INFO", "WARNING", "ERROR"];
31+
32+
33 var Log = {
34- _write: function(message) {
35+ _log_opened: false,
36+ _log_stream: null,
37+
38+ _get_log_stream: function() {
39+ if (!this._log_opened) {
40+ if (envService.exists('BINDWOOD_LOGFILE')) {
41+ try {
42+ var logfile = Cc["@mozilla.org/file/local;1"].
43+ createInstance(Ci.nsILocalFile);
44+ logfile.initWithPath(envService.get('BINDWOOD_LOGFILE'));
45+
46+ // Create an output stream appending to the log
47+ // file with default permissions.
48+ var ostream = Cc["@mozilla.org/network/file-output-stream;1"].
49+ createInstance(Ci.nsIFileOutputStream);
50+ ostream.init(
51+ logfile, PR_WRONLY|PR_CREATE_FILE | PR_APPEND, -1, 0);
52+
53+ // Wrap the output stream with a UTF-8 encoder.
54+ this._log_stream = Cc["@mozilla.org/intl/converter-output-stream;1"].
55+ createInstance(Ci.nsIConverterOutputStream);
56+ this._log_stream.init(
57+ ostream, "UTF-8", 4096,
58+ Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
59+ } catch (e) {
60+ dump("Error setting up log file: " + e + "\n");
61+ this._log = null;
62+ }
63+ }
64+ this._log_opened = true;
65+ }
66+ return this._log_stream;
67+ },
68+
69+ _write: function(level, message) {
70+ var log = this._get_log_stream();
71+ if (log) {
72+ log.writeString((new Date()).toUTCString() + " " +
73+ LEVEL_NAMES[level] + ": " + message + "\n");
74+ }
75+
76+ if (level <= LEVEL_DEBUG) {
77+ try {
78+ var debug = prefsBranch.getBoolPref('debug');
79+ } catch(e) {
80+ var debug = false;
81+ }
82+ if (!debug) {
83+ // The user has not requested logging of debug
84+ // messages to the error console.
85+ return;
86+ }
87+ }
88 consoleService.logStringMessage("Bindwood: " + message);
89- /* Uncomment the following to log messages to the console. */
90- //dump(message + "\n");
91 },
92
93 debug: function(message) {
94- var debug;
95- try {
96- debug = prefsBranch.getBoolPref('debug');
97- } catch(e) {
98- debug = false;
99- }
100- if (debug) {
101- this._write(message);
102- }
103+ this._write(LEVEL_DEBUG, message);
104 },
105
106 error: function(message) {
107- this._write(message);
108+ this._write(LEVEL_ERROR, message);
109 },
110
111 exception: function(message, error) {
112
113=== modified file 'modules/sync.jsm'
114--- modules/sync.jsm 2011-03-08 15:45:54 +0000
115+++ modules/sync.jsm 2011-03-11 07:44:33 +0000
116@@ -99,7 +99,7 @@
117 try {
118 doc = this.couch.open(design_doc_id);
119 } catch (e) {
120- Log.exception("Problem retrieving view view");
121+ Log.exception("Problem retrieving view view", e);
122 return;
123 }
124 if (!doc) {
125@@ -132,7 +132,7 @@
126 try {
127 this.couch.save(doc);
128 } catch (e) {
129- Log.exception("Problem saving view");
130+ Log.exception("Problem saving view", e);
131 }
132 },
133
134@@ -165,6 +165,7 @@
135 0, annotationService.EXPIRE_NEVER);
136 // Cache the GUID->Item mapping for later calls.
137 this.guid_item_map[guid] = item_id;
138+ Log.debug("Set GUID on item " + item_id + " to " + guid);
139 return guid;
140 },
141
142@@ -292,6 +293,7 @@
143 pullChanges: function() {
144 var info = this.couch.info();
145 if (this.last_seq <= info.purge_seq) {
146+ Log.debug("Retrieving all bookmarks for profile " + this.profile);
147 // We haven't pulled any records before, or the database
148 // has been compacted past the recorded last_seq.
149 this.last_seq = info.update_seq;
150@@ -303,6 +305,8 @@
151 this.processRecord(row.doc);
152 }
153 } else {
154+ Log.debug("Retrieving bookmarks for profile " + this.profile +
155+ " since sequence number " + this.last_seq);
156 var changes = this.couch.changes({
157 since: this.last_seq,
158 filter: "bindwood/by_profile",
159@@ -346,8 +350,12 @@
160 if (doc._deleted) {
161 /* Bookmark must have been created and deleted within the
162 * period of one sync cycle, so ignore. */
163+ Log.debug("Not creating item, since document " + doc._id +
164+ " is marked deleted");
165 return;
166 }
167+ Log.debug("Creating local item for document " + doc._id);
168+
169 // Determine the parent folder. If it doesn't exist,
170 // temporarily add it as an unfiled bookmark to handle later.
171 var parent_id = this.guid_to_id(doc.parent_guid);
172@@ -385,6 +393,7 @@
173 item_id = null;
174 }
175 if (item_id) {
176+ Log.debug("Created item " + item_id + " for document " + doc._id);
177 this.set_guid(item_id, doc._id);
178 if (!has_parent) {
179 this.set_orphan(item_id, doc.parent_guid);
180@@ -398,15 +407,23 @@
181 if (doc._deleted) {
182 // Document has been deleted in Couch: propagate to local.
183 Log.debug("Removing local item.");
184- bookmarksService.removeItem(item_id);
185+ try {
186+ bookmarksService.removeItem(item_id);
187+ } catch (e) {
188+ Log.exception("Remove failed", e);
189+ throw e;
190+ }
191 return;
192 }
193
194 // If the local item is newer than the version in Couch,
195 // ignore.
196- if (bookmarksService.getItemLastModified(item_id) >=
197+ if (doc.application_annotations &&
198+ doc.application_annotations.Firefox &&
199+ doc.application_annotations.Firefox.last_modified &&
200+ bookmarksService.getItemLastModified(item_id) >=
201 doc.application_annotations.Firefox.last_modified) {
202- Log.debug("Local item is newer than CouchDB version.");
203+ Log.debug("Ignoring changes, since local item is newer.");
204 return;
205 }
206
207@@ -415,6 +432,8 @@
208 this.set_orphan(item_id, doc.parent_guid);
209 } else {
210 if (bookmarksService.getFolderIdForItem(item_id) != parent_id) {
211+ Log.debug("Moving local item " + item_id + " to new parent " +
212+ parent_id);
213 bookmarksService.moveItem(
214 item_id, parent_id, bookmarksService.DEFAULT_INDEX);
215 }
216@@ -450,12 +469,15 @@
217 },
218
219 set_orphan: function (item_id, parent_guid) {
220+ Log.debug("Setting local item " + item_id +
221+ " as an orphan of parent " + parent_guid);
222 annotationService.setItemAnnotation(
223 item_id, PARENT_ANNOTATION, parent_guid,
224 0, annotationService.EXPIRE_NEVER);
225 },
226
227 reparent_orphans: function (parent_id, parent_guid) {
228+ Log.debug("Reparenting orphans of " + parent_guid);
229 var items = annotationService.getItemsWithAnnotation(
230 PARENT_ANNOTATION, {});
231 for each (orphan_id in items) {
232@@ -463,6 +485,7 @@
233 orphan_id, PARENT_ANNOTATION) != parent_guid) {
234 continue;
235 }
236+ Log.debug("Reclaiming orphaned item " + orphan_id);
237 // XXX: check for errors
238 bookmarksService.moveItem(
239 orphan_id, parent_id, bookmarksService.DEFAULT_INDEX)
240@@ -477,6 +500,7 @@
241 if (!parent_id)
242 continue;
243
244+ Log.debug("Reordering children for local item " + parent_id);
245 var children = this.get_folder_children(parent_id);
246 var idx = 0;
247 for each (child_guid in this.folders_to_reorder[parent_guid]) {

Subscribers

People subscribed via source and target branches