public void TraceLineDiscovered(string sourceFile, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { string hash = decodedTraceLine.UniqueId; CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(_ModuleName); if (!_inited) { if (!moduleSettings.CustomSettings.ContainsKey("ETWManifestFile")) { throw new CLogEnterReadOnlyModeException("ETWManifestFileNotSpecified", CLogHandledException.ExceptionType.MustSpecifiyETWManifest, decodedTraceLine.match); } xmlFileName = moduleSettings.CustomSettings["ETWManifestFile"]; xmlFileName = Path.Combine(Path.GetDirectoryName(decodedTraceLine.macro.ConfigFileWithMacroDefination), xmlFileName); Init(); } if (!moduleSettings.CustomSettings.ContainsKey("ETW_Provider")) { Console.WriteLine($"The 'CustomSettings' dictionary for macro {decodedTraceLine.macro.MacroName} does not contain a GUID for the EtwProvider"); Console.WriteLine(" Please add an entry and rerun"); Console.WriteLine(""); Console.WriteLine($"Configuration File : {decodedTraceLine.configFile.FilePath}"); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine(""); throw new CLogEnterReadOnlyModeException("ETW_Provider:NotSpecified", CLogHandledException.ExceptionType.MustSpecifyETWProvider, decodedTraceLine.match); } Guid providerId = new Guid(moduleSettings.CustomSettings["ETW_Provider"]); ManifestInformation manifest = FindProviderCache(providerId); string eventNamePrefix; if (!moduleSettings.CustomSettings.TryGetValue("EventNamePrefix", out eventNamePrefix)) { eventNamePrefix = string.Empty; } if (null == manifest) { Console.WriteLine($"Unable to locate ETW provider {providerId} in CLOG macro {decodedTraceLine.macro.MacroName}"); Console.WriteLine(" CLOG will not create this provider within the manifest; it will only add to an existing provider"); Console.WriteLine(" please consult the MSDN documentation for an ETW manifest for instructions"); Console.WriteLine(""); Console.WriteLine($"Macro: {providerId} is defined in {decodedTraceLine.configFile.FilePath}"); Console.WriteLine($"ETW Manifest : is set as {xmlFileName}"); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine(""); throw new CLogEnterReadOnlyModeException("ManifestedETWProviderNotFoundInManifest", CLogHandledException.ExceptionType.ManifestedETWProviderNotFound, decodedTraceLine.match); } // // Only allow a hash one time for now.... // if (manifest.knownHashes.Contains(hash)) { return; } manifest.knownHashes.Add(hash); // // See if our event already exists - if it does we do not want to add it a second time // List <XmlElement> toRemove = new List <XmlElement>(); XmlElement newEvent = null; foreach (var p in manifest.events.ChildNodes) { if (!(p is XmlElement)) { continue; } XmlElement pe = (XmlElement)p; if (pe.Name == "event") { if (!pe.HasAttribute("symbol")) { continue; } string symbol = pe.GetAttribute("symbol"); if (0 == symbol.CompareTo(eventNamePrefix + hash)) { toRemove.Add(pe); newEvent = pe; break; } } } // // Add the event if it doesnt already exist // if (null == newEvent) { newEvent = doc.CreateElement("event", manifest.events.NamespaceURI); manifest.events.AppendChild(newEvent); _dirty = true; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $"Adding event {eventNamePrefix + hash} to ETW manifest {xmlFileName}"); } int hashUInt; string eventAsString; decodedTraceLine.macro.DecodeUniqueId(decodedTraceLine.match, hash, out eventAsString, out hashUInt); uint eventId; if (!newEvent.HasAttribute("value")) { eventId = FindUnusedEventId(providerId, decodedTraceLine.match); SetAttribute(newEvent, "value", eventId.ToString()); } else { eventId = Convert.ToUInt32(newEvent.GetAttribute("value")); } // // Store the eventID for future decode as well as every configuration setting attached to this module // decodedTraceLine.AddConfigFileProperty(ModuleName, "EventID", eventId.ToString()); foreach (var setting in moduleSettings.CustomSettings) { decodedTraceLine.AddConfigFileProperty(ModuleName, setting.Key, setting.Value); } SetAttribute(newEvent, "symbol", eventNamePrefix + hash); string oldTemplate = null; if (newEvent.HasAttribute("template")) { oldTemplate = newEvent.GetAttribute("template"); } string templateId = DiscoverOrCreateTemplate(decodedTraceLine, sidecar, providerId, oldTemplate, eventId); SetAttribute(newEvent, "template", templateId); if (moduleSettings.CustomSettings.ContainsKey("Level")) { SetAttribute(newEvent, "level", moduleSettings.CustomSettings["Level"]); } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, $"Manifested ETW Level not specified; if you desire a Level, add 'Level' to CustomSettings in {decodedTraceLine.configFile.FilePath}"); } if (moduleSettings.CustomSettings.ContainsKey("Keywords")) { SetAttribute(newEvent, "keywords", moduleSettings.CustomSettings["Keywords"]); } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, $"Manifested ETW Keywords not specified; if you desire a Keyword, add 'Keywords' to CustomSettings in {decodedTraceLine.configFile.FilePath}"); } // // Construct the function signature // string traceLine = $"EventWrite{eventNamePrefix + hash}("; bool haveMultipleArgs = false; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } if (haveMultipleArgs) { traceLine += ", "; } haveMultipleArgs = true; switch (node.EncodingType) { case CLogEncodingType.ByteArray: traceLine += $"{arg.MacroVariableName}_len, {arg.MacroVariableName}"; continue; default: traceLine += $"{arg.MacroVariableName}"; break; } } traceLine += "); \\"; inline.AppendLine(traceLine); Save(decodedTraceLine.match); }
public void TraceLineDiscovered(string sourceFile, CLogOutputInfo outputInfo, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { CLogFileProcessor.DecomposedString clean; CLogFileProcessor.CLogTypeContainer[] types = CLogFileProcessor.BuildTypes(decodedTraceLine.configFile, null, decodedTraceLine.TraceString, null, out clean); CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(ModuleName); string printmacro; if (!moduleSettings.CustomSettings.TryGetValue("PrintMacro", out printmacro)) { printmacro = "printf"; } if (!emittedHeader) { string printHeader; if (!moduleSettings.CustomSettings.TryGetValue("PrintHeader", out printHeader)) { printHeader = "stdio.h"; } emittedHeader = true; } // // Only emit the function once; we may be called multiple times should someone emit an event multiple times in the same file // (usually error paths) // string argsString = string.Empty; string macroString = string.Empty; foreach (var arg in decodedTraceLine.splitArgs) { if (!arg.TypeNode.Synthesized && arg.TypeNode.EncodingType != CLogEncodingType.UniqueAndDurableIdentifier && arg.TypeNode.EncodingType != CLogEncodingType.UserEncodingString) { string seperatorA = ""; string seperatorB = ""; if (string.IsNullOrEmpty(argsString)) { seperatorA = ","; seperatorB = ""; } else { seperatorA = ""; seperatorB = ","; } // If the encided type is 'binary' (length and payload) - for DTrace we emit the payload // length with the variable name <suggestedName>_len if (CLogEncodingType.ByteArray == arg.TypeNode.EncodingType) { argsString += $"{seperatorB} unsigned int {arg.VariableInfo.SuggestedTelemetryName}_len{seperatorA}"; macroString += $"{seperatorB} {arg.MacroVariableName}_len{seperatorA}"; } argsString += $"{seperatorB} {arg.TypeNode.CType} {arg.MacroVariableName}"; macroString += $"{seperatorB} {arg.MacroVariableName}"; } } string printf = ""; foreach (var t in types) { printf += t.LeadingString; switch (t.TypeNode.EncodingType) { case CLogEncodingType.Int32: printf += "%d"; break; case CLogEncodingType.UInt32: printf += "%u"; break; case CLogEncodingType.Int64: printf += "%lld"; break; case CLogEncodingType.UInt64: printf += "%llu"; break; case CLogEncodingType.ANSI_String: printf += "%s"; break; case CLogEncodingType.UNICODE_String: printf += "%S"; break; case CLogEncodingType.Pointer: printf += "0x%llx"; break; case CLogEncodingType.GUID: printf += "%p"; break; case CLogEncodingType.Int16: printf += "%d"; break; case CLogEncodingType.UInt16: printf += "%d"; break; case CLogEncodingType.Int8: printf += "%d"; break; case CLogEncodingType.UInt8: printf += "%d"; break; case CLogEncodingType.ByteArray: printf += "[Not_Supported]"; break; } } // // Print the remainder of user text (the tail end); if there are no types at all then 'TraceString' is just a constant string // if (types.Length >= 1) { string tail = decodedTraceLine.TraceString.Substring(types[types.Length - 1].ArgStartingIndex + types[types.Length - 1].ArgLength); printf += tail; } else { printf += decodedTraceLine.TraceString; } printf += "\\n"; inline.Append($" {printmacro}(\"{printf}\""); foreach (var arg in decodedTraceLine.splitArgs) { if (arg.TypeNode.Synthesized || arg.TypeNode.EncodingType == CLogEncodingType.UniqueAndDurableIdentifier || arg.TypeNode.EncodingType == CLogEncodingType.UserEncodingString) { continue; } string cast = ""; switch (arg.TypeNode.EncodingType) { case CLogEncodingType.Int32: //cast = "(int)"; break; case CLogEncodingType.UInt32: //cast = "(unsigned int)"; break; case CLogEncodingType.Int64: //cast = "(__int64)"; break; case CLogEncodingType.UInt64: //cast = "(unsigned __int64)"; break; case CLogEncodingType.ANSI_String: break; case CLogEncodingType.UNICODE_String: break; case CLogEncodingType.Pointer: cast = "(unsigned long long int)"; break; case CLogEncodingType.GUID: cast = "(void*)"; break; case CLogEncodingType.Int16: //cast = "(__int16)"; break; case CLogEncodingType.UInt16: //cast = "(unsigned __int16)"; break; case CLogEncodingType.Int8: //cast = "(int)"; break; case CLogEncodingType.UInt8: //cast = "(int)"; break; case CLogEncodingType.ByteArray: //cast = "(void*)"; continue; } inline.Append($", {cast}(" + arg.MacroVariableName + ")"); } inline.Append(");"); }
public void TraceLineDiscovered(string sourceFile, CLogDecodedTraceLine decodedTraceLine, CLogSidecar sidecar, StringBuilder macroPrefix, StringBuilder inline, StringBuilder function) { int hashUInt; string hash; CLogExportModuleDefination moduleSettings = decodedTraceLine.GetMacroConfigurationProfile().FindExportModule(ModuleName); decodedTraceLine.macro.DecodeUniqueId(decodedTraceLine.match, decodedTraceLine.UniqueId, out hash, out hashUInt); if (knownHashes.Contains(hash)) { return; } knownHashes.Add(hash); inline.AppendLine( $"__annotation(L\"Debug\", L\"CLOG\", L\"{hash}\"); \\"); //, msg, id, \"{sourceFile}\");"); string traceloggingLine = "TraceLoggingWrite(clog_hTrace, \"" + decodedTraceLine.UniqueId + "\""; foreach (var a in decodedTraceLine.splitArgs) { CLogFileProcessor.CLogVariableBundle arg = a; CLogEncodingCLogTypeSearch node = decodedTraceLine.configFile.FindType(arg, decodedTraceLine); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } // // Documentation for each of the TraceLogging macros // https://docs.microsoft.com/en-gb/windows/win32/tracelogging/tracelogging-wrapper-macros // switch (node.EncodingType) { case CLogEncodingType.Int8: traceloggingLine += ",\\\n TraceLoggingInt8" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt8: traceloggingLine += ",\\\n TraceLoggingUInt8" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int16: traceloggingLine += ",\\\n TraceLoggingInt16" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt16: traceloggingLine += ",\\\n TraceLoggingUInt16" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int32: traceloggingLine += ",\\\n TraceLoggingInt32" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt32: traceloggingLine += ",\\\n TraceLoggingUInt32" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Int64: traceloggingLine += ",\\\n TraceLoggingInt64" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UInt64: traceloggingLine += ",\\\n TraceLoggingUInt64" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.Pointer: traceloggingLine += ",\\\n TraceLoggingPointer" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.ByteArray: traceloggingLine += ",\\\n TraceLoggingUInt8Array" + $"({arg.MacroVariableName}, {arg.MacroVariableName}_len, \"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.ANSI_String: traceloggingLine += ",\\\n TraceLoggingString" + $"((const char *)({arg.MacroVariableName}),\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; case CLogEncodingType.UNICODE_String: traceloggingLine += ",\\\n TraceLoggingWideString" + $"({arg.MacroVariableName},\"{arg.VariableInfo.SuggestedTelemetryName}\")"; break; } } // Emit keywords (if supplied by the user) if (moduleSettings.CustomSettings.ContainsKey("Keyword")) { traceloggingLine += ",\\\n TraceLoggingKeyword" + $"({moduleSettings.CustomSettings["Keyword"]})"; } if (moduleSettings.CustomSettings.ContainsKey("Level")) { traceloggingLine += ",\\\n TraceLoggingLevel" + $"({moduleSettings.CustomSettings["Level"]})"; } traceloggingLine += "); \\"; inline.AppendLine(traceloggingLine); }