mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-22 14:48:30 +00:00
gui: Add debug tab to settings (ref #2644)
Just because there are a ton of people struggling to set env vars. Perhaps this should live in advanced settings, and perhaps we should have a button to view the log. GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4604 LGTM: calmh, imsodin
This commit is contained in:
parent
2547a29dd7
commit
c58b383b6d
@ -78,6 +78,7 @@
|
||||
<li><a href="" data-toggle="modal" data-target="#about"><span class="fa fa-fw fa-heart-o"></span> <span translate>About</span></a></li>
|
||||
<li class="divider" aria-hidden="true"></li>
|
||||
<li><a href="" ng-click="advanced()"><span class="fa fa-fw fa-cogs"></span> <span translate>Advanced</span></a></li>
|
||||
<li><a href="" ng-click="logging.show()"><span class="fa fa-fw fa-book"></span> <span translate>Logs</span></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -734,6 +735,7 @@
|
||||
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/removeFolderDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/removeDeviceDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/logViewerModalView.html'"></ng-include>
|
||||
|
||||
<!-- vendor scripts -->
|
||||
<script type="text/javascript" src="vendor/jquery/jquery-2.2.2.js"></script>
|
||||
|
36
gui/default/syncthing/core/logViewerModalView.html
Normal file
36
gui/default/syncthing/core/logViewerModalView.html
Normal file
@ -0,0 +1,36 @@
|
||||
<modal id="logViewer" icon="book" status="default" heading="{{'Logs' | translate}}" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle="tab" href="#log-viewer-log" translate>Log</a></li>
|
||||
<li><a data-toggle="tab" href="#log-viewer-facilities" translate>Debugging Facilities</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
|
||||
<div id="log-viewer-log" class="tab-pane in active">
|
||||
<label translate ng-if="logging.logEntries.length == 0">Loading...</label>
|
||||
<textarea ng-focus="logging.paused = true" ng-blur="logging.paused = false" id="logViewerText" class="form-control" rows="20" ng-if="logging.logEntries.length != 0" readonly style="font-family: Consolas; font-size: 11px; overflow: auto;">{{ logging.content() }}</textarea>
|
||||
<p translate class="help-block" ng-style="{'visibility': logging.paused ? 'visible' : 'hidden'}">Log tailing paused. Click here to continue.</p>
|
||||
</div>
|
||||
|
||||
<div id="log-viewer-facilities" class="tab-pane">
|
||||
<label>Available debug logging facilities:</label>
|
||||
<table class="table table-condensed table-striped">
|
||||
<tbody>
|
||||
<tr ng-repeat="(name, data) in logging.facilities">
|
||||
<td>
|
||||
<input type="checkbox" ng-model="data.enabled" ng-change="logging.onFacilityChange(name)" ng-disabled="data.enabled == null"> <span>{{ name }}</span>
|
||||
</td>
|
||||
<td>{{ data.description }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fa fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
@ -2,7 +2,7 @@ angular.module('syncthing.core')
|
||||
.config(function($locationProvider) {
|
||||
$locationProvider.html5Mode({enabled: true, requireBase: false}).hashPrefix('!');
|
||||
})
|
||||
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter, $q) {
|
||||
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter, $q, $interval) {
|
||||
'use strict';
|
||||
|
||||
// private/helper definitions
|
||||
@ -1090,6 +1090,76 @@ angular.module('syncthing.core')
|
||||
$('#discovery-failures').modal();
|
||||
};
|
||||
|
||||
$scope.logging = {
|
||||
facilities: {},
|
||||
refreshFacilities: function() {
|
||||
$http.get(urlbase + '/system/debug').success(function (data) {
|
||||
var facilities = {};
|
||||
data.enabled = data.enabled || [];
|
||||
$.each(data.facilities, function(key, value) {
|
||||
facilities[key] = {
|
||||
description: value,
|
||||
enabled: data.enabled.indexOf(key) > -1
|
||||
}
|
||||
})
|
||||
$scope.logging.facilities = facilities;
|
||||
}).error($scope.emitHTTPError);
|
||||
},
|
||||
show: function() {
|
||||
$scope.logging.refreshFacilities();
|
||||
$scope.logging.timer = $interval($scope.logging.fetch, 0, 1);
|
||||
$('#logViewer').modal().on('hidden.bs.modal', function () {
|
||||
$interval.cancel($scope.logging.timer);
|
||||
$scope.logging.timer = null;
|
||||
$scope.logging.entries = [];
|
||||
});
|
||||
},
|
||||
onFacilityChange: function(facility) {
|
||||
var enabled = $scope.logging.facilities[facility].enabled;
|
||||
// Disable checkboxes while we're in flight.
|
||||
$.each($scope.logging.facilities, function(key) {
|
||||
$scope.logging.facilities[key].enabled = null;
|
||||
})
|
||||
$http.post(urlbase + '/system/debug?' + (enabled ? 'enable=':'disable=') + facility)
|
||||
.success($scope.logging.refreshFacilities)
|
||||
.error($scope.emitHTTPError);
|
||||
},
|
||||
timer: null,
|
||||
entries: [],
|
||||
paused: false,
|
||||
content: function() {
|
||||
var content = "";
|
||||
$.each($scope.logging.entries, function (idx, entry) {
|
||||
content += entry.when.split('.')[0].replace('T', ' ') + ' ' + entry.message + "\n";
|
||||
});
|
||||
return content;
|
||||
},
|
||||
fetch: function() {
|
||||
var textArea = $('#logViewerText');
|
||||
if (textArea.is(":focus")) {
|
||||
if (!$scope.logging.timer) return;
|
||||
$scope.logging.timer = $interval($scope.logging.fetch, 500, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
var last = null;
|
||||
if ($scope.logging.entries.length > 0) {
|
||||
last = $scope.logging.entries[$scope.logging.entries.length-1].when;
|
||||
}
|
||||
|
||||
$http.get(urlbase + '/system/log' + (last ? '?since=' + encodeURIComponent(last) : '')).success(function (data) {
|
||||
if (!$scope.logging.timer) return;
|
||||
$scope.logging.timer = $interval($scope.logging.fetch, 2000, 1);
|
||||
if (!textArea.is(":focus")) {
|
||||
if (data.messages) {
|
||||
$scope.logging.entries.push.apply($scope.logging.entries, data.messages);
|
||||
}
|
||||
textArea.scrollTop(textArea[0].scrollHeight);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.editSettings = function () {
|
||||
// Make a working copy
|
||||
$scope.tmpOptions = angular.copy($scope.config.options);
|
||||
|
@ -150,6 +150,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="settings-connections" class="tab-pane">
|
||||
<div class="form-group">
|
||||
<label translate for="ListenAddressesStr">Sync Protocol Listen Addresses</label> <a href="https://docs.syncthing.net/users/config.html#listen-addresses" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
@ -221,11 +222,12 @@
|
||||
<label translate for="GlobalAnnServersStr">Global Discovery Servers</label>
|
||||
<input ng-disabled="!tmpOptions.globalAnnounceEnabled" id="GlobalAnnServersStr" class="form-control" type="text" ng-model="tmpOptions._globalAnnounceServersStr"/>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("filesystem", "Filesystem access")
|
||||
l = logger.DefaultLogger.NewFacility("fs", "Filesystem access")
|
||||
)
|
||||
|
||||
func init() {
|
||||
l.SetDebug("filesystem", strings.Contains(os.Getenv("STTRACE"), "filesystem") || os.Getenv("STTRACE") == "all")
|
||||
l.SetDebug("fs", strings.Contains(os.Getenv("STTRACE"), "fs") || os.Getenv("STTRACE") == "all")
|
||||
}
|
||||
|
@ -308,6 +308,7 @@ type recorder struct {
|
||||
type Line struct {
|
||||
When time.Time `json:"when"`
|
||||
Message string `json:"message"`
|
||||
Level LogLevel `json:"level"`
|
||||
}
|
||||
|
||||
func NewRecorder(l Logger, level LogLevel, size, initial int) Recorder {
|
||||
@ -324,18 +325,18 @@ func (r *recorder) Since(t time.Time) []Line {
|
||||
defer r.mut.Unlock()
|
||||
|
||||
res := r.lines
|
||||
for i := 0; i < len(res) && res[i].When.Before(t); i++ {
|
||||
// nothing, just incrementing i
|
||||
}
|
||||
if len(res) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We must copy the result as r.lines can be mutated as soon as the lock
|
||||
// is released.
|
||||
cp := make([]Line, len(res))
|
||||
copy(cp, res)
|
||||
return cp
|
||||
for i := 0; i < len(res); i++ {
|
||||
if res[i].When.After(t) {
|
||||
// We must copy the result as r.lines can be mutated as soon as the lock
|
||||
// is released.
|
||||
res = res[i:]
|
||||
cp := make([]Line, len(res))
|
||||
copy(cp, res)
|
||||
return cp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *recorder) Clear() {
|
||||
@ -348,6 +349,7 @@ func (r *recorder) append(l LogLevel, msg string) {
|
||||
line := Line{
|
||||
When: time.Now(),
|
||||
Message: msg,
|
||||
Level: l,
|
||||
}
|
||||
|
||||
r.mut.Lock()
|
||||
@ -367,6 +369,6 @@ func (r *recorder) append(l LogLevel, msg string) {
|
||||
|
||||
r.lines = append(r.lines, line)
|
||||
if len(r.lines) == r.initial {
|
||||
r.lines = append(r.lines, Line{time.Now(), "..."})
|
||||
r.lines = append(r.lines, Line{time.Now(), "...", l})
|
||||
}
|
||||
}
|
||||
|
@ -130,4 +130,24 @@ func TestRecorder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check that since works
|
||||
now := time.Now()
|
||||
|
||||
time.Sleep(time.Millisecond)
|
||||
|
||||
lines = r1.Since(now)
|
||||
if len(lines) != 0 {
|
||||
t.Error("unexpected lines")
|
||||
}
|
||||
|
||||
l.Infoln("hah")
|
||||
|
||||
lines = r1.Since(now)
|
||||
if len(lines) != 1 {
|
||||
t.Fatalf("unexpected line count: %d", len(lines))
|
||||
}
|
||||
if lines[0].Message != "hah" {
|
||||
t.Errorf("incorrect line: %s", lines[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user