目標は、ロギングクラスを作成し、ストレージにRavenDBを使用することです。私はもともとRavenDbターゲットに付属していないNLogを使用したかったのですが、簡単に追加できます。私もそうしましたが、ターゲットが意図したとおりに動作していなかったので、それを理解しようとして車輪を回し、最終的に独自のサービスを作成することにしました。
私の意図は、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()
は、ロガーがデータベースに2回ヒットします['info 1'の場合、次に'info2'の場合。ロギングを非常に詳細に行うことにした場合、これは非常におしゃべりなアプローチになります。すべてlogger.Info(...)
を1つにまとめてから、session.SaveChanges()
一度呼び出してすべてのエントリを一度に保存するにはどうすればよいですか? IDocumentStore
このように実装 を置き換えるx.For<IDocumentStore>().Singleton().Use(() => new EmbeddableDocumentStore { RunInMemory = true, UseEmbeddedHttpServer = true }).OnCreation<IDocumentStore>(c => c.Initialize());
と、2番目の呼び出しのみlogger.Info(..)
が実際にデータベースに保存されます。なんで?