public void ExportBuildLog(int buildId, BuildLogOptions opts) { switch (_exportType) { #region Text case LogExportType.Text: { LogModel.BuildInfo dbBuild = _db.Table <LogModel.BuildInfo>().First(x => x.Id == buildId); _w.WriteLine($"- PEBakery Build <{dbBuild.Name}> -"); _w.WriteLine($"Built by PEBakery {dbBuild.PEBakeryVersion}"); _w.WriteLine($"Exported by PEBakery {Global.Const.ProgramVersionStrFull}"); _w.WriteLine(); _w.WriteLine($"Started at {dbBuild.StartTime.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss tt K", CultureInfo.InvariantCulture)}"); if (dbBuild.FinishTime != DateTime.MinValue) { // Put these lines only if a build successfully finished _w.WriteLine($"Finished at {dbBuild.FinishTime.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss tt K", CultureInfo.InvariantCulture)}"); TimeSpan elapsed = dbBuild.FinishTime - dbBuild.StartTime; _w.WriteLine($"Took {elapsed:h\\:mm\\:ss}"); } _w.WriteLine(); _w.WriteLine(); // Log Statistics _w.WriteLine("<Log Statistics>"); var states = ((LogState[])Enum.GetValues(typeof(LogState))).Where(x => x != LogState.None && x != LogState.CriticalError); foreach (LogState state in states) { int count = _db.Table <LogModel.BuildLog>().Count(x => x.BuildId == buildId && x.State == state); _w.WriteLine($"{state,-10}: {count}"); } _w.WriteLine(); _w.WriteLine(); // Show ErrorLogs LogModel.BuildLog[] errors = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Error).ToArray(); if (0 < errors.Length) { _w.WriteLine("<Errors>"); int[] scLogIds = errors.Select(x => x.ScriptId).OrderBy(x => x).Distinct().ToArray(); int[] refScLogIds = errors.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId && scLogIds.Contains(x.Id)) .ToArray(); LogModel.Script[] scOriginLogs = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId && (scLogIds.Contains(x.Id) || refScLogIds.Contains(x.Id))) .ToArray(); foreach (LogModel.Script scLog in scLogs) { LogModel.BuildLog[] eLogs = errors.Where(x => x.ScriptId == scLog.Id).ToArray(); if (eLogs.Length == 1) { _w.WriteLine($"- [{eLogs.Length}] Error in script [{scLog.Name}] ({scLog.TreePath})"); } else { _w.WriteLine($"- [{eLogs.Length}] Errors in script [{scLog.Name}] ({scLog.TreePath})"); } foreach (LogModel.BuildLog eLog in eLogs) { _w.WriteLine(eLog.Export(LogExportType.Text, false, false)); string refScriptText = ExportRefScriptText(eLog, scOriginLogs); if (refScriptText != null) { // Referenced scripts _w.Write(" "); _w.WriteLine(refScriptText); } } _w.WriteLine(); } _w.WriteLine(); } // Show WarnLogs LogModel.BuildLog[] warns = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Warning).ToArray(); if (0 < warns.Length) { _w.WriteLine("<Warnings>"); int[] scLogIds = warns.Select(x => x.ScriptId).OrderBy(x => x).Distinct().ToArray(); int[] refScLogIds = warns.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId && scLogIds.Contains(x.Id)) .ToArray(); LogModel.Script[] scOriginLogs = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId && refScLogIds.Contains(x.Id)) // .Where(x => x.BuildId == buildId && (scLogIds.Contains(x.Id) || refScLogIds.Contains(x.Id))) .ToArray(); foreach (LogModel.Script scLog in scLogs) { LogModel.BuildLog[] wLogs = warns.Where(x => x.ScriptId == scLog.Id).ToArray(); Debug.Assert(0 < wLogs.Length); if (wLogs.Length == 1) { _w.WriteLine($"- [{wLogs.Length}] Warning in script [{scLog.Name}] ({scLog.TreePath})"); } else { _w.WriteLine($"- [{wLogs.Length}] Warnings in script [{scLog.Name}] ({scLog.TreePath})"); } foreach (LogModel.BuildLog wLog in wLogs) { _w.WriteLine(wLog.Export(LogExportType.Text, false, false)); string refScriptText = ExportRefScriptText(wLog, scOriginLogs); if (refScriptText != null) { // Referenced scripts _w.Write(" "); _w.WriteLine(refScriptText); } } _w.WriteLine(); } _w.WriteLine(); } // Script LogModel.Script[] scripts = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId) .ToArray(); // Script - Processed Scripts LogModel.Script[] processedScripts = scripts .Where(x => 0 < x.Order) .OrderBy(x => x.Order) .ToArray(); int pathColumnPos; _w.WriteLine("<Scripts>"); { (string Title, string Elapsed, string Path)[] scriptStrs = new (string, string, string)[processedScripts.Length];
public void ExportBuildLog(int buildId, BuildLogOptions opts) { switch (_exportType) { #region Text case LogExportType.Text: { LogModel.BuildInfo dbBuild = _db.Table <LogModel.BuildInfo>().First(x => x.Id == buildId); if (dbBuild.EndTime == DateTime.MinValue) { dbBuild.EndTime = DateTime.UtcNow; } _w.WriteLine($"- PEBakery Build <{dbBuild.Name}> -"); _w.WriteLine($"Started at {dbBuild.StartTime.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss tt K", CultureInfo.InvariantCulture)}"); _w.WriteLine($"Finished at {dbBuild.EndTime.ToLocalTime().ToString("yyyy-MM-dd hh:mm:ss tt K", CultureInfo.InvariantCulture)}"); TimeSpan t = dbBuild.EndTime - dbBuild.StartTime; _w.WriteLine($"Took {t:h\\:mm\\:ss}"); _w.WriteLine(); _w.WriteLine(); // Log Statistics _w.WriteLine("<Log Statistics>"); var states = ((LogState[])Enum.GetValues(typeof(LogState))).Where(x => x != LogState.None && x != LogState.CriticalError); foreach (LogState state in states) { int count = _db.Table <LogModel.BuildLog>().Count(x => x.BuildId == buildId && x.State == state); _w.WriteLine($"{state.ToString().PadRight(9)}: {count}"); } _w.WriteLine(); _w.WriteLine(); // Show ErrorLogs LogModel.BuildLog[] errors = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Error).ToArray(); if (0 < errors.Length) { _w.WriteLine("<Errors>"); int[] scLogIds = errors.Select(x => x.ScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && scLogIds.Contains(x.Id)).ToArray(); int[] refScLogIds = errors.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] refScLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && refScLogIds.Contains(x.Id)).ToArray(); foreach (LogModel.Script scLog in scLogs) { LogModel.BuildLog[] eLogs = errors.Where(x => x.ScriptId == scLog.Id).ToArray(); if (eLogs.Length == 1) { _w.WriteLine($"- [{eLogs.Length}] Error in script [{scLog.Name}] ({scLog.TreePath})"); } else { _w.WriteLine($"- [{eLogs.Length}] Errors in script [{scLog.Name}] ({scLog.TreePath})"); } foreach (LogModel.BuildLog eLog in eLogs) { _w.WriteLine(eLog.Export(LogExportType.Text, false)); if (eLog.RefScriptId != 0 && eLog.RefScriptId != eLog.ScriptId) { _w.Write(" "); _w.WriteLine(ExportRefScriptText(eLog, refScLogs)); } } _w.WriteLine(); } _w.WriteLine(); } // Show WarnLogs LogModel.BuildLog[] warns = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Warning).ToArray(); if (0 < warns.Length) { _w.WriteLine("<Warnings>"); int[] scLogIds = warns.Select(x => x.ScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && scLogIds.Contains(x.Id)).ToArray(); int[] refScLogIds = warns.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] refScLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && refScLogIds.Contains(x.Id)).ToArray(); foreach (LogModel.Script scLog in scLogs) { LogModel.BuildLog[] wLogs = warns.Where(x => x.ScriptId == scLog.Id).ToArray(); Debug.Assert(0 < wLogs.Length); if (wLogs.Length == 1) { _w.WriteLine($"- [{wLogs.Length}] Warning in script [{scLog.Name}] ({scLog.TreePath})"); } else { _w.WriteLine($"- [{wLogs.Length}] Warnings in script [{scLog.Name}] ({scLog.TreePath})"); } foreach (LogModel.BuildLog wLog in wLogs) { _w.WriteLine(wLog.Export(LogExportType.Text, false)); if (wLog.RefScriptId != 0 && wLog.RefScriptId != wLog.ScriptId) { _w.Write(" "); _w.WriteLine(ExportRefScriptText(wLog, refScLogs)); } } _w.WriteLine(); } _w.WriteLine(); } // Script LogModel.Script[] scripts = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId) .ToArray(); LogModel.Script[] processedScripts = scripts .Where(x => 0 < x.Order) .OrderBy(x => x.Order) .ToArray(); _w.WriteLine("<Scripts>"); { int count = processedScripts.Length; int idx = 1; foreach (LogModel.Script sc in processedScripts) { _w.WriteLine($"[{idx}/{count}] {sc.Name} v{sc.Version} ({sc.ElapsedMilliSec / 1000.0:0.000}s)"); idx++; } _w.WriteLine($"Total {count} Scripts"); _w.WriteLine(); _w.WriteLine(); } // Variables _w.WriteLine("<Variables>"); VarsType[] typeList = { VarsType.Fixed, VarsType.Global }; foreach (VarsType varsType in typeList) { _w.WriteLine($"- {varsType} Variables"); var vars = _db.Table <LogModel.Variable>() .Where(x => x.BuildId == buildId && x.Type == varsType) .OrderBy(x => x.Key); foreach (LogModel.Variable log in vars) { _w.WriteLine($"%{log.Key}% = {log.Value}"); } _w.WriteLine(); } _w.WriteLine(); // Code Logs _w.WriteLine("<Code Logs>"); { foreach (LogModel.Script scLog in processedScripts) { // Log codes var cLogs = _db.Table <LogModel.BuildLog>() .Where(x => x.BuildId == buildId && x.ScriptId == scLog.Id); if (!opts.IncludeComments) { cLogs = cLogs.Where(x => (x.Flags & LogModel.BuildLogFlag.Comment) != LogModel.BuildLogFlag.Comment); } if (!opts.IncludeMacros) { cLogs = cLogs.Where(x => (x.Flags & LogModel.BuildLogFlag.Macro) != LogModel.BuildLogFlag.Macro); } cLogs = cLogs.OrderBy(x => x.Id); foreach (LogModel.BuildLog log in cLogs) { _w.WriteLine(log.Export(LogExportType.Text, true)); } // Log local variables var vLogs = _db.Table <LogModel.Variable>() .Where(x => x.BuildId == buildId && x.ScriptId == scLog.Id && x.Type == VarsType.Local) .OrderBy(x => x.Key); if (vLogs.Any()) { _w.WriteLine($"- Local Variables of Script [{scLog.Name}]"); foreach (LogModel.Variable vLog in vLogs) { _w.WriteLine($"%{vLog.Key}% = {vLog.Value}"); } _w.WriteLine(Logger.LogSeparator); } _w.WriteLine(); } } } break; #endregion #region HTML case LogExportType.Html: { LogModel.BuildInfo dbBuild = _db.Table <LogModel.BuildInfo>().First(x => x.Id == buildId); if (dbBuild.EndTime == DateTime.MinValue) { dbBuild.EndTime = DateTime.UtcNow; } ExportBuildLogHtmlModel m = new ExportBuildLogHtmlModel { PEBakeryVersion = Global.Const.StringVersionFull, BuildName = dbBuild.Name, BuildStartTimeStr = dbBuild.StartTime.ToLocalTime().ToString("yyyy-MM-dd h:mm:ss tt K", CultureInfo.InvariantCulture), BuildEndTimeStr = dbBuild.EndTime.ToLocalTime().ToString("yyyy-MM-dd h:mm:ss tt K", CultureInfo.InvariantCulture), BuildTookTimeStr = $"{dbBuild.EndTime - dbBuild.StartTime:h\\:mm\\:ss}", LogStats = new List <LogStatHtmlModel>(), }; // Log Statistics var states = ((LogState[])Enum.GetValues(typeof(LogState))).Where(x => x != LogState.None && x != LogState.CriticalError); foreach (LogState state in states) { int count = _db.Table <LogModel.BuildLog>().Count(x => x.BuildId == buildId && x.State == state); m.LogStats.Add(new LogStatHtmlModel { State = state, Count = count, }); } // Show ErrorLogs m.ErrorCodeDicts = new Dictionary <ScriptHtmlModel, Tuple <CodeLogHtmlModel, string>[]>(); { int errIdx = 0; LogModel.BuildLog[] errors = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Error).ToArray(); if (0 < errors.Length) { int[] pLogIds = errors.Select(x => x.ScriptId).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && pLogIds.Contains(x.Id)).ToArray(); int[] refScLogIds = errors.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] refScLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && refScLogIds.Contains(x.Id)).ToArray(); foreach (LogModel.Script scLog in scLogs) { ScriptHtmlModel scModel = new ScriptHtmlModel { Name = scLog.Name, Path = scLog.TreePath, }; m.ErrorCodeDicts[scModel] = errors .Where(x => x.ScriptId == scLog.Id) .Select(x => new Tuple <CodeLogHtmlModel, string>( new CodeLogHtmlModel { State = x.State, Message = x.Export(LogExportType.Html, false), Href = errIdx++, }, ExportRefScriptText(x, refScLogs))).ToArray(); } } } // Show WarnLogs m.WarnCodeDicts = new Dictionary <ScriptHtmlModel, Tuple <CodeLogHtmlModel, string>[]>(); { int warnIdx = 0; LogModel.BuildLog[] warns = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.State == LogState.Warning).ToArray(); if (0 < warns.Length) { int[] pLogIds = warns.Select(x => x.ScriptId).Distinct().ToArray(); LogModel.Script[] scLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && pLogIds.Contains(x.Id)).ToArray(); int[] refScLogIds = warns.Select(x => x.RefScriptId).OrderBy(x => x).Distinct().ToArray(); LogModel.Script[] refScLogs = _db.Table <LogModel.Script>().Where(x => x.BuildId == buildId && refScLogIds.Contains(x.Id)).ToArray(); foreach (LogModel.Script scLog in scLogs) { ScriptHtmlModel pModel = new ScriptHtmlModel { Name = scLog.Name, Path = scLog.TreePath, }; m.WarnCodeDicts[pModel] = warns .Where(x => x.ScriptId == scLog.Id) .Select(x => new Tuple <CodeLogHtmlModel, string>( new CodeLogHtmlModel { State = x.State, Message = x.Export(LogExportType.Html, false), Href = warnIdx++, }, ExportRefScriptText(x, refScLogs))).ToArray(); } } } // Scripts var scripts = _db.Table <LogModel.Script>() .Where(x => x.BuildId == buildId && 0 < x.Order) .OrderBy(x => x.Order); m.Scripts = new List <ScriptHtmlModel>(); { int idx = 1; foreach (LogModel.Script scLog in scripts) { m.Scripts.Add(new ScriptHtmlModel { Index = idx, Name = scLog.Name, Path = scLog.TreePath, Version = $"v{scLog.Version}", TimeStr = $"{scLog.ElapsedMilliSec / 1000.0:0.000}s", }); idx++; } } // Variables m.Vars = new List <VarHtmlModel>(); { var vars = _db.Table <LogModel.Variable>() .Where(x => x.BuildId == buildId && (x.Type == VarsType.Fixed || x.Type == VarsType.Global)) .OrderBy(x => x.Type) .ThenBy(x => x.Key); foreach (LogModel.Variable vLog in vars) { m.Vars.Add(new VarHtmlModel { Type = vLog.Type, Key = vLog.Key, Value = vLog.Value, }); } } // CodeLogs m.CodeLogs = new List <Tuple <ScriptHtmlModel, CodeLogHtmlModel[], VarHtmlModel[]> >(); { int pIdx = 0; int errIdx = 0; int warnIdx = 0; foreach (LogModel.Script scLog in scripts) { pIdx += 1; // Log codes var cLogs = _db.Table <LogModel.BuildLog>().Where(x => x.BuildId == buildId && x.ScriptId == scLog.Id); if (!opts.IncludeComments) { cLogs = cLogs.Where(x => (x.Flags & LogModel.BuildLogFlag.Comment) != LogModel.BuildLogFlag.Comment); } if (!opts.IncludeMacros) { cLogs = cLogs.Where(x => (x.Flags & LogModel.BuildLogFlag.Macro) != LogModel.BuildLogFlag.Macro); } LogModel.BuildLog[] codeLogs = cLogs.OrderBy(x => x.Id).OrderBy(x => x.Id).ToArray(); ScriptHtmlModel pModel = new ScriptHtmlModel { Index = pIdx, Name = scLog.Name, Path = scLog.TreePath, }; List <CodeLogHtmlModel> logModel = new List <CodeLogHtmlModel>(codeLogs.Length); foreach (LogModel.BuildLog log in codeLogs) { CodeLogHtmlModel item = new CodeLogHtmlModel { State = log.State, Message = log.Export(LogExportType.Html, true), }; if (log.State == LogState.Error) { item.Href = errIdx++; } else if (log.State == LogState.Warning) { item.Href = warnIdx++; } logModel.Add(item); } // Log local variables VarHtmlModel[] localVarModel = _db.Table <LogModel.Variable>() .Where(x => x.BuildId == buildId && x.ScriptId == scLog.Id && x.Type == VarsType.Local) .OrderBy(x => x.Key) .Select(x => new VarHtmlModel { Type = x.Type, Key = x.Key, Value = x.Value, }).ToArray(); m.CodeLogs.Add(new Tuple <ScriptHtmlModel, CodeLogHtmlModel[], VarHtmlModel[]>(pModel, logModel.ToArray(), localVarModel)); } } string html = RazorEngine.Engine.Razor.RunCompile(Properties.Resources.BuildLogHtmlTemplate, "BuildLogHtmlTemplateKey", null, m); _w.WriteLine(html); } break; #endregion } }