Example #1
0
        private static bool AddStatementToAggregatedCallTree(
            ProfilerEvent?currentProfilerEvent,
            ref AggregatedEventNode currentAggregatedEventNode,
            ref Stack <ProfilerEvent> callStack)
        {
            if (currentAggregatedEventNode.Parent == null)
            {
                // Do not add statements to root node
                return(true);
            }

            // If there are two consecutive statements then first we need to calculate the duration for the previous
            // one and pop it from the statement call stack.
            // Then we push the current statement event into the stack
            if (currentAggregatedEventNode.Parent != null && currentAggregatedEventNode.EvaluatedType == EventType.Statement ||
                // Function or sql statement called for previous statement has just ended
                currentAggregatedEventNode.EvaluatedType == EventType.StopMethod &&
                !currentAggregatedEventNode.IsExecutingFunction)
            {
                currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);
            }

            currentAggregatedEventNode.EvaluatedType = EventType.Statement;

            currentAggregatedEventNode = currentAggregatedEventNode.PushEventIntoCallStack(currentProfilerEvent.Value);

            return(true);
        }
Example #2
0
        private static void PopEventFromCallStackForPreviousAlStopMethodEvent(
            ProfilerEvent?previousProfilerEvent,
            ProfilerEvent?currentProfilerEvent,
            ref AggregatedEventNode currentAggregatedEventNode)
        {
            if (previousProfilerEvent.HasValue && previousProfilerEvent.Value.Type == EventType.StopMethod &&
                previousProfilerEvent.Value.SubType != EventSubType.SqlEvent)
            {
                // We have already calculated duration for the previous statement
                // and pop it from the statement call stack.

                // We should never pop root event. This can happen if we miss some events in the begining.
                if (currentAggregatedEventNode.Parent != null)
                {
                    if (!currentProfilerEvent.HasValue || // Previous event is the last one.
                        // The current event is none AL event. It comes after stop event. Need to pop the the current aggregated node. Only close AL events.
                        (currentProfilerEvent.Value.IsNonAlEvent && previousProfilerEvent.Value.IsAlEvent) ||
                        // Here we have statement after function call.
                        currentProfilerEvent.Value.Type == EventType.Statement ||
                        // Here we have funtion call in the end of other function.
                        currentProfilerEvent.Value.Type == EventType.StopMethod ||
                        // If we have two consecutive root method calls
                        (currentAggregatedEventNode.OriginalType == EventType.StartMethod &&
                         currentAggregatedEventNode.IsAlEvent))
                    {
                        currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(previousProfilerEvent.Value.TimeStampRelativeMSec);
                    }
                }
            }
        }
Example #3
0
        private static bool AddStopMethodToAggregatedCallTree(
            ProfilerEvent?currentProfilerEvent,
            ref AggregatedEventNode currentAggregatedEventNode,
            ref Stack <ProfilerEvent> callStack)
        {
            if (currentAggregatedEventNode.Parent != null)
            {
                if (callStack.Count() == 0)
                {
                    // Discard current tree
                    while (currentAggregatedEventNode.Parent != null)
                    {
                        currentAggregatedEventNode = currentAggregatedEventNode.Parent;
                    }

                    currentAggregatedEventNode.Children.Clear();

                    return(false);
                }

                ProfilerEvent startEvent = callStack.Peek();
                if (currentProfilerEvent.Value.ObjectType != startEvent.ObjectType ||
                    currentProfilerEvent.Value.ObjectId != startEvent.ObjectId ||
                    currentProfilerEvent.Value.StatementName != startEvent.StatementName)
                {
                    // Skip stop event from empty functions
                    return(false);
                }

                // We need to calculate duration for the previous statement and pop it from the statement call stack.
                if (currentAggregatedEventNode.EvaluatedType == EventType.Statement ||
                    currentAggregatedEventNode.EvaluatedType == EventType.StopMethod ||
                    // Always close non events.
                    currentProfilerEvent.Value.IsNonAlEvent)
                {
                    currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);

                    if (currentProfilerEvent.Value.SubType == EventSubType.AlEvent &&
                        currentAggregatedEventNode.SubType == EventSubType.AlEvent &&
                        currentAggregatedEventNode.Parent != null &&
                        currentAggregatedEventNode.Parent.Parent == null)
                    {
                        // Also pop function node created for root functions
                        currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);
                    }
                }

                currentAggregatedEventNode.EvaluatedType = EventType.StopMethod;

                if (currentProfilerEvent.Value.IsAlEvent)
                {
                    currentAggregatedEventNode.IsExecutingFunction = false;
                }

                callStack.Pop();
            }

            return(true);
        }
Example #4
0
        private static void PopEventFromCallStackForPreviousAlStopMethodEvent(
            ProfilerEvent?previousProfilerEvent,
            ProfilerEvent?currentProfilerEvent,
            ref AggregatedEventNode currentAggregatedEventNode,
            ref Stack <ProfilerEvent> callStack)
        {
            if (previousProfilerEvent.HasValue && previousProfilerEvent.Value.Type == EventType.StopMethod &&
                previousProfilerEvent.Value.SubType != EventSubType.SqlEvent)
            {
                // We have already calculated duration for the previous statement
                // and pop it from the statement call stack.

                // We should never pop root event. This can happen if we miss some events in the begining.
                if (currentAggregatedEventNode.Parent != null)
                {
                    if (!currentProfilerEvent.HasValue || // Previous event is the last one.
                                                          // The current event is none AL event. It comes after stop event. Need to pop the the current aggregated node. Only close AL events.
                        (currentProfilerEvent.Value.IsNonAlEvent && previousProfilerEvent.Value.IsAlEvent) ||
                        // Here we have statement after function call.
                        currentProfilerEvent.Value.Type == EventType.Statement ||
                        // Here we have funtion call in the end of other function.
                        currentProfilerEvent.Value.Type == EventType.StopMethod ||
                        // If we have two consecutive root method calls
                        (currentAggregatedEventNode.OriginalType == EventType.StartMethod &&
                         currentAggregatedEventNode.IsAlEvent))
                    {
                        if (currentProfilerEvent.HasValue && currentProfilerEvent.Value.IsNonAlEvent && previousProfilerEvent.Value.IsAlEvent)
                        {
                            return;
                        }

                        if (currentProfilerEvent.HasValue && currentProfilerEvent.Value.Type == EventType.StopMethod && currentProfilerEvent.Value.SubType == EventSubType.AlEvent && (
                                callStack.Count() == 0 ||
                                callStack.Peek().ObjectType != currentProfilerEvent.Value.ObjectType ||
                                callStack.Peek().ObjectId != currentProfilerEvent.Value.ObjectId ||
                                callStack.Peek().FunctionName != currentProfilerEvent.Value.StatementName))
                        {
                            return;
                        }

                        //AggregatedEventNode currentAggregatedEventNode2 = currentAggregatedEventNode;
                        //List<AggregatedEventNode> before = currentAggregatedEventNode.Parent.Children.TakeWhile(x => x != currentAggregatedEventNode2).ToList();

                        //if (currentAggregatedEventNode.OriginalType == EventType.StartMethod && currentAggregatedEventNode.IsAlEvent)
                        //    if (before.Any(x => x.EvaluatedType == EventType.StartMethod) && !before.Any(x => x.OriginalType == EventType.Statement))
                        //        return;

                        currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(previousProfilerEvent.Value.TimeStampRelativeMSec);
                    }
                }
            }
        }
Example #5
0
        private static bool AddStatementToAggregatedCallTree(ProfilerEvent?currentProfilerEvent, ref AggregatedEventNode currentAggregatedEventNode)
        {
            // If there are two consecutive statements then first we need to calculate the duration for the previous
            // one and pop it from the statement call stack.
            // Then we push the current statement event into the stack
            if (currentAggregatedEventNode.Parent != null && currentAggregatedEventNode.EvaluatedType == EventType.Statement)
            {
                currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);
            }

            currentAggregatedEventNode = currentAggregatedEventNode.PushEventIntoCallStack(currentProfilerEvent.Value);

            return(true);
        }
Example #6
0
        private static bool AddStopMethodToAggregatedCallTree(ProfilerEvent?currentProfilerEvent, ref AggregatedEventNode currentAggregatedEventNode)
        {
            if (currentAggregatedEventNode.Parent != null)
            {
                // We need to calculate duration for the previous statement and pop it from the statement call stack.
                if (currentAggregatedEventNode.EvaluatedType == EventType.Statement ||
                    // Always close non events.
                    currentProfilerEvent.Value.IsNonAlEvent)
                {
                    currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);
                }
            }

            return(true);
        }
Example #7
0
        private static bool PopEventFromCallStackIfSomeEventsWereMissing(
            ProfilerEvent?previousProfilerEvent,
            ProfilerEvent?currentProfilerEvent,
            ref AggregatedEventNode currentAggregatedEventNode,
            ref Stack <ProfilerEvent> callStack,
            out bool skipCurrentEvent)
        {
            if (currentAggregatedEventNode.Parent != null &&
                currentAggregatedEventNode.OriginalType == EventType.StartMethod &&
                currentAggregatedEventNode.SubType == EventSubType.SqlEvent &&
                currentProfilerEvent.HasValue && !(currentProfilerEvent.Value.Type == EventType.StopMethod && currentProfilerEvent.Value.SubType == EventSubType.SqlEvent))
            {
                // TODO: Here we have two consecutive start events. First event is of the SQL subtype. This should never happen because SQL queries cannot be nested.
                // TODO: It could indicates an issue in evening.
                // TODO: Need to pop previous event and push current.

                ProfilerEvent missingProfilerEvent = new ProfilerEvent
                {
                    SessionId     = currentAggregatedEventNode.SessionId,
                    ObjectType    = currentAggregatedEventNode.ObjectType,
                    ObjectId      = currentAggregatedEventNode.ObjectId,
                    LineNo        = currentAggregatedEventNode.LineNo,
                    Type          = EventType.StartMethod,
                    StatementName = StopEventIsMissing + currentAggregatedEventNode.StatementName
                };

                currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(previousProfilerEvent.Value.TimeStampRelativeMSec);

                currentAggregatedEventNode = currentAggregatedEventNode.PushEventIntoCallStack(missingProfilerEvent);
                currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(missingProfilerEvent.TimeStampRelativeMSec);

                if (currentProfilerEvent.Value.Type == EventType.StartMethod || currentProfilerEvent.Value.Type == EventType.Statement)
                {
                    currentAggregatedEventNode = currentAggregatedEventNode.PushEventIntoCallStack(currentProfilerEvent.Value);
                }

                skipCurrentEvent = true;
                return(true);
            }

            if (currentAggregatedEventNode.Parent != null &&
                previousProfilerEvent.HasValue && previousProfilerEvent.Value.Type == EventType.StopMethod &&
                currentProfilerEvent.HasValue && currentProfilerEvent.Value.Type == EventType.StopMethod &&
                currentProfilerEvent.Value.IsAlEvent != currentAggregatedEventNode.IsAlEvent)
            {
                //TODO: We hit this block for example in the case if Codeunit 1 trigger is called and it does not have any code.
                //TODO: We should consider if we want to fix it in the product.
                // Skip this event. Should never happen. Indicates a issue in the event generation.
                // Some events were missed.

                // Create fake start event.
                ProfilerEvent profilerEvent = currentProfilerEvent.Value;
                profilerEvent.Type          = EventType.StartMethod;
                profilerEvent.StatementName = StartEventIsMissing + profilerEvent.StatementName;

                currentAggregatedEventNode = currentAggregatedEventNode.PushEventIntoCallStack(profilerEvent);
                currentAggregatedEventNode = currentAggregatedEventNode.PopEventFromCallStackAndCalculateDuration(currentProfilerEvent.Value.TimeStampRelativeMSec);

                skipCurrentEvent = false;
                return(true);
            }

            skipCurrentEvent = false;
            return(false);
        }