| File: Debugging\PrintLineDebuggerWriters.cs | Web Access |
| Project: Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.Linq; using CommonWriterType = System.Action<string, string, System.Collections.Generic.IEnumerable<string>>; #nullable disable namespace Microsoft.Build.Shared.Debugging; /// <summary> /// A collection of useful writers /// </summary> internal static class PrintLineDebuggerWriters { public sealed class IdBasedFilesWriter { private string LogFileRoot { get; } public CommonWriterType Writer => (id, callsite, args) => { try { var file = Path.Combine(LogFileRoot, string.IsNullOrEmpty(id) ? "NoId" : id) + ".csv"; File.AppendAllText(file, CsvFormat(string.Empty, callsite, args)); } catch (Exception e) { var errorFile = Path.Combine(LogFileRoot, $"LoggingException_{Guid.NewGuid()}"); File.AppendAllText(errorFile, $"{SimpleFormat(id, callsite, args)}\n{e.Message}\n{e.StackTrace}"); } }; public IdBasedFilesWriter(string logFileRoot) { this.LogFileRoot = logFileRoot; Directory.CreateDirectory(logFileRoot); } public static IdBasedFilesWriter FromArtifactLogDirectory() { return new IdBasedFilesWriter(ArtifactsLogDirectory); } } public sealed class CompositeWriter { private IEnumerable<CommonWriterType> Writers { get; } public CommonWriterType Writer => (id, callsite, args) => { var argsArray = args as string[] ?? args.ToArray(); foreach (var writer in Writers) { writer(id, callsite, argsArray); } }; public CompositeWriter(IEnumerable<CommonWriterType> writers) { Writers = writers; } } public static CommonWriterType StdOutWriter = (id, callsite, args) => Console.WriteLine(SimpleFormat(id, callsite, args)); private static readonly Lazy<string> _artifactsLogs = new Lazy<string>( () => { var executingAssembly = typeof(PrintLineDebuggerWriters).GetAssemblyPath(); var binPart = $"bin"; var logIndex = executingAssembly.IndexOf(binPart, StringComparison.Ordinal); var artifactsPart = executingAssembly.Substring(0, logIndex); return logIndex < 0 ? null : Path.Combine(artifactsPart, "log", "Debug"); }); public static string ArtifactsLogDirectory => _artifactsLogs.Value; public static string SimpleFormat(string id, string callsite, IEnumerable<string> args) { return $"\n{(id == null ? string.Empty : id + ": ")}{callsite}:{string.Join(";", args)}"; } public static string CsvFormat(string id, string callsite, IEnumerable<string> args) { var joinedArgs = $"{EscapeCommas(callsite)},{string.Join(",", args.Select(arg => EscapeCommas(arg)))}\n"; return string.IsNullOrEmpty(id) ? joinedArgs : $"{EscapeCommas(id)},{joinedArgs}"; string EscapeCommas(string s) { return s.Replace(",", ";"); } } }