redwarrior’s diary

C#, ASP.NET, WEB, G*などの雑多な情報

ストアドプロシージャからNLogを使用してログを出力する

2015/06/01追記:下記はパフォーマンスに問題がある可能性があります。実際に使う場合は時間の計測を行って頻度などを考慮してください。

前回の記事でアプリからのログ出力は、NLogに任せることが出来るようになりました。

redwarrior.hateblo.jp

しかし、ログ出力が必要なのはアプリだけではありません。たとえば管理用スクリプトや、ストアドプロシージャでログ出力したいことがあります。

ただ、前回の記事と同じルール(過去のログファイル名には日付をつける。ローテーションはログ出力時、スケジューラへの登録は行わない。保存期間を過ぎたログファイルは削除する)でローテーションを行うスクリプトを作るのは、考えることが多くてかなり大変です。

アプリのルールと同じにしないという解決策もありますが、出来ればルールは統一したい。NLog使えればなあ~。と思って調べてたところPowerShellからNLogを実行できそうだというのがわかったので、
NLogを呼び出すPowerShellスクリプトを作成し、ストアドプロシージャからそのスクリプトを呼び出すことでログ出力をする方法を試してみました。

実現するために、以下の方法を組み合わせています。

  1. ストアドプロシージャからコマンドを実行する
  2. コマンドからPowerShellを実行する
  3. PowerShellからNLogを実行する
  4. NLogによってファイル出力を行う

以下、一つずつ見ていきます。

ストアドプロシージャからコマンドを実行する

xp_cmdshellを使用します。

まず、以下のサイトに従って、xp_cmdshellオプションを有効にします。

xp_cmdshell サーバー構成オプション

次に、xp_cmdshellプロキシ アカウントを設定します。今回はSQL Server Management Studioで設定しました。

xp_cmdshell (Transact-SQL)

コマンドからPowerShellを実行する

xp_cmdshellからPowerShellを使用します。以下のサイトを参考にPowerShellスクリプトを呼び出します。

The PoSh DBA: Solutions using PowerShell and SQL Server

今回は処理をスクリプトにまとめるので、-commandオプションではなく-Fileオプションを使用します。

いろいろな方法で PowerShell スクリプトを実行してみる【前編】 - 鷲ノ巣

PowerShellからNLogを実行する

PowerShellからNLogを呼び出す方法は、以下を参考にしました。ログレベルの振り分けは、PowerShellの中で行いました。

PowerShellとNLog | 84zume Works

PowerShellからlog4netでロガー作って使ってみた - YOMON8.NET

NLogによってファイル出力を行う

デフォルトの設定で良いので、今回は省略します。

まとめ

最後にソースをのせておきます。

ストアドプロシージャ(一部)
EXEC xp_cmdshell 'PowerShell.exe -File .\nlog_execute.ps1 "Hello World!" DEBUG SPLogger'
PowerShellスクリプト(nlog_execute.ps1)
param(
    [Parameter(Mandatory=$True)] [string] $Message,
    [Parameter(Mandatory=$True)] [string] $Level,
    [Parameter(Mandatory=$True)] [string] $LoggerName
)

Add-Type -Path ".\lib\NLog.dll"

$config = new-object NLog.Config.XmlLoggingConfiguration(".\conf\NLog.config")
([NLog.LogManager]::Configuration) = $config
$logger = [NLog.LogManager]::GetLogger($LoggerName)

switch ($Level)
{
  "TRACE" { $logger.Trace($Message); break }
  "DEBUG" { $logger.Debug($Message); break }
  "INFO"  { $logger.Info($Message); break }
  "WARN"  { $logger.Warn($Message); break }
  "ERROR" { $logger.Error($Message); break }
  "FATAL" { $logger.Fatal($Message); break }
}

ストアドプロシージャからもログ出力が出来るようになったので、色々と捗りそうです。

使用環境

クライアント:Windows 8.1 Pro 64bit

PowerShell 1.0(?)

サーバー:Windows 2008

SQL Server 2012

NLog 3.2.1