AppDomains上的NLog配置

时间:2011-03-17 23:00:56

标签: c# logging appdomain nlog

我有一个服务将dll加载到一个单独的appdomain中(需要appdomain,因为dll正在加载一个动态生成的程序集,需要能够卸载它们)

如何复制nlog配置以便新的appdomain使用相同的设置?

另一个复杂因素是我在程序开头使用GlobalDiagnosticsContext设置日志记录参数。除了必须在每个appdomain中重新设置它们之外,还有其他选择吗?

static void Main()
{
    // Setup NLog variables
    GlobalDiagnosticsContext.Set("ConnectionString", @"...");
    GlobalDiagnosticsContext.Set("ApplicationName", @"appName");

    // ... loads appdomain and does logging from the new appdomain

这是我的配置文件:

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <variable name="TextErrorLayout" value ="${gdc:item=ApplicationName} ${date:format=yyyy-MM-dd HH\:mm\:ss.fff}${newline}
Level: ${level}${newline}
Description: ${message}${newline}
Machine: ${machinename}${newline}
User: ${windows-identity}${newline}
Process: ${processname}${newline}
WorkingDir: ${basedir}${newline}
Exception: ${exception:format=tostring}${newline}
DetailedMessage: ${event-context:item=Details}${newline}"/>

  <targets async="true">
    <target name="LogMill" xsi:type="FallbackGroup">
      <target xsi:type="Database"
              connectionString="${gdc:item=ConnectionString}"
              commandText="exec dbo.Usp_Log_CreateWithExtended @applicationName, @logLevel, @entryDate, @description, @machineName, @userName, @assembly, @workingDirectory, @exception, @detailedMessage">
        <dbProvider>mssql</dbProvider>
        <parameter name="@applicationName" layout="${gdc:item=ApplicationName}"/>
        <parameter name="@logLevel" layout="${level}"/>
        <parameter name="@entryDate" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}"/>
        <parameter name="@description" layout="${message}"/>
        <parameter name="@machineName" layout="${machinename}"/>
        <parameter name="@userName" layout="${windows-identity}"/>
        <parameter name="@assembly" layout="${processname}"/>
        <parameter name="@workingDirectory" layout="${basedir}"/>
        <parameter name="@exception" layout="${exception:format=tostring}"/>
        <parameter name="@detailedMessage" layout="${event-context:item=Details}"/>
      </target>
      <target xsi:type="File" fileName="LogMill-FailSafe.log" layout="${TextErrorLayout}"/>
    </target>

    <target name="EmailDevelopers" xsi:type="Mail"
            smtpServer="smtp.local"
            from="errors@email.com"
            to="email@email.com"
            subject="${gdc:item=ApplicationName} ${level} Error: ${message}"
            layout="${TextErrorLayout}"/>

    <target name="Console" xsi:type="ColoredConsole" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff} ${message} ${exception:format=tostring}"/>
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="LogMill" />
    <logger name="*" minlevel="Error" writeTo="EmailDevelopers" />
  </rules>
</nlog>

2 个答案:

答案 0 :(得分:2)

我不知道是否有更自动的方式让每个AppDomain使用相同的配置信息,但您可以在这篇文章中使用该技术:

Most useful NLog configurations

通过XML以编程方式设置配置。对于您加载的每个AppDomain,您可以读取NLog配置文件,然后在新AppDomain中的NLog上设置XML。

将全局值提供给新AppDomain的一种可能解决方案是使用CallContext.LogicalSetData存储它们。值将流向新的AppDomain。编写自定义LayoutRenderer以使用CallContext.LogicalGetData获取值。 LayoutRenderer非常容易编写。

有关如何编写基于键查找值的自定义LayoutRenderer(就像GDC一样),请参阅此文章。对于内部,只需使用CallContext.LogicalGetData来检索值:

Custom log4net property PatternLayoutConverter (with index)

请参阅Jeffrey Richter关于使用CallContext的博客文章:

http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing-data-across-threads-appdomains-and-processes.aspx

答案 1 :(得分:1)

我只是做了一些非常相似的事情,我发现每个子AppDomain中的静态成员NLog.LogManager.Configuration开始具有与父AppDomain中该成员相同的值。我不确定它是否结束了重新读取app.config中的值,或者是否直接从父AppDomain复制静态成员。

此外,我最终使用CallContext过滤所有符合特定条件的日志消息(无论记录器名称)(例如,导致程序运行的激励请求ID),并将它们分组到内存中的日志目标。