目标是创建日志类并使用 RavenDB 进行存储。我最初想使用 NLog,它不附带 RavenDb 目标,但可以轻松添加它。我也这样做了,但我的目标没有按预期行事,我正在旋转我的轮子试图弄清楚它并最终决定创建我自己的服务。
我还打算使用 StructureMap 将此日志服务注入客户端。这是我最初的 SM 配置:
x.For<ILogger>().Use<Logger>()
.Ctor<IDocumentStore>("store").Is(c => c.GetInstance<IDocumentStore>())
.Ctor<ILogEntry>("logEntry").Is(c => c.GetInstance<ILogEntry>())
.Ctor<ILogLevelConfig>("logLevelConfig")
.Is(c => c.GetInstance<ILogLevelConfig>());
x.For<IDocumentStore>()
.Singleton()
.Use(() => new DocumentStore { Url="http://localhost:8080/" })
.OnCreation<IDocumentStore>(c => c.Initialize());
// ILogEntry is implemented by a class, which will eventually be saved in Raven
// ILogLevelConfig is used for configuration purposes
以下是简化版Logger
:
public class Logger : ILogger
{
private readonly ILogEntry _logEntry;
private readonly IDocumentStore _store;
private readonly ILogLevelConfig _logLevelConfig;
public Logger(IDocumentStore store, ILogEntry logEntry, ILogLevelConfig logLevelConfig)
{
_logEntry = logEntry;
_logEntry.TimeStamp = new DateTimeOffset(DateTime.UtcNow);
_logLevelConfig = logLevelConfig;
_store = store;
}
public void Info(string message, string userId = null)
{
if (!_logLevelConfig.IsAllEnabled && !_logLevelConfig.IsInfoEnabled) return;
_logEntry.LogLevel = LogLevel.Info;
_logEntry.Message = message;
_logEntry.UserIdentity = userId;
Write();
}
private void Write()
{
using(var session = _store.OpenSession())
{
session.Store(_logEntry);
session.SaveChanges();
}
}
现在,让我们模拟注入Logger
一些客户端:
var logger = ObjectFactory.GetInstance<ILogger>();
logger.Info("info 1");
logger.Info("info 2");
问题:
- 实现的方式
Write()
记录器将两次访问数据库[对于'info 1',然后对于'info 2'。如果我决定非常详细地记录我的日志,这将是一种非常健谈的方法。我该怎么做才能将所有内容收集logger.Info(...)
到一个中,然后session.SaveChanges()
调用一次并一次性保存所有条目? - 当我像这样替换
IDocumentStore
实现时:x.For<IDocumentStore>().Singleton().Use(() => new EmbeddableDocumentStore { RunInMemory = true, UseEmbeddedHttpServer = true }).OnCreation<IDocumentStore>(c => c.Initialize());
只有第二次调用logger.Info(..)
才会实际保存在数据库中。为什么?