public async ValueTask <SourceInformation> Source(TreeNode node) { var index = this.GetSourceLocation(node.BackingNode, node.Name, out Dictionary <StackSourceFrameIndex, float> retVal); var generic = this.callTree.StackSource.BaseStackSource as GenericStackSource; var sourceLocation = await generic.GetSourceLocation(index); // TODO: needs cleanup if (sourceLocation != null) { var buildTimePath = sourceLocation.SourceFile.BuildTimeFilePath; var srcSrvString = sourceLocation.SourceFile.GetSourceFile(); var lines = File.ReadAllLines(sourceLocation.SourceFile.GetSourceFile()); var list = new List <LineInformation>(); int i = 1; foreach (var line in lines) { var li = new LineInformation { Line = line, LineNumber = i++ }; list.Add(li); } var si = new SourceInformation { BuildTimeFilePath = buildTimePath, Lines = list, Summary = new List <LineInformation> { new LineInformation { LineNumber = sourceLocation.LineNumber, Metric = retVal[index] } } }; return(si); } return(null); // TODO: need to implement the local case i.e. this is the build machine }
public async ValueTask <SourceInformation> Source(string authorizationHeader, string name, char sep, string path = "") { var node = await this.GetCallerTreeNode(name, sep, path); var asCallTreeNodeBase = node.BackingNode; string cellText = node.Name; var m = Regex.Match(cellText, "<<(.*!.*)>>"); if (m.Success) { cellText = m.Groups[1].Value; } var ss = this.tuple.CallTree.StackSource; var frameIndexCounts = new Dictionary <StackSourceFrameIndex, float>(); asCallTreeNodeBase.GetSamples(false, sampleIdx => { var matchingFrameIndex = StackSourceFrameIndex.Invalid; var sample = ss.GetSampleByIndex(sampleIdx); var callStackIdx = sample.StackIndex; while (callStackIdx != StackSourceCallStackIndex.Invalid) { var frameIndex = ss.GetFrameIndex(callStackIdx); var frameName = ss.GetFrameName(frameIndex, false); if (frameName == cellText) { matchingFrameIndex = frameIndex; } callStackIdx = ss.GetCallerIndex(callStackIdx); } if (matchingFrameIndex != StackSourceFrameIndex.Invalid) { frameIndexCounts.TryGetValue(matchingFrameIndex, out float count); frameIndexCounts[matchingFrameIndex] = count + sample.Metric; } return(true); }); StackSourceFrameIndex maxFrameIdx = StackSourceFrameIndex.Invalid; float maxFrameIdxCount = -1; foreach (var keyValue in frameIndexCounts) { if (keyValue.Value >= maxFrameIdxCount) { maxFrameIdxCount = keyValue.Value; maxFrameIdx = keyValue.Key; } } if (maxFrameIdx == StackSourceFrameIndex.Invalid) { // TODO: Error handling ("Could not find " + cellText + " in call stack!") return(null); } var asTraceEventStackSource = GetTraceEventStackSource(ss); if (asTraceEventStackSource == null) { // TODO: Error handling ("Source does not support symbolic lookup.") return(null); } var log = new StringWriter(); using var reader = new SymbolReader(log) { AuthorizationHeaderForSourceLink = authorizationHeader }; var sourceLocation = asTraceEventStackSource.GetSourceLine(maxFrameIdx, reader); if (sourceLocation == null) { // TODO: Error handling ("Source could not find a source location for the given Frame.") return(null); } var sourceFile = sourceLocation.SourceFile; var filePathForMax = sourceFile.BuildTimeFilePath; var metricOnLine = new SortedDictionary <int, float>(Comparer <int> .Create((x, y) => y.CompareTo(x))); foreach (StackSourceFrameIndex frameIdx in frameIndexCounts.Keys) { var loc = asTraceEventStackSource.GetSourceLine(frameIdx, reader); if (loc != null && loc.SourceFile.BuildTimeFilePath == filePathForMax) { metricOnLine.TryGetValue(loc.LineNumber, out var metric); metric += frameIndexCounts[frameIdx]; metricOnLine[loc.LineNumber] = metric; } } var data = File.ReadAllText(sourceFile.GetSourceFile()); var list = new LineInformation[metricOnLine.Count]; int i = 0; foreach (var lineMetric in metricOnLine) { list[i++] = new LineInformation { LineNumber = lineMetric.Key, Metric = lineMetric.Value }; } var si = new SourceInformation { Url = sourceFile.Url, Log = log.ToString(), BuildTimeFilePath = filePathForMax, Summary = list, Data = data, }; return(si); }