public void TraceLineDiscovered(CLogDecodedTraceLine decodedTraceLine, StringBuilder results) { Dictionary <int, string> map = new Dictionary <int, string>(); int idx = 1; if (skip) { results.Append(decodedTraceLine.match.MatchedRegEx.ToString()); return; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, decodedTraceLine.match.MatchedRegEx.ToString()); int c = -1; try { for (; ;) { foreach (var m in decodedTraceLine.configFile.AllKnownMacros()) { map[idx] = m.MacroName; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. {m.MacroName}"); ++idx; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. <skip the reset in this file and save"); string choice = Console.ReadLine(); c = Convert.ToInt32(choice); if (c == idx) { skip = true; results.Append(decodedTraceLine.match.MatchedRegEx.ToString()); return; } break; } } catch (Exception) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "ERROR : invalid input"); } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "UNIQUE ID"); string id = Console.ReadLine().Trim().ToUpper(); results.Append($"{map[c]}("); results.Append("" + id); results.Append($", \"{decodedTraceLine.TraceString}\""); foreach (var arg in decodedTraceLine.splitArgs) { results.Append($", {arg.VariableInfo.UserSpecifiedUnModified}"); } results.Append(");"); }
public static void PrintMatchDiagnostic(CLogLineMatch traceLineMatch) { if (null == traceLineMatch) { return; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Failing Line : {traceLineMatch.MatchedRegExX.Value}"); }
public void LoadCustomCSharp(string customTypeClogCSharpFile, CLogConfigurationFile configFile) { if (!File.Exists(customTypeClogCSharpFile)) { CLogConsoleTrace.TraceLine(TraceType.Err, $"Custom C# file for custom decoder is missing. Please create the file, or remove its reference from the config file"); CLogConsoleTrace.TraceLine(TraceType.Err, $" Missing File: {customTypeClogCSharpFile}"); CLogConsoleTrace.TraceLine(TraceType.Err, $" Defined In Config File: {configFile.FilePath}"); throw new CLogEnterReadOnlyModeException("CustomCSharpFileMissing: " + customTypeClogCSharpFile, CLogHandledException.ExceptionType.UnableToOpenCustomDecoder, null); } string sourceCode = File.ReadAllText(customTypeClogCSharpFile); string sourceHash = Path.GetFileName(configFile.FilePath); _traceEmittorX.SetSourceCode(sourceCode); }
private static int PerformInstall(string outputDir) { if (File.Exists(outputDir)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Output file for install cannot be a file. It either must not exist, or be a directory"); return(-11); } Directory.CreateDirectory(outputDir); Assembly utilsAssembly = typeof(CLogConsoleTrace).Assembly; string baseName = utilsAssembly.GetName().Name; void ExtractFile(string name) { using Stream embeddedStream = utilsAssembly.GetManifestResourceStream($"{baseName}.{name}"); using StreamReader reader = new StreamReader(embeddedStream); string contents = reader.ReadToEnd(); string fileName = Path.Combine(outputDir, name); if (File.Exists(fileName)) { string existingContents = File.ReadAllText(fileName); if (existingContents == contents) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"Skipping file {name} as its up to date"); return; } } File.WriteAllText(fileName, contents); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"Installed file {name}"); } ExtractFile("clog.h"); ExtractFile("CLog.cmake"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "--installDirectory overrides all arguments. Dependencies successfully installed!"); return(0); }
public bool IsValid() { if (!string.IsNullOrWhiteSpace(this.InstallDependencies)) { return(true); } if (!string.IsNullOrEmpty(this.OutputDirectory)) { if (string.IsNullOrEmpty(this.InputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "OutputDirectory specified, and InputFile is empty"); return(false); } if (!string.IsNullOrEmpty(this.OutputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "OutputDirectory specified, but OutputFile is not empty"); return(false); } this.OutputFile = Path.Combine(this.OutputDirectory, Path.GetFileName(this.InputFile)); this.OutputFile += ".clog.h"; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "Setting Output file to : " + this.OutputFile); } // // If either input or output is empty, require that we're linting or upgrading // if (string.IsNullOrEmpty(this.InputFile) || string.IsNullOrEmpty(this.OutputFile)) { if (!LintConfig && !UpgradeConfigFile && !RefreshCustomTypeProcessor) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "input file and output file are required if not linting or upgrading config file"); return(false); } } else { if (string.IsNullOrEmpty(this.InputFile) || string.IsNullOrEmpty(this.OutputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify both an input and and output file"); return(false); } if (string.IsNullOrEmpty(ScopePrefix)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify scope prefix"); return(false); } if (string.IsNullOrEmpty(SidecarFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify sidecar file"); return(false); } } if (LintConfig || UpgradeConfigFile) { if (!string.IsNullOrEmpty(this.InputFile) || !string.IsNullOrEmpty(this.OutputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "do not specify input or output files if you're linting or upgrading the config file"); return(false); } } if (RefreshCustomTypeProcessor) { if (string.IsNullOrEmpty(this.SidecarFile) || string.IsNullOrEmpty(this.ConfigurationFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Please specify both the side car to update, and the configuration file that contains a reference to the new type processor"); return(false); } } // // Makesure ConfigurationProfile is specified for all but those who do not need it // if (!RefreshCustomTypeProcessor) { if (string.IsNullOrEmpty(this.ConfigurationProfile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Please specify both the side car to update, and the configuration file that contains a reference to the new type processor"); return(false); } } return(true); }
private static int Main(string[] cmdLineArgs) { ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(cmdLineArgs); return(o.MapResult( options => { string sidecarJson = File.ReadAllText(options.SideCarFile); CLogSidecar sidecar = CLogSidecar.FromJson(sidecarJson); TextReader file = Console.In; if (!File.Exists(options.ETLFile)) { TraceLine(TraceType.Err, $"ETL File {options.ETLFile} doesnt exist"); return -1; } StreamWriter outputfile = null; if (!String.IsNullOrEmpty(options.OutputFile)) { outputfile = new StreamWriter(new FileStream(options.OutputFile, FileMode.Create)); } try { TraceProcessorSettings traceSettings = new TraceProcessorSettings { AllowLostEvents = true, AllowTimeInversion = true }; using (ITraceProcessor etwfile = TraceProcessor.Create(options.ETLFile, traceSettings)) { HashSet <Guid> ids = new HashSet <Guid>(); foreach (var m in sidecar.EventBundlesV2) { foreach (var prop in m.Value.ModuleProperites) { if (prop.Key.Equals("MANIFESTED_ETW")) { ids.Add(new Guid(prop.Value["ETW_Provider"])); } else if (prop.Key.Equals("TRACELOGGING")) { ids.Add(new Guid(prop.Value["ETW_Provider"])); } } } var events = etwfile.UseGenericEvents(ids.ToArray()); etwfile.Process(); foreach (var e in events.Result.Events) { string line = ""; try { Dictionary <string, IClogEventArg> fixedUpArgs = new Dictionary <string, IClogEventArg>(); string errorString = "ERROR"; if (null == e.Fields) { continue; } Dictionary <string, IClogEventArg> args = new Dictionary <string, IClogEventArg>(); foreach (var f in e.Fields) { args[f.Name] = new ManifestedETWEvent(f); } CLogDecodedTraceLine bundle = null; int eidAsInt = -1; foreach (var b in sidecar.EventBundlesV2) { Dictionary <string, string> keys; if (!e.IsTraceLogging) { if (!b.Value.ModuleProperites.TryGetValue("MANIFESTED_ETW", out keys)) { continue; } string eid; if (!keys.TryGetValue("EventID", out eid)) { continue; } eidAsInt = Convert.ToInt32(eid); if (eidAsInt == e.Id) { bundle = b.Value; errorString = "ERROR:" + eidAsInt; break; } } else { if (e.ActivityName.Equals(b.Key)) { bundle = b.Value; errorString = "ERROR:" + b.Key; break; } } } if (null == bundle) { continue; } Dictionary <string, string> argMap; if (e.IsTraceLogging) { argMap = new Dictionary <string, string>(); foreach (var arg in args) { argMap[arg.Key] = arg.Key; } } else { argMap = sidecar.GetTracelineMetadata(bundle, "MANIFESTED_ETW"); } var types = CLogFileProcessor.BuildTypes(sidecar.ConfigFile, null, bundle.TraceString, null, out string clean); if (0 == types.Length) { errorString = bundle.TraceString; goto toPrint; } int argIndex = 0; foreach (var type in types) { var arg = bundle.splitArgs[argIndex]; CLogEncodingCLogTypeSearch node = sidecar.ConfigFile.FindType(arg); switch (node.EncodingType) { case CLogEncodingType.Synthesized: continue; case CLogEncodingType.Skip: continue; } string lookupArgName = argMap[arg.VariableInfo.SuggestedTelemetryName]; if (!args.ContainsKey(lookupArgName)) { Console.WriteLine($"Argmap missing {lookupArgName}"); throw new Exception("InvalidType : " + node.DefinationEncoding); } if (0 != node.DefinationEncoding.CompareTo(type.TypeNode.DefinationEncoding)) { Console.WriteLine("Invalid Types in Traceline"); throw new Exception("InvalidType : " + node.DefinationEncoding); } fixedUpArgs[arg.VariableInfo.SuggestedTelemetryName] = args[lookupArgName]; ++argIndex; } toPrint: EventInformation ei = new EventInformation(); ei.Timestamp = e.Timestamp.DateTimeOffset; ei.ProcessId = e.ProcessId.ToString("x"); ei.ThreadId = e.ThreadId.ToString("x"); DecodeAndTraceToConsole(outputfile, bundle, errorString, sidecar.ConfigFile, fixedUpArgs, ei, options.ShowTimestamps, options.ShowCPUInfo); } catch (Exception) { Console.WriteLine($"Invalid TraceLine : {line}"); } } } } catch (Exception e) { CLogConsoleTrace.TraceLine(TraceType.Err, "ERROR : " + e); if (null != outputfile) { outputfile.WriteLine("ERROR : " + e); } } finally { if (null != outputfile) { outputfile.Flush(); outputfile.Close(); } } return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }
public bool IsValid() { // // If either input or output is empty, require that we're linting or upgrading // if (string.IsNullOrEmpty(this.InputFile) || string.IsNullOrEmpty(this.OutputFile)) { if (!LintConfig && !UpgradeConfigFile && !RefreshCustomTypeProcessor) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "input file and output file are required if not linting or upgrading config file"); return(false); } } else { if (string.IsNullOrEmpty(this.InputFile) || string.IsNullOrEmpty(this.OutputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify both an input and and output file"); return(false); } if (string.IsNullOrEmpty(ScopePrefix)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify scope prefix"); return(false); } if (string.IsNullOrEmpty(SidecarFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "please specify sidecar file"); return(false); } } if (LintConfig || UpgradeConfigFile) { if (!string.IsNullOrEmpty(this.InputFile) || !string.IsNullOrEmpty(this.OutputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "do not specify input or output files if you're linting or upgrading the config file"); return(false); } } if (RefreshCustomTypeProcessor) { if (string.IsNullOrEmpty(this.SidecarFile) || string.IsNullOrEmpty(this.ConfigurationFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Please specify both the side car to update, and the configuration file that contains a reference to the new type processor"); return(false); } } // // Makesure ConfigurationProfile is specified for all but those who do not need it // if (!RefreshCustomTypeProcessor) { if (string.IsNullOrEmpty(this.ConfigurationProfile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Please specify both the side car to update, and the configuration file that contains a reference to the new type processor"); return(false); } } return(true); }
private static int Main(string[] args) { ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(args); return(o.MapResult( options => { try { // // The CommandLineArguments library validates most input arguments for us, there are few ones that are complicated // this secondary check looks for those and errors out if present // if (!options.IsValid()) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Invalid args"); return -1; } CLogConfigurationFile configFile = CLogConfigurationFile.FromFile(options.ConfigurationFile); configFile.ProfileName = options.ConfigurationProfile; CLogSidecar sidecar; if (!Directory.Exists(Path.GetDirectoryName(options.SidecarFile))) { Directory.CreateDirectory(Path.GetDirectoryName(options.SidecarFile)); } if (!File.Exists(options.SidecarFile)) { sidecar = new CLogSidecar(); } else { string json = File.ReadAllText(options.SidecarFile); sidecar = CLogSidecar.FromJson(json); if (null == sidecar) { sidecar = new CLogSidecar(); } } sidecar.SetConfigFile(configFile); string outputCFile = Path.Combine(Path.GetDirectoryName(options.OutputFile), options.ScopePrefix + "_" + Path.GetFileName(options.OutputFile)) + ".c"; configFile.ScopePrefix = options.ScopePrefix; configFile.FilePath = Path.GetFullPath(options.ConfigurationFile); configFile.OverwriteHashCollisions = options.OverwriteHashCollisions; CLogTraceMacroDefination syslog = new CLogTraceMacroDefination(); syslog.EncodedArgNumber = 1; syslog.MacroName = "syslog"; syslog.MacroConfiguration = new System.Collections.Generic.Dictionary <string, string>(); syslog.MacroConfiguration[options.ConfigurationProfile] = options.ConfigurationProfile; configFile.SourceCodeMacros.Add(syslog); CLogFileProcessor processor = new CLogFileProcessor(configFile); SysLogToClog converter = new SysLogToClog(); string content = File.ReadAllText(options.InputFile); string output = processor.ConvertFile(configFile, null, converter, content, options.InputFile, true); if (!Directory.Exists(Path.GetDirectoryName(options.OutputFile))) { Directory.CreateDirectory(Path.GetDirectoryName(options.OutputFile)); } File.WriteAllText(options.InputFile, output); } catch (CLogHandledException e) { e.PrintDiagnostics(); return -2; } return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }
public void TraceLineDiscovered(CLogDecodedTraceLine decodedTraceLine, CLogOutputInfo outputInfo, StringBuilder results) { Dictionary <int, string> map = new Dictionary <int, string>(); int idx = 1; if (skip) { results.Append(decodedTraceLine.match.MatchedRegExX.ToString()); return; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, decodedTraceLine.match.MatchedRegExX.ToString()); int c = -1; try { for (; ;) { foreach (var m in decodedTraceLine.configFile.AllKnownMacros()) { map[idx] = m.MacroName; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. {m.MacroName}"); ++idx; } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"{idx}. <skip the rest in this file and save>"); string choice = null; while (String.IsNullOrEmpty(choice)) { try { choice = Console.ReadLine(); c = Convert.ToInt32(choice); } catch (Exception) { Console.WriteLine("try again please"); } } if (c == idx) { skip = true; results.Append(decodedTraceLine.match.MatchedRegExX.ToString()); return; } break; } } catch (Exception) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "ERROR : invalid input"); } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "UNIQUE ID"); string id = Console.ReadLine().Trim().ToUpper(); while (takenIds.Contains(id)) { Console.WriteLine("ID is taken please use a unique ID"); id = Console.ReadLine().Trim().ToUpper(); } takenIds.Add(id); results.Append($"{map[c]}("); results.Append("" + id); results.Append($", \"{decodedTraceLine.TraceString}\""); for (int i = 2; i < decodedTraceLine.splitArgs.Length; ++i) { var arg = decodedTraceLine.splitArgs[i]; results.Append($", {arg.VariableInfo.UserSuppliedTrimmed}"); } results.Append(");"); }
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); }
private string DiscoverOrCreateTemplate(CLogDecodedTraceLine traceLine, CLogSidecar sidecar, Guid providerId, string existingTemplateName, uint eventId) { string hash = ""; // // Construct a list of the desired types - we'll use this to see if we can find a preexisting suitable template // List <TemplateNode> listofArgsAsSpecifiedBySourceFile = ConstructTemplateArgs(traceLine); string templateId = existingTemplateName; if (string.IsNullOrEmpty(existingTemplateName)) { templateId = "template_" + hash; foreach (TemplateNode arg in listofArgsAsSpecifiedBySourceFile) { templateId += arg.Hash; } } // // See if the template already exists; for example from a different file // ManifestInformation manifest = FindProviderCache(providerId); XmlElement template = null; foreach (var p in manifest.templates.ChildNodes) { if (!(p is XmlElement)) { continue; } XmlElement pe = (XmlElement)p; if (pe.Name == "template") { if (!pe.HasAttribute("tid")) { continue; } string tid = pe.GetAttribute("tid"); if (0 == tid.CompareTo(templateId)) { template = pe; break; } } } // // If we dont have an existing template, add one // if (null == template) { template = doc.CreateElement("template", manifest.events.NamespaceURI); foreach (var arg in listofArgsAsSpecifiedBySourceFile) { var dataNode = doc.CreateElement("data", manifest.events.NamespaceURI); dataNode.SetAttribute("name", arg.Name); if (!string.IsNullOrEmpty(arg.LengthOfSelf)) { dataNode.SetAttribute("length", arg.LengthOfSelf); } dataNode.SetAttribute("inType", arg.Type); template.AppendChild(dataNode); } // Only apply a template ID if it's not empty - otherwise choose the default if (!templateId.Equals("templateId_")) { template.SetAttribute("tid", templateId); } manifest.templates.AppendChild(template); } // // int argIdx = 0; Dictionary <string, string> argLookup = sidecar.GetTracelineMetadata(traceLine, ModuleName); if (null == argLookup) { argLookup = new Dictionary <string, string>(); } foreach (var a in template.ChildNodes) { if (!(a is XmlElement)) { continue; } XmlElement pe = (XmlElement)a; if (pe.Name != "data") { continue; } string inType = pe.GetAttribute("inType"); string name = pe.GetAttribute("name"); if (listofArgsAsSpecifiedBySourceFile.Count <= argIdx) { if (traceLine.configFile.DeveloperMode) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Template Argument Type Mismatch - overwriting due to developer mode"); _dirty = true; return(DiscoverOrCreateTemplate(traceLine, sidecar, providerId, null, eventId)); } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Template Argument Type Mismatch - manifested ETW template and CLOG string differ"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event ID : {eventId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event Provider : {providerId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event UID : {traceLine.UniqueId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, "Recommended Course of action:"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 1. (best) from within the manifest, delete the template ({templateId}) from your event ({eventId})"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 2. cleanup your template to be in this format"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 3. set the environment variable CLOG_DEVELOPMENT_MODE=1 ($env:CLOG_DEVELOPMENT_MODE=1)"); throw new CLogEnterReadOnlyModeException("ETWManifestTypeMismatch", CLogHandledException.ExceptionType.ETWTypeMismatch, traceLine.match); } TemplateNode templateReference = listofArgsAsSpecifiedBySourceFile[argIdx]; argLookup[templateReference.ArgBundle.MacroVariableName] = name; if (templateReference.Type != inType) { if (traceLine.configFile.DeveloperMode) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Template Argument Type Mismatch - overwriting due to developer mode"); _dirty = true; return(DiscoverOrCreateTemplate(traceLine, sidecar, providerId, null, eventId)); } CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Template Argument Type Mismatch: "); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event ID : {eventId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event Provider : {providerId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Event UID : {traceLine.UniqueId}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" Mismatch Arg Name : {name}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" CLOG specified Type : {templateReference.Type}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" ETW Manifest Type : {inType}"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Source Line:"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, CLogConsoleTrace.GetFileLine(traceLine.match)); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, traceLine.match.MatchedRegEx.ToString()); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, "Recommended Course of action:"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 1. (best) from within the manifest, delete the template ({templateId}) from your event ({eventId})"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 2. cleanup your template to be in this format"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" 3. set the environment variable CLOG_DEVELOPMENT_MODE=1 ($env:CLOG_DEVELOPMENT_MODE=1)"); foreach (var t in listofArgsAsSpecifiedBySourceFile) { if (string.IsNullOrEmpty(t.LengthOfSelf)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" name={t.Name} inType={t.Type}"); } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Tip, $" name={t.Name} inType={t.Type} length={t.LengthOfSelf}"); } } throw new CLogEnterReadOnlyModeException("ETWManifestTypeMismatch", CLogHandledException.ExceptionType.ETWTypeMismatch, traceLine.match); } ++argIdx; } // // Store our metadata into the side car // sidecar.SetTracelineMetadata(traceLine, ModuleName, argLookup); return(templateId); }
private static int Main(string[] args) { // Manually parse installDirectory, as it interferes with the required configFile // The argument still shows up in CommandLineArguments to be shown in help. for (int i = 0; i < args.Length; i++) { if (args[i] == "--installDirectory") { if (i + 1 == args.Length) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Must pass an argument to --installDirectory"); return(-1); } return(PerformInstall(args[i + 1])); } } ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(args); return(o.MapResult( options => { try { // // The CommandLineArguments library validates most input arguments for us, there are few ones that are complicated // this secondary check looks for those and errors out if present // if (!options.IsValid()) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Invalid args"); return -1; } if (!string.IsNullOrWhiteSpace(options.InstallDependencies)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Internal error, this should have been handled at a previous step"); return -1; } CLogConfigurationFile configFile = CLogConfigurationFile.FromFile(options.ConfigurationFile); configFile.ProfileName = options.ConfigurationProfile; if (options.ReadOnly && !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_FORCE_WRITABLE"))) { options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed via --readOnly not to emit changes however this was overridden with CLOG_FORCE_WRITABLE environment variable"); } if (options.OverwriteHashCollisions || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_OVERWRITE_COLLISIONS"))) { options.OverwriteHashCollisions = true; options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Overwriting of sidecare collisions is set by environment variable CLOG_OVERWRITE_COLLISIONS. This setting is only to be used while making large refactors and should not be included in build environments or standard development environments"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); } if (options.Devmode || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_DEVELOPMENT_MODE"))) { options.ReadOnly = false; options.OverwriteHashCollisions = true; configFile.DeveloperMode = true; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed to enter a developer mode"); } if (options.LintConfig) { if (!configFile.MarkPhase) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Lint operation only works on config files placed into the 'MarkPhase'. This can be a destricutive action, please read the docs for more information"); return -10; } configFile.Lint(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Lint operation complete"); return 0; } if (options.UpgradeConfigFile) { configFile.UpdateVersion(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Config upgrade complete"); return 0; } CLogSidecar sidecar; if (!Directory.Exists(Path.GetDirectoryName(options.SidecarFile))) { Directory.CreateDirectory(Path.GetDirectoryName(options.SidecarFile)); } if (!File.Exists(options.SidecarFile)) { sidecar = new CLogSidecar(); } else { string json = File.ReadAllText(options.SidecarFile); sidecar = CLogSidecar.FromJson(json); if (null == sidecar) { sidecar = new CLogSidecar(); } } // Check for outdated config file sidecar.UpdateConfigFile(configFile); if (options.RefreshCustomTypeProcessor) { configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); return 0; } string outputCFile = Path.Combine(Path.GetDirectoryName(options.OutputFile), options.ScopePrefix + "_" + Path.GetFileName(options.OutputFile)) + ".c"; configFile.ScopePrefix = options.ScopePrefix; configFile.FilePath = Path.GetFullPath(options.ConfigurationFile); configFile.OverwriteHashCollisions = options.OverwriteHashCollisions; //Delete the output file; we want to encourage build breaks if something goes wrong if (File.Exists(options.OutputFile)) { File.Delete(options.OutputFile); } if (File.Exists(outputCFile)) { File.Delete(outputCFile); } CLogFileProcessor processor = new CLogFileProcessor(configFile); CLogFullyDecodedMacroEmitter fullyDecodedMacroEmitter = new CLogFullyDecodedMacroEmitter(options.InputFile, sidecar); fullyDecodedMacroEmitter.AddClogModule(sidecar); CLogTraceLoggingOutputModule traceLoggingEmitter = new CLogTraceLoggingOutputModule(); fullyDecodedMacroEmitter.AddClogModule(traceLoggingEmitter); CLogDTraceOutputModule dtrace = new CLogDTraceOutputModule(); fullyDecodedMacroEmitter.AddClogModule(dtrace); CLogSystemTapModule systemTap = new CLogSystemTapModule(); fullyDecodedMacroEmitter.AddClogModule(systemTap); CLogSysLogModule syslog = new CLogSysLogModule(); fullyDecodedMacroEmitter.AddClogModule(syslog); CLogSTDOUT stdout = new CLogSTDOUT(); fullyDecodedMacroEmitter.AddClogModule(stdout); CLogManifestedETWOutputModule manifestedEtwOutput = new CLogManifestedETWOutputModule(options.ReadOnly); fullyDecodedMacroEmitter.AddClogModule(manifestedEtwOutput); CLogLTTNGOutputModule lttngOutput = new CLogLTTNGOutputModule(options.InputFile, options.OutputFile, options.OutputFile + ".lttng.h", options.DynamicTracepointProvider); fullyDecodedMacroEmitter.AddClogModule(lttngOutput); if (!File.Exists(options.InputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"Invalid Input File : {Path.GetFileName(options.InputFile)}"); throw new CLogEnterReadOnlyModeException("InvalidInputFile", CLogHandledException.ExceptionType.InvalidInputFile, null); } string content = File.ReadAllText(options.InputFile); string output = processor.ConvertFile(configFile, fullyDecodedMacroEmitter, content, options.InputFile, false); if (!content.Contains(Path.GetFileName(options.OutputFile))) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"You must #include the clog output file {Path.GetFileName(options.OutputFile)}"); throw new CLogEnterReadOnlyModeException("MustIncludeCLogHeader", CLogHandledException.ExceptionType.SourceMustIncludeCLOGHeader, null); } fullyDecodedMacroEmitter.FinishedProcessing(); StringBuilder clogFile = new StringBuilder(); clogFile.AppendLine("#include <clog.h>"); clogFile.Append(fullyDecodedMacroEmitter.HeaderInit); foreach (var macro in processor.MacrosInUse) { clogFile.AppendLine($"#ifndef _clog_MACRO_{macro.MacroName}"); clogFile.AppendLine($"#define _clog_MACRO_{macro.MacroName} 1"); clogFile.AppendLine( $"#define {macro.MacroName}(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))"); clogFile.AppendLine("#endif"); } clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("extern \"C\" {"); clogFile.AppendLine("#endif"); clogFile.Append(fullyDecodedMacroEmitter.HeaderFile); clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("}"); clogFile.AppendLine("#endif"); clogFile.AppendLine("#ifdef CLOG_INLINE_IMPLEMENTATION"); clogFile.AppendLine("#include \"" + Path.GetFileName(outputCFile) + "\""); clogFile.AppendLine("#endif"); if (!Directory.Exists(Path.GetDirectoryName(options.OutputFile))) { Console.WriteLine("Creating Directory for Output : " + Path.GetDirectoryName(options.OutputFile)); Directory.CreateDirectory(Path.GetDirectoryName(options.OutputFile)); } if (sidecar.AreDirty || configFile.AreWeDirty()) { if (options.ReadOnly) { if (sidecar.AreDirty) { Console.WriteLine("Sidecar is dirty"); } if (configFile.AreWeDirty()) { Console.WriteLine("ConfigFile is dirty"); } sidecar.PrintDirtyReasons(); throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:SideCar", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); } if (configFile.AreWeDirty() || configFile.AreWeInMarkPhase()) { if (options.ReadOnly) { throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:ConfigFile", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } Console.WriteLine("Configuration file was updated, saving..."); Console.WriteLine($" {configFile.FilePath}"); configFile.Save(false); } File.WriteAllText(options.OutputFile, clogFile.ToString()); File.WriteAllText(outputCFile, fullyDecodedMacroEmitter.SourceFile); } catch (CLogHandledException e) { e.PrintDiagnostics(); return -2; } return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }
private static int Main(string[] args) { ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(args); return(o.MapResult( options => { string sidecarJson = File.ReadAllText(options.SideCarFile); CLogSidecar textManifest = CLogSidecar.FromJson(sidecarJson); TextReader file = Console.In; if (!string.IsNullOrEmpty(options.BabelTrace)) { file = new StreamReader(options.BabelTrace); } string line; LTTNGEventDecoder lttngDecoder = new LTTNGEventDecoder(textManifest); int lines = 0; StreamWriter outputfile = null; if (!String.IsNullOrEmpty(options.OutputFile)) { outputfile = new StreamWriter(new FileStream(options.OutputFile, FileMode.Create)); } DateTimeOffset startTime = DateTimeOffset.Now; try { while (!string.IsNullOrEmpty(line = file.ReadLine())) { ++lines; if (0 == lines % 10000) { Console.WriteLine($"Line : {lines}"); } Dictionary <string, IClogEventArg> valueBag; EventInformation ei; CLogDecodedTraceLine bundle = lttngDecoder.DecodedTraceLine(line, out ei, out valueBag); DecodeAndTraceToConsole(outputfile, bundle, line, textManifest.ConfigFile, valueBag, ei, options.ShowTimestamps, options.ShowCPUInfo); } } catch (Exception e) { CLogConsoleTrace.TraceLine(TraceType.Err, "ERROR : " + e); if (null != outputfile) { outputfile.WriteLine("ERROR : " + e); } } finally { if (null != outputfile) { outputfile.Flush(); outputfile.Close(); } } Console.WriteLine($"Decoded {lines} in {DateTimeOffset.Now - startTime}"); return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }
private void Init() { if (_inited) { return; } if (!File.Exists(xmlFileName)) { Console.WriteLine($"ETW Manifest {xmlFileName} doesnt exist"); throw new CLogEnterReadOnlyModeException("Output Manifest Missing", CLogHandledException.ExceptionType.ETWManifestNotFound, null); } try { doc.PreserveWhitespace = true; doc.Load(xmlFileName); XmlElement assembly = doc["assembly"]; XmlElement stringTable = null; if (null == assembly) { assembly = doc["instrumentationManifest"]; } var instrumentation = assembly["instrumentation"]; var rootEvents = instrumentation["events"]; var stringEvents = assembly["localization"]; foreach (var culture in stringEvents.ChildNodes) { if (!(culture is XmlElement)) { continue; } XmlElement pe = (XmlElement)culture; if (pe.Name == "resources") { if (!pe.HasAttribute("culture")) { continue; } string attr = pe.GetAttribute("culture"); if (!attr.Equals("en-US")) { continue; } stringTable = pe["stringTable"]; } } foreach (var p in rootEvents.ChildNodes) { if (!(p is XmlElement)) { continue; } XmlElement pe = (XmlElement)p; if (pe.Name == "provider") { if (!pe.HasAttribute("guid")) { continue; } string attr = pe.GetAttribute("guid"); Guid id = new Guid(attr); if (!_providerCache.ContainsKey(id)) { _providerCache[id] = new ManifestInformation(doc, pe, stringTable); } } } _inited = true; } catch (Exception) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Error processing ETW manifest {xmlFileName}"); throw; } }
private static int Main(string[] args) { ParserResult <CommandLineArguments> o = Parser.Default.ParseArguments <CommandLineArguments>(args); return(o.MapResult( options => { string currentFile = null; try { // // The CommandLineArguments library validates most input arguments for us, there are few ones that are complicated // this secondary check looks for those and errors out if present // if (!options.IsValid()) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Invalid args"); return -1; } CLogConfigurationFile configFile = CLogConfigurationFile.FromFile(options.ConfigurationFile); configFile.ProfileName = options.ConfigurationProfile; if (options.ReadOnly && !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_FORCE_WRITABLE"))) { options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed via --readOnly not to emit changes however this was overridden with CLOG_FORCE_WRITABLE environment variable"); } if (options.OverwriteHashCollisions || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_OVERWRITE_COLLISIONS"))) { options.OverwriteHashCollisions = true; options.ReadOnly = false; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Overwriting of sidecare collisions is set by environment variable CLOG_OVERWRITE_COLLISIONS. This setting is only to be used while making large refactors and should not be included in build environments or standard development environments"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "***********************************************"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, ""); } if (options.Devmode || !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("CLOG_DEVELOPMENT_MODE"))) { options.ReadOnly = false; options.OverwriteHashCollisions = true; configFile.DeveloperMode = true; CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Wrn, "WARNING: CLOG was instructed to enter a developer mode"); } if (options.LintConfig) { if (!configFile.MarkPhase) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, "Lint operation only works on config files placed into the 'MarkPhase'. This can be a destricutive action, please read the docs for more information"); return -10; } configFile.Lint(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Lint operation complete"); return 0; } if (options.UpgradeConfigFile) { configFile.UpdateVersion(); configFile.Save(false); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, "Config upgrade complete"); return 0; } CLogSidecar sidecar; if (!Directory.Exists(Path.GetDirectoryName(options.SidecarFile))) { Directory.CreateDirectory(Path.GetDirectoryName(options.SidecarFile)); } if (!File.Exists(options.SidecarFile)) { sidecar = new CLogSidecar(); } else { string json = File.ReadAllText(options.SidecarFile); sidecar = CLogSidecar.FromJson(json); if (null == sidecar) { sidecar = new CLogSidecar(); } } sidecar.SetConfigFile(configFile); if (options.RefreshCustomTypeProcessor) { configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); return 0; } // // BUGBUG: refactoring needed for handling batches of input files, expecially // now that managed languages are coming along. Leaving this unaddressed // for now while the best way is still elusive // List <ICLogBatchingModule> batchingModules = new List <ICLogBatchingModule>(); Console.WriteLine("Number of files : " + (new List <string>(options.InputFiles)).Count); foreach (string inputFile in options.InputFiles) { Console.WriteLine("Processing: " + inputFile); currentFile = inputFile; string outputFile = options.GetOutputFileName(inputFile); string outputCFile = Path.Combine(Path.GetDirectoryName(outputFile), options.ScopePrefix + "_" + Path.GetFileName(outputFile)) + ".c"; configFile.ScopePrefix = options.ScopePrefix; configFile.FilePath = Path.GetFullPath(options.ConfigurationFile); configFile.OverwriteHashCollisions = options.OverwriteHashCollisions; //Delete the output file; we want to encourage build breaks if something goes wrong if (File.Exists(outputFile)) { File.Delete(outputFile); } if (File.Exists(outputCFile)) { File.Delete(outputCFile); } CLogFileProcessor processor = new CLogFileProcessor(configFile); CLogFullyDecodedMacroEmitter fullyDecodedMacroEmitter = new CLogFullyDecodedMacroEmitter(inputFile, sidecar); fullyDecodedMacroEmitter.AddClogModule(sidecar); CLogTraceLoggingOutputModule traceLoggingEmitter = new CLogTraceLoggingOutputModule(); fullyDecodedMacroEmitter.AddClogModule(traceLoggingEmitter); CLogDTraceOutputModule dtrace = new CLogDTraceOutputModule(); fullyDecodedMacroEmitter.AddClogModule(dtrace); CLogSysLogModule syslog = new CLogSysLogModule(); fullyDecodedMacroEmitter.AddClogModule(syslog); CLogSTDOUT stdout = new CLogSTDOUT(); fullyDecodedMacroEmitter.AddClogModule(stdout); CLogManifestedETWOutputModule manifestedEtwOutput = new CLogManifestedETWOutputModule(options.ReadOnly); fullyDecodedMacroEmitter.AddClogModule(manifestedEtwOutput); CLogLTTNGOutputModule lttngOutput = new CLogLTTNGOutputModule(inputFile, outputFile, outputFile + ".lttng.h", options.DynamicTracepointProvider); fullyDecodedMacroEmitter.AddClogModule(lttngOutput); if (!File.Exists(inputFile)) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"Invalid Input File (file doesnt exist) : {inputFile}"); throw new CLogEnterReadOnlyModeException("InvalidInputFile", CLogHandledException.ExceptionType.InvalidInputFile, null); } CLogOutputInfo outputInfo = new CLogOutputInfo(); outputInfo.OutputDirectory = options.OutputDirectory; outputInfo.OutputFileName = outputFile; outputInfo.InputFileName = inputFile; string content = File.ReadAllText(inputFile); string output = processor.ConvertFile(configFile, outputInfo, fullyDecodedMacroEmitter, content, inputFile, false); // TODO: BUGBUG - Java won't ever do this //if (!content.Contains(Path.GetFileName(outputFile))) //{ // CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Std, $"You must #include the clog output file {Path.GetFileName(outputFile)}"); // throw new CLogEnterReadOnlyModeException("MustIncludeCLogHeader", CLogHandledException.ExceptionType.SourceMustIncludeCLOGHeader, null); //} fullyDecodedMacroEmitter.FinishedProcessing(outputInfo); StringBuilder clogFile = new StringBuilder(); clogFile.AppendLine($"#ifndef CLOG_DO_NOT_INCLUDE_HEADER"); clogFile.AppendLine("#include <clog.h>"); clogFile.AppendLine($"#endif"); clogFile.Append(fullyDecodedMacroEmitter.HeaderInit); foreach (var macro in processor.MacrosInUse) { clogFile.AppendLine($"#ifndef _clog_MACRO_{macro.MacroName}"); clogFile.AppendLine($"#define _clog_MACRO_{macro.MacroName} 1"); clogFile.AppendLine( $"#define {macro.MacroName}(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))"); clogFile.AppendLine("#endif"); } clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("extern \"C\" {"); clogFile.AppendLine("#endif"); clogFile.Append(fullyDecodedMacroEmitter.HeaderFile); clogFile.AppendLine("#ifdef __cplusplus"); clogFile.AppendLine("}"); clogFile.AppendLine("#endif"); clogFile.AppendLine("#ifdef CLOG_INLINE_IMPLEMENTATION"); clogFile.AppendLine("#include \"" + Path.GetFileName(outputCFile) + "\""); clogFile.AppendLine("#endif"); // // BUGBUG : the intent in saving needs to be // 1. delete any output files early - before we start, getting us into a safe state (build breaks) // 2. save sidecars and other items that make assumptions about the emitted code // 3. save emitted code // // the goal of these orderings is to be safe in the event of failure/crash // if (!Directory.Exists(Path.GetDirectoryName(outputFile))) { Console.WriteLine("Creating Directory for Output : " + Path.GetDirectoryName(outputFile)); Directory.CreateDirectory(Path.GetDirectoryName(outputFile)); } if (sidecar.AreDirty || configFile.AreWeDirty()) { if (options.ReadOnly) { if (sidecar.AreDirty) { Console.WriteLine("Sidecar is dirty"); } if (configFile.AreWeDirty()) { Console.WriteLine("ConfigFile is dirty"); } sidecar.PrintDirtyReasons(); throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:SideCar", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } configFile.ForceDecoderCompile(); sidecar.Save(options.SidecarFile); } if (configFile.AreWeDirty() || configFile.AreWeInMarkPhase()) { if (options.ReadOnly) { throw new CLogEnterReadOnlyModeException("WontWriteWhileInReadonlyMode:ConfigFile", CLogHandledException.ExceptionType.WontWriteInReadOnlyMode, null); } Console.WriteLine("Configuration file was updated, saving..."); Console.WriteLine($" {configFile.FilePath}"); configFile.Save(false); } File.WriteAllText(outputFile, clogFile.ToString()); File.WriteAllText(outputCFile, fullyDecodedMacroEmitter.SourceFile); } currentFile = null; // // Enumerate batching modules, allowing them to save // foreach (var m in batchingModules) { CLogOutputInfo outputInfo = new CLogOutputInfo(); outputInfo.OutputDirectory = options.OutputDirectory; m.FinishedBatch(outputInfo); } } catch (CLogHandledException e) { if (null != currentFile) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Failure in file : {currentFile}"); } e.PrintDiagnostics(options.VerboseErrors); return -2; } catch (Exception e) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"---------------------------------------------------------------------------"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"CLOG has crashed processing : {currentFile}."); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" if you're reading this, we consider seeing this message a bug. Even if the message"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" you're about to read is sufficient to diagnose, we'd like to improve the user experience"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $" please consider filing a bug, with repro files and --verboseErrors"); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $""); CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, $"Exception:"); if (!options.VerboseErrors) { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, " " + e.Message); return -1; } else { CLogConsoleTrace.TraceLine(CLogConsoleTrace.TraceType.Err, e.ToString()); } } return 0; }, err => { Console.WriteLine("Bad Args : " + err); return -1; })); }