Skip to content

Commit

Permalink
TraceParserGen: Fix task guids and RegisterTemplate.
Browse files Browse the repository at this point in the history
Add Task class and keep instances in m_tasks dictionary
instead of m_taskNames, m_taskValues and potential m_taskGuids.

Generate guids variables or pass Guid.Empty

Add basic RegisterTemplate implementation.

fix microsoft#1351
  • Loading branch information
dorian-apanel-intel committed Apr 20, 2021
1 parent ecf8d35 commit 656de09
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 41 deletions.
86 changes: 54 additions & 32 deletions src/TraceParserGen/ETWManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,12 @@ public static List<Provider> ParseManifest(XmlReader reader, string fileName = n
}
}

if (provider.m_taskNames != null)
if (provider.m_tasks != null)
{
foreach (var taskId in new List<int>(provider.m_taskNames.Keys))
foreach (var keyValuePair in provider.m_tasks)
{
var taskName = provider.m_taskNames[taskId];
if (Provider.Replace(ref taskName, stringMap))
{
provider.m_taskNames[taskId] = taskName;
}
Task task = keyValuePair.Value;
Provider.Replace(ref task.LocalizedMessageOrName, stringMap);
}
}

Expand Down Expand Up @@ -176,15 +173,16 @@ public string GetKeywordSetString(ulong keywords, string separator = ",")
/* These are relatively rare APIs, normally you only care in the context of an event */
public string GetTaskName(ushort taskId)
{
if (m_taskNames == null)
if (m_tasks == null)
{
return "";
}

string ret;
if (m_taskNames.TryGetValue(taskId, out ret))
foreach(var kv in m_tasks)
{
return ret;
Task task = kv.Value;
if (task.Value == taskId)
return task.Name;
}

if (taskId == 0)
Expand Down Expand Up @@ -213,6 +211,20 @@ public string GetOpcodeName(ushort taskId, byte opcodeId)
return "Opcode" + opcodeId;
}

public string GetGuidName(string taskName)
{
string empty = "Guid.Empty";

if(string.IsNullOrEmpty(taskName))
return empty;

Task task = m_tasks[taskName];
if (task != null && task.EventGuid != Guid.Empty)
return $"{taskName}TaskGuid";
else
return empty;
}

/// <summary>
/// For debugging
/// </summary>
Expand Down Expand Up @@ -273,25 +285,15 @@ internal Provider(XmlReader reader, string fileName)
break;
case "task":
{
if (m_taskNames == null)
if (m_tasks == null)
{
m_taskNames = new Dictionary<int, string>();
m_taskValues = new Dictionary<string, int>();
m_tasks = new Dictionary<string, Task>();
}
string name = reader.GetAttribute("name");
int value = (int)ParseNumber(reader.GetAttribute("value"));
Task task = new Task(reader, this, lineInfo.LineNumber);
m_tasks.Add(task.Name, task);

string message = reader.GetAttribute("message");
if (message == null)
{
message = name;
}

m_taskNames.Add(value, message);
m_taskValues.Add(name, value);

// Remember enuough to resolve opcodes nested inside this task.
curTask = value;
// Remember enough to resolve opcodes nested inside this task.
curTask = task.Value;
curTaskDepth = reader.Depth;
reader.Read();
}
Expand Down Expand Up @@ -358,7 +360,6 @@ internal Provider(XmlReader reader, string fileName)
}

// We are done with these. Free up some space.
m_taskValues = null;
m_opcodeValues = null;
m_keywordValues = null;
m_templateValues = null;
Expand Down Expand Up @@ -555,12 +556,10 @@ private void ReadTemplate(XmlReader reader)

private List<Event> m_events = new List<Event>();
internal string[] m_keywordNames;
internal Dictionary<int, string> m_taskNames;
internal Dictionary<string, Task> m_tasks;
// Note that the key is task << 8 + opcode to allow for private opcode names
internal Dictionary<int, string> m_opcodeNames;

// These are not used after parsing.
internal Dictionary<string, int> m_taskValues;
// Note that the value is task << 8 + opcode to allow for private opcode names
// Also the key is taskId : opcodeName again to allow private opcode names or simply opcodeName if it is global.
internal Dictionary<string, int> m_opcodeValues;
Expand Down Expand Up @@ -747,7 +746,7 @@ internal void ResolveIdsInEvent(string fileName = null)
m_taskId = null;
if (id != null)
{
Task = (ushort)m_provider.m_taskValues[id];
Task = (ushort)m_provider.m_tasks[id].Value;
}

id = m_opcodeId;
Expand Down Expand Up @@ -833,6 +832,29 @@ internal void UpdateStrings(Dictionary<string, string> stringMap)
#endregion
}

/// <summary>
/// A task represents the Task Element in the manifest.
/// </summary>
public sealed class Task
{
public int Value { get; internal set; }
public string Name { get; internal set; }
public string Message { get; internal set; }
public string LocalizedMessageOrName;
public Guid EventGuid { get; internal set; }

internal Task(XmlReader reader, Provider provider, int lineNum)
{
Name = reader.GetAttribute("name");
Value = (int)Provider.ParseNumber(reader.GetAttribute("value"));

Message = reader.GetAttribute("message");
LocalizedMessageOrName = Message ?? Name;

string guid = reader.GetAttribute("eventGUID");
EventGuid = (guid != null) ? Guid.Parse(guid) : Guid.Empty;
}
}
/// <summary>
/// A field represents one field in a ETW event
/// </summary>
Expand Down
36 changes: 27 additions & 9 deletions src/TraceParserGen/TraceParserGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private void GenerateTraceEventParserClass(TextWriter output)
output.WriteLine(" public sealed class " + ClassNamePrefix + "TraceEventParser : TraceEventParser ");
output.WriteLine(" {");
output.WriteLine(" public static string ProviderName = \"" + m_provider.Name + "\";");
output.WriteLine(" public static Guid ProviderGuid = " + CodeForGuidLiteral(m_provider.Id) + ";");
GenerateGuids(output);
GenerateKeywords(output);
output.WriteLine(" public " + ClassNamePrefix + "TraceEventParser(TraceEventSource source) : base(source) {}");
output.WriteLine("");
Expand Down Expand Up @@ -190,6 +190,21 @@ private void GenerateTraceEventParserClass(TextWriter output)
output.WriteLine("}");
}

private void GenerateGuids(TextWriter output)
{
output.WriteLine(" public static Guid ProviderGuid = " + CodeForGuidLiteral(m_provider.Id) + ";");
foreach (var kv in m_provider.m_tasks)
{
string taskName = kv.Key;
Task task = kv.Value;
if(task.EventGuid != Guid.Empty)
{
string guidName = m_provider.GetGuidName(taskName);
output.WriteLine(" public static Guid {0} = {1};", guidName, CodeForGuidLiteral(task.EventGuid));
}
}
}

private void GenerateKeywords(TextWriter output)
{
output.WriteLine(" public enum Keywords : long");
Expand Down Expand Up @@ -297,14 +312,13 @@ private void GenerateTemplateDefs(TextWriter output)
for (int i = 0; i < m_provider.Events.Count; i++)
{
var evnt = m_provider.Events[i];
string guid = m_provider.GetGuidName(evnt.TaskName);

// check if the same event template has not been already defined (different versions of the same event)
output.WriteLine(" templates[{0}] = new {1}TraceData(null, {2}, {3}, \"{4}\", {4}TaskGuid, {5}, \"{6}\", ProviderGuid, ProviderName);",
i, TraceParserGen.ToCSharpName(evnt.EventName),
evnt.Id, evnt.Task, TraceParserGen.ToCSharpName(evnt.TaskName), evnt.Opcode, TraceParserGen.ToCSharpName(evnt.OpcodeName)
output.WriteLine(" templates[{0}] = new {1}(null, {2}, {3}, \"{4}\", {5}, {6}, \"{7}\", ProviderGuid, ProviderName);",
i, GetTemplateNameForEvent(evnt, evnt.EventName),
evnt.Id, evnt.Task, TraceParserGen.ToCSharpName(evnt.TaskName), guid, evnt.Opcode, TraceParserGen.ToCSharpName(evnt.OpcodeName)
);
// as of today, the generated code won't compile because the task GUID is not defined
// TODO: define the xxxTaskGuid based on eventGUID attribute of <task> elements of the .man file
}

output.WriteLine(" s_templates = templates;");
Expand All @@ -314,6 +328,12 @@ private void GenerateTemplateDefs(TextWriter output)
output.WriteLine(" callback(template);");
output.WriteLine(" }");
output.WriteLine();

output.WriteLine(" private void RegisterTemplate(TraceEvent template)");
output.WriteLine(" {");
output.WriteLine(" Debug.Assert(template.ProviderGuid == " + ClassNamePrefix + "TraceEventParser.ProviderGuid);");
output.WriteLine(" source.RegisterEventTemplate(template);");
output.WriteLine(" }");
}

/// <summary>
Expand All @@ -340,9 +360,7 @@ private void GenerateEvents(TextWriter output)
output.WriteLine(" {");
output.WriteLine(" add");
output.WriteLine(" {");
var taskGuid = (string.IsNullOrEmpty(evnt.TaskName))
? "Guid.Empty"
: evnt.TaskName + "TaskGuid";
var taskGuid = m_provider.GetGuidName(evnt.TaskName);
var taskName = TraceParserGen.ToCSharpName(evnt.TaskName);
if (string.IsNullOrEmpty(taskName)) taskName = evntName;
// Call the *Template() function that does the work
Expand Down

0 comments on commit 656de09

Please sign in to comment.