示例#1
0
        // Resets all state data that might be associated with an earlier binary file
        // and prepares for the next (specified) opening of the file.
        internal void ResetBinaryFileStateData(int fileNum, DataFlags flags)
        {
            BinaryFileState.LastFileNumber = fileNum;
            BinaryFileState.LastTraceLevel = TraceLevel.Off;
            BinaryFileState.LastThreadName = null;
            BinaryFileState.LastMethod     = string.Empty;
            BinaryFileState.LastLogger     = null;
            BinaryFileState.LastBlock      = 0;

            // For simplicity, abandon the stack rather than deal with the fact that there
            // may be a deep call stack when the file is closed and reopened.

            BinaryFileState.StackDepth = 0;

            for (StackEntry stackEntry = TopStackEntry; stackEntry != null; stackEntry = stackEntry.Caller)
            {
                if (stackEntry.BinaryFileState == BinaryFileState)
                {
                    stackEntry.Destinations   &= ~Destinations.BinaryFile;
                    stackEntry.BinaryFileState = null;
                }
            }

            // I'm not sure why we wouldn't always do this.
            if ((flags & DataFlags.MethodEntry) == 0)
            {
                BinaryFileState.CurrentMethod = string.Empty;
            }
        }
 internal StackEntry(Logger logger, TraceLevel level, string method, StackEntry caller, Destinations destinations)
 {
     Logger       = logger;
     Level        = level;
     MethodName   = method;
     Caller       = caller;
     Destinations = destinations;
 }
        // Search down the stack for the next caller for the specified destination.
        private string GetCaller(Destinations destination)
        {
            for (StackEntry caller = TopStackEntry.Caller; caller != null; caller = caller.Caller)
            {
                if ((caller.Destinations & destination) == destination)
                {
                    return(caller.MethodName);
                }
            }

            return("");
        }
        // Search down the stack for the next caller for the specified text file.
        private string GetCaller(TextFileState fileData)
        {
            // For text files, the stack depth is decremented BEFORE this is called,
            // so check stackdepth > 0.
            if (fileData.StackDepth > 0)
            {
                for (StackEntry caller = TopStackEntry.Caller; caller != null; caller = caller.Caller)
                {
                    if (caller.TextFileState == fileData)
                    {
                        return(caller.MethodName);
                    }
                }

                Debug.Assert(false, "A caller should have been found.");
            }

            return("");
        }
        // 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. 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);
        }
示例#7
0
        // This is what actually writes the output. The dataFlags parameter specifies what to write.
        private void WriteData(DataFlags dataFlags, ThreadData threadData, BinaryFileState fileThreadState, Logger logger, TraceLevel lineLevel, string msg)
        {
            ++_lineCnt;

            // Write the flags first so the viewer will know what else the record contains.
            _logfile.Write((ushort)dataFlags);

            if (CircularStarted)
            {
                _logfile.Write(_curBlock);

                if ((dataFlags & DataFlags.BlockStart) != DataFlags.None)
                {
                    // This will be the first record in the block.
                    // This stuff helps the viewer find the first chronological block
                    // even after wrapping.  Writting _lastBlockPosition forms a linked
                    // list of blocks that the viewer can follow.

                    //System.Diagnostics.Debug.Print("Block {0} starting at line {1}, position {2}", _curBlock, _lineCnt, _logfile.BaseStream.Position);
                    _logfile.Write(_lineCnt);
                    _logfile.Write(_lastBlockPosition);
                }
            }

            if ((dataFlags & DataFlags.Time) != DataFlags.None)
            {
                _logfile.Write(_curTime.Ticks);
            }

            if ((dataFlags & DataFlags.ThreadId) != DataFlags.None)
            {
                _logfile.Write(threadData.TracerXID);
            }

            if ((dataFlags & DataFlags.ThreadName) != DataFlags.None)
            {
                // ThreadPool thread names get reset to null when a thread is returned
                // to the pool and reused later.
                if (_hasPassword)
                {
                    _encryptor.Encrypt(threadData.Name ?? string.Empty);
                }
                else
                {
                    _logfile.Write(threadData.Name ?? string.Empty);
                }
            }

            if ((dataFlags & DataFlags.TraceLevel) != DataFlags.None)
            {
                _logfile.Write((byte)lineLevel);
            }

            // In format version 5 and later, the viewer subtracts 1 from the stack depth on
            // MethodExit lines instead of the logger, so just write the depth as-is.
            if ((dataFlags & DataFlags.StackDepth) != DataFlags.None)
            {
                _logfile.Write(fileThreadState.StackDepth);

                if (CircularStarted)
                {
                    // In the circular part, include the thread's call stack with the first line
                    // logged for each thread in each block.  This enables the viewer to
                    // regenerate method entry/exit lines lost due to wrapping.
                    // Added in format version 5.
                    int count = 0;
                    for (StackEntry stackEntry = threadData.TopStackEntry; stackEntry != null; stackEntry = stackEntry.Caller)
                    {
                        if (stackEntry.BinaryFileState == fileThreadState)
                        {
                            ++count;
                            _logfile.Write(stackEntry.EntryLine); // Changed to ulong in version 6.
                            _logfile.Write((byte)stackEntry.Level);

                            if (_hasPassword)
                            {
                                Debug.Assert(stackEntry.Logger.Name != null);
                                _encryptor.Encrypt(stackEntry.Logger.Name);

                                Debug.Assert(stackEntry.MethodName != null);
                                _encryptor.Encrypt(stackEntry.MethodName);
                            }
                            else
                            {
                                _logfile.Write(stackEntry.Logger.Name);
                                _logfile.Write(stackEntry.MethodName);
                            }
                        }
                    }

                    // The StackDepth we wrote previously is how the viewer will know how many
                    // stack entries to read.
                    System.Diagnostics.Debug.Assert(count == fileThreadState.StackDepth);
                }
            }

            if ((dataFlags & DataFlags.LoggerName) != DataFlags.None)
            {
                if (_hasPassword)
                {
                    _encryptor.Encrypt(logger.Name);
                }
                else
                {
                    _logfile.Write(logger.Name);
                }
            }

            if ((dataFlags & DataFlags.MethodName) != DataFlags.None)
            {
                if (_hasPassword)
                {
                    _encryptor.Encrypt(fileThreadState.CurrentMethod);
                }
                else
                {
                    _logfile.Write(fileThreadState.CurrentMethod);
                }

                fileThreadState.LastMethod = fileThreadState.CurrentMethod;
            }

            if ((dataFlags & DataFlags.Message) != DataFlags.None)
            {
                if (_hasPassword)
                {
                    _encryptor.Encrypt(msg ?? "");
                }
                else
                {
                    _logfile.Write(msg);
                }
            }

            _lastBlock  = _curBlock;
            _lastThread = threadData;
            fileThreadState.LastBlock      = _curBlock;
            fileThreadState.LastThreadName = threadData.Name;
            fileThreadState.LastTraceLevel = lineLevel;
            fileThreadState.LastLogger     = logger;
        }
示例#8
0
 // Log the entry (start) of a method call.
 // stackEntry is not yet on the stack.
 internal void LogEntry(ThreadData threadData, StackEntry stackEntry)
 {
     // Remember the line number where the MethodEntry flag is written so
     // we can write it into the log when the method exits.
     stackEntry.EntryLine = WriteLine(DataFlags.MethodEntry, threadData, stackEntry.Logger, stackEntry.Level, DateTime.MinValue, null, false);
 }
示例#9
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);
        }