diff --git a/src/index.html b/src/index.html
index 0203d33..35ccc50 100644
--- a/src/index.html
+++ b/src/index.html
@@ -234,6 +234,9 @@
+
+ AriaNg Debug Console
+
@@ -356,6 +359,7 @@
+
@@ -377,6 +381,7 @@
+
diff --git a/src/langs/zh_Hans.txt b/src/langs/zh_Hans.txt
index 7322334..e47f5f8 100644
--- a/src/langs/zh_Hans.txt
+++ b/src/langs/zh_Hans.txt
@@ -59,6 +59,7 @@ BitTorrent Settings=BitTorrent 设置
Metalink Settings=Metalink 设置
RPC Settings=RPC 设置
Advanced Settings=高级设置
+AriaNg Debug Console=AriaNg 调试控制台
Aria2 Status=Aria2 状态
File Name=文件名
File Size=大小
@@ -193,6 +194,8 @@ GET=GET
Disabled=禁用
BitTorrent=BitTorrent
Changes to the settings take effect after refreshing page.=设置将在页面刷新后生效.
+Show Detail=显示详情
+Log Detail=日志详情
Type is illegal!=类型错误!
Parameter is invalid!=请求参数无效!
Option value cannot be empty!=参数内容不能为空!
@@ -206,6 +209,7 @@ RPC secret is not base64 encoded!=RPC 密钥不是 Base64 编码后的字符串!
URL is not base64 encoded!=指定 URL 不是 Base64 编码后的字符串!
Tap to configure and get started with AriaNg.=您还没有进行过设置, 点击这里进行设置.
Cannot initialize WebSocket!=无法初始化 WebSocket!
+Access Denied!=拒绝访问!
[error]
unknown=未知错误.
@@ -255,6 +259,7 @@ task.pieceinfo=已完成: {{completed}}, 共计: {{total}} 块
task.error-occurred=发生错误 ({{errorcode}})
settings.file-count=({{count}} 个文件)
settings.total-count=(共计: {{count}}个)
+debug.latest-logs=最近 {{count}} 条日志
[rpc.error]
unauthorized=认证失败!
diff --git a/src/langs/zh_Hant.txt b/src/langs/zh_Hant.txt
index 7fb8cb4..4888153 100644
--- a/src/langs/zh_Hant.txt
+++ b/src/langs/zh_Hant.txt
@@ -59,6 +59,7 @@ BitTorrent Settings=BitTorrent 設定
Metalink Settings=Metalink 設定
RPC Settings=RPC 設定
Advanced Settings=進階設定
+AriaNg Debug Console=AriaNg 調試控制台
Aria2 Status=Aria2 狀態
File Name=文件名
File Size=大小
@@ -158,6 +159,8 @@ Waiting Count=正在等待數量
Stopped Count=已停止數量
You have disabled notification in your browser. You should change your browser's settings before you enable this function.=您已經在瀏覽器中禁用通知功能. 如需使用此功能, 請修改您瀏覽器的設定.
Configuration has been modified, please reload the page for the changes to take effect.=配置已經修改, 請重新載入頁面使其生效.
+Show Detail=顯示詳情
+Log Detail=日誌詳情
Reload Page=重新載入頁面
Show Secret=顯示密鑰
Hide Secret=隱藏密鑰
@@ -206,6 +209,7 @@ RPC secret is not base64 encoded!=RPC 密鑰不是 Base64 編碼後的字元串!
URL is not base64 encoded!=指定 URL 不是 Base64 編碼後的字元串!
Tap to configure and get started with AriaNg.=您還沒有進行過設定, 點擊這裡進行設定.
Cannot initialize WebSocket!=無法初始化 WebSocket!
+Access Denied!=拒絕訪問!
[error]
unknown=未知錯誤.
@@ -255,6 +259,7 @@ task.pieceinfo=已完成: {{completed}}, 共計: {{total}} 塊
task.error-occurred=發生錯誤 ({{errorcode}})
settings.file-count=({{count}} 個文件)
settings.total-count=(共計: {{count}}個)
+debug.latest-logs=最近 {{count}} 條日誌
[rpc.error]
unauthorized=認證失敗!
diff --git a/src/scripts/config/constants.js b/src/scripts/config/constants.js
index d169c51..3909874 100644
--- a/src/scripts/config/constants.js
+++ b/src/scripts/config/constants.js
@@ -15,7 +15,8 @@
taskStatStorageCapacity: 300,
lazySaveTimeout: 500,
errorTooltipDelay: 500,
- notificationInPageTimeout: 2000
+ notificationInPageTimeout: 2000,
+ cachedDebugLogsLimit: 100
}).constant('ariaNgDefaultOptions', {
language: 'en',
title: '${downspeed}, ${upspeed} - ${title}',
diff --git a/src/scripts/config/defaultLanguage.js b/src/scripts/config/defaultLanguage.js
index e7594b0..d51c0b3 100644
--- a/src/scripts/config/defaultLanguage.js
+++ b/src/scripts/config/defaultLanguage.js
@@ -63,6 +63,7 @@
'Metalink Settings': 'Metalink Settings',
'RPC Settings': 'RPC Settings',
'Advanced Settings': 'Advanced Settings',
+ 'AriaNg Debug Console': 'AriaNg Debug Console',
'Aria2 Status': 'Aria2 Status',
'File Name': 'File Name',
'File Size': 'File Size',
@@ -197,6 +198,9 @@
'Disabled': 'Disabled',
'BitTorrent': 'BitTorrent',
'Changes to the settings take effect after refreshing page.': 'Changes to the settings take effect after refreshing page.',
+ 'Latest {{count}} Logs': 'Latest {{count}} Logs',
+ 'Show Detail': 'Show Detail',
+ 'Log Detail': 'Log Detail',
'Type is illegal!': 'Type is illegal!',
'Parameter is invalid!': 'Parameter is invalid!',
'Option value cannot be empty!': 'Option value cannot be empty!',
@@ -210,6 +214,7 @@
'URL is not base64 encoded!': 'URL is not base64 encoded!',
'Tap to configure and get started with AriaNg.': 'Tap to configure and get started with AriaNg.',
'Cannot initialize WebSocket!': 'Cannot initialize WebSocket!',
+ 'Access Denied!': 'Access Denied!',
'error': {
'unknown': 'Unknown error occurred.',
'operation.timeout': 'Operation timed out.',
@@ -257,7 +262,8 @@
'task.pieceinfo': 'Completed: {{completed}}, Total: {{total}}',
'task.error-occurred': 'Error Occurred ({{errorcode}})',
'settings.file-count': '({{count}} Files)',
- 'settings.total-count': '(Total Count: {{count}})'
+ 'settings.total-count': '(Total Count: {{count}})',
+ 'debug.latest-logs': 'Latest {{count}} Logs'
},
'rpc': {
'error': {
diff --git a/src/scripts/controllers/debug.js b/src/scripts/controllers/debug.js
new file mode 100644
index 0000000..9b6c46d
--- /dev/null
+++ b/src/scripts/controllers/debug.js
@@ -0,0 +1,38 @@
+(function () {
+ 'use strict';
+
+ angular.module('ariaNg').controller('AriaNgDebugController', ['$rootScope', '$scope', '$location', '$timeout', 'ariaNgConstants', 'ariaNgCommonService', 'ariaNgSettingService', 'ariaNgLogService', function ($rootScope, $scope, $location, $timeout, ariaNgConstants, ariaNgCommonService, ariaNgSettingService, ariaNgLogService) {
+ $scope.logMaxCount = ariaNgConstants.cachedDebugLogsLimit;
+ $scope.currentLog = null;
+
+ $scope.enableDebugMode = function () {
+ return ariaNgSettingService.isEnableDebugMode();
+ };
+
+ $scope.reloadLogs = function () {
+ $scope.logs = ariaNgLogService.getDebugLogs().slice();
+ };
+
+ $scope.showLogDetail = function (log) {
+ $scope.currentLog = log;
+ angular.element('#log-detail-modal').modal();
+ };
+
+ $('#log-detail-modal').on('hide.bs.modal', function (e) {
+ $scope.currentLog = null;
+ });
+
+ $rootScope.loadPromise = $timeout(function () {
+ if (!ariaNgSettingService.isEnableDebugMode()) {
+ ariaNgCommonService.showError('Access Denied!', function () {
+ if (!ariaNgSettingService.isEnableDebugMode()) {
+ $location.path('/settings/ariang');
+ }
+ });
+ return;
+ }
+
+ $scope.reloadLogs();
+ }, 100);
+ }]);
+}());
diff --git a/src/scripts/controllers/main.js b/src/scripts/controllers/main.js
index 1d929c8..7f51230 100644
--- a/src/scripts/controllers/main.js
+++ b/src/scripts/controllers/main.js
@@ -36,6 +36,10 @@
data: ariaNgMonitorService.getGlobalStatsData()
};
+ $scope.enableDebugMode = function () {
+ return ariaNgSettingService.isEnableDebugMode();
+ };
+
$scope.quickSettingContext = null;
$scope.rpcSettings = ariaNgSettingService.getAllRpcSettings();
diff --git a/src/scripts/core/router.js b/src/scripts/core/router.js
index aa61b6a..c550e53 100644
--- a/src/scripts/core/router.js
+++ b/src/scripts/core/router.js
@@ -75,6 +75,10 @@
template: '',
controller: 'CommandController'
})
+ .when('/debug', {
+ templateUrl: 'views/debug.html',
+ controller: 'AriaNgDebugController'
+ })
.when('/status', {
templateUrl: 'views/status.html',
controller: 'Aria2StatusController'
diff --git a/src/scripts/filters/reverse.js b/src/scripts/filters/reverse.js
new file mode 100644
index 0000000..7f67070
--- /dev/null
+++ b/src/scripts/filters/reverse.js
@@ -0,0 +1,13 @@
+(function () {
+ 'use strict';
+
+ angular.module('ariaNg').filter('reverse', function () {
+ return function(array) {
+ if (!array) {
+ return array;
+ }
+
+ return array.slice().reverse();
+ };
+ });
+}());
diff --git a/src/scripts/services/aria2HttpRpcService.js b/src/scripts/services/aria2HttpRpcService.js
index 952b97f..d14be0b 100644
--- a/src/scripts/services/aria2HttpRpcService.js
+++ b/src/scripts/services/aria2HttpRpcService.js
@@ -66,12 +66,12 @@
requestContext.url = getUrlWithQueryString(requestContext.url, context.requestBody);
}
- ariaNgLogService.debug('[aria2HttpRpcService.request] request start', requestContext);
+ ariaNgLogService.debug('[aria2HttpRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'request start', requestContext);
return $http(requestContext).then(function onSuccess(response) {
var data = response.data;
- ariaNgLogService.debug('[aria2HttpRpcService.request] response success', data);
+ ariaNgLogService.debug('[aria2HttpRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'response success', response);
if (!data) {
return;
@@ -83,7 +83,7 @@
}).catch(function onError(response) {
var data = response.data;
- ariaNgLogService.debug('[aria2HttpRpcService.request] response error', data);
+ ariaNgLogService.debug('[aria2HttpRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'response error', response);
if (!data) {
data = {
diff --git a/src/scripts/services/aria2TaskService.js b/src/scripts/services/aria2TaskService.js
index 21e05a3..f46a591 100644
--- a/src/scripts/services/aria2TaskService.js
+++ b/src/scripts/services/aria2TaskService.js
@@ -190,6 +190,8 @@
}
}
+ ariaNgLogService.debug('[aria2TaskService.processDownloadTask] process success', task);
+
return task;
};
@@ -469,7 +471,7 @@
}
if (!response.success) {
- ariaNgLogService.warn('[aria2TaskService.restartTask] response is not success');
+ ariaNgLogService.warn('[aria2TaskService.restartTask] response is not success', response);
deferred.reject(response);
callback(response);
return;
@@ -528,7 +530,7 @@
silent: !!silent,
callback: function (response) {
if (!response.success) {
- ariaNgLogService.warn('[aria2TaskService.restartTask] addUri response is not success');
+ ariaNgLogService.warn('[aria2TaskService.restartTask] addUri response is not success', response);
deferred.reject(response);
callback(response);
return;
@@ -540,7 +542,7 @@
silent: true,
callback: function (response) {
if (!response.success) {
- ariaNgLogService.warn('[aria2TaskService.restartTask] removeDownloadResult response is not success');
+ ariaNgLogService.warn('[aria2TaskService.restartTask] removeDownloadResult response is not success', response);
}
}
});
@@ -685,7 +687,7 @@
},
processDownloadTasks: function (tasks) {
if (!angular.isArray(tasks)) {
- ariaNgLogService.warn('[aria2TaskService.processDownloadTasks] tasks is not array');
+ ariaNgLogService.warn('[aria2TaskService.processDownloadTasks] tasks is not array', tasks);
return;
}
@@ -701,7 +703,7 @@
},
estimateHealthPercentFromPeers: function (task, peers) {
if (!task || task.numPieces < 1 || peers.length < 1) {
- ariaNgLogService.warn('[aria2TaskService.estimateHealthPercentFromPeers] tasks is null or numPieces < 1 or peers < 1');
+ ariaNgLogService.warn('[aria2TaskService.estimateHealthPercentFromPeers] tasks is null or numPieces < 1 or peers < 1', task);
return task.completePercent;
}
diff --git a/src/scripts/services/aria2WebSocketRpcService.js b/src/scripts/services/aria2WebSocketRpcService.js
index 95f4718..09e3152 100644
--- a/src/scripts/services/aria2WebSocketRpcService.js
+++ b/src/scripts/services/aria2WebSocketRpcService.js
@@ -29,13 +29,13 @@
});
if (content.result && context.successCallback) {
- ariaNgLogService.debug('[aria2WebSocketRpcService.request] response success', content);
+ ariaNgLogService.debug('[aria2WebSocketRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'response success', content);
context.successCallback(context.id, content.result);
}
if (content.error && context.errorCallback) {
- ariaNgLogService.debug('[aria2WebSocketRpcService.request] response error', content);
+ ariaNgLogService.debug('[aria2WebSocketRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'response error', content);
context.errorCallback(context.id, content.error);
}
@@ -110,7 +110,7 @@
var uniqueId = context.uniqueId;
var requestBody = angular.toJson(context.requestBody);
- ariaNgLogService.debug('[aria2WebSocketRpcService.request] request start', context);
+ ariaNgLogService.debug('[aria2WebSocketRpcService.request] ' + (context && context.requestBody && context.requestBody.method ? context.requestBody.method + ' ' : '') + 'request start', context);
var deferred = $q.defer();
diff --git a/src/scripts/services/ariaNgCommonService.js b/src/scripts/services/ariaNgCommonService.js
index 5ad0186..cded4f9 100644
--- a/src/scripts/services/ariaNgCommonService.js
+++ b/src/scripts/services/ariaNgCommonService.js
@@ -9,21 +9,25 @@
return hashedId;
},
- showDialog: function (title, text, type) {
+ showDialog: function (title, text, type, callback) {
$timeout(function () {
SweetAlert.swal({
title: $translate.instant(title),
text: $translate.instant(text),
type: type,
confirmButtonText: $translate.instant('OK')
+ }, function () {
+ if (callback) {
+ callback();
+ }
});
}, 100);
},
- showError: function (text) {
- this.showDialog('Error', text, 'error');
+ showError: function (text, callback) {
+ this.showDialog('Error', text, 'error', callback);
},
- showOperationSucceeded: function (text) {
- this.showDialog('Operation Succeeded', text, 'success');
+ showOperationSucceeded: function (text, callback) {
+ this.showDialog('Operation Succeeded', text, 'success', callback);
},
confirm: function (title, text, type, callback, notClose, extendSettings) {
var options = {
diff --git a/src/scripts/services/ariaNgLogService.js b/src/scripts/services/ariaNgLogService.js
index 427cdfa..deeead2 100644
--- a/src/scripts/services/ariaNgLogService.js
+++ b/src/scripts/services/ariaNgLogService.js
@@ -1,7 +1,30 @@
(function () {
'use strict';
- angular.module('ariaNg').factory('ariaNgLogService', ['$log', 'ariaNgSettingService', function ($log, ariaNgSettingService) {
+ angular.module('ariaNg').factory('ariaNgLogService', ['$log', 'moment', 'ariaNgConstants', 'ariaNgSettingService', function ($log, moment, ariaNgConstants, ariaNgSettingService) {
+ var cachedDebugLogs = [];
+
+ var createNewCacheLogItem = function (msg, level, obj) {
+ return {
+ time: moment(),
+ level: level,
+ content: msg,
+ attachment: obj
+ };
+ };
+
+ var pushLogToCache = function (msg, level, obj) {
+ if (!ariaNgSettingService.isEnableDebugMode()) {
+ return;
+ }
+
+ if (cachedDebugLogs.length >= ariaNgConstants.cachedDebugLogsLimit) {
+ cachedDebugLogs.shift();
+ }
+
+ cachedDebugLogs.push(createNewCacheLogItem(msg, level, obj));
+ };
+
return {
debug: function (msg, obj) {
if (ariaNgSettingService.isEnableDebugMode()) {
@@ -10,6 +33,8 @@
} else {
$log.debug('[AriaNg Debug]' + msg);
}
+
+ pushLogToCache(msg, 'DEBUG', obj);
}
},
info: function (msg, obj) {
@@ -18,6 +43,8 @@
} else {
$log.info('[AriaNg Info]' + msg);
}
+
+ pushLogToCache(msg, 'INFO', obj);
},
warn: function (msg, obj) {
if (obj) {
@@ -25,6 +52,8 @@
} else {
$log.warn('[AriaNg Warn]' + msg);
}
+
+ pushLogToCache(msg, 'WARN', obj);
},
error: function (msg, obj) {
if (obj) {
@@ -32,6 +61,15 @@
} else {
$log.error('[AriaNg Error]' + msg);
}
+
+ pushLogToCache(msg, 'ERROR', obj);
+ },
+ getDebugLogs: function () {
+ if (ariaNgSettingService.isEnableDebugMode()) {
+ return cachedDebugLogs;
+ } else {
+ return [];
+ }
}
};
}]);
diff --git a/src/views/debug.html b/src/views/debug.html
new file mode 100644
index 0000000..d3a83a7
--- /dev/null
+++ b/src/views/debug.html
@@ -0,0 +1,49 @@
+