mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 20:12:41 +02:00
added /logs
This commit is contained in:
parent
fc7d4536ac
commit
9160343a51
@ -8,6 +8,7 @@
|
|||||||
using NzbDrone.Api.Episodes;
|
using NzbDrone.Api.Episodes;
|
||||||
using NzbDrone.Api.History;
|
using NzbDrone.Api.History;
|
||||||
using NzbDrone.Api.Indexers;
|
using NzbDrone.Api.Indexers;
|
||||||
|
using NzbDrone.Api.Logs;
|
||||||
using NzbDrone.Api.Mapping;
|
using NzbDrone.Api.Mapping;
|
||||||
using NzbDrone.Api.Qualities;
|
using NzbDrone.Api.Qualities;
|
||||||
using NzbDrone.Api.RootFolders;
|
using NzbDrone.Api.RootFolders;
|
||||||
@ -15,6 +16,7 @@
|
|||||||
using NzbDrone.Api.Update;
|
using NzbDrone.Api.Update;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Instrumentation;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
@ -40,6 +42,7 @@ public class ResourceMappingFixture : TestBase
|
|||||||
[TestCase(typeof(UpdatePackage), typeof(UpdateResource))]
|
[TestCase(typeof(UpdatePackage), typeof(UpdateResource))]
|
||||||
[TestCase(typeof(QualityProfile), typeof(QualityProfileResource))]
|
[TestCase(typeof(QualityProfile), typeof(QualityProfileResource))]
|
||||||
[TestCase(typeof(Quality), typeof(QualityResource))]
|
[TestCase(typeof(Quality), typeof(QualityResource))]
|
||||||
|
[TestCase(typeof(Log), typeof(LogResource))]
|
||||||
public void matching_fields(Type modelType, Type resourceType)
|
public void matching_fields(Type modelType, Type resourceType)
|
||||||
{
|
{
|
||||||
MappingValidation.ValidateMapping(modelType, resourceType);
|
MappingValidation.ValidateMapping(modelType, resourceType);
|
||||||
|
25
NzbDrone.Api/Logs/LogModule.cs
Normal file
25
NzbDrone.Api/Logs/LogModule.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.History;
|
||||||
|
using NzbDrone.Core.Instrumentation;
|
||||||
|
using NzbDrone.Api.Mapping;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Logs
|
||||||
|
{
|
||||||
|
public class LogModule : NzbDroneRestModule<LogResource>
|
||||||
|
{
|
||||||
|
private readonly ILogService _logService;
|
||||||
|
private readonly IHistoryService _historyService;
|
||||||
|
|
||||||
|
public LogModule(ILogService logService)
|
||||||
|
{
|
||||||
|
_logService = logService;
|
||||||
|
GetResourcePaged = GetLogs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PagingResource<LogResource> GetLogs(PagingResource<LogResource> pagingResource)
|
||||||
|
{
|
||||||
|
var pageSpec = pagingResource.InjectTo<PagingSpec<Log>>();
|
||||||
|
return ApplyToPage(_logService.Paged, pageSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
NzbDrone.Api/Logs/LogResource.cs
Normal file
16
NzbDrone.Api/Logs/LogResource.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Logs
|
||||||
|
{
|
||||||
|
public class LogResource : RestResource
|
||||||
|
{
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
public String Exception { get; set; }
|
||||||
|
public String ExceptionType { get; set; }
|
||||||
|
public String Level { get; set; }
|
||||||
|
public String Logger { get; set; }
|
||||||
|
public String Message { get; set; }
|
||||||
|
public String Method { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -115,6 +115,8 @@
|
|||||||
<Compile Include="Indexers\IndexerResource.cs" />
|
<Compile Include="Indexers\IndexerResource.cs" />
|
||||||
<Compile Include="Indexers\ReleaseModule.cs" />
|
<Compile Include="Indexers\ReleaseModule.cs" />
|
||||||
<Compile Include="Extensions\LazyExtensions.cs" />
|
<Compile Include="Extensions\LazyExtensions.cs" />
|
||||||
|
<Compile Include="Logs\LogModule.cs" />
|
||||||
|
<Compile Include="Logs\LogResource.cs" />
|
||||||
<Compile Include="Mapping\CloneInjection.cs" />
|
<Compile Include="Mapping\CloneInjection.cs" />
|
||||||
<Compile Include="Mapping\MappingValidation.cs" />
|
<Compile Include="Mapping\MappingValidation.cs" />
|
||||||
<Compile Include="Mapping\ResourceMappingException.cs" />
|
<Compile Include="Mapping\ResourceMappingException.cs" />
|
||||||
|
@ -195,21 +195,25 @@ private PagingResource<TResource> ReadPagingResourceFromRequest()
|
|||||||
Int32.TryParse(Request.Query.Page.ToString(), out page);
|
Int32.TryParse(Request.Query.Page.ToString(), out page);
|
||||||
if (page == 0) page = 1;
|
if (page == 0) page = 1;
|
||||||
|
|
||||||
var sortKey = Request.Query.SortKey.ToString();
|
|
||||||
if (String.IsNullOrEmpty(sortKey)) sortKey = "AirDate";
|
|
||||||
|
|
||||||
var sortDirection = Request.Query.SortDir.ToString()
|
|
||||||
.Equals("Asc", StringComparison.InvariantCultureIgnoreCase)
|
|
||||||
? SortDirection.Ascending
|
|
||||||
: SortDirection.Descending;
|
|
||||||
|
|
||||||
var pagingResource = new PagingResource<TResource>
|
var pagingResource = new PagingResource<TResource>
|
||||||
{
|
{
|
||||||
PageSize = pageSize,
|
PageSize = pageSize,
|
||||||
Page = page,
|
Page = page,
|
||||||
SortKey = sortKey,
|
};
|
||||||
SortDirection = sortDirection
|
|
||||||
};
|
if (Request.Query.SortKey != null)
|
||||||
|
{
|
||||||
|
pagingResource.SortKey = Request.Query.SortKey.ToString();
|
||||||
|
|
||||||
|
if (Request.Query.SortDir != null)
|
||||||
|
{
|
||||||
|
pagingResource.SortDirection = Request.Query.SortDir.ToString()
|
||||||
|
.Equals("Asc", StringComparison.InvariantCultureIgnoreCase)
|
||||||
|
? SortDirection.Ascending
|
||||||
|
: SortDirection.Descending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pagingResource;
|
return pagingResource;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
void DeleteMany(IEnumerable<int> ids);
|
void DeleteMany(IEnumerable<int> ids);
|
||||||
void SetFields(TModel model, params Expression<Func<TModel, object>>[] properties);
|
void SetFields(TModel model, params Expression<Func<TModel, object>>[] properties);
|
||||||
TModel Single();
|
TModel Single();
|
||||||
|
PagingSpec<TModel> GetPaged(PagingSpec<TModel> pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -198,6 +199,21 @@ public void SetFields(TModel model, params Expression<Func<TModel, object>>[] pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual PagingSpec<TModel> GetPaged(PagingSpec<TModel> pagingSpec)
|
||||||
|
{
|
||||||
|
var pagingQuery = Query.OrderBy(pagingSpec.OrderByClause(), pagingSpec.ToSortDirection())
|
||||||
|
.Skip(pagingSpec.PagingOffset())
|
||||||
|
.Take(pagingSpec.PageSize);
|
||||||
|
|
||||||
|
pagingSpec.Records = pagingQuery.ToList();
|
||||||
|
|
||||||
|
//TODO: Use the same query for count and records
|
||||||
|
pagingSpec.TotalRecords = Count();
|
||||||
|
|
||||||
|
return pagingSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PublishModelEvent(TModel model, RepositoryAction action)
|
private void PublishModelEvent(TModel model, RepositoryAction action)
|
||||||
{
|
{
|
||||||
if (PublishModelEvents)
|
if (PublishModelEvents)
|
||||||
|
@ -13,7 +13,6 @@ public interface IHistoryRepository : IBasicRepository<History>
|
|||||||
{
|
{
|
||||||
void Trim();
|
void Trim();
|
||||||
List<QualityModel> GetEpisodeHistory(int episodeId);
|
List<QualityModel> GetEpisodeHistory(int episodeId);
|
||||||
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
|
public class HistoryRepository : BasicRepository<History>, IHistoryRepository
|
||||||
@ -36,7 +35,7 @@ public List<QualityModel> GetEpisodeHistory(int episodeId)
|
|||||||
return history.Select(h => h.Quality).ToList();
|
return history.Select(h => h.Quality).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PagingSpec<History> Paged(PagingSpec<History> pagingSpec)
|
public override PagingSpec<History> GetPaged(PagingSpec<History> pagingSpec)
|
||||||
{
|
{
|
||||||
var pagingQuery = Query.Join<History, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id)
|
var pagingQuery = Query.Join<History, Series>(JoinType.Inner, h => h.Series, (h, s) => h.SeriesId == s.Id)
|
||||||
.Join<History, Episode>(JoinType.Inner, h => h.Episode, (h, e) => h.EpisodeId == e.Id)
|
.Join<History, Episode>(JoinType.Inner, h => h.Episode, (h, e) => h.EpisodeId == e.Id)
|
||||||
|
@ -36,7 +36,7 @@ public List<History> All()
|
|||||||
|
|
||||||
public PagingSpec<History> Paged(PagingSpec<History> pagingSpec)
|
public PagingSpec<History> Paged(PagingSpec<History> pagingSpec)
|
||||||
{
|
{
|
||||||
return _historyRepository.Paged(pagingSpec);
|
return _historyRepository.GetPaged(pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Purge()
|
public void Purge()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Instrumentation
|
namespace NzbDrone.Core.Instrumentation
|
||||||
{
|
{
|
||||||
@ -6,6 +7,7 @@ public interface ILogService
|
|||||||
{
|
{
|
||||||
void DeleteAll();
|
void DeleteAll();
|
||||||
void Trim();
|
void Trim();
|
||||||
|
PagingSpec<Log> Paged(PagingSpec<Log> pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LogService : ILogService
|
public class LogService : ILogService
|
||||||
@ -26,5 +28,10 @@ public void Trim()
|
|||||||
{
|
{
|
||||||
_logRepository.Trim();
|
_logRepository.Trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PagingSpec<Log> Paged(PagingSpec<Log> pagingSpec)
|
||||||
|
{
|
||||||
|
return _logRepository.GetPaged(pagingSpec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ define(['app',
|
|||||||
'Series/Details/SeriesDetailsLayout',
|
'Series/Details/SeriesDetailsLayout',
|
||||||
'Series/EpisodeCollection',
|
'Series/EpisodeCollection',
|
||||||
'Settings/SettingsLayout',
|
'Settings/SettingsLayout',
|
||||||
|
'Logs/Layout',
|
||||||
'Missing/MissingLayout',
|
'Missing/MissingLayout',
|
||||||
'History/HistoryLayout'],
|
'History/HistoryLayout'],
|
||||||
function () {
|
function () {
|
||||||
@ -62,11 +63,17 @@ define(['app',
|
|||||||
NzbDrone.mainRegion.show(new NzbDrone.History.HistoryLayout());
|
NzbDrone.mainRegion.show(new NzbDrone.History.HistoryLayout());
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logs: function () {
|
||||||
|
this._setTitle('logs');
|
||||||
|
NzbDrone.mainRegion.show(new NzbDrone.Logs.Layout());
|
||||||
|
},
|
||||||
|
|
||||||
notFound: function () {
|
notFound: function () {
|
||||||
this._setTitle('Not Found');
|
this._setTitle('Not Found');
|
||||||
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));
|
NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
_setTitle: function (title) {
|
_setTitle: function (title) {
|
||||||
//$('#title-region').html(title);
|
//$('#title-region').html(title);
|
||||||
|
|
||||||
|
37
UI/Logs/Collection.js
Normal file
37
UI/Logs/Collection.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
"use strict";
|
||||||
|
define(['app', 'Logs/Model'], function () {
|
||||||
|
NzbDrone.Logs.Collection = Backbone.PageableCollection.extend({
|
||||||
|
url : NzbDrone.Constants.ApiRoot + '/log',
|
||||||
|
model : NzbDrone.Logs.Model,
|
||||||
|
|
||||||
|
state: {
|
||||||
|
pageSize: 50,
|
||||||
|
sortKey: "time",
|
||||||
|
order: 1
|
||||||
|
},
|
||||||
|
|
||||||
|
queryParams: {
|
||||||
|
totalPages: null,
|
||||||
|
totalRecords: null,
|
||||||
|
pageSize: 'pageSize',
|
||||||
|
sortKey: "sortKey",
|
||||||
|
order: "sortDir",
|
||||||
|
directions: {
|
||||||
|
"-1": "asc",
|
||||||
|
"1": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parseState: function (resp, queryParams, state) {
|
||||||
|
return {totalRecords: resp.totalRecords};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseRecords: function (resp) {
|
||||||
|
if (resp) {
|
||||||
|
return resp.records;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
72
UI/Logs/Layout.js
Normal file
72
UI/Logs/Layout.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
"use strict";
|
||||||
|
define([
|
||||||
|
'app',
|
||||||
|
'Logs/Collection',
|
||||||
|
'Shared/Toolbar/ToolbarLayout'
|
||||||
|
],
|
||||||
|
function () {
|
||||||
|
NzbDrone.Logs.Layout = Backbone.Marionette.Layout.extend({
|
||||||
|
template: 'Logs/LayoutTemplate',
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
grid : '#x-grid',
|
||||||
|
toolbar: '#x-toolbar',
|
||||||
|
pager : '#x-pager'
|
||||||
|
},
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name : 'level',
|
||||||
|
label : 'Level',
|
||||||
|
sortable: true,
|
||||||
|
cell : Backgrid.StringCell
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'logger',
|
||||||
|
label : 'Component',
|
||||||
|
sortable: true,
|
||||||
|
cell : Backgrid.StringCell
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'message',
|
||||||
|
label : 'Message',
|
||||||
|
sortable: false,
|
||||||
|
cell : Backgrid.StringCell
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'time',
|
||||||
|
label: 'Time',
|
||||||
|
cell : Backgrid.DatetimeCell
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
showTable: function () {
|
||||||
|
|
||||||
|
this.grid.show(new Backgrid.Grid(
|
||||||
|
{
|
||||||
|
row : Backgrid.Row,
|
||||||
|
columns : this.columns,
|
||||||
|
collection: this.collection,
|
||||||
|
className : 'table table-hover'
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.pager.show(new Backgrid.NzbDronePaginator({
|
||||||
|
columns : this.columns,
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.collection = new NzbDrone.Logs.Collection();
|
||||||
|
this.collection.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow: function () {
|
||||||
|
this.showTable();
|
||||||
|
//this.toolbar.show(new NzbDrone.Shared.Toolbar.ToolbarLayout({right: [ viewButtons], context: this}));
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
;
|
||||||
|
})
|
||||||
|
;
|
11
UI/Logs/LayoutTemplate.html
Normal file
11
UI/Logs/LayoutTemplate.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<div id="x-toolbar"></div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<div id="x-grid"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="span12">
|
||||||
|
<div id="x-pager"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
14
UI/Logs/Model.js
Normal file
14
UI/Logs/Model.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
"use strict";
|
||||||
|
define(['app'], function (app) {
|
||||||
|
NzbDrone.Logs.Model = Backbone.Model.extend({
|
||||||
|
/* mutators: {
|
||||||
|
seasonNumber: function () {
|
||||||
|
return this.get('episode').seasonNumber;
|
||||||
|
},
|
||||||
|
|
||||||
|
paddedEpisodeNumber: function () {
|
||||||
|
return this.get('episode').episodeNumber.pad(2);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
});
|
||||||
|
});
|
@ -16,6 +16,7 @@ require(['app', 'Controller'], function (app, controller) {
|
|||||||
'settings/:action(/:query)' : 'settings',
|
'settings/:action(/:query)' : 'settings',
|
||||||
'missing' : 'missing',
|
'missing' : 'missing',
|
||||||
'history' : 'history',
|
'history' : 'history',
|
||||||
|
'logs' : 'logs',
|
||||||
':whatever' : 'notFound'
|
':whatever' : 'notFound'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -82,6 +82,7 @@ define('app', ['shared/modal/region'], function (ModalRegion) {
|
|||||||
|
|
||||||
window.NzbDrone.Missing = {};
|
window.NzbDrone.Missing = {};
|
||||||
window.NzbDrone.History = {};
|
window.NzbDrone.History = {};
|
||||||
|
window.NzbDrone.Logs = {};
|
||||||
window.NzbDrone.Mixins = {};
|
window.NzbDrone.Mixins = {};
|
||||||
|
|
||||||
window.NzbDrone.Events = {
|
window.NzbDrone.Events = {
|
||||||
|
Loading…
Reference in New Issue
Block a user