2012-10-15 8 views
6

Ich habe nach Protokollierung für WCF-Dienste (einschließlich Technologien wie NLog und PostSharp) gesucht, aber ich habe etwas, das ich noch nicht gelöst habe ... Ich weiß nicht, ob ich vermisse etwas Offensichtliches oder es ist einfach nicht möglich.WCF-Dienste, Protokollierung vertikal

Angenommen, ich verfüge über eine WCF-Serviceebene mit über 100 Web-Service-Anrufeinstiegspunkten. Einer davon verursacht ein Problem. Unterhalb dieser Ebene befindet sich eine Business-Logik-Ebene und eine Datenbank-Ebene. Was ich tun möchte (denke ich), ist die Protokollierung für diesen Service-Aufruf (der die Aktivitäts-ID für die Korrelation enthalten würde), so dass alle Aufrufe an diesen Service protokolliert werden und alle Protokollnachrichten in den unteren Schichten protokolliert werden. Ich möchte die Protokollierung auf Assembly-Ebene für die unteren Ebenen nicht wirklich aktivieren, da sie von vielen Web-Service-Methoden gemeinsam genutzt werden.

Ist dies sogar möglich, über ein vorhandenes Framework oder indem man etwas wie den CorrelationManager auf kreative Weise verwendet?

Antwort

1

In log4net können Sie eine Eigenschaft für den Threadkontext festlegen, der in allen Protokollierungsereignissen für den Thread enthalten sein wird.

public class WcfServiceClass 
{ 
    public void ProblemServiceMethod() 
    { 
     using (log4net.ThreadContext.Stacks["logThisMethod"].Push("ProblemServiceMethod")) 
     { 
      // can also add the correlationId to the logs using this method. 
      // call business logic... 

     } 
    } 
} 

Dann create a custom appender, dass die Filter durch.

public class IfContextSetFilterAppender : log4net.Appender.AppenderSkeleton 
{ 
    protected override void Append(LoggingEvent loggingEvent) 
    { 
     bool logThisEntry = false; 
     string serviceMethodBeingLogged; 

     foreach (object p in loggingEvent.GetProperties()) 
     { 
      System.Collections.DictionaryEntry dEntry = (System.Collections.DictionaryEntry)p; 
      if (dEntry.Key == "logThisMethod") 
      { 
       logThisEntry = true; 
       serviceMethodBeingLogged = dEntry.Value.ToString(); 
      } 
     } 

     if (!logThisEntry) 
      return; // don't log it. 

     // log it. 
    } 
} 

Das ist das sehr simple (aber klare) Beispiel der Idee.

Wenn ich wirklich das Gebäude in so großem Umfang einen Service, wie Sie beschreiben, würde ich:

  1. erstellen IOperationInvoker Endpunkt Verhalten, das den Namen der Methode packt und setzt einen log4net Kontextwert für alle Anrufe seine angewendet.

  2. (Optional) Lassen Sie den Appender aus app.config die Filterliste aller Namen der Servicemethoden lesen, die protokolliert werden sollen. (Wenn Sie selektiv sind, in welchem ​​Verfahren das OperationInvoker Verhaltens angewandt werden, wird die appender nicht diese Komplexität benötigen.)

durch das Verhalten zu tun haben Sie mehrere Möglichkeiten zur Protokollierung Steuerung auf einem Produktions Service durch Konfiguration allein ohne jemals den Service-Code zu berühren.

+0

Danke! Das ist genau die Art von Dingen, nach denen ich suche. Idealerweise würde ich NLog über log4net verwenden, da es ein bisschen aktiver scheint, aber genau das ist die Art von Sache, die mich dazu bringen könnte, meine Meinung zu ändern ... Hast du Code wie diesen in Wut benutzt? Wie würde es mit einem Multi-Thread-Dienst umgehen? –

+0

log4net.ThreadContext verwendet lokalen Thread-Speicher. Solange ein Service-Aufruf keine Threads hopst (lesen Sie asych), funktioniert das in einer Multithread-Umgebung. Ja, ich habe mehrere davon für echte Enterprise-Produktionsdienste gemacht. Die letzte war, eine Korrelations-ID in alle Log-Ganzzahlen zu setzen (alles, was auf den ThreadContext geschoben wird, kann in das Konvertierungsmuster des Appenders eingeschlossen werden). Log4net ist nicht sehr aktiv, da sehr wenig fehlt und es sehr gut dokumentiert ist. Wenn Sie glauben, dass es vor Generika geschrieben wurde, behandelt es Sie gut. – ErnieL

+0

Danke Ernie. Das war genau die Art von Dingen, die ich suchte! –

0

Sie könnten eine neue Protokollierungsquelle für diesen bestimmten Serviceaufruf erstellen und dann die Diagnose aktivieren, um sie zu filtern.

<system.diagnostics> 
    <sources> 
     <source name="Your.Source.Here" switchValue="Verbose"> 
     <listeners> 
      <add name="xml" /> 
     </listeners> 
     </source> 
    </sources> 
    <sharedListeners> 
     <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="LogicalOperationStack" initializeData="l:\logs\N4S.MSO.ADC.Host.svclog" /> 
    </sharedListeners> 
    </system.diagnostics> 
+0

Bedeutet das nicht, dass die Aufrufe des Logging-Frameworks in den unteren Ebenen auch den Quellennamen kennen müssen? –

+0

Chris - übrigens, danke für die Eingabe; sehr geschätzt! –