2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ASP.NET CoreでNLogを設定する(EF Migration付き)

Last updated at Posted at 2018-04-11

#ASP.NET CoreでNLogを設定する

背景

.NETCoreに触れる機会があったので、
EntityFrameworkを使用したログDBのMigrationを含めた
NLogのDB出力設定サンプルを製造してみました。
(とかかっこつけながら、備忘録として記録します) φ(-ω-)メモメモ

環境

  • TargetFramework
    • NetCore2.0
  • ライブラリ
ライブラリ名 バージョン
Microsoft.AspNetCore.All 2.0.3
NLog.Web.AspNetCore 4.5.0-rc2
Swashbuckle.AspNetCore 1.1.0
Microsoft.EntityFrameworkCore.Tools.DotNet 2.0.0

ログDBのMigration

サーバ端末が変更される度にログのDB環境を構築するのは面倒なので、
EF Coreのマイグレーション機能を使いサーバ起動時に
ログDBを自動でマイグレーションするよう設定した。

LogDbContext.cs
    public class LogDbContext : DbContext
    {

        public LogDbContext(DbContextOptions<LogDbContext> options)
        {
            // DBがなかった場合にマイグレーションする
            Database.EnsureCreated();
        }

しかし、これだと以下の点が問題になりました。

  1. マイグレーション履歴テーブルができずEntity変更履歴が取れないので、DB更新ができない *1
  2. DBContextがDIされたときにマイグレーションされるので、LOGDBのDBContextを使用するAPIを呼び出さないとDBができない

サーバ起動時にはDBが出来ていてほしいのでスタートアップでマイグレーション処理を呼ぶように変更する。

Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        { 

            // Swaggerミドルウェアの登録
            app.UseSwagger();
            // SwaggerUIミドルウェアの登録
            app.UseSwaggerUI(option =>
            {
                option.SwaggerEndpoint("/swagger/orders/swagger.json", "Order APIs sandbox.");
            });
            loggerFactory.AddNLog();
            // DBマイグレーション処理
            DbInitailizer.InitializeDatabase(app);
            LogManager.Configuration.Variables["ConnectionStrings"] = Configuration.GetConnectionString("NLogDb");
            
            app.UseMvc();
		}

DB初期設定クラス

DbInitailizer.cs
using AspNetCoreNlog.Model;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System.Linq;

namespace AspNetCoreNlog
{
    public static class DbInitailizer
    {
        public static void InitializeDatabase(IApplicationBuilder app)
        {
            using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
            {

                var logDbContext = serviceScope.ServiceProvider.GetRequiredService<LogDbContext>();
                logDbContext.Database.Migrate();

            }
        }
    }
}

Nlog設定

"Program.cs"にて、
"Nlog.conf"(ログ設定ファイル)を読込みます。
NetCore2.0で読込み方法が代わりました。

Program.cs
    public class Program
    {
        public static void Main(string[] args)
        {
            
            var logger = NLogBuilder.ConfigureNLog("NLog.config").GetCurrentClassLogger();
          
            try
            {
                logger.Debug("init main");
                BuildWebHost(args).Run();
            }
            catch (Exception e)
            {
                logger.Error(e, "Stopped program because of exception");
                throw;
            }
        }

*"Nlog.conf"*はこんな感じ

NLog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Warn"
      internalLogFile="Logs\internal-nlog.txt">

  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>

  <targets>
    <target name="database" xsi:type="Database" connectionString="${var:ConnectionStrings}" >
      <!--LogDB用インサート文-->
      <commandText>
        insert into Logs (
        Application, Logged, Level, Message,
        Logger, CallSite, Exception, KBN
        ) values (
        @Application, @Logged, @Level, @Message,
        @Logger, @Callsite, @Exception, @kbn
        );
      </commandText>
      <!--[レイアウトレンダラー一覧](https://github.com/NLog/NLog/wiki/Layout-Renderers) -->
      <parameter name="@application" layout="AspNetCoreNlog" />
      <parameter name="@logged" layout="${date}" />
      <parameter name="@level" layout="${level}" />
      <parameter name="@message" layout="url: ${aspnet-request-url} | action: ${aspnet-mvc-action} | ${message}" />
      <parameter name="@logger" layout="${logger}" />
      <parameter name="@callSite" layout="${callsite:filename=true}" />
      <parameter name="@exception" layout="${exception:tostring}" />
      <parameter name="@kbn" layout="${mdlc:item=kbn}" />
    </target>

  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="database" />
  </rules>
</nlog>

DB接続先は、appsettings.jsonに持つようにしています。

appsettings.json
{
  "ConnectionStrings": {
    "NLogDb": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=logdb1;Integrated Security=True;Connect Timeout=1;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
    //"NLogDb": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=logdb;"
  }
}

実行するとDBがマイグレーションされます。
Debug.PNG

DBが勝手にできた!v(`皿´)ノ~'' ヤッター!!

ソースコードを公開しているので、
参考になればと思います。

次は、ロガーでのログ出力時にパラメータを渡してDBに登録する方法とか書ければなぁ
あと、EFの発行クエリをパラメータ代入してログに出力する方法とか書ければなぁ

*1: どうもマイグレーションコマンドを実行しマイグレーションデザインを作成するのではなく、
OnModelCreatingメソッドが呼ばれるっぽい

参考資料:

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?