MSBuild 利用多个处理器的能力可以减少项目生成时间,但也增加了生成事件日志记录的复杂性。 在单处理器环境中,事件、消息、警告和错误以可预测的顺序方式到达记录器。 但是,在多处理器环境中,来自不同源的事件可能同时到达或者顺序错乱。
生成二进制日志(-binlog 或 -bl 切换),并使用 结构化日志查看器 查看它在很大程度上解决了此问题。 使用 MSBuild 版本 17.8 或更高版本,还可以在控制台中实时尝试终端记录器(-tl 开关),以获得更多用户友好的日志记录输出。
对于更常规的解决方案,MSBuild 提供了多处理器感知记录器和日志记录模型,可用于创建自定义“转发记录器”。
多处理器日志记录挑战
在多处理器或多核心系统上生成一个或多个项目时,将同时生成所有项目的 MSBuild 生成事件。 事件消息可能会像雪崩一样同时到达记录器,或者到达的顺序可能会乱。 由于 MSBuild 2.0 记录器未设计为处理这种情况,因此它可能会使记录器不知所措,并导致生成时间增加、记录器输出不正确,甚至生成中断。 若要解决这些问题,记录器可以处理序列外事件,并关联事件及其源。
可以通过创建自定义转发记录器来提高日志记录效率。 自定义转发记录器通过让你在生成之前仅选择要监视的事件来充当筛选器。 使用自定义转发记录器时,不需要的事件无法使记录器不堪重负、日志混乱或生成时间缓慢。
多处理器日志记录模型
为了提供与多处理器相关的生成问题,MSBuild 支持两种日志记录模型,即中央和分布式。
中央日志记录模型
在中央日志记录模型中, MSBuild.exe的单个 实例充当“中央节点”,中心节点(“辅助节点”)的子实例附加到中心节点,以帮助其执行生成任务。
附加到中央节点的各种类型的记录器称为“中央记录器”。每个记录器类型的一个实例只能同时附加到中心节点。
生成发生时,辅助节点将其生成事件路由到中心节点。 中心节点将其所有事件以及辅助节点的所有事件路由到一个或多个附加的中央记录器。 然后,记录器创建基于传入数据的日志文件。
尽管中央记录器只需要实现ILogger,但我们建议您也实现INodeLogger,这样中央记录器可以用参与构建的节点数量初始化。 引擎初始化记录器时,将调用方法 Initialize 的以下重载。
public interface INodeLogger: ILogger
{
public void Initialize(IEventSource eventSource, int nodeCount);
}
任何预先存在的 ILogger记录器都可以充当中央记录器,并且可以附加到构建。 但是,在没有显式支持多处理器日志记录方案和事件无序的情况下编写的中央记录器可能会中断构建或产出毫无意义的输出。
分布式日志记录模型
在中央日志记录模型中,过多的传入消息流量可能会使中心节点不知所措,例如,当许多项目同时生成时。 这可能会给系统资源增加压力并降低生成性能。 为了缓解此问题,MSBuild 支持分布式日志记录模型。
分布式日志记录模型通过创建转发记录器来扩展中心日志记录模型。
转发日志记录器
转发记录器是一个辅助轻型记录器,它具有一个事件筛选器,该筛选器附加到辅助节点,并从该节点接收传入生成事件。 它会筛选传入事件,并仅将指定的事件转发到中心节点。 这减少了发送到中央节点的消息流量,并提高了整体生成性能。
有两种方法可以使用分布式日志记录,如下所示:
自定义名为ConfigurableForwardingLogger的预制转发记录器。
编写自己的自定义转发记录器。
可以修改 ConfigurableForwardingLogger 以满足你的要求。 为此,请使用 MSBuild.exe调用命令行上的记录器,并列出希望记录器转发到中央节点的生成事件。
或者,可以创建自定义转发记录器。 通过创建自定义转发记录器,可以微调记录器的行为。 但是,创建自定义转发记录器比自定义可配置ForwardingLogger 更为复杂。 可以通过实现派生自IForwardingLogger的ILogger接口来创建转发记录器。 接口定义为:
public interface IForwardingLogger: INodeLogger
{
public IEventRedirector EventRedirector { get; set; }
public int NodeId { get; set; }
}
若要转发您的记录器所关注的事件,请在转发记录器中调用 IEventRedirector 接口的 ForwardEvent 方法。 将相应的 BuildEventArgs或派生体作为参数传递。 然后,事件将被转发到中央日志记录系统,并可在该系统中执行相关操作。
有关详细信息,请参阅 创建转发记录器。
使用 ConfigurableForwardingLogger 进行简单的分布式日志记录
若要附加ConfigurableForwardingLogger或自定义转发记录器,请在MSBuild.exe命令行构建中使用-distributedlogger开关(简称-dl)。 指定记录器类型和类的名称的格式与 -logger 开关的名称相同,不同之处在于分布式记录器始终具有两个日志记录类,而不是一个日志记录类,即转发记录器和中央记录器。 下面是有关如何附加名为 XMLForwardingLogger 的自定义转发记录器的示例。
msbuild.exe myproj.proj -distributedlogger:XMLCentralLogger,MyLogger,Version=1.0.2,Culture=neutral*XMLForwardingLogger,MyLogger,Version=1.0.2,Culture=neutral
注释
星号(*)必须在 -dl 开关中分隔两个日志记录器名称。
使用ConfigurableForwardingLogger如同使用任何其他记录器(如获取生成日志中所述),你连接的记录器是 ConfigurableForwardingLogger 而不是典型的 MSBuild 记录器,并且你指定希望它传递到中心节点的事件作为参数。
例如,如果只想在生成开始和结束时以及发生错误时收到通知,则传递BUILDSTARTEDEVENTBUILDFINISHEDEVENT和ERROREVENT作为参数。 可以通过用分号分隔多个参数来传递这些参数。 下面是一个如何使用 ConfigurableForwardingLogger 来仅转发 BUILDSTARTEDEVENT、BUILDFINISHEDEVENT 及 ERROREVENT 事件的示例。
msbuild.exe myproj.proj -distributedlogger:XMLCentralLogger,MyLogger,Version=1.0.2,Culture=neutral*ConfigureableForwardingLogger,C:\My.dll;BUILDSTARTEDEVENT; BUILDFINISHEDEVENT;ERROREVENT
下面是可用的可配置ForwardingLogger 参数的列表。
| 可配置的ForwardingLogger参数 |
|---|
| BUILDSTARTEDEVENT |
| 构建完成事件 |
| PROJECTSTARTEDEVENT |
| 项目完成事件 |
| TARGETSTARTEDEVENT |
| TARGETFINISHEDEVENT |
| 任务启动事件 |
| 任务完成事件 |
| ERROREVENT |
| 警告事件 |
| 高优先消息事件 |
| NORMALMESSAGEEVENT |
| LOWMESSAGEEVENT |
| CUSTOMEVENT |
| 命令行 |
| 性能摘要 |
| NOSUMMARY |
| 显示命令行 |