You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	Log files are viewable in the UI
This commit is contained in:
		
							
								
								
									
										29
									
								
								NzbDrone.Api/Frontend/LogFileMapper.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								NzbDrone.Api/Frontend/LogFileMapper.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| using System.IO; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Common.EnvironmentInfo; | ||||
|  | ||||
| namespace NzbDrone.Api.Frontend | ||||
| { | ||||
|     public class LogFileMapper : IMapHttpRequestsToDisk | ||||
|     { | ||||
|         private readonly IAppFolderInfo _appFolderInfo; | ||||
|  | ||||
|         public LogFileMapper(IAppFolderInfo appFolderInfo) | ||||
|         { | ||||
|             _appFolderInfo = appFolderInfo; | ||||
|         } | ||||
|  | ||||
|         public string Map(string resourceUrl) | ||||
|         { | ||||
|             var path = resourceUrl.Replace('/', Path.DirectorySeparatorChar); | ||||
|             path = Path.GetFileName(path); | ||||
|  | ||||
|             return Path.Combine(_appFolderInfo.GetLogFolder(), path); | ||||
|         } | ||||
|  | ||||
|         public bool CanHandle(string resourceUrl) | ||||
|         { | ||||
|             return resourceUrl.StartsWith("/log"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								NzbDrone.Api/Logs/LogFileModule.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								NzbDrone.Api/Logs/LogFileModule.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Common.EnvironmentInfo; | ||||
|  | ||||
| namespace NzbDrone.Api.Logs | ||||
| { | ||||
|     public class LogFileModule : NzbDroneRestModule<LogFileResource> | ||||
|     { | ||||
|         private readonly IAppFolderInfo _appFolderInfo; | ||||
|         private readonly IDiskProvider _diskProvider; | ||||
|  | ||||
|         public LogFileModule(IAppFolderInfo appFolderInfo, | ||||
|                              IDiskProvider diskProvider) | ||||
|             : base("log/files") | ||||
|         { | ||||
|             _appFolderInfo = appFolderInfo; | ||||
|             _diskProvider = diskProvider; | ||||
|             GetResourceAll = GetLogFiles; | ||||
|         } | ||||
|  | ||||
|         private List<LogFileResource> GetLogFiles() | ||||
|         { | ||||
|             var result = new List<LogFileResource>(); | ||||
|              | ||||
|             var files = _diskProvider.GetFiles(_appFolderInfo.GetLogFolder(), SearchOption.TopDirectoryOnly); | ||||
|  | ||||
|             for (int i = 0; i < files.Length; i++) | ||||
|             { | ||||
|                 var file = files[i]; | ||||
|                  | ||||
|                 result.Add(new LogFileResource | ||||
|                 { | ||||
|                     Id = i + 1, | ||||
|                     Filename = Path.GetFileName(file), | ||||
|                     LastWriteTime = _diskProvider.GetLastFileWrite(file) | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return result.OrderByDescending(l => l.LastWriteTime).ToList(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								NzbDrone.Api/Logs/LogFileResource.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								NzbDrone.Api/Logs/LogFileResource.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| using System; | ||||
| using NzbDrone.Api.REST; | ||||
|  | ||||
| namespace NzbDrone.Api.Logs | ||||
| { | ||||
|     public class LogFileResource : RestResource | ||||
|     { | ||||
|         public String Filename { get; set; } | ||||
|         public DateTime LastWriteTime { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,4 @@ | ||||
| using NzbDrone.Core.Datastore; | ||||
| using NzbDrone.Core.History; | ||||
| using NzbDrone.Core.Instrumentation; | ||||
| using NzbDrone.Api.Mapping; | ||||
|  | ||||
| @@ -8,7 +7,6 @@ namespace NzbDrone.Api.Logs | ||||
|     public class LogModule : NzbDroneRestModule<LogResource> | ||||
|     { | ||||
|         private readonly ILogService _logService; | ||||
|         private readonly IHistoryService _historyService; | ||||
|  | ||||
|         public LogModule(ILogService logService) | ||||
|         { | ||||
|   | ||||
| @@ -92,6 +92,7 @@ | ||||
|     <Compile Include="Extensions\CacheHeaderPipeline.cs" /> | ||||
|     <Compile Include="Extensions\GZipPipeline.cs" /> | ||||
|     <Compile Include="Extensions\NancyJsonSerializer.cs" /> | ||||
|     <Compile Include="Frontend\LogFileMapper.cs" /> | ||||
|     <Compile Include="Frontend\IAddCacheHeaders.cs" /> | ||||
|     <Compile Include="Frontend\MediaCoverMapper.cs" /> | ||||
|     <Compile Include="Frontend\IMapHttpRequestsToDisk.cs" /> | ||||
| @@ -106,6 +107,8 @@ | ||||
|     <Compile Include="Indexers\ReleaseModule.cs" /> | ||||
|     <Compile Include="Extensions\LazyExtensions.cs" /> | ||||
|     <Compile Include="Indexers\ReleaseResource.cs" /> | ||||
|     <Compile Include="Logs\LogFileResource.cs" /> | ||||
|     <Compile Include="Logs\LogFileModule.cs" /> | ||||
|     <Compile Include="Logs\LogModule.cs" /> | ||||
|     <Compile Include="Logs\LogResource.cs" /> | ||||
|     <Compile Include="Mapping\CloneInjection.cs" /> | ||||
|   | ||||
| @@ -10,11 +10,7 @@ define( | ||||
|             className: 'episode-title-cell', | ||||
|  | ||||
|             events: { | ||||
|                 'click': 'showDetails' | ||||
|             }, | ||||
|  | ||||
|             showDetails: function () { | ||||
|                 App.vent.trigger(App.Commands.ShowEpisodeDetails, {episode: this.cellValue}); | ||||
|                 'click': '_showDetails' | ||||
|             }, | ||||
|  | ||||
|             render: function () { | ||||
| @@ -26,6 +22,10 @@ define( | ||||
|  | ||||
|                 this.$el.html(title); | ||||
|                 return this; | ||||
|             }, | ||||
|  | ||||
|             _showDetails: function () { | ||||
|                 App.vent.trigger(App.Commands.ShowEpisodeDetails, {episode: this.cellValue}); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -12,12 +12,13 @@ define( | ||||
|         'Series/SeriesModel', | ||||
|         'Calendar/CalendarLayout', | ||||
|         'Logs/Layout', | ||||
|         'Logs/Files/Layout', | ||||
|         'Release/Layout', | ||||
|         'System/Layout', | ||||
|         'Shared/NotFoundView', | ||||
|         'Shared/Modal/Region' | ||||
|     ], function (App, Marionette, HistoryLayout, SettingsLayout, AddSeriesLayout, SeriesIndexLayout, SeriesDetailsLayout, MissingLayout, SeriesModel, CalendarLayout, | ||||
|         LogsLayout, ReleaseLayout, SystemLayout, NotFoundView) { | ||||
|         LogsLayout, LogFileLayout, ReleaseLayout, SystemLayout, NotFoundView) { | ||||
|         return Marionette.Controller.extend({ | ||||
|  | ||||
|             series       : function () { | ||||
| @@ -71,9 +72,16 @@ define( | ||||
|                 App.mainRegion.show(new ReleaseLayout()); | ||||
|             }, | ||||
|  | ||||
|             logs: function () { | ||||
|                 this._setTitle('logs'); | ||||
|                 App.mainRegion.show(new LogsLayout()); | ||||
|             logs: function (action) { | ||||
|                 if (action) { | ||||
|                     this._setTitle('log files'); | ||||
|                     App.mainRegion.show(new LogFileLayout()); | ||||
|                 } | ||||
|  | ||||
|                 else { | ||||
|                     this._setTitle('logs'); | ||||
|                     App.mainRegion.show(new LogsLayout()); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             system: function () { | ||||
|   | ||||
							
								
								
									
										13
									
								
								UI/Logs/Files/Collection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								UI/Logs/Files/Collection.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| 'use strict'; | ||||
| define(['Logs/Files/Model' ], | ||||
| function (LogFileModel) { | ||||
|     return Backbone.Collection.extend({ | ||||
|         url  : window.ApiRoot + '/log/files', | ||||
|         model: LogFileModel, | ||||
|  | ||||
|         state: { | ||||
|             sortKey : 'lastWriteTime', | ||||
|             order   : 1 | ||||
|         } | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										8
									
								
								UI/Logs/Files/ContentsModel.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								UI/Logs/Files/ContentsModel.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'backbone' | ||||
|     ], function (Backbone) { | ||||
|         return Backbone.Model.extend({ | ||||
|         }); | ||||
|     }); | ||||
							
								
								
									
										11
									
								
								UI/Logs/Files/ContentsView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								UI/Logs/Files/ContentsView.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| define( | ||||
|     [ | ||||
|         'app', | ||||
|         'marionette' | ||||
|     ], function (App, Marionette) { | ||||
|         return Marionette.ItemView.extend({ | ||||
|             template: 'Logs/Files/ContentsViewTemplate' | ||||
|         }); | ||||
|     }); | ||||
							
								
								
									
										11
									
								
								UI/Logs/Files/ContentsViewTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								UI/Logs/Files/ContentsViewTemplate.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <div class="row"> | ||||
|     <div class="span12"> | ||||
|         <h3>{{filename}}</h3> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <div class="row"> | ||||
|     <div class="span12"> | ||||
|         <pre>{{contents}}</pre> | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										18
									
								
								UI/Logs/Files/FilenameCell.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								UI/Logs/Files/FilenameCell.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'Cells/NzbDroneCell' | ||||
|     ], function (NzbDroneCell) { | ||||
|         return NzbDroneCell.extend({ | ||||
|  | ||||
|             className: 'log-filename-cell', | ||||
|  | ||||
|             render: function () { | ||||
|  | ||||
|                 var filename = this._getValue(); | ||||
|                 this.$el.html(filename); | ||||
|  | ||||
|                 return this; | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
							
								
								
									
										79
									
								
								UI/Logs/Files/Layout.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								UI/Logs/Files/Layout.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'app', | ||||
|         'marionette', | ||||
|         'backgrid', | ||||
|         'Logs/Files/FilenameCell', | ||||
|         'Cells/RelativeDateCell', | ||||
|         'Logs/Files/Collection', | ||||
|         'Logs/Files/Row', | ||||
|         'Logs/Files/ContentsView', | ||||
|         'Logs/Files/ContentsModel' | ||||
|     ], function (App, Marionette, Backgrid, FilenameCell, RelativeDateCell, LogFileCollection, LogFileRow, ContentsView, ContentsModel) { | ||||
|         return Marionette.Layout.extend({ | ||||
|             template: 'Logs/Files/LayoutTemplate', | ||||
|  | ||||
|             regions: { | ||||
|                 grid     : '#x-grid', | ||||
|                 contents : '#x-contents' | ||||
|             }, | ||||
|  | ||||
|             columns: | ||||
|                 [ | ||||
|                     { | ||||
|                         name : 'filename', | ||||
|                         label: 'Filename', | ||||
|                         cell : FilenameCell | ||||
|                     }, | ||||
|                     { | ||||
|                         name : 'lastWriteTime', | ||||
|                         label: 'Last Write Time', | ||||
|                         cell : RelativeDateCell | ||||
|                     } | ||||
|                 ], | ||||
|  | ||||
|             initialize: function () { | ||||
|                 this.collection = new LogFileCollection(); | ||||
|                 this.collectionPromise = this.collection.fetch(); | ||||
|  | ||||
|                 App.vent.on(App.Commands.ShowLogFile, this._showLogFile, this); | ||||
|             }, | ||||
|  | ||||
|             onShow: function () { | ||||
|                 var self = this; | ||||
|                 this._showTable(); | ||||
|  | ||||
|                 this.collectionPromise.done(function (){ | ||||
|                     self._showLogFile({ model: _.first(self.collection.models) }); | ||||
|                 }); | ||||
|             }, | ||||
|  | ||||
|             _showTable: function () { | ||||
|  | ||||
|                 this.grid.show(new Backgrid.Grid({ | ||||
|                     row       : LogFileRow, | ||||
|                     columns   : this.columns, | ||||
|                     collection: this.collection, | ||||
|                     className : 'table table-hover' | ||||
|                 })); | ||||
|             }, | ||||
|  | ||||
|             _showLogFile: function (options) { | ||||
|                 var self = this; | ||||
|                 var filename = options.model.get('filename'); | ||||
|  | ||||
|                 $.ajax({ | ||||
|                     url: '/log/' + filename, | ||||
|                     success: function (data) { | ||||
|                         var model = new ContentsModel({ | ||||
|                             filename: filename, | ||||
|                             contents: data | ||||
|                         }); | ||||
|  | ||||
|                         self.contents.show(new ContentsView({ model: model })); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
							
								
								
									
										11
									
								
								UI/Logs/Files/LayoutTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								UI/Logs/Files/LayoutTemplate.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <div class="row"> | ||||
|     <div class="span12"> | ||||
|         <div id="x-grid"/> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <div class="row"> | ||||
|     <div class="span12"> | ||||
|         <div id="x-contents"/> | ||||
|     </div> | ||||
| </div> | ||||
							
								
								
									
										8
									
								
								UI/Logs/Files/Model.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								UI/Logs/Files/Model.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'backbone' | ||||
|     ], function (Backbone) { | ||||
|         return Backbone.Model.extend({ | ||||
|         }); | ||||
|     }); | ||||
							
								
								
									
										19
									
								
								UI/Logs/Files/Row.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								UI/Logs/Files/Row.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'app', | ||||
|         'backgrid' | ||||
|     ], function (App, Backgrid) { | ||||
|  | ||||
|         return Backgrid.Row.extend({ | ||||
|             className: 'log-file-row', | ||||
|  | ||||
|             events: { | ||||
|                 'click': '_showContents' | ||||
|             }, | ||||
|  | ||||
|             _showContents: function () { | ||||
|                 App.vent.trigger(App.Commands.ShowLogFile, { model: this.model }); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
| @@ -6,8 +6,9 @@ define( | ||||
|         'Logs/LogTimeCell', | ||||
|         'Logs/LogLevelCell', | ||||
|         'Shared/Grid/Pager', | ||||
|         'Logs/Collection' | ||||
|     ], function (Marionette, Backgrid, LogTimeCell, LogLevelCell, GridPager, LogCollection) { | ||||
|         'Logs/Collection', | ||||
|         'Shared/Toolbar/ToolbarLayout' | ||||
|     ], function (Marionette, Backgrid, LogTimeCell, LogLevelCell, GridPager, LogCollection, ToolbarLayout) { | ||||
|         return Marionette.Layout.extend({ | ||||
|             template: 'Logs/LayoutTemplate', | ||||
|  | ||||
| @@ -52,7 +53,30 @@ define( | ||||
|                     } | ||||
|                 ], | ||||
|  | ||||
|             showTable: function () { | ||||
|             leftSideButtons: { | ||||
|                 type      : 'default', | ||||
|                 storeState: false, | ||||
|                 items     : | ||||
|                     [ | ||||
|                         { | ||||
|                             title: 'Files', | ||||
|                             icon : 'icon-file', | ||||
|                             route: 'logs/files' | ||||
|                         } | ||||
|                     ] | ||||
|             }, | ||||
|  | ||||
|             initialize: function () { | ||||
|                 this.collection = new LogCollection(); | ||||
|                 this.collection.fetch(); | ||||
|             }, | ||||
|  | ||||
|             onShow: function () { | ||||
|                 this._showToolbar(); | ||||
|                 this._showTable(); | ||||
|             }, | ||||
|  | ||||
|             _showTable: function () { | ||||
|  | ||||
|                 this.grid.show(new Backgrid.Grid({ | ||||
|                     row       : Backgrid.Row, | ||||
| @@ -67,14 +91,14 @@ define( | ||||
|                 })); | ||||
|             }, | ||||
|  | ||||
|             initialize: function () { | ||||
|                 this.collection = new LogCollection(); | ||||
|                 this.collection.fetch(); | ||||
|             }, | ||||
|  | ||||
|             onShow: function () { | ||||
|                 this.showTable(); | ||||
|             _showToolbar: function () { | ||||
|                 this.toolbar.show(new ToolbarLayout({ | ||||
|                     left   : | ||||
|                         [ | ||||
|                             this.leftSideButtons | ||||
|                         ], | ||||
|                     context: this | ||||
|                 })); | ||||
|             } | ||||
|  | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| @import "../Content/FontAwesome/font-awesome"; | ||||
| @import "../Shared/Styles/clickable"; | ||||
|  | ||||
| #logs-screen { | ||||
|  | ||||
| @@ -45,6 +46,8 @@ | ||||
|     .icon(@remove-sign); | ||||
|     color : purple; | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| .log-file-row { | ||||
|   .clickable; | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| 'use strict'; | ||||
| define( | ||||
|     [ | ||||
|         'backgrid' | ||||
|     ], function (Backgrid) { | ||||
|  | ||||
|         return Backgrid.Row.extend({ | ||||
|             events: { | ||||
|                 'click .x-search': 'search' | ||||
|             }, | ||||
|             search: function () { | ||||
|                 window.alert('Episode Search'); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
| @@ -22,6 +22,7 @@ require( | ||||
|                 'missing'                   : 'missing', | ||||
|                 'history'                   : 'history', | ||||
|                 'logs'                      : 'logs', | ||||
|                 'logs/:action'              : 'logs', | ||||
|                 'rss'                       : 'rss', | ||||
|                 'system'                    : 'system', | ||||
|                 ':whatever'                 : 'notFound' | ||||
|   | ||||
| @@ -179,7 +179,8 @@ define( | ||||
|             DeleteSeriesCommand: 'DeleteSeriesCommand', | ||||
|             CloseModalCommand  : 'CloseModalCommand', | ||||
|             ShowEpisodeDetails : 'ShowEpisodeDetails', | ||||
|             SaveSettings       : 'saveSettings' | ||||
|             SaveSettings       : 'saveSettings', | ||||
|             ShowLogFile        : 'showLogFile' | ||||
|         }; | ||||
|  | ||||
|         app.addInitializer(function () { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user