// Possibly logs the entry of a method call. Returns true if the message is logged, meaning // the corresponding method-exit should also be logged when it occurs. internal bool LogCallEntry(Logger logger, TraceLevel level, string method, Destinations destinations) { bool result = true; if (MasterStackDepth < byte.MaxValue) { if ((destinations & Destinations.EventHandler) == Destinations.EventHandler) { string originalMethod = EventHandlerState.CurrentMethod; EventHandlerState.CurrentMethod = method; // The LogMsg method returns true if the event is cancelled. result = !EventHandlerLogging.LogMsg(logger, this, level, method + " entered", true, false); if (result) { ++EventHandlerState.StackDepth; } else { // Event was cancelled, so restore the original method. EventHandlerState.CurrentMethod = originalMethod; } } if (result) { StackEntry stackEntry = new StackEntry(logger, level, method, TopStackEntry, destinations); // Don't put the stack entry on the stack (i.e. set TopStackEntry) until after the method-entry // is logged because of code in BinaryFile.WriteLine(). if ((destinations & Destinations.BinaryFile) == Destinations.BinaryFile) { // This may be the first output to be written to the file, so commit to it. logger.CommitToBinaryFile(); // Lookup the BinaryFileState that applies to this thread and file. stackEntry.BinaryFileState = GetBinaryFileState(logger.BinaryFile); BinaryFileState.CurrentMethod = method; logger.BinaryFile.LogEntry(this, stackEntry); ++BinaryFileState.StackDepth; } if ((destinations & Destinations.TextFile) == Destinations.TextFile) { // This may be the first output to be written to the file, so commit to it. logger.CommitToTextFile(); stackEntry.TextFileState = GetTextFileState(logger.TextFile); TextFileState.CurrentMethod = method; logger.TextFile.LogMsg(logger, this, level, method + " entered"); ++TextFileState.StackDepth; } if ((destinations & Destinations.Console) == Destinations.Console) { ConsoleState.CurrentMethod = method; ConsoleLogging.LogMsg(logger, this, level, method + " entered"); ++ConsoleState.StackDepth; } if ((destinations & Destinations.Debug) == Destinations.Debug) { DebugState.CurrentMethod = method; DebugLogging.LogMsg(logger, this, level, method + " entered"); ++DebugState.StackDepth; } if ((destinations & Destinations.EventLog) == Destinations.EventLog) { // Method-entry messages seem like a dumb thing to put in the event log, // but we'll keep track of the stack anyway. EventLogState.CurrentMethod = method; //EventLogging.LogMsg(logger, this, level, method + " entered"); ++EventLogState.StackDepth; } ++MasterStackDepth; TopStackEntry = stackEntry; } } else { // Already at max depth, so don't log this. Return false so // the corresponding future call to LogCallExit won't happen either. result = false; } LastLoggerAnyDest = logger; return(result); }
// Log the exit of a method call to each destination indicated by TopStackEntry. internal void LogCallExit() { if ((TopStackEntry.Destinations & Destinations.EventHandler) != 0) { // Although this LogMsg() call raises a cancellable event, method-exit messages aren't really cancellable because // we must "balance" the original method-entry message. --EventHandlerState.StackDepth; EventHandlerLogging.LogMsg(TopStackEntry.Logger, this, TopStackEntry.Level, TopStackEntry.MethodName + " exiting", false, true); EventHandlerState.CurrentMethod = GetCaller(Destinations.EventHandler); } if ((TopStackEntry.Destinations & Destinations.BinaryFile) != 0) { // Make sure BinaryFileState corresponds to the BinaryFile instance // the method-exit should be logged to (the same BinaryFile the // method-entry for TopStackEntry was logged to). BinaryFileState = TopStackEntry.BinaryFileState; if (TopStackEntry.Logger.BinaryFile.LogExit(this)) { // BinaryFileState.StackDepth depth is decremented after logging so any meta-logging has the right depth. // GetCaller() also depends on the stack depth. BinaryFileState.CurrentMethod = GetCaller(BinaryFileState); --BinaryFileState.StackDepth; } } if ((TopStackEntry.Destinations & Destinations.TextFile) != 0) { // Make sure BinaryFileState corresponds to the BinaryFile instance // the method-exit should be logged to (the same BinaryFile the // method-entry for TopStackEntry was logged to). TextFileState = TopStackEntry.TextFileState; --TextFileState.StackDepth; TopStackEntry.Logger.TextFile.LogMsg(TopStackEntry.Logger, this, TopStackEntry.Level, TopStackEntry.MethodName + " exiting"); TextFileState.CurrentMethod = GetCaller(TextFileState); } if ((TopStackEntry.Destinations & Destinations.Console) != 0) { --ConsoleState.StackDepth; ConsoleLogging.LogMsg(TopStackEntry.Logger, this, TopStackEntry.Level, TopStackEntry.MethodName + " exiting"); ConsoleState.CurrentMethod = GetCaller(Destinations.Console); } if ((TopStackEntry.Destinations & Destinations.Debug) != 0) { --DebugState.StackDepth; DebugLogging.LogMsg(TopStackEntry.Logger, this, TopStackEntry.Level, TopStackEntry.MethodName + " exiting"); DebugState.CurrentMethod = GetCaller(Destinations.Debug); } if ((TopStackEntry.Destinations & Destinations.EventLog) != 0) { --EventLogState.StackDepth; //EventLogging.LogMsg(TopStackEntry.Logger, this, TopStackEntry.Level, TopStackEntry.MethodName + " exiting"); EventLogState.CurrentMethod = GetCaller(Destinations.EventLog); } LastLoggerAnyDest = TopStackEntry.Logger; TopStackEntry = TopStackEntry.Caller; --MasterStackDepth; }
// Possibly logs the entry of a method call and/or changes the current thread's name. // Returns true if the message is logged or the thread name is changed, meaning the // corresponding method-exit should also be logged (and/or the thread name changed back) // when LogCallExit() is called. internal bool LogCallEntry(Logger logger, TraceLevel level, string method, Destinations destinations, string threadName) { bool result = true; bool cancelled = false; string originalThreadName; if (MasterStackDepth < byte.MaxValue) { if (threadName == null) { // _doNotRestore is a special value that prevents LogCallExit() from // restoring the thread name. originalThreadName = _doNotRestore; } else { // Because the user specified a thread name, we arrange for the current // thread name to be restored by LogCallExit() before changing it. originalThreadName = _name; _name = threadName; } // The EventHandler destination is processed first because the event it raises is cancellable. // If the event's handler cancels the event, the method call won't be logged to the other // destinations. However, the thread name can still be changed. if ((destinations & Destinations.EventHandler) == Destinations.EventHandler) { string originalMethod = EventHandlerState.CurrentMethod; EventHandlerState.CurrentMethod = method; // The LogMsg method returns true if the event is cancelled. cancelled = EventHandlerLogging.LogMsg(logger, this, level, method + " entered", true, false); if (cancelled) { // Event was cancelled, so restore the original method. EventHandlerState.CurrentMethod = originalMethod; } else { ++EventHandlerState.StackDepth; } } if (!cancelled || threadName != null) { StackEntry stackEntry = new StackEntry(logger, level, method, TopStackEntry, destinations, originalThreadName); // Don't put the stack entry on the stack (i.e. set TopStackEntry) until after the method-entry // is logged because of code in BinaryFile.WriteLine(). // Note that each destination effectively has it's own stack because a given method entry isn't // necessarily logged to all of them. if ((destinations & Destinations.BinaryFile) == Destinations.BinaryFile) { // This may be the first output to be written to the file, so commit to it. logger.CommitToBinaryFile(); // Lookup the BinaryFileState that applies to this thread and file. stackEntry.BinaryFileState = GetBinaryFileState(logger.BinaryFile); BinaryFileState.CurrentMethod = method; logger.BinaryFile.LogEntry(this, stackEntry); ++BinaryFileState.StackDepth; } if ((destinations & Destinations.TextFile) == Destinations.TextFile) { // This may be the first output to be written to the file, so commit to it. logger.CommitToTextFile(); stackEntry.TextFileState = GetTextFileState(logger.TextFile); TextFileState.CurrentMethod = method; logger.TextFile.LogMsg(logger, this, level, method + " entered"); ++TextFileState.StackDepth; } if ((destinations & Destinations.Console) == Destinations.Console) { ConsoleState.CurrentMethod = method; ConsoleLogging.LogMsg(logger, this, level, method + " entered"); ++ConsoleState.StackDepth; } if ((destinations & Destinations.Debug) == Destinations.Debug) { DebugState.CurrentMethod = method; DebugLogging.LogMsg(logger, this, level, method + " entered"); ++DebugState.StackDepth; } if ((destinations & Destinations.EventLog) == Destinations.EventLog) { // Method-entry messages seem like a dumb thing to put in the event log, // but we'll keep track of the stack anyway. EventLogState.CurrentMethod = method; //EventLogging.LogMsg(logger, this, level, method + " entered"); ++EventLogState.StackDepth; } ++MasterStackDepth; TopStackEntry = stackEntry; result = true; } } else { // Already at max depth, so don't log this. Return false so // the corresponding future call to LogCallExit won't happen either. result = false; } LastLoggerAnyDest = logger; return(result); }