|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace DiagnosticExplorer.Silverlight
{
public static class TraceParser
{
private static Regex itemRegex = new Regex(@"\[([0-9]+\.[0-9]+)\] \[([0-9]+\.[0-9]+)\]( (BEGIN|END|BEGIN/END))? (.*)");
private static Regex secondsRegex = new Regex(@" \(([0-9]+\.[0-9]+) seconds\)?");
public static TraceItem Parse(string text)
{
try
{
TraceParent parent = ParseFromText(text);
if (parent != null)
{
foreach (TraceItem child in parent.Children)
PopulateInterest(child, parent.Total);
parent.Expanded = true;
}
return parent;
}
catch (Exception ex)
{
TraceParent error = new TraceParent();
error.Text = ex.Message;
error.Detail = ex.ToString();
return error;
}
}
private static void PopulateInterest(TraceItem item, TimeSpan total)
{
TraceParent parent = item as TraceParent;
if (parent != null)
{
foreach (TraceItem child in parent.Children)
PopulateInterest(child, total);
parent.InterestLevel = GetInterestLevel(parent.Total, total);
parent.Expanded = parent.Children.Any(x => x.InterestLevel == InterestLevel.High);
}
else
{
item.InterestLevel = GetInterestLevel(item.TimeDelta, total);
}
}
private static InterestLevel GetInterestLevel(TimeSpan delta, TimeSpan total)
{
if (total.TotalMilliseconds == 0) return InterestLevel.Low;
double timePercentage = delta.TotalMilliseconds / total.TotalMilliseconds * 100;
if (timePercentage > 10) return InterestLevel.High;
if (timePercentage > 5) return InterestLevel.Medium;
return InterestLevel.Low;
}
public static TraceParent ParseFromText(string text)
{
if (string.IsNullOrEmpty(text))
return null;
Match firstMatch = itemRegex.Match(text);
if (!firstMatch.Success)
return null;
text = text.Substring(firstMatch.Index);
string[] lines = Regex.Split(text, Environment.NewLine);
Stack<TraceParent> stack = new Stack<TraceParent>();
foreach (string line in lines)
{
Match match = itemRegex.Match(line);
if (!match.Success)
{
TraceItem item = stack.Peek().Children.Last();
if (item.Detail != null)
item.Detail += Environment.NewLine;
string pattern = string.Format("^ {{1,{0}}}", stack.Count * 4 + 14);
item.Detail += Regex.Replace(line, pattern, "");
continue;
}
string rawText = match.Groups[5].Value;
string itemText = secondsRegex.Replace(rawText, "");
TimeSpan time1 = TimeSpan.FromSeconds(double.Parse(match.Groups[1].Value));
TimeSpan time2 = TimeSpan.FromSeconds(double.Parse(match.Groups[2].Value));
string type = match.Groups[4].Value;
switch (type)
{
case "BEGIN":
{
TraceParent newParent = new TraceParent();
newParent.TimeTotal = time1;
newParent.TimeDelta = time2;
newParent.Text = itemText;
Match secondsMatch = secondsRegex.Match(rawText);
if (secondsMatch.Success)
{
double seconds = double.Parse(secondsMatch.Groups[1].Value);
newParent.EndTimeTotal = newParent.TimeTotal + TimeSpan.FromSeconds(seconds);
}
if (stack.Count != 0)
stack.Peek().Children.Add(newParent);
stack.Push(newParent);
break;
}
case "END":
{
TraceParent parent = stack.Pop();
// parent.EndTimeTotal = time1;
parent.EndTimeDelta = time2;
TraceItem item = new TraceItem();
item.TimeTotal = time1;
item.TimeDelta = time2;
item.Text = "End";
parent.Children.Add(item);
if (stack.Count == 0)
return parent;
break;
}
case "":
case "BEGIN/END":
{
TraceItem item = new TraceItem();
item.TimeTotal = time1;
item.TimeDelta = time2;
item.Text = itemText;
stack.Peek().Children.Add(item);
break;
}
}
}
if (stack.Count == 0)
return null;
TraceParent result = stack.Pop();
while (stack.Count != 0)
result = stack.Pop();
return result;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I am a software developer originally from Auckland, New Zealand. I have lived and worked in London since 2005.