Laden...

Loggen in C#

Erstellt von Christoph K. vor 14 Jahren Letzter Beitrag vor 14 Jahren 5.963 Views
Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 14 Jahren
Loggen in C#

Hi Leute,

ich möchte in meine C# Anwendung Logging-Informationen reinbauen, welche ich jedoch im späteren Release nicht drinne haben möchte

Ich hatte mir überlegt mit #define log und #if log #endif Präprozessor-Anweisungen zu arbeiten, allerdings greifen diese ja nur immer pro Datei und ich müsste in jeder Datei beim Releas das #define log entfernen.

Wie regelt ihr sowas ?

Gruß

1.346 Beiträge seit 2008
vor 14 Jahren

es gibt die deriktive DEBUG. diese gibt es im debug modus, im relesase aber nicht. Diese kannst du verwenden.

Gruß pdelvo

946 Beiträge seit 2008
vor 14 Jahren

diese gibt es im debug modus, im relesase aber nicht. Nicht ganz. Per default ist sie im Release-Modus zwar ausgeschalten, aber sie lösst sich wieder einschalten bei den Projekt-Einstellungen unter "Erstellen".
Da gibt es übrigens auch die Trace-Konstante, für die sich die Logging-Informationen besser eignen sollten.
Ich würde #if TRACE verwenden.

mfg
SeeQuark

S
142 Beiträge seit 2007
vor 14 Jahren
M
1.439 Beiträge seit 2005
vor 14 Jahren

Für solche Zwecke gibt es das System.Diagnostics.ConditionalAttribute.

4.207 Beiträge seit 2003
vor 14 Jahren

Alternativ zu log4net: NLog

Wissensvermittler und Technologieberater
für .NET, Codequalität und agile Methoden

www.goloroden.de
www.des-eisbaeren-blog.de

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 14 Jahren

Die Produkte die ihr gepostet hat sehen ja sehr interessant aus, jedoch wunder ich mich, warum ich dort in den Tutorials die angesprochenen Präprozessor - Anweisungen nicht finde.

Der zusätzliche code der zum logging verwendet wird, hat doch eigentlich nichts im Release zu suchen, auch wenn er vielleicht keine Auswirkungen hat.

Oder machen die angesprochenen Produkte das irgendwie anders, dass der Code im Release nicht verwedet wird ?

Noch eine Frage:

wenn ich eine Funktion habe

public void Log(string message)
{
    #if DEBUG
    ...
    ...
    ...
    #endif
}

und diese dann im Quellcode verwende. Wird die Funktion dann im Release vollständig wegoptimiert (weil diese im Release ja lehr ist)

Gruß
Christoph

3.511 Beiträge seit 2005
vor 14 Jahren

Wird die Funktion dann im Release vollständig wegoptimiert

Ja, wird Sie, wenn in solch einem Falle das ConditionalAttribute verwendet wird.

Der Compiler schmeißt auch selbständig bestimmte Methodenaufrufe raus. Z.B. wird aus


public void FooBar()
{
  Debug.WriteLine("Bla");
  MessageBox.Show("Bla");
}

im Release zu


public void FooBar()
{
  MessageBox.Show("Bla");
}

Um auch im Release etwas loggen zu können, muss man dann in dem Fall mit Trace arbeiten, da Trace nicht im Release wegoptimiert wird.

Der zusätzliche code der zum logging verwendet wird, hat doch eigentlich nichts im Release zu suchen

Naja, gerade das ist doch der Kernpunkt. Kein Kunde bekommt eine Debugversion vorgelegt. Treten jetzt beim Kunden Fehler auf, ist es doch wichtig, das diese Stellen mit geloggt werden, sonst weis man doch gar nicht was passiert ist.

Ich logge z.B. fast alles mit. Und per log4net (nutze ich), kann man auch schön festlegen, was auch geloggt wird. Per default sind das bei mir Fehler und Warnungen. Meldet ein Kunde ein Fehler, wird das untersucht. Sind die Infos nicht ausreichend, wird beim Kunden der Loglevel auf Debug runtergefahren und gebeten, das der Kunde den Fehler erneut provoziert. Und meist dann weis ich wo es brennt.

[Edit]
Eine kleine Unklarheit korrigiert, mit dem bezug auf das ConditionalAttribute.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

Christoph K. Themenstarter:in
821 Beiträge seit 2009
vor 14 Jahren

und mit welchen Methoden steuerst du das Logging ?

3.511 Beiträge seit 2005
vor 14 Jahren

Das Verhalten des Loggers, wird in der config Datei von log4net festgelegt. Also, welcher Loglevel, in welche Datei, welche Appender, usw...
Vorteil ist daran, das man den bestehenden Sourcecode nicht anpacken muss.

Meintest du das, oder was anderes?

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

3.728 Beiträge seit 2005
vor 14 Jahren
Tracing

Hallo Zusammen,

warum einen externen Logger wie Log4Net (was ein Java Port ist) verwenden, wo das .NET Framework doch mit der Klasse TraceSource einen exzellenten Logger im Namensraum System.Diagnostics eingabut hat?

Doku zum .NET Tracing: TraceSource-Klasse (System.Diagnostics)

3.511 Beiträge seit 2005
vor 14 Jahren

In meinem Falle, weil TraceSource erst ab dem 2.0 FW da ist, und das Projekt ursprünglich auf dem 1.1er entwickelt wurde.

Da ich auch lieber MS Sachen verwende als Komponenten von Drittanbietern, ist es natürlich eine Überlegung wert, bei Zeiten das Logging umzubauen.

Auch wenn es hier an dieser Stele nicht hingehört: Kann man auch eigene Appender für das .NET Tracing schreiben, so wie es unter log4net der Fall ist? Ich verwende nämlich eigene, die ich ungerne verwerfen würde.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

F
10.010 Beiträge seit 2004
vor 14 Jahren

Klar, TraceListener sind einfach zu schreiben.

3.511 Beiträge seit 2005
vor 14 Jahren

Hallo,

muss mal den Thread wieder ausgraben. Ich wollte jetzt mal zum Testen auf das .NET Tracing umschwenken. Dabei stoße ich aber auf ein kleines Problem, wo ich noch keine Lösung gefunden habe.

Und zwar habe ich log4net zurzeit so konfiguriert, das die verschiedenen Loglevel (Debug, Info, Warn, Error, Fatal) auch in verschiedenen Dateien landen. Also immer {loglevel}.txt. Kann es sein, das das .NET Tracing das nicht unterstützt? Jedenfalls habe ich noch nichts gefunden darüber. Ich kann zwar TraceListener registrieren, die gelten dann aber für alle Meldungen. Wäre schade, wenn .NET das nicht unterstützt.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

6.911 Beiträge seit 2009
vor 14 Jahren

Hallo,

du kannst für jeden Level eine TraceSource erstellen und den SwitchValue entsprechend setzen. Hier ist ein gute Einführung darüber.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

3.511 Beiträge seit 2005
vor 14 Jahren

Danke für den Link. Werde ich mir dann mal morgen genauer anschauen. Sieht aber vielversprechend aus.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

1.564 Beiträge seit 2007
vor 14 Jahren

Wer's extra groß (und extra mächtig) haben will kann sich mal die Microsoft Enterprise Library anschauen. Enterprise Library

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

161 Beiträge seit 2007
vor 14 Jahren

Ich denke das Framework von TheObjectGuy sollte hier nicht unerwähnt bleiben. Habe das seit ein paar Monaten im produktiven Einsatz und es bis jetzt nicht bereut die 3€ dafür ausgegeben zu haben.

@Rainbird
Ich hatte davor die hauseigenen Mitteln verwendet und auch wenn ich versuche so wenig "Fremdcode" wie möglich zu verwenden, so muss man bei TraceSource doch einiges selbst zusammenschnitzen (Stichwort RollingFileTraceListener) bis es so läuft wie man es braucht.
Wer dafür keine Zeit/Budget hat, ist mit (zB) dem von mir genannten Framework oder auch log4net sicher besser bedient.

"Eine wirklich gute Idee erkennt man daran,
dass ihre Verwirklichung von vorneherein ausgeschlossen erscheint."
(Albert Einstein)

3.511 Beiträge seit 2005
vor 14 Jahren

So, ich hab mal was zusammengebastelt, was aber irgendwie nicht so läuft, wie ich mir es vorgestellt habe.


private void button1_Click(object sender, EventArgs e)
{
  this.m_TS.Listeners.Remove("Default");
  this.m_TS.Switch.Level = SourceLevels.All;

  TextWriterTraceListener debugTrace = new TextWriterTraceListener("debug.txt");
  debugTrace.Filter = new EventTypeFilter(SourceLevels.Verbose);

  TextWriterTraceListener infoTrace = new TextWriterTraceListener("info.txt");
  infoTrace.Filter = new EventTypeFilter(SourceLevels.Information);

  this.m_TS.Listeners.Add(debugTrace);
  this.m_TS.Listeners.Add(infoTrace);

  this.m_TS.TraceEvent(TraceEventType.Verbose, 1, "Debug");
  this.m_TS.TraceEvent(TraceEventType.Information, 2, "Information");

  this.m_TS.Flush();
  this.m_TS.Close();
}

So, läuft ja ganz schön, aber:
Im debugTrace landen jetzt beide Ausgaben, was ja laut Doku auch richtig ist, den SourceLevels.Verbose nimmt alles mit, was größer gleich TraceEventType.Verbose ist. Das will ich aber nicht 😃 Ich will das komplett getrennt.

Ich habe es mit verschiedenen TraceSources probiert, aber da kommt das gleiche bei raus. Kann man den Krams nicht komplett voneinander trennen?

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

1.361 Beiträge seit 2007
vor 14 Jahren

Hi Khalid,

wenn ich mir so den Source-Level-Enum anschaue,


    [Flags]
    public enum SourceLevels
    {
        All = -1,
        Off = 0,
        Critical = 1,
        Error = 3,
        Warning = 7,
        Information = 15,
        Verbose = 31,
        ActivityTracing = 65280,
    }

dann kann man die ja bitweise kombinieren. Und die dort angegeben Stufen sind nicht nur jeweils in Bit sondern immer die Verknüpfung der jeweils niedrigsten Bits. (1, 3, 7, 15, 31 = 00001, 00011, 00111, 01111, 11111)

Wenn du also nur die zusätzlichen eines jeden Levels haben willst, kannst du vielleicht

SourceLevels.Verbose ^ SourceLevels.Information // = 10000

bzw.

SourceLevels.Information ^ SourceLevels.Warning // = 01000

nutzen um nur das jeweilige Bit zu setzen.

beste Grüße
zommi

3.511 Beiträge seit 2005
vor 14 Jahren

Danke dir!

Genau das wars. So langsam wirds 😃 Muss nur noch die fehlenden TraceListener nachbauen...

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

S
8.746 Beiträge seit 2005
vor 14 Jahren

Wer dafür keine Zeit/Budget hat, ist mit (zB) dem von mir genannten Framework oder auch log4net sicher besser bedient.

Ggf. kommt - neben der Funktionalität - ein weiterer Aspekt zum Tragen: Die unterstützten Plattformen. log4net ist eines der wenigen Frameworks, die überhaupt und mit vollem Umfang auf CF und Mono laufen.

L
553 Beiträge seit 2007
vor 14 Jahren


>

Kann man log4net auch durch Sorcecode configurieren? Ich bin kein fan von conf Dateien.

S
8.746 Beiträge seit 2005
vor 14 Jahren

Kann man.