/// <inheritdoc/>
        public override T?GetAdaptedValue(PipelineDiagnostics source, Envelope envelope)
        {
            var receiver = source?.GetAllReceiverDiagnostics()?.FirstOrDefault(rd => rd.Id == this.receiverId);

            if (receiver == null)
            {
                return(null);
            }
            else
            {
                return(this.memberFunc(receiver));
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Update diagnostics graph.
        /// </summary>
        /// <param name="graph">Current diagnostics graph.</param>
        /// <param name="forceRelayout">Force re-layout of graph (otherwise, updates labels, colors, etc. in place).</param>
        public void UpdateGraph(PipelineDiagnostics graph, bool forceRelayout)
        {
            this.model.Graph = graph;
            if (graph == null)
            {
                this.VisualGraph = null;
            }
            else
            {
                var pipelineIdToPipelineDiagnostics = graph.GetAllPipelineDiagnostics().ToDictionary(p => p.Id);
                var currentGraph = this.Breadcrumbs.Count() > 0 ? pipelineIdToPipelineDiagnostics[this.Breadcrumbs.Last()] : graph;
                this.VisualGraph = this.BuildVisualGraph(currentGraph, pipelineIdToPipelineDiagnostics);
            }

            this.view.Update(forceRelayout);
        }
Esempio n. 3
0
        /// <summary>
        /// Update diagnostics graph.
        /// </summary>
        /// <param name="graph">Current diagnostics graph.</param>
        public void UpdateGraph(PipelineDiagnostics graph)
        {
            this.model.Graph = graph;
            foreach (var view in this.Breadcrumbs)
            {
                if (!graph.Subpipelines.TryGetValue(view, out PipelineDiagnostics subgraph))
                {
                    graph = null;
                    break;
                }

                graph = subgraph;
            }

            this.VisualGraph = graph != null?this.BuildVisualGraph(graph) : null;

            this.view.Update();
        }
Esempio n. 4
0
        private Graph BuildVisualGraph(PipelineDiagnostics diagnostics, Dictionary <int, PipelineDiagnostics> pipelineIdToPipelineDiagnostics)
        {
            var subpipelineIdToPipelineDiagnostics = diagnostics.SubpipelineDiagnostics.ToDictionary(p => p.Id);
            var graph = new Graph($"{diagnostics.Name} (running={diagnostics.IsPipelineRunning})", $"g{diagnostics.Id}");

            switch (this.model.VisualizationObject.LayoutDirection)
            {
            case PipelineDiagnosticsVisualizationObject.GraphLayoutDirection.LeftToRight:
                graph.Attr.LayerDirection = LayerDirection.LR;
                break;

            case PipelineDiagnosticsVisualizationObject.GraphLayoutDirection.TopToBottom:
                graph.Attr.LayerDirection = LayerDirection.TB;
                break;

            case PipelineDiagnosticsVisualizationObject.GraphLayoutDirection.RightToLeft:
                graph.Attr.LayerDirection = LayerDirection.RL;
                break;

            case PipelineDiagnosticsVisualizationObject.GraphLayoutDirection.BottomToTop:
                graph.Attr.LayerDirection = LayerDirection.BT;
                break;
            }

            graph.UserData             = diagnostics.Id;
            graph.Attr.BackgroundColor = Color.Transparent;
            var subpipelineNodes             = new Dictionary <int, PipelineDiagnostics.PipelineElementDiagnostics>();
            var connectorsWithinSubpipelines = new Dictionary <int, PipelineDiagnostics.PipelineElementDiagnostics>();
            var statsSelector = this.StatsSelector(false);

            // add nodes
            foreach (var node in diagnostics.PipelineElements.Where(n => !this.IsConnectorBridge(n)))
            {
                var vis = this.BuildVisualNode(node);
                if (node.Kind == PipelineElementKind.Subpipeline && node.RepresentsSubpipeline != null)
                {
                    vis.UserData = node.RepresentsSubpipeline;
                    subpipelineNodes.Add(node.RepresentsSubpipeline.Id, node);
                    foreach (var n in node.RepresentsSubpipeline.PipelineElements.Where(n => n.Kind == PipelineElementKind.Connector))
                    {
                        connectorsWithinSubpipelines.Add(n.Id, n);
                    }
                }
                else if (node.Kind == PipelineElementKind.Connector)
                {
                    this.SetConnectorVisualAttributes(vis, node.Name);
                }

                graph.AddNode(vis);
            }

            // add connectors
            foreach (var node in diagnostics.PipelineElements.Where(this.IsConnectorBridge))
            {
                var connectsToSubpipeline = subpipelineNodes.ContainsKey(node.ConnectorBridgeToPipelineElement.PipelineId);
                if (!connectsToSubpipeline)
                {
                    if (!this.ShowExporterConnections && IsBridgeToExporter(node))
                    {
                        continue;
                    }

                    var connector       = new Node($"n{node.Id}");
                    var bridgedPipeline = pipelineIdToPipelineDiagnostics[node.ConnectorBridgeToPipelineElement.PipelineId];
                    this.SetConnectorVisualAttributes(connector, $"{node.Name} ({bridgedPipeline.Name})");
                    graph.AddNode(connector);
                }
            }

            // add edges
            var selectedEdgeUpdated = false;

            foreach (var n in diagnostics.PipelineElements)
            {
                foreach (var i in n.Receivers)
                {
                    if (i.Source != null)
                    {
                        if (this.AddVisualEdge(i.Source.PipelineElement.Id, n.Id, i, graph, statsSelector))
                        {
                            selectedEdgeUpdated = true;
                        }
                    }
                }
            }

            // add connector bridge edges
            foreach (var n in diagnostics.PipelineElements.Where(this.IsConnectorBridge))
            {
                if (!this.ShowExporterConnections && IsBridgeToExporter(n))
                {
                    continue;
                }

                // connector bridging to subpipeline?
                if (subpipelineNodes.TryGetValue(n.ConnectorBridgeToPipelineElement.PipelineId, out PipelineDiagnostics.PipelineElementDiagnostics subNode))
                {
                    // edges from connector source directly to bridge target (subpipeline)
                    var sub = graph.FindNode($"n{subNode.Id}");
                    if (sub != null)
                    {
                        foreach (var i in n.Receivers)
                        {
                            if (i.Source != null)
                            {
                                var source = graph.FindNode($"n{i.Source.PipelineElement.Id}");
                                if (source != null)
                                {
                                    if (this.AddVisualEdge(source, sub, i, graph, statsSelector))
                                    {
                                        selectedEdgeUpdated = true;
                                    }
                                }
                            }
                        }

                        // edges from connector bridge source (subpipeline) to connector targets
                        foreach (var o in n.Emitters)
                        {
                            foreach (var t in o.Targets)
                            {
                                var target = graph.FindNode($"n{t.PipelineElement.Id}");
                                if (target != null)
                                {
                                    if (this.AddVisualEdge(sub, target, t, graph, statsSelector))
                                    {
                                        selectedEdgeUpdated = true;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    // connector bridging graphs
                    var bridgedPipeline = pipelineIdToPipelineDiagnostics[n.ConnectorBridgeToPipelineElement.PipelineId];
                    var connector       = graph.FindNode($"n{n.Id}");

                    // add dotted line edge representing connector bridged to descendant pipeline
                    var targetPipeline = bridgedPipeline;
                    while (targetPipeline != null)
                    {
                        if (subpipelineIdToPipelineDiagnostics.ContainsKey(targetPipeline.Id))
                        {
                            var targetNode = graph.FindNode($"n{subpipelineNodes[targetPipeline.Id].Id}");
                            graph.AddPrecalculatedEdge(this.BuildVisualEdge(connector, targetNode, n.Name, bridgedPipeline.Name, string.Empty, string.Empty, Style.Dotted));
                            break;
                        }

                        // walk up ancestor chain until we're at a direct child subpipeline
                        targetPipeline = targetPipeline.ParentPipelineDiagnostics;
                    }
                }
            }

            // add connector bridge edges between descendants (shown between current-level subpiplines)
            int?TryFindCurrentLevelAncestorSubpipelineId(int id)
            {
                foreach (var ancestor in pipelineIdToPipelineDiagnostics[id].AncestorPipelines)
                {
                    if (subpipelineNodes.TryGetValue(ancestor.Id, out PipelineDiagnostics.PipelineElementDiagnostics subpipeline))
                    {
                        return(subpipeline.Id);
                    }
                }

                return(null);
            }

            foreach (var descendantConnector in diagnostics.GetAllPipelineElementDiagnostics().Where(this.IsConnectorBridge))
            {
                if (descendantConnector.Emitters.Length == 0 /* source-side of connector pair */)
                {
                    var sourceId             = descendantConnector.PipelineId;
                    var targetId             = descendantConnector.ConnectorBridgeToPipelineElement.PipelineId;
                    var sourceCurrentLevelId = TryFindCurrentLevelAncestorSubpipelineId(sourceId);
                    var targetCurrentLevelId = TryFindCurrentLevelAncestorSubpipelineId(targetId);
                    if (sourceCurrentLevelId != null && targetCurrentLevelId != null && sourceCurrentLevelId != targetCurrentLevelId)
                    {
                        var sourceNode = graph.FindNode($"n{sourceCurrentLevelId}");
                        var targetNode = graph.FindNode($"n{targetCurrentLevelId}");
                        graph.AddPrecalculatedEdge(this.BuildVisualEdge(sourceNode, targetNode, string.Empty, descendantConnector.Name, string.Empty, string.Empty, Style.Dotted));
                    }
                }
            }

            // add direct connections from one subpipeline (connector) to another
            foreach (var c in connectorsWithinSubpipelines.Values)
            {
                if (c.ConnectorBridgeToPipelineElement != null)
                {
                    if (c.ConnectorBridgeToPipelineElement.PipelineId == diagnostics.Id && c.ConnectorBridgeToPipelineElement.Receivers.Length == 1)
                    {
                        var i = c.ConnectorBridgeToPipelineElement.Receivers[0];
                        if (i.Source != null && i.Source.PipelineElement.PipelineId == diagnostics.Id && i.Source.PipelineElement.ConnectorBridgeToPipelineElement != null)
                        {
                            if (subpipelineNodes.TryGetValue(i.Source.PipelineElement.ConnectorBridgeToPipelineElement.PipelineId, out PipelineDiagnostics.PipelineElementDiagnostics source) &&
                                subpipelineNodes.TryGetValue(c.PipelineId, out PipelineDiagnostics.PipelineElementDiagnostics target))
                            {
                                if (this.AddVisualEdge(source.Id, target.Id, i, graph, statsSelector))
                                {
                                    selectedEdgeUpdated = true;
                                }
                            }
                        }
                    }
                }
            }

            if (!selectedEdgeUpdated && this.model.SelectedEdgeId != -1)
            {
                // hide while in subpipeline
                this.model.SelectedEdgeDetails = string.Empty;
            }

            this.VisualizeEdgeColoring(graph);
            return(graph);
        }
Esempio n. 5
0
        private Graph BuildVisualGraph(PipelineDiagnostics diagnostics)
        {
            var graph = new Graph($"{diagnostics.Name} (running={diagnostics.IsPipelineRunning})", $"g{diagnostics.Id}");

            switch (this.model.Config.LayoutDirection)
            {
            case Config.DiagnosticsVisualizationObjectConfiguration.GraphLayoutDirection.LeftToRight:
                graph.Attr.LayerDirection = LayerDirection.LR;
                break;

            case Config.DiagnosticsVisualizationObjectConfiguration.GraphLayoutDirection.TopToBottom:
                graph.Attr.LayerDirection = LayerDirection.TB;
                break;

            case Config.DiagnosticsVisualizationObjectConfiguration.GraphLayoutDirection.RightToLeft:
                graph.Attr.LayerDirection = LayerDirection.RL;
                break;

            case Config.DiagnosticsVisualizationObjectConfiguration.GraphLayoutDirection.BottomToTop:
                graph.Attr.LayerDirection = LayerDirection.BT;
                break;
            }

            graph.UserData             = diagnostics.Id;
            graph.Attr.BackgroundColor = Color.Transparent;
            var subpipelineNodes             = new Dictionary <int, PipelineDiagnostics.PipelineElementDiagnostics>();
            var connectorsWithinSubpipelines = new Dictionary <int, PipelineDiagnostics.PipelineElementDiagnostics>();
            var statsSelector = this.StatsSelector(false);

            // add nodes
            var nodes = diagnostics.PipelineElements.Select(n => n.Value).Where(n => !this.IsConnectorBridge(n));

            foreach (var node in nodes)
            {
                var vis = this.BuildVisualNode(node);
                if (node.Kind == PipelineDiagnostics.PipelineElementDiagnostics.PipelineElementKind.Subpipeline)
                {
                    vis.UserData = node.RepresentsSubpipeline;
                    subpipelineNodes.Add(node.RepresentsSubpipeline.Id, node);
                    foreach (var n in node.RepresentsSubpipeline.PipelineElements.Values.Where(n => n.Kind == PipelineDiagnostics.PipelineElementDiagnostics.PipelineElementKind.Connector))
                    {
                        connectorsWithinSubpipelines.Add(n.Id, n);
                    }
                }
                else if (node.Kind == PipelineDiagnostics.PipelineElementDiagnostics.PipelineElementKind.Connector)
                {
                    vis.Attr.Color     = this.ConnectorColor;
                    vis.Attr.FillColor = this.ConnectorColor;
                    vis.Attr.Shape     = Shape.Circle;
                    vis.LabelText      = string.Empty;
                }

                graph.AddNode(vis);
            }

            // add edges
            var selectedEdgeUpdated = false;

            foreach (var n in diagnostics.PipelineElements)
            {
                foreach (var i in n.Value.Receivers)
                {
                    if (i.Value.Source != null)
                    {
                        if (this.AddVisualEdge(i.Value.Source.PipelineElement.Id, n.Value.Id, i.Value, graph, statsSelector))
                        {
                            selectedEdgeUpdated = true;
                        }
                    }
                }
            }

            // add connectors
            foreach (var n in diagnostics.PipelineElements.Where(n => this.IsConnectorBridge(n.Value)))
            {
                // connector bridging to subpipeline?
                if (subpipelineNodes.TryGetValue(n.Value.ConnectorBridgeToPipelineElement.ParentPipeline.Id, out PipelineDiagnostics.PipelineElementDiagnostics subNode))
                {
                    // edges from connector source directly to bridge target (subpipeline)
                    var sub = graph.FindNode($"n{subNode.Id}");
                    if (sub != null)
                    {
                        foreach (var i in n.Value.Receivers)
                        {
                            if (i.Value.Source != null)
                            {
                                var source = graph.FindNode($"n{i.Value.Source.PipelineElement.Id}");
                                if (source != null)
                                {
                                    graph.AddPrecalculatedEdge(this.BuildVisualEdge(source, sub, i.Value, statsSelector));
                                }
                            }
                        }

                        // edges from connector bridge source (subpipeline) to connector targets
                        foreach (var o in n.Value.Emitters)
                        {
                            foreach (var t in o.Value.Targets)
                            {
                                var target = graph.FindNode($"n{t.Value.PipelineElement.Id}");
                                if (target != null)
                                {
                                    graph.AddPrecalculatedEdge(this.BuildVisualEdge(sub, target, t.Value, statsSelector));
                                }
                            }
                        }
                    }
                }
                else
                {
                    // connector bridging to parent graph
                    var connector = new Node($"n{n.Value.Id}");
                    connector.Attr.Color     = this.ConnectorColor;
                    connector.Attr.FillColor = this.ConnectorColor;
                    connector.Attr.Shape     = Shape.Circle;
                    connector.LabelText      = string.Empty;
                    graph.AddNode(connector);

                    // edges from connector to target node
                    foreach (var o in n.Value.Emitters)
                    {
                        foreach (var t in o.Value.Targets)
                        {
                            var target = graph.FindNode($"n{t.Value.PipelineElement.Id}");
                            if (target != null)
                            {
                                graph.AddPrecalculatedEdge(this.BuildVisualEdge(connector, target, t.Value, statsSelector));
                            }
                        }
                    }

                    // edges to connector from source node
                    foreach (var i in n.Value.Receivers)
                    {
                        if (i.Value.Source != null)
                        {
                            var source = graph.FindNode($"n{i.Value.Source.PipelineElement.Id}");
                            if (source != null)
                            {
                                graph.AddPrecalculatedEdge(this.BuildVisualEdge(source, connector, i.Value, statsSelector));
                            }
                        }
                    }
                }
            }

            // add direct connections from one subpipeline (connector) to another
            foreach (var c in connectorsWithinSubpipelines.Values)
            {
                if (c.ConnectorBridgeToPipelineElement != null)
                {
                    if (c.ConnectorBridgeToPipelineElement.ParentPipeline == diagnostics && c.ConnectorBridgeToPipelineElement.Receivers.Count == 1)
                    {
                        var i = c.ConnectorBridgeToPipelineElement.Receivers.Values.First();
                        if (i.Source != null && i.Source.PipelineElement.ParentPipeline == diagnostics && i.Source.PipelineElement.ConnectorBridgeToPipelineElement != null)
                        {
                            if (subpipelineNodes.TryGetValue(i.Source.PipelineElement.ConnectorBridgeToPipelineElement.ParentPipeline.Id, out PipelineDiagnostics.PipelineElementDiagnostics source) &&
                                subpipelineNodes.TryGetValue(c.ParentPipeline.Id, out PipelineDiagnostics.PipelineElementDiagnostics target))
                            {
                                if (this.AddVisualEdge(source.Id, target.Id, i, graph, statsSelector))
                                {
                                    selectedEdgeUpdated = true;
                                }
                            }
                        }
                    }
                }
            }

            if (!selectedEdgeUpdated && this.selectedEdgeId != -1)
            {
                // hide while in subpipeline
                this.SelectedEdgeDetails = string.Empty;
            }

            this.VisualizeHeatmap(graph);
            return(graph);
        }