c# - 跨AppDomains的NLog配置

标签 c# logging appdomain nlog

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

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

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

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="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="85e0f7f7eaf7f6c5e0e8e4ece9abe6eae8" rel="noreferrer noopener nofollow">[email protected]</a>"
            to="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="73161e121a1f33161e121a1f5d101c1e" rel="noreferrer noopener nofollow">[email protected]</a>"
            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>

最佳答案

我不知道是否有更自动的方法让每个 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

关于c# - 跨AppDomains的NLog配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5346336/

相关文章:

c# - 表达式树的问题

c# - 解析 1 TB 的文本并有效地计算每个单词的出现次数

java - Spring Boot : use logback instead of log4j

c++ - 如何在 log4cpp 属性文件中使用环境变量

c# - 如何从 Web API 应用程序的 Bin 目录访问 Xml 文件?

C#:如何设置不安全结构的成员数组

c# - DirectX 游戏 Hook

Python调试,在特定输出处停止

c# - C++ DLL 不使用 AppDomain 卸载

c# - 使用 IDisposable 时卸载 AppDomain