moved log to object db.

This commit is contained in:
kay.one 2013-02-23 11:38:25 -08:00
parent 71dcd623f7
commit b3c6db5997
21 changed files with 157 additions and 321 deletions

View File

@ -130,8 +130,8 @@
<Content Include="Upcoming\UpcomingCollection.js" />
<Content Include="Upcoming\UpcomingCollectionTemplate.html" />
<Content Include="Upcoming\UpcomingCollectionView.js" />
<Content Include="Upcoming\UpcomingGroupTemplate.html" />
<Content Include="Upcoming\UpcomingGroupView.js" />
<Content Include="Upcoming\UpcomingItemTemplate.html" />
<Content Include="Upcoming\UpcomingItemView.js" />
<Content Include="Upcoming\UpcomingModel.js" />
</ItemGroup>
<ItemGroup>

View File

@ -19,8 +19,6 @@ namespace NzbDrone.Core.Test.Datastore
[SetUp]
public void SetUp()
{
WithObjectDb(memory:false);
childModel = Builder<ChildModel>
.CreateNew()
.With(s => s.OID = 0)
@ -31,7 +29,6 @@ namespace NzbDrone.Core.Test.Datastore
.With(e => e.OID = 0)
.Build();
}
[Test]

View File

@ -17,7 +17,7 @@ namespace NzbDrone.Core.Test.Datastore
}
[TestFixture]
public class SimpleRepositoryFixture : ObjectDbTest<BasicRepository<SampleType>>
public class SimpleRepositoryFixture : ObjectDbTest<BasicRepository<SampleType>,SampleType>
{
private SampleType sampleType;
@ -25,7 +25,6 @@ namespace NzbDrone.Core.Test.Datastore
[SetUp]
public void Setup()
{
WithObjectDb();
sampleType = Builder<SampleType>
.CreateNew()
.With(c => c.OID = 0)

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NUnit.Framework;
@ -7,32 +8,35 @@ using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Test.Framework
{
public abstract class RepositoryTest<TRepository, TModel> : ObjectDbTest<TRepository>
where TRepository : class, IBasicRepository<TModel>
public abstract class ObjectDbTest<TSubject, TModel> : ObjectDbTest
where TSubject : class
where TModel : ModelBase, new()
{
private TSubject _subject;
protected BasicRepository<TModel> Storage { get; private set; }
[SetUp]
public void RepositoryTestSetup()
protected IList<TModel> AllStoredModels
{
WithObjectDb();
Storage = Mocker.Resolve<BasicRepository<TModel>>();
get
{
return Storage.All().ToList();
}
}
}
public abstract class ObjectDbTest<TSubject> : ObjectDbTest where TSubject : class
{
private TSubject _subject;
protected TModel StoredModel
{
get
{
return Storage.All().Single();
}
}
[SetUp]
public void CoreTestSetup()
{
_subject = null;
Storage = Mocker.Resolve<BasicRepository<TModel>>();
}
protected TSubject Subject
@ -65,20 +69,18 @@ namespace NzbDrone.Core.Test.Framework
}
}
protected void WithObjectDb(bool memory = true)
private void WithObjectDb(bool memory = true)
{
//if (memory)
//{
// _db = new SiaqoDbFactory(new DiskProvider(),new EnvironmentProvider()).CreateMemoryDb();
//}
//else
//{
_db = new SiaqoDbFactory(new DiskProvider(), new EnvironmentProvider()).Create(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Guid.NewGuid().ToString()));
//}
Mocker.SetConstant(Db);
}
[SetUp]
public void SetupReadDb()
{
WithObjectDb();
}
[TearDown]
public void ObjectDbTearDown()
{

View File

@ -18,7 +18,7 @@ using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
public class JobRepositoryFixture : RepositoryTest<JobRepository, JobDefinition>
public class JobRepositoryFixture : ObjectDbTest<JobRepository, JobDefinition>
{
FakeJob _fakeJob;
DisabledJob _disabledJob;

View File

@ -233,7 +233,7 @@
<Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" />
<Compile Include="ProviderTests\DiskScanProviderTests\ImportFileFixture.cs" />
<Compile Include="FluentTest.cs" />
<Compile Include="ProviderTests\LogProviderTests\LogProviderFixture.cs" />
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
<Compile Include="ProviderTests\UpcomingEpisodesProviderTest.cs" />
<Compile Include="ProviderTests\MediaFileProviderTests\GetNewFilenameFixture.cs" />
<Compile Include="Framework\SqlCeTest.cs" />

View File

@ -55,5 +55,5 @@
<RegularExpression>NzbDrone\.Core\.Test\.ParserTests\.ParserFixture\..*</RegularExpression>
</RegexTestSelector>
</IgnoredTests>
<HiddenWarnings>PostBuildEventDisabled</HiddenWarnings>
<HiddenWarnings>PostBuildEventDisabled;PreBuildEventDisabled</HiddenWarnings>
</ProjectConfiguration>

View File

@ -1,171 +0,0 @@
// ReSharper disable InconsistentNaming
using System;
using System.Diagnostics;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NLog;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.ProviderTests.LogProviderTests
{
[TestFixture]
public class LogProviderFixture : SqlCeTest
{
private const string LOGGER_NAME = "Core.Test.ProviderTests.LogProviderTests.LogProviderFixture";
private static string UniqueMessage;
Logger Logger;
[SetUp]
public void Setup()
{
WithRealDb();
new DatabaseTarget(Db).Register();
Logger = LogManager.GetCurrentClassLogger();
UniqueMessage = "Unique message: " + Guid.NewGuid().ToString();
}
[Test]
public void write_log()
{
Logger.Info(UniqueMessage);
//Assert
var logItem = Db.Fetch<Log>().Single();
logItem.Message.Should().Be(UniqueMessage);
VerifyLog(logItem, LogLevel.Info);
}
[Test]
public void write_long_log()
{
//setup
var message = String.Empty;
for (int i = 0; i < 100; i++)
{
message += Guid.NewGuid();
}
//Act
Logger.Info(message);
var logItem = Db.Fetch<Log>().Single();
logItem.Message.Should().HaveLength(message.Length);
logItem.Message.Should().Be(message);
VerifyLog(logItem, LogLevel.Info);
}
[Test]
public void clearLog()
{
WithTempAsAppPath();
//Act
for (int i = 0; i < 10; i++)
{
Logger.Info(UniqueMessage);
}
var provider = Mocker.Resolve<LogProvider>();
provider.GetAllLogs().Should().HaveCount(10);
provider.DeleteAll();
provider.GetAllLogs().Should().HaveCount(1);
}
[Test]
public void write_log_exception()
{
var ex = new InvalidOperationException("Fake Exception");
//Act
Logger.ErrorException(UniqueMessage, ex);
//Assert
var logItem = Db.Fetch<Log>().Single();
VerifyLog(logItem, LogLevel.Error);
logItem.Message.Should().Be(UniqueMessage + ": " + ex.Message);
logItem.ExceptionType.Should().Be(ex.GetType().ToString());
logItem.Exception.Should().Be(ex.ToString());
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void exception_log_with_no_message_should_use_exceptions_message()
{
var ex = new InvalidOperationException("Fake Exception");
UniqueMessage = String.Empty;
Logger.ErrorException(UniqueMessage, ex);
var logItem = Db.Fetch<Log>().Single();
logItem.Message.Should().Be(ex.Message);
VerifyLog(logItem, LogLevel.Error);
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void null_string_as_arg_should_not_fail()
{
var epFile = new EpisodeFile();
Logger.Trace("File {0} no longer exists on disk. removing from database.", epFile.Path);
epFile.Path.Should().BeNull();
}
[Test]
public void Trim_Logs_should_clear_logs_older_than_30_days()
{
//Setup
var historyItem = Builder<Log>.CreateListOfSize(30)
.TheFirst(20).With(c => c.Time = DateTime.Now)
.TheNext(10).With(c => c.Time = DateTime.Now.AddDays(-31))
.Build();
Db.InsertMany(historyItem);
//Act
Db.Fetch<Log>().Should().HaveCount(30);
Mocker.Resolve<LogProvider>().Trim();
//Assert
var result = Db.Fetch<Log>();
result.Should().HaveCount(20);
result.Should().OnlyContain(s => s.Time > DateTime.Now.AddDays(-30));
}
private void VerifyLog(Log logItem, LogLevel level)
{
logItem.Time.Should().BeWithin(TimeSpan.FromSeconds(2));
logItem.Logger.Should().Be(LOGGER_NAME);
logItem.Level.Should().Be(level.Name);
logItem.Method.Should().Be(new StackTrace().GetFrame(1).GetMethod().Name);
Logger.Name.Should().EndWith(logItem.Logger);
}
}
}

View File

@ -80,7 +80,7 @@ namespace NzbDrone.Core
container.RegisterGeneric(typeof(BasicRepository<>)).As(typeof(IBasicRepository<>));
container.RegisterType<DatabaseTarget>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("DatabaseTarget"));
container.RegisterType<LogProvider>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("LogProvider"));
container.RegisterType<LogService>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("LogProvider"));
}
}
}

View File

@ -6,6 +6,7 @@ namespace NzbDrone.Core.Datastore
public interface IBasicRepository<TModel>
{
IEnumerable<TModel> All();
int Count();
TModel Get(int id);
TModel Insert(TModel model);
TModel Update(TModel model);
@ -13,6 +14,7 @@ namespace NzbDrone.Core.Datastore
void Delete(int id);
IList<TModel> InsertMany(IList<TModel> model);
IList<TModel> UpdateMany(IList<TModel> model);
void Purge();
}
public class BasicRepository<TModel> : IBasicRepository<TModel> where TModel : ModelBase, new()
@ -31,6 +33,11 @@ namespace NzbDrone.Core.Datastore
return Queryable.ToList();
}
public int Count()
{
return Queryable.Count();
}
public TModel Get(int id)
{
return Queryable.Single(c => c.OID == id);
@ -58,11 +65,11 @@ namespace NzbDrone.Core.Datastore
public TModel Upsert(TModel model)
{
if(model.OID == 0)
{
return ObjectDatabase.Insert(model);
}
return ObjectDatabase.Update(model);
if (model.OID == 0)
{
return ObjectDatabase.Insert(model);
}
return ObjectDatabase.Update(model);
}
public void Delete(int id)
@ -70,5 +77,18 @@ namespace NzbDrone.Core.Datastore
var itemToDelete = Get(id);
ObjectDatabase.Delete(itemToDelete);
}
public void DeleteMany(IEnumerable<int> ids)
{
foreach (var id in ids)
{
Delete(id);
}
}
public void Purge()
{
DeleteMany(Queryable.Select(c => c.OID));
}
}
}

View File

@ -2,23 +2,20 @@
using NLog.Config;
using NLog;
using NLog.Targets;
using NLog.Targets.Wrappers;
using NzbDrone.Common;
using PetaPoco;
namespace NzbDrone.Core.Instrumentation
{
public class DatabaseTarget : Target
{
private readonly IDatabase _database;
private readonly ILogRepository _repository;
public DatabaseTarget(IDatabase database)
public DatabaseTarget(ILogRepository repository)
{
_database = database;
_repository = repository;
}
public void Register()
{
LogManager.Configuration.AddTarget("DbLogger", this);
@ -62,7 +59,7 @@ namespace NzbDrone.Core.Instrumentation
log.Level = logEvent.Level.Name;
_database.Insert(log);
_repository.Insert(log);
}
}
}

View File

@ -1,15 +1,12 @@
using System;
using PetaPoco;
using NzbDrone.Core.Datastore;
using Sqo.Attributes;
namespace NzbDrone.Core.Instrumentation
{
[TableName("Logs")]
[PrimaryKey("LogId", autoIncrement = true)]
public class Log
public class Log : ModelBase
{
public Int64 LogId { get; protected set; }
[Text]
public string Message { get; set; }
public DateTime Time { get; set; }
@ -18,11 +15,11 @@ namespace NzbDrone.Core.Instrumentation
public string Method { get; set; }
[Text]
public string Exception { get; set; }
public string ExceptionType { get; set; }
public String Level { get; set; }
}
}

View File

@ -1,90 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using DataTables.Mvc.Core.Helpers;
using DataTables.Mvc.Core.Models;
using NLog;
using NzbDrone.Common;
using PetaPoco;
namespace NzbDrone.Core.Instrumentation
{
public class LogProvider
{
private readonly IDatabase _database;
private readonly DiskProvider _diskProvider;
private readonly EnvironmentProvider _environmentProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public LogProvider(IDatabase database, DiskProvider diskProvider, EnvironmentProvider environmentProvider)
{
_database = database;
_diskProvider = diskProvider;
_environmentProvider = environmentProvider;
}
public List<Log> GetAllLogs()
{
return _database.Fetch<Log>();
}
public IList<Log> TopLogs(int count)
{
var logs = _database.Fetch<Log>("SELECT TOP " + count + " * FROM Logs ORDER BY Time Desc");
logs.Add(new Log
{
Time = DateTime.Now.AddYears(-100),
Level = "Info",
Logger = "Core.Instrumentation.LogProvider",
Message = String.Format("Number of logs currently shown: {0}. More may exist, check 'All' to see everything", Math.Min(count, logs.Count))
});
return logs;
}
public virtual Page<Log> GetPagedItems(DataTablesPageRequest pageRequest)
{
var query = Sql.Builder
.Select(@"*")
.From("Logs");
var startPage = (pageRequest.DisplayLength == 0) ? 1 : pageRequest.DisplayStart / pageRequest.DisplayLength + 1;
if (!string.IsNullOrEmpty(pageRequest.Search))
{
var whereClause = string.Join(" OR ", SqlBuilderHelper.GetSearchClause(pageRequest));
if (!string.IsNullOrEmpty(whereClause))
query.Append("WHERE " + whereClause, "%" + pageRequest.Search + "%");
}
var orderBy = string.Join(",", SqlBuilderHelper.GetOrderByClause(pageRequest));
if (!string.IsNullOrEmpty(orderBy))
{
query.Append("ORDER BY " + orderBy);
}
return _database.Page<Log>(startPage, pageRequest.DisplayLength, query);
}
public virtual long Count()
{
return _database.Single<long>(@"SELECT COUNT(*) from Logs");
}
public void DeleteAll()
{
_database.Delete<Log>("");
_diskProvider.DeleteFile(_environmentProvider.GetLogFileName());
_diskProvider.DeleteFile(_environmentProvider.GetArchivedLogFileName());
Logger.Info("Cleared Log History");
}
public void Trim()
{
_database.Delete<Log>("WHERE Time < @0", DateTime.Now.AddDays(-30).Date);
Logger.Debug("Logs have been trimmed, events older than 30 days have been removed");
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Linq;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Instrumentation
{
public interface ILogRepository : IBasicRepository<Log>
{
void Trim();
}
public class LogRepository : BasicRepository<Log>, ILogRepository
{
public LogRepository(IObjectDatabase objectDatabase)
: base(objectDatabase)
{
}
public void Trim()
{
var oldIds = Queryable.Where(c => c.Time < DateTime.Now.AddDays(-30).Date).Select(c => c.OID);
DeleteMany(oldIds);
}
}
}

View File

@ -0,0 +1,39 @@
using System.Linq;
using NLog;
using NzbDrone.Common;
namespace NzbDrone.Core.Instrumentation
{
public interface ILogService
{
void DeleteAll();
void Trim();
}
public class LogService : ILogService
{
private readonly ILogRepository _logRepository;
private readonly DiskProvider _diskProvider;
private readonly EnvironmentProvider _environmentProvider;
private readonly Logger _logger;
public LogService(ILogRepository logRepository, DiskProvider diskProvider,
EnvironmentProvider environmentProvider, Logger logger)
{
_logRepository = logRepository;
_diskProvider = diskProvider;
_environmentProvider = environmentProvider;
_logger = logger;
}
public void DeleteAll()
{
_logRepository.Purge();
}
public void Trim()
{
_logRepository.Trim();
}
}
}

View File

@ -7,11 +7,11 @@ namespace NzbDrone.Core.Instrumentation
{
public class TrimLogsJob : IJob
{
private readonly LogProvider _logProvider;
private readonly LogService _logService;
public TrimLogsJob(LogProvider logProvider)
public TrimLogsJob(LogService logService)
{
_logProvider = logProvider;
_logService = logService;
}
public string Name
@ -26,7 +26,7 @@ namespace NzbDrone.Core.Instrumentation
public virtual void Start(ProgressNotification notification, dynamic options)
{
_logProvider.Trim();
_logService.Trim();
}
}
}

View File

@ -271,6 +271,7 @@
<Compile Include="Indexers\IndexerRepository.cs" />
<Compile Include="Indexers\NewznabRepository.cs" />
<Compile Include="Instrumentation\LogInjectionModule.cs" />
<Compile Include="Instrumentation\LogRepository.cs" />
<Compile Include="Jobs\CleanupRecycleBinJob.cs" />
<Compile Include="Jobs\JobRepository.cs" />
<Compile Include="Lifecycle\AppShutdownJob.cs" />
@ -283,7 +284,7 @@
<Compile Include="Lifecycle\IInitializable.cs" />
<Compile Include="Model\HistoryQueryModel.cs" />
<Compile Include="Model\DownloadClientType.cs" />
<Compile Include="Instrumentation\LogProvider.cs" />
<Compile Include="Instrumentation\LogService.cs" />
<Compile Include="Instrumentation\DatabaseTarget.cs" />
<Compile Include="Model\AtomicParsleyTitleType.cs" />
<Compile Include="Model\ConnectionInfoModel.cs" />

View File

@ -0,0 +1,16 @@
using System.Linq;
using NzbDrone.Test.Common.AutoMoq;
namespace NzbDrone.Test.Common
{
public static class MockerExtensions
{
public static TInterface Resolve<TInterface, TService>(this AutoMoqer mocker)
where TService : TInterface
{
var service = mocker.Resolve<TService>();
mocker.SetConstant<TInterface>(service);
return service;
}
}
}

View File

@ -88,6 +88,7 @@
<Compile Include="AutoMoq\Unity\AutoMockingContainerExtension.cs" />
<Compile Include="ExceptionVerification.cs" />
<Compile Include="LoggingTest.cs" />
<Compile Include="MockerExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionExtensions.cs" />
<Compile Include="TestBase.cs" />

View File

@ -2,6 +2,7 @@
<FileVersion>1</FileVersion>
<AutoEnableOnStartup>True</AutoEnableOnStartup>
<AllowParallelTestExecution>true</AllowParallelTestExecution>
<AllowTestsToRunInParallelWithThemselves>true</AllowTestsToRunInParallelWithThemselves>
<FrameworkUtilisationTypeForNUnit>UseDynamicAnalysis</FrameworkUtilisationTypeForNUnit>
<FrameworkUtilisationTypeForGallio>Disabled</FrameworkUtilisationTypeForGallio>
<FrameworkUtilisationTypeForMSpec>Disabled</FrameworkUtilisationTypeForMSpec>

View File

@ -13,7 +13,9 @@
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
<DefaultTestTimeout>60000</DefaultTestTimeout>
<UseBuildConfiguration />
<ProxyProcessPath />
<UseBuildConfiguration></UseBuildConfiguration>
<UseBuildPlatform />
<ProxyProcessPath></ProxyProcessPath>
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
<HiddenWarnings>PostBuildEventDisabled</HiddenWarnings>
</ProjectConfiguration>