/// <summary>
        /// Passes message to be logged to custom log method in derived class.
        /// </summary>
        /// <param name="message">Message to write to log.</param>
        /// <param name="category">Category name used to organise log or the type of event that raised the trace.</param>
        /// <param name="detailedMessage">Detailed error message.  Only used with Fail method.</param>
        /// <param name="eventID">Unique event ID.</param>
        /// <param name="source">The name of the source that raised the trace.</param>
        /// <param name="eventCache">A TraceEventCache object that contains the current process ID, thread ID, and stack trace information.</param>
        /// <param name="relatedActivityID">A Guid identifying a related activity.</param>
        /// <param name="doWriteLine">Determines whether to perform a WriteLine or a Write to the log.</param>
        /// <returns>True if successful.</returns>
        protected virtual bool WriteToLog(string message, string category, string detailedMessage, int eventID,
                                          string source, TraceEventCache eventCache, string relatedActivityID, bool doWriteLine)
        {
            bool isOK = false;

            try
            {
                LogEntryFields            logEntryFields            = new LogEntryFields();
                OptionalTraceOutputFields optionalTraceOutputFields = new OptionalTraceOutputFields();

                GetOptionalTraceOutput(eventCache, category, out optionalTraceOutputFields);

                logEntryFields.Message              = message;
                logEntryFields.Category             = category;
                logEntryFields.DetailedMessage      = detailedMessage;
                logEntryFields.EventID              = eventID;
                logEntryFields.Source               = source;
                logEntryFields.MethodThatWroteToLog =
                    GetCallingMethodName(this.MethodNameClassesToIgnore,
                                         this.MethodNameMethodsToIgnore);
                logEntryFields.EventDateTime         = optionalTraceOutputFields.DateTime;
                logEntryFields.EventTimestamp        = optionalTraceOutputFields.Timestamp;
                logEntryFields.RelatedActivityID     = relatedActivityID;
                logEntryFields.ProcessID             = optionalTraceOutputFields.ProcessID;
                logEntryFields.ThreadID              = optionalTraceOutputFields.ThreadID;
                logEntryFields.CallStack             = optionalTraceOutputFields.CallStack;
                logEntryFields.LogicalOperationStack = optionalTraceOutputFields.LogicalOperationStack;

                isOK = WriteToCustomLog(logEntryFields, doWriteLine);
            }
            catch
            {
                isOK = false;
            }
            return(isOK);
        }
        /// <summary>
        /// Get optional trace output.
        /// </summary>
        /// <param name="eventCache">A TraceEventCache object that contains the current process ID, thread ID,
        /// and stack trace information.</param>
        /// <param name="category">Category name used to organise log, or the type of event that raised
        /// the trace.</param>
        /// <param name="oOptionalTraceOutputFields">Output parameter.  Structure representing all the
        /// optional fields in the trace output.</param>
        protected void GetOptionalTraceOutput(TraceEventCache eventCache, string category,
                                              out OptionalTraceOutputFields oOptionalTraceOutputFields)
        {
            DateTime eventDateTime      = DateTime.MinValue;
            long     eventTimestamp     = 0;
            int      processID          = 0;
            string   threadID           = null;
            string   callStack          = null;
            string   operationStackText = null;

            if (eventCache != null)
            {
                if (IsEnabled(TraceOptions.DateTime))
                {
                    // TraceEventCache.DateTime is always in UTC.  Convert it to local time.
                    eventDateTime = eventCache.DateTime.ToLocalTime();
                }
                if (IsEnabled(TraceOptions.Timestamp))
                {
                    eventTimestamp = eventCache.Timestamp;
                }
                if (IsEnabled(TraceOptions.ProcessId))
                {
                    processID = eventCache.ProcessId;
                }
                if (IsEnabled(TraceOptions.ThreadId))
                {
                    threadID = eventCache.ThreadId;
                }
                if (IsEnabled(TraceOptions.Callstack))
                {
                    callStack = eventCache.Callstack;
                }
                if (IsEnabled(TraceOptions.LogicalOperationStack))
                {
                    StringBuilder builder        = new StringBuilder();
                    Stack         operationStack = eventCache.LogicalOperationStack;
                    bool          isFirstItem    = true;
                    foreach (object stackItem in operationStack)
                    {
                        if (isFirstItem)
                        {
                            isFirstItem = false;
                        }
                        else
                        {
                            builder.Append(Environment.NewLine);
                        }
                        builder.Append(stackItem.ToString());
                    }
                    operationStackText = builder.ToString();
                }
            }
            // For Trace.Write/WriteLine: EventCache will be null.
            else
            {
                if (ShouldSaveStackTrace(category))
                {
                    // Skip the 5 stack frames relating to this class and to Trace.Write/WriteLine/Fail or
                    //	TraceSource.TraceData/TraceEvent/TraceTransfer.
                    StackTrace stackTrace = new StackTrace(5, true);
                    callStack = stackTrace.ToString();
                }

                if (IsEnabled(TraceOptions.DateTime))
                {
                    eventDateTime = DateTime.Now;
                }
            }
            oOptionalTraceOutputFields.DateTime              = eventDateTime;
            oOptionalTraceOutputFields.Timestamp             = eventTimestamp;
            oOptionalTraceOutputFields.ProcessID             = processID;
            oOptionalTraceOutputFields.ThreadID              = threadID;
            oOptionalTraceOutputFields.CallStack             = callStack;
            oOptionalTraceOutputFields.LogicalOperationStack = operationStackText;
        }