add debug console page, add log
This commit is contained in:
parent
94e295f184
commit
4bb0a9b972
|
@ -234,6 +234,9 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="ng-cloak" data-href-match="/debug" ng-if="enableDebugMode()">
|
||||
<a href="#!/debug"><i class="fa fa-wrench"></i> <span translate>AriaNg Debug Console</span></a>
|
||||
</li>
|
||||
<li data-href-match="/status">
|
||||
<a href="#!/status">
|
||||
<span class="label pull-right" ng-if="globalStatusContext.isEnabled" ng-class="{'label-primary': taskContext.rpcStatus === 'Connecting', 'label-success': taskContext.rpcStatus === 'Connected', 'label-danger': taskContext.rpcStatus === 'Not Connected'}" ng-bind="taskContext.rpcStatus | translate"></span>
|
||||
|
@ -356,6 +359,7 @@
|
|||
<script src="scripts/config/aria2Errors.js"></script>
|
||||
<script src="scripts/config/aria2RpcConstants.js"></script>
|
||||
<script src="scripts/controllers/command.js"></script>
|
||||
<script src="scripts/controllers/debug.js"></script>
|
||||
<script src="scripts/controllers/main.js"></script>
|
||||
<script src="scripts/controllers/new.js"></script>
|
||||
<script src="scripts/controllers/list.js"></script>
|
||||
|
@ -377,6 +381,7 @@
|
|||
<script src="scripts/filters/longDate.js"></script>
|
||||
<script src="scripts/filters/peerOrderBy.js"></script>
|
||||
<script src="scripts/filters/percent.js"></script>
|
||||
<script src="scripts/filters/reverse.js"></script>
|
||||
<script src="scripts/filters/taskOrderBy.js"></script>
|
||||
<script src="scripts/filters/taskStatus.js"></script>
|
||||
<script src="scripts/filters/volume.js"></script>
|
||||
|
|
|
@ -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=认证失败!
|
||||
|
|
|
@ -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=認證失敗!
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
taskStatStorageCapacity: 300,
|
||||
lazySaveTimeout: 500,
|
||||
errorTooltipDelay: 500,
|
||||
notificationInPageTimeout: 2000
|
||||
notificationInPageTimeout: 2000,
|
||||
cachedDebugLogsLimit: 100
|
||||
}).constant('ariaNgDefaultOptions', {
|
||||
language: 'en',
|
||||
title: '${downspeed}, ${upspeed} - ${title}',
|
||||
|
|
|
@ -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': {
|
||||
|
|
38
src/scripts/controllers/debug.js
Normal file
38
src/scripts/controllers/debug.js
Normal file
|
@ -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);
|
||||
}]);
|
||||
}());
|
|
@ -36,6 +36,10 @@
|
|||
data: ariaNgMonitorService.getGlobalStatsData()
|
||||
};
|
||||
|
||||
$scope.enableDebugMode = function () {
|
||||
return ariaNgSettingService.isEnableDebugMode();
|
||||
};
|
||||
|
||||
$scope.quickSettingContext = null;
|
||||
|
||||
$scope.rpcSettings = ariaNgSettingService.getAllRpcSettings();
|
||||
|
|
|
@ -75,6 +75,10 @@
|
|||
template: '',
|
||||
controller: 'CommandController'
|
||||
})
|
||||
.when('/debug', {
|
||||
templateUrl: 'views/debug.html',
|
||||
controller: 'AriaNgDebugController'
|
||||
})
|
||||
.when('/status', {
|
||||
templateUrl: 'views/status.html',
|
||||
controller: 'Aria2StatusController'
|
||||
|
|
13
src/scripts/filters/reverse.js
Normal file
13
src/scripts/filters/reverse.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
angular.module('ariaNg').filter('reverse', function () {
|
||||
return function(array) {
|
||||
if (!array) {
|
||||
return array;
|
||||
}
|
||||
|
||||
return array.slice().reverse();
|
||||
};
|
||||
});
|
||||
}());
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 [];
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
49
src/views/debug.html
Normal file
49
src/views/debug.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<section class="content no-padding ng-cloak" ng-if="enableDebugMode()">
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active">
|
||||
<a class="pointer-cursor" ng-bind="('format.debug.latest-logs' | translate: {count: logMaxCount})" ng-click="reloadLogs()">Latest Logs</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content no-padding">
|
||||
<div class="settings-table striped hoverable">
|
||||
<div class="row" ng-repeat="log in logs | reverse">
|
||||
<div class="col-sm-12">
|
||||
<span class="label label-default" ng-bind="'#' + ($index + 1)"></span>
|
||||
<span ng-bind="log.time | longDate"></span>
|
||||
<span class="label" ng-class="{'DEBUG':'label-default', 'INFO':'label-primary', 'WARN':'label-warning', 'ERROR':'label-danger'}[log.level]" ng-bind="log.level"></span>
|
||||
<span ng-bind="log.content"></span>
|
||||
<a class="pointer-cursor" ng-click="showLogDetail(log)" ng-if="log.attachment"><i class="fa fa-file-o"></i> <span translate>Show Detail</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="log-detail-modal" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" translate>Log Detail</h4>
|
||||
</div>
|
||||
<div class="modal-body no-padding">
|
||||
<div class="settings-table striped">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<span ng-bind="currentLog.time | longDate"></span>
|
||||
<span class="label" ng-class="{'DEBUG':'label-default', 'INFO':'label-primary', 'WARN':'label-warning', 'ERROR':'label-danger'}[currentLog.level]" ng-bind="currentLog.level"></span>
|
||||
<span ng-bind="currentLog.content"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-if="currentLog.attachment">
|
||||
<div class="col-sm-12">
|
||||
<pre ng-bind="currentLog.attachment | json"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
Reference in a new issue