// 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;
        }
Пример #3
0
        // 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);
        }