2 Stimmen

NLog-Konfiguration über AppDomains hinweg

Ich habe einen Dienst, der eine DLL in eine separate Appdomain lädt (die Appdomain wird benötigt, weil die DLL eine dynamisch generierte Assembly lädt und in der Lage sein muss, sie zu entladen)

Wie kann ich die nlog-Konfiguration kopieren, so dass die neue App-Domain die gleichen Einstellungen verwendet?

Eine zusätzliche Komplikation besteht darin, dass ich die Protokollierungsparameter mit Hilfe des GlobalDiagnosticsContext zu Beginn des Programms einstelle. Gibt es eine andere Möglichkeit, als sie in jeder App-Domäne neu zu setzen?

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

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

Dies ist meine Konfigurationsdatei:

<?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>

2voto

wageoghe Punkte 26872

Ich weiß nicht, ob es einen automatischeren Weg gibt, um jede AppDomain dazu zu bringen, die gleichen Konfigurationsinformationen zu verwenden, aber vielleicht können Sie die Technik in diesem Beitrag verwenden:

Die nützlichsten NLog-Konfigurationen

Um die Konfiguration programmatisch über XML einzustellen. Für jede AppDomain, die Sie laden, könnten Sie die NLog-Konfigurationsdatei lesen und dann die XML auf NLog in der neuen AppDomain einstellen.

Eine mögliche Lösung, um Ihre globalen Werte in die neue AppDomain zu übertragen, wäre, sie mit CallContext.LogicalSetData zu speichern. Die Werte fließen dann in die neue AppDomain. Schreiben Sie einen benutzerdefinierten LayoutRenderer, um die Werte mit CallContext.LogicalGetData abzurufen. Der LayoutRenderer ist ziemlich einfach zu schreiben.

In diesem Beitrag finden Sie ein Beispiel dafür, wie Sie einen benutzerdefinierten LayoutRenderer schreiben können, der einen Wert anhand eines Schlüssels abruft (genau wie der GDC). Für die Interna, verwenden Sie einfach CallContext.LogicalGetData, um den Wert abzurufen:

Benutzerdefinierte log4net-Eigenschaft PatternLayoutConverter (mit Index)

Siehe diesen Blogbeitrag von Jeffrey Richter über die Verwendung des CallContext:

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

1voto

gap Punkte 2678

Ich habe gerade etwas sehr Ähnliches gemacht und festgestellt, dass das statische Mitglied NLog.LogManager.Configuration in jeder untergeordneten AppDomain denselben Wert hatte wie das Mitglied in der übergeordneten AppDomain. Ich bin mir nicht sicher, ob es am Ende die Werte aus der app.config neu liest oder ob die statischen Mitglieder direkt aus der übergeordneten AppDomain kopiert werden.

Außerdem habe ich schließlich CallContext verwendet, um alle Protokollnachrichten (unabhängig vom Loggernamen) zu filtern, die einem bestimmten Kriterium entsprechen (z. B. der motivierenden Anforderungs-ID, die das Programm zur Ausführung veranlasst hat), und sie in einem speicherinternen Protokollziel zu gruppieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X