All: Log last requests in case of a sync error

pull/1901/head
Laurent Cozic 2019-09-25 18:58:15 +00:00
parent 820e32ddca
commit effbf10571
5 changed files with 78 additions and 1 deletions

View File

@ -16,6 +16,38 @@ class WebDavApi {
constructor(options) {
this.logger_ = new Logger();
this.options_ = options;
this.lastRequests_ = [];
}
logRequest_(request, responseText) {
if (this.lastRequests_.length > 10) this.lastRequests_.splice(0, 1);
const serializeRequest = (r) => {
const options = Object.assign({}, r.options);
if (typeof options.body === 'string') options.body = options.body.substr(0, 4096);
const output = [];
output.push(options.method ? options.method : 'GET');
output.push(r.url);
options.headers = Object.assign({}, options.headers);
if (options.headers['Authorization']) options.headers['Authorization'] = '********';
delete options.method;
output.push(JSON.stringify(options));
return output.join(' ');
};
this.lastRequests_.push({
timestamp: Date.now(),
request: serializeRequest(request),
response: responseText ? responseText.substr(0, 4096) : '',
});
}
lastRequests() {
return this.lastRequests_;
}
clearLastRequests() {
this.lastRequests_ = [];
}
setLogger(l) {
@ -340,6 +372,8 @@ class WebDavApi {
const responseText = await response.text();
this.logRequest_({ url: url, options: fetchOptions }, responseText);
// console.info('WebDAV Response', responseText);
// Creates an error object with as much data as possible as it will appear in the log, which will make debugging easier

View File

@ -15,6 +15,14 @@ class FileApiDriverWebDav {
return 3;
}
lastRequests() {
return this.api().lastRequests();
}
clearLastRequests() {
return this.api().clearLastRequests();
}
async stat(path) {
try {
const result = await this.api().execPropFind(path, 0, ['d:getlastmodified', 'd:resourcetype']);

View File

@ -9,8 +9,15 @@ const { time } = require('lib/time-utils.js');
function requestCanBeRepeated(error) {
const errorCode = typeof error === 'object' && error.code ? error.code : null;
// The target is explicitely rejecting the item so repeating wouldn't make a difference.
if (errorCode === 'rejectedByTarget') return false;
// We don't repeat failSafe errors because it's an indication of an issue at the
// server-level issue which usually cannot be fixed by repeating the request.
// Also we print the previous requests and responses to the log in this case,
// so not repeating means there will be less noise in the log.
if (errorCode === 'failSafe') return false;
return true;
}
@ -60,6 +67,14 @@ class FileApi {
return 0;
}
lastRequests() {
return this.driver_.lastRequests ? this.driver_.lastRequests() : [];
}
clearLastRequests() {
if (this.driver_.clearLastRequests) this.driver_.clearLastRequests();
}
baseDir() {
return this.baseDir_;
}

View File

@ -173,6 +173,17 @@ class Synchronizer {
return this.cancelling_;
}
logLastRequests() {
const lastRequests = this.api().lastRequests();
if (!lastRequests || !lastRequests.length) return;
for (const r of lastRequests) {
const timestamp = time.unixMsToLocalHms(r.timestamp);
this.logger().info(`Req ${timestamp}: ${r.request}`);
this.logger().info(`Res ${timestamp}: ${r.response}`);
}
}
static stateToLabel(state) {
if (state === 'idle') return _('Idle');
if (state === 'in_progress') return _('In progress');
@ -703,6 +714,8 @@ class Synchronizer {
// in the application, and needs to be resolved by the user.
// Or it's a temporary issue that will be resolved on next sync.
this.logger().info(error.message);
if (error.code === 'failSafe') this.logLastRequests();
} else if (error.code === 'unknownItemType') {
this.progressReport_.errors.push(_('Unknown item type downloaded - please upgrade Joplin to the latest version'));
this.logger().error(error);
@ -710,7 +723,10 @@ class Synchronizer {
this.logger().error(error);
// Don't save to the report errors that are due to things like temporary network errors or timeout.
if (!shim.fetchRequestCanBeRetried(error)) this.progressReport_.errors.push(error);
if (!shim.fetchRequestCanBeRetried(error)) {
this.progressReport_.errors.push(error);
this.logLastRequests();
}
}
}

View File

@ -74,6 +74,10 @@ class Time {
return moment.unix(ms / 1000).format('DD/MM/YYYY HH:mm');
}
unixMsToLocalHms(ms) {
return moment.unix(ms / 1000).format('HH:mm:ss');
}
formatMsToLocal(ms, format = null) {
if (format === null) format = this.dateTimeFormat();
return moment(ms).format(format);