| File: Logging\BinaryLogger\BinaryLogEventFilter.cs | Web Access |
| Project: Microsoft.Build.csproj (Microsoft.Build) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; #if NETFRAMEWORK using System.Runtime.Serialization; #endif using Microsoft.Build.Framework; using Microsoft.Build.Shared; namespace Microsoft.Build.Logging; /// <summary> /// Metadata passed to a binary log event filter. /// </summary> public readonly struct BinaryLogEventMetadata { internal BinaryLogEventMetadata( BinaryLogRecordKind recordKind, BuildEventContext? buildEventContext, BuildEventContext? originalBuildEventContext = null) { RecordKind = recordKind; BuildEventContext = buildEventContext; OriginalBuildEventContext = originalBuildEventContext; } /// <summary> /// Gets the serialized event type. /// </summary> public BinaryLogRecordKind RecordKind { get; } /// <summary> /// Gets the event's build context, or <see langword="null"/> if absent. /// </summary> public BuildEventContext? BuildEventContext { get; } /// <summary> /// Gets the original context of a target-skipped event, or <see langword="null"/>. /// </summary> public BuildEventContext? OriginalBuildEventContext { get; } } /// <summary> /// Decides whether a binary log event should be deserialized and dispatched. /// </summary> /// <param name="metadata">The event metadata.</param> /// <returns><see langword="true"/> to keep the event; <see langword="false"/> to skip it.</returns> /// <remarks> /// Rejected payloads are skipped in length-framed logs (v18+). Legacy logs and /// <see cref="TargetSkippedEventArgs"/> require deserialization; auxiliary records are always read. /// Filters must preserve any event structure required by consumers, including matching start/finish events. /// </remarks> public delegate bool BinaryLogEventFilter(BinaryLogEventMetadata metadata); /// <summary> /// Wraps an exception thrown by a <see cref="BinaryLogEventFilter"/> callback. /// </summary> /// <remarks> /// Filter failures abort replay; they are not recoverable read errors. /// The original failure is preserved in <see cref="Exception.InnerException"/>. /// On .NET Framework, legacy serialization preserves the exception and supplied record diagnostics /// when marshaling exceptions across AppDomain boundaries. /// </remarks> #if NETFRAMEWORK [Serializable] #endif public sealed class BinaryLogEventFilterException : Exception { /// <summary> /// Creates a filter failure without record diagnostics. /// </summary> /// <param name="innerException">The exception thrown by the filter callback.</param> public BinaryLogEventFilterException(Exception innerException) : base(ResourceUtilities.GetResourceString("Binlog_EventFilterThrew"), innerException) { } /// <summary> /// Creates a filter failure with record diagnostics. /// </summary> /// <param name="metadata">The failing callback's event metadata.</param> /// <param name="recordNumber">The zero-based record number, including auxiliary records.</param> /// <param name="fileFormatVersion">The source binlog's format version.</param> /// <param name="innerException">The exception thrown by the filter callback.</param> public BinaryLogEventFilterException( BinaryLogEventMetadata metadata, long recordNumber, int fileFormatVersion, Exception innerException) : base(ResourceUtilities.FormatResourceStringStripCodeAndKeyword( "Binlog_EventFilterThrewWithContext", recordNumber, metadata.RecordKind, fileFormatVersion, metadata.BuildEventContext, metadata.OriginalBuildEventContext), innerException) { RecordKind = metadata.RecordKind; BuildEventContext = metadata.BuildEventContext; OriginalBuildEventContext = metadata.OriginalBuildEventContext; RecordNumber = recordNumber; FileFormatVersion = fileFormatVersion; } /// <summary> /// Gets the record kind, or <see langword="null"/> if unavailable. /// </summary> public BinaryLogRecordKind? RecordKind { get; } /// <summary> /// Gets the build context passed to the filter, or <see langword="null"/> if unavailable. /// </summary> public BuildEventContext? BuildEventContext { get; } /// <summary> /// Gets the original target-skipped context, or <see langword="null"/> if unavailable. /// </summary> public BuildEventContext? OriginalBuildEventContext { get; } /// <summary> /// Gets the zero-based record number, including auxiliary and rejected records, /// or <see langword="null"/> if unavailable. /// </summary> public long? RecordNumber { get; } /// <summary> /// Gets the source binlog's format version, or <see langword="null"/> if unavailable. /// </summary> public int? FileFormatVersion { get; } #if NETFRAMEWORK private BinaryLogEventFilterException(SerializationInfo info, StreamingContext context) : base(info, context) { RecordKind = (BinaryLogRecordKind?)info.GetValue(nameof(RecordKind), typeof(BinaryLogRecordKind?)); BuildEventContext = (BuildEventContext?)info.GetValue(nameof(BuildEventContext), typeof(BuildEventContext)); OriginalBuildEventContext = (BuildEventContext?)info.GetValue(nameof(OriginalBuildEventContext), typeof(BuildEventContext)); RecordNumber = (long?)info.GetValue(nameof(RecordNumber), typeof(long?)); FileFormatVersion = (int?)info.GetValue(nameof(FileFormatVersion), typeof(int?)); } /// <summary> /// Serializes the exception and record diagnostics. /// </summary> /// <param name="info">The serialization data to populate.</param> /// <param name="context">The serialization context.</param> #if FEATURE_SECURITY_PERMISSIONS [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] #endif public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue(nameof(RecordKind), RecordKind, typeof(BinaryLogRecordKind?)); info.AddValue(nameof(BuildEventContext), BuildEventContext, typeof(BuildEventContext)); info.AddValue(nameof(OriginalBuildEventContext), OriginalBuildEventContext, typeof(BuildEventContext)); info.AddValue(nameof(RecordNumber), RecordNumber, typeof(long?)); info.AddValue(nameof(FileFormatVersion), FileFormatVersion, typeof(int?)); } #endif }