最近想改一下项目,发现有很多警告,想把所有的 warning 导出到 JSON 以方便统计 warning 类型以及出现的次数,但是目前 dotnet build 还不支持,于是想提一个 issue 希望支持一下,然后有大佬说可以自定义一个 msbuild logger 来实现,.NET SDK 里的 Terminal Logger 也是这种方式实现的,于是就找了下文档动手尝试了一下,分享一下,希望对大家有所帮助
首先我们来创建一个新的类库项目,并添加 Microsoft.Build.Framework
nuget 包的引用
然后就可以创建一个 logger,实现:Microsoft.Build.Framework.ILogger
接口即可,代码实现如下:
public sealed class JsonErrorLogger : ILogger
{
private const string ErrorLogFileName = "json-error-logger.json";
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
{
WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
private readonly List<BuildError> _errors = new(), _warnings = new();
public void Initialize(IEventSource eventSource)
{
eventSource.WarningRaised += EventSourceOnWarningRaised;
eventSource.ErrorRaised += EventSourceOnErrorRaised;
}
private void EventSourceOnWarningRaised(object sender, BuildWarningEventArgs e)
{
_warnings.Add(new BuildError(e.Subcategory, e.Code, e.File, e.LineNumber, e.ColumnNumber, e.EndLineNumber, e.EndColumnNumber, e.Message, e.HelpKeyword, e.SenderName));
}
private void EventSourceOnErrorRaised(object sender, BuildErrorEventArgs e)
{
_errors.Add(new BuildError(e.Subcategory, e.Code, e.File, e.LineNumber, e.ColumnNumber, e.EndLineNumber, e.EndColumnNumber, e.Message, e.HelpKeyword, e.SenderName));
}
public void Shutdown()
{
using var fs = File.Create(ErrorLogFileName);
JsonSerializer.Serialize(fs, new
{
warnings = _warnings,
errors = _errors
}, JsonSerializerOptions);
_errors.Clear();
}
public LoggerVerbosity Verbosity { get; set; }
public string? Parameters { get; set; }
}
public sealed record BuildError(
string Subcategory,
string Code,
string File,
int LineNumber,
int ColumnNumber,
int EndLineNumber,
int EndColumnNumber,
string? Message,
string? HelpKeyword,
string? SenderName);
这里实现的逻辑比较简单,在 Initialize
的时候注册 warning 和 error 事件,将 warning 和 error 信息记录下来,并在 Shutdown
的时候将其导出到 json 文件中,代码搞好之后编译我们的项目,确保成功生成 dll 文件
然后在原来 dotnet build
的基础上添加 -logger
参数使用我们自定义的这个 logger,示例如下:
dotnet build -logger:"JsonErrorLogger,C:\projects\source\SamplesInPractice\MSBuildLoggerSample\MSBuildJsonLogger\bin\Debug\net8.0\MSBuildJsonLogger.dll"
此时就会生成一个类似下面的 json 文件
这样我们就可以知道哪里出错了,发生了什么错误,也可以更加方便地根据 error code 来统计,我们也可以在自定义 logger 的实现里,在导出之前进行统计,生成统计信息等
前面的这个 logger 比较简单,目前 path 是写死的,也只关心 warning 和 error log,msbuild 提供了一个 ILogger
的实现 Logger
, 也可以继承这个 Logger
来实现,实际要复用的话可以结合 msbuild 的一些参数和自己的需求进行改进和定制
除了自定义 msbuild logger 之外 Roslyn 在编译的时候也可以生成一个编译 error 的文件,可以导出成 json,可以在项目文件里配置
<ErrorLog>logVersion21.json,version=2.1</ErrorLog>
不过这种方式我试下来应该只有 Roslyn 代码编译的 error log,一些补充的自定义的 task report 的 error 不会出现,比如像 NuGet Audit 的 Error 是没有的,所以想要获取完整的 error 建议还是要通过自定义 msbuild logger 的方式
本文分享了一个 msbuild logger 的 demo 来导出 msbuild warning/error 为 json 文件,感谢热心帮忙的大佬们,希望对大家有所帮助