跨AppDomains的NLog配置
我有一个将 dll 加载到单独的应用程序域中的服务(需要该应用程序域,因为该 dll 正在加载动态生成的程序集并且需要能够卸载它们)
如何复制 nlog 配置以便新的应用程序域使用相同的配置设置?
另一个复杂之处是我在程序开始时使用 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="[email protected]"
to="[email protected]"
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>
I have a service that loads a dll into a seperate appdomain(the appdomain is needed because the dll is loading a dynamically generated assembly and needs to be able to unload them)
How can I copy the nlog configuration so that the new appdomain uses the same settings?
One additional complication is that I setup logging parameters using the GlobalDiagnosticsContext at the beginning of the program. Is there any option besides having to set them over again in each appdomain?
static void Main()
{
// Setup NLog variables
GlobalDiagnosticsContext.Set("ConnectionString", @"...");
GlobalDiagnosticsContext.Set("ApplicationName", @"appName");
// ... loads appdomain and does logging from the new appdomain
This is my config file:
<?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="[email protected]"
to="[email protected]"
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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道是否有更自动的方法让每个 AppDomain 使用相同的配置信息,但您也许可以使用这篇文章中的技术:
最有用的 NLog 配置
通过 XML 以编程方式设置配置。对于加载的每个 AppDomain,您可以读取 NLog 配置文件,然后在新 AppDomain 中的 NLog 上设置 XML。
将全局值获取到新 AppDomain 的一种可能的解决方案是使用 CallContext.LogicalSetData 存储它们。这些值将流向新的 AppDomain。编写自定义 LayoutRenderer 以使用 CallContext.LogicalGetData 获取值。 LayoutRenderer 非常容易编写。
请参阅这篇文章,了解如何编写基于键查找值的自定义 LayoutRenderer 的示例(就像 GDC 一样)。对于内部结构,只需使用 CallContext.LogicalGetData 来检索值:
自定义 log4net 属性 PatternLayoutConverter (与index)
请参阅 Jeffrey Richter 撰写的有关使用 CallContext 的博客文章:
http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/逻辑调用上下文流动数据跨线程appdomains-and-processes.aspx
I don't know if there is a more automatic way to get each AppDomain to use the same config information, but you might be able to use the technique in this post:
Most useful NLog configurations
To set the configuration programmatically via XML. For each AppDomain you load, you could read the NLog config file and then set the XML on NLog in the new AppDomain.
One possible solution for getting your global values to the new AppDomain would be to store them using CallContext.LogicalSetData. The values will flow to the new AppDomain. Write a custom LayoutRenderer to get the values using CallContext.LogicalGetData. The LayoutRenderer is pretty easy to write.
See this post for an example of how to write a custom LayoutRenderer that looks up a value based on a key (just like the GDC). For the internals, just use CallContext.LogicalGetData to retrieve the value:
Custom log4net property PatternLayoutConverter (with index)
See this blog post by Jeffrey Richter about using the CallContext:
http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing-data-across-threads-appdomains-and-processes.aspx
我刚刚做了一些非常类似的事情,我发现每个子 AppDomain 中的静态成员 NLog.LogManager.Configuration 开始时与父 AppDomain 中的该成员具有相同的值。我不确定它是否最终重新读取app.config 中的值或者静态成员是否直接从父 AppDomain 复制。
另外,我最终使用 CallContext 来过滤匹配特定条件(例如,导致程序运行的激励请求 ID)的所有日志消息(无论记录器名称如何),并将它们分组到内存中日志目标。
I just did something very similar, and I found that the static member NLog.LogManager.Configuration in each child AppDomain started out having the same value as that member in the parent AppDomain.. I'm not sure if it ended up re-reading the values from the app.config or if the static members are copied from the parent AppDomain directly.
Also, I ended up using CallContext to filter all log messages (regardless of logger name) matching a certain criteria (eg, the motivating request ID which caused the program to run), and group them to an in-memory log target.