2009-08-28 2 views
9

Ich möchte grundsätzlich einen Kundenlogger/Tracer schreiben, der auch den Klassen- und Methodennamen der Methode protokolliert, die den Logger/Tracer aufruft. Dies sollte schnell sein, so dass es die Leistung der Anwendung nicht stark beeinflusst, stark typisiert und sauber ist. Hat jemand gute Ideen?Was ist der leistungsfähigste Weg, um den Namen von Klasse und Methode zu protokollieren?

Hier sind die wenigen, die ich hatte, aber ich über die Leistung sorgen durch Reflexion: (zu viel Overhead)

  • Stacktrace/StackFrame-

  • MethodInfo.GetCurrentMethod() (noch zu langsam? und nicht sehr sauber)

  • Pass-Methode als Delegierter (C#, dass implizit tun, und ich habe Zugriff auf die Method, aber nicht sehr sauber)

Ich freue mich über alle Kommentare.

UPDATE:

Ich mochte die cleanless von StackFrame- so fragte ich eine spezifischere Frage here in Bezug auf StackFrame- Leistung und ich habe einige wirklich gute Antwort einschließlich Leistungstests. Es stellt sich heraus, dass MethodInfo.GetCurrentMethod() ist die schnellste (dauert etwa 1 Mikrosekunde auf meinem Computer) und new StackFrame(1) kann auf Anfrage angefordert werden (dauert etwa 15-20 Mikrosekunden auf meinem Computer). Ich habe die Methode als Delegate Option weggeworfen, da es zu chaotisch ist, wenn die Methode mehrere Parameter hat.

FAZIT:

Ich habe bei allen Optionen gesucht und das Beste ist, eine benutzerdefinierte Plug-In für Postsharp zu schreiben, die den Methodennamen als String in MSIL während der Kompilierung einspritzt, wenn wie ein benutzerdefiniertes Attribut Anwendung [Trace] dazu. Es ist meiner Meinung nach die schnellste und wartungsfreundlichste Option. Dies ermöglicht sogar viel mehr Dinge wie das Übergeben der Parameternamen und Argumente ohne irgendeine Art von Reflektion und das automatische Erfassen und Protokollieren von Ausnahmen. Diese my related question für weitere Informationen.

+0

Darf ich fragen, warum Sie log4net nicht verwenden möchten? – nWorx

+0

Ich mag es nicht, sich auf andere Komponenten zu verlassen. Und auch im Fall von log4net ist es viel zu komplex. –

+2

Hermann, das wird in unserer Branche allgemein als "nicht erfundenes Syndrom" bezeichnet und ist am besten zu vermeiden. Hier ist ein Wikipedia-Link mit weiteren Informationen über dieses Leiden: http://en.wikipedia.org/wiki/Not_Invented_Here –

Antwort

3

Einfach ausgedrückt, ist der schnellste Weg, es zu tun statisch zur Compile-Zeit:

public void DoSomething() 
{ 
    TraceCall("DoSomething"); 
} 

public void TraceCall(string methodName) 
{ 
    if (!tracingEnabled) { return; } 
    // Log the call 
} 

Die Frage ist dann im Wesentlichen der gleiche wie Ihre vorherige Frage; Was ist der beste Weg dies in einem wartbaren und präzisen Vortrag zu tun? Die Laufzeitoptionen, die wir zuvor besprochen haben, haben einen relativ starken Leistungseinbruch, aber der Nachteil ist, dass sie leicht implementiert werden können.

Wie bereits im vorherigen Thread erwähnt, beginnt sich dieser Ansatz auf aspektorientierte Programmierung zu beziehen; PostSharp ist eine solche Bibliothek, die Ihnen helfen kann, die Balance von statisch kompilierter Leistung mit einfacher Wartung zu finden.

+0

Sie haben Recht. Ich hoffe, dass es nicht zu aufwendig ist, dies mit PostSharp umzusetzen. Ich schätze es kommt auf jeden einzelnen auf die Bedürfnisse an, aber ich würde 20 Mikrosekunden keinen schweren Leistungseinbruch nennen. –

+0

@Hermann: Wenn Sie nicht etwas schreiben, das mit dem Durchsatz von Google umgehen muss, ist 20ms völlig vernachlässigbar. Die Tests, die wir in der anderen Frage durchgeführt haben, haben gezeigt, dass, wenn Sie Protokollierungsaufrufe für 100.000 Methoden initiieren müssten, es höchstens 1,5 Sekunden hinzufügen würde. Ungeachtet der Tatsache, dass einige Methoden wesentlich schneller sind als andere, sind alle Methoden am Ende des Tages marginal. – STW

2

Wenn Sie bereits innerhalb der Methode sind (oder wenn Sie die Methode abfangen), glaube ich nicht, dass Sie viel besser als MethodInfo.GetCurrentMethod - die nicht zu schrecklich schnell ist - wenn Sie Typ bleiben wollen -sicher.

Da Sie dies für die Protokollierung tun möchten, haben Sie in Betracht gezogen, dies in einem asynchronen Vorgang zu tun, damit Sie den Hauptthread nicht verlangsamen?

Abhängig von der Auslastung Ihrer Anwendung kann es hilfreich sein oder auch nicht.

+0

Ja, darüber habe ich auch nachgedacht. Aber was passiert, wenn die Anwendung beschäftigt ist? Würde das nicht die Protokollierung verschieben und wäre es nicht verloren, wenn die Anwendung abstürzt? –

+0

Hängt davon ab, wie Sie die asynchrone Operation implementieren. Wenn Sie es einfach auf den ThreadPool werfen, dann, ja, Sie sind richtig, und die Bestellung ist nicht garantiert. Sie können es jedoch auch in MSMQ schreiben, wodurch Sie eine dauerhafte Protokollierung erhalten. –

+1

Die Async-Option würde nur das tatsächliche Schreiben in das Protokoll erleichtern (was immer noch nützlich sein könnte). Der eigentliche "GetCurrentMethod" -Aufruf würde immer noch die Leistungseinbuße für den Hauptthread erzwingen. – STW

0

Der beste Weg, dies zu tun, ist bei der Kompilierung: C++ verwendet traditionell die Präprozessorsymbole ____FILE____ und ____LINE____ in Makros, um dies zu tun. Leider bietet der C# -Compiler im Moment keine Makros oder ein Äquivalent zu ____FILE____ und ____LINE____.

Dies bedeutet effektiv, dass Ihre einzige Option ist, diese Informationen zur Laufzeit zu protokollieren, was bedeutet, mühsame manuelle Tracing zu jeder Methode hinzufügen, die Sie protokollieren oder den Treffer der Reflexion verwenden möchten, wie Sie beschrieben.

0

Ich denke Log4PostSharp würde die Arbeit sehr gut machen.

+0

Ich möchte nicht einen anderen Logger verwenden, vor allem nicht etwas auf log4net basiert, aber ich _really) wie die Idee von Injektion von MSIL-Code. Ich muss herausfinden, ob ich das irgendwie benutzen kann. –

+0

Reading Stus Antwort - es würde ca. eine Stunde, um das Äquivalent von __FILE__ und __LINE__ mit PostSharp (oder __TYPE__ und __METHOD__) zu entwickeln. Nun, 1 Stunden für mich. –

+0

Ich sehe PostSharp. Danke Gael! –

0

Wenn Sie sich mit der Geschwindigkeit befassen, sollte die tatsächliche Protokollnachricht mit Event Tracing for Windows erstellt werden. ETW ist eine Hochgeschwindigkeitsprotokollierungsbibliothek, die als ein Treiber implementiert ist, auf den sowohl vom Kernel-Modus als auch vom Benutzermodus zugegriffen werden kann. Die Verfolgung kann dynamisch ein- und ausgeschaltet werden. Die Protokollierung fügt der Anwendung sehr wenig Aufwand hinzu. Ich habe ETW verwendet, um die Ablaufverfolgung in Serveranwendungen mit hohem Durchsatz zu implementieren. Schauen Sie sich NTrace an.

4

Der schnellste Weg ist zu tun, dass zum Zeitpunkt der Kompilierung, das ist wahr, aber die bequemste Art und Weise, in .NET zu tun ist durch Verwendung der CallerMemberName, CallerFilePath und anderen Compiler Service-Attribute incroduced in .NET 4.5:

public void TraceMethodCall([CallerMemberName]string methodName) 
{ 
} 
Verwandte Themen