/// <summary> /// Ascertain, i.e. assess and setup, whether the payload of a message body <paramref name="trackingStream"/> /// needs to be captured outside of the BAM monitoring database, that is in the <see cref="ClaimStore"/>, or not. /// </summary> /// <param name="trackingStream"> /// The stream to assess. /// </param> /// <param name="trackingModes"> /// The extent to which a messaging activity will be recorded. /// </param> /// <param name="transactionFactory"> /// The <see cref="IKernelTransaction"/> factory method whose offspring transaction has to be piggybacked if the /// message body's payload needs to be claimed to disk. It can be <c>null</c> if piggybacking is not desired nor /// possible, like for instance when calling this method from a send pipeline, as BizTalk does not provide for /// transaction piggybacking in send pipelines. /// </param> /// <returns> /// The ascertained <see cref="ActivityTrackingModes"/>, that is the one that will actually be applied. /// </returns> /// <remarks> /// <para> /// If the size of the <see cref="TrackingStream"/> does not exceed a 512KB threshold, the <see /// cref="TrackingStream"/>'s capture will be setup according to a <see cref="MessageBodyCaptureDescriptor"/> /// whose <see cref="MessageBodyCaptureDescriptor.Data"/> will contain a base64-encoding of the compressed stream /// content. /// </para> /// <para> /// If the size of the <see cref="TrackingStream"/> exceeds the 512KB threshold, the <see /// cref="TrackingStream"/>'s capture will be setup according to a <see cref="MessageBodyCaptureDescriptor"/> /// whose <see cref="MessageBodyCaptureDescriptor.Data"/> will contain the relative URL that can be used to get /// back the payload from the <see cref="ClaimStore"/>. /// </para> /// <para> /// The 512KB threshold has been chosen according to the BizTalk documentation which proscribes BAM /// <c>LongReferenceData</c> item of more than 512 KB. /// </para> /// </remarks> public virtual void SetupMessageBodyCapture(TrackingStream trackingStream, ActivityTrackingModes trackingModes, Func <IKernelTransaction> transactionFactory) { if (trackingStream == null) { throw new ArgumentNullException("trackingStream"); } if (_logger.IsDebugEnabled) { _logger.DebugFormat( "Message body capture is being set up for '{0}' tracking requirements.", Convert.ToString(trackingModes)); } // never want to claim (save to disk) a payload if it is small, hence always probe for its size string encodedCompression; var isCompressible = trackingStream.AsMarkable().TryCompressToBase64String(PAYLOAD_SIZE_THRESHOLD, out encodedCompression); if (isCompressible) { var captureDescriptor = new MessageBodyCaptureDescriptor(encodedCompression, MessageBodyCaptureMode.Unclaimed); trackingStream.SetupCapture(captureDescriptor); } else { var captureDescriptor = new MessageBodyCaptureDescriptor(GenerateClaimStoreEntry(), MessageBodyCaptureMode.Claimed); var capturingStream = CreateCapturingStream(captureDescriptor.Data, trackingModes, transactionFactory); trackingStream.SetupCapture(captureDescriptor, capturingStream); } }
public void StepOnly() { const ActivityTrackingModes sut = ActivityTrackingModes.Step; sut.RequiresStepTracking().Should().BeTrue(); sut.RequiresContextTracking().Should().BeFalse(); sut.RequiresBodyTracking().Should().BeFalse(); sut.RequiresBodyClaimChecking().Should().BeFalse(); Convert.ToString(sut).Should().Be("Step"); }
public void StepOnly() { const ActivityTrackingModes sut = ActivityTrackingModes.Step; Assert.That(sut.RequiresStepTracking()); Assert.That(sut.RequiresContextTracking(), Is.False); Assert.That(sut.RequiresBodyTracking(), Is.False); Assert.That(sut.RequiresBodyClaimChecking(), Is.False); Assert.That(Convert.ToString(sut), Is.EqualTo("Step")); }
public void ClaimRequiresBody() { const ActivityTrackingModes sut = ActivityTrackingModes.Claim; Assert.That(sut, Is.EqualTo(ActivityTrackingModes.Claim | ActivityTrackingModes.Body)); Assert.That(sut.RequiresBodyClaimChecking()); Assert.That(sut.RequiresBodyTracking()); Assert.That(Convert.ToString(sut), Is.EqualTo("Claim")); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Claim"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Claim, Body"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Body"), Is.Not.EqualTo(sut)); }
public void ContextRequiresStep() { const ActivityTrackingModes sut = ActivityTrackingModes.Context; sut.Should().Be(ActivityTrackingModes.Context | ActivityTrackingModes.Step); sut.RequiresContextTracking().Should().BeTrue(); sut.RequiresStepTracking().Should().BeTrue(); Convert.ToString(sut).Should().Be("Context"); Enum.Parse(typeof(ActivityTrackingModes), "Context").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Context, Step").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Step").Should().NotBe(sut); }
public void ContextRequiresStep() { const ActivityTrackingModes sut = ActivityTrackingModes.Context; Assert.That(sut, Is.EqualTo(ActivityTrackingModes.Context | ActivityTrackingModes.Step)); Assert.That(sut.RequiresContextTracking()); Assert.That(sut.RequiresStepTracking()); Assert.That(Convert.ToString(sut), Is.EqualTo("Context")); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Context"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Context, Step"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Step"), Is.Not.EqualTo(sut)); }
public void ClaimRequiresBody() { const ActivityTrackingModes sut = ActivityTrackingModes.Claim; sut.Should().Be(ActivityTrackingModes.Claim | ActivityTrackingModes.Body); sut.RequiresBodyClaimChecking().Should().BeTrue(); sut.RequiresBodyTracking().Should().BeTrue(); Convert.ToString(sut).Should().Be("Claim"); Enum.Parse(typeof(ActivityTrackingModes), "Claim").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Claim, Body").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Body").Should().NotBe(sut); }
public void BodyRequiresContext() { const ActivityTrackingModes sut = ActivityTrackingModes.Body; sut.Should().Be(ActivityTrackingModes.Body | ActivityTrackingModes.Context); sut.RequiresBodyTracking().Should().BeTrue(); sut.RequiresContextTracking().Should().BeTrue(); sut.RequiresBodyClaimChecking().Should().BeFalse(); Convert.ToString(sut).Should().Be("Body"); Enum.Parse(typeof(ActivityTrackingModes), "Body").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Body, Context").Should().Be(sut); Enum.Parse(typeof(ActivityTrackingModes), "Context").Should().NotBe(sut); }
/// <summary> /// Creates a BAM <c>MessagingStep</c> activity that captures descriptive information about the <see /// cref="IBaseMessage"/> being processed. /// </summary> /// <param name="trackingModes"> /// The extent to which information about a messaging step activity will be tracked and recorded. /// </param> /// <param name="trackingStream"> /// The <see cref="TrackingStream"/> that wraps the actual message body's stream that will captured. /// </param> internal virtual void TrackActivity(ActivityTrackingModes trackingModes, TrackingStream trackingStream) { if (trackingModes.RequiresStepTracking()) { TrackStep(trackingStream.Length); } if (trackingModes.RequiresContextTracking()) { TrackMessageContext(); } if (trackingModes.RequiresBodyTracking()) { TrackMessageBody(trackingStream.CaptureDescriptor); } }
public void BodyRequiresContext() { const ActivityTrackingModes sut = ActivityTrackingModes.Body; Assert.That(sut, Is.EqualTo(ActivityTrackingModes.Body | ActivityTrackingModes.Context)); Assert.That(sut.RequiresBodyTracking()); Assert.That(sut.RequiresContextTracking()); Assert.That(sut.RequiresBodyClaimChecking(), Is.False); Assert.That(Convert.ToString(sut), Is.EqualTo("Body")); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Body"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Body, Context"), Is.EqualTo(sut)); Assert.That(Enum.Parse(typeof(ActivityTrackingModes), "Context"), Is.Not.EqualTo(sut)); }
private void Complete(ActivityTrackingModes trackingModes, TrackingStream trackingStream) { var isMessagingProcess = _previousMessagingStep != null; if (_logger.IsDebugEnabled) { _logger.Debug($"Completing tracking of a messaging {(isMessagingProcess ? "process" : "step")}."); } // track the whole wealth of messaging activity, it might be a complete process or a single messaging step if (isMessagingProcess) { _process.TrackActivity(); _process.AddStep(_previousMessagingStep); } _messagingStep.TrackActivity(trackingModes, trackingStream); _process.IfNotNull(p => p.AddStep(_messagingStep)); }
/// <summary> /// Create a <see cref="Stream"/> to an entry in the claim store that piggies back a kernel transaction if one can /// be factored. /// </summary> /// <param name="url"> /// The claim store entry. /// </param> /// <param name="trackingModes"> /// </param> /// <param name="transactionFactory"> /// The <see cref="IKernelTransaction"/> factory. /// </param> /// <returns> /// The <see cref="Stream"/> to the claim store entry. /// </returns> private Stream CreateCapturingStream(string url, ActivityTrackingModes trackingModes, Func <IKernelTransaction> transactionFactory) { // RequiresCheckInAndOut entails payloads are first saved locally and moved by ClaimStore.Agent into claim // store where there will be a subfolder for each date that some payload has been saved/tracked to disk. To // ease the job of the ClaimStore.Agent the subfolder is not created locally (but the current date is however // kept in the name). When not RequiresCheckInAndOut, the payloads are tracked/saved to disk at the exact same // place that it will be redeemed from afterwards, that is in a subfolder corresponding to the current date (of // course, one needs to ensure the folders get created). string filePath; if (RequiresCheckInAndOut) { // .trk extension is used to denote simple message body's payload tracking scenarios, i.e. where the // message's payload is large enough that it would not fit in the BAM tracking database. Message body's // payload are therefore tracked to the local disk are then brought asynchronously to the central claim // store by the ClaimStore.Agent. // .chk extension is used to denote full-fledged claim check scenarios, i.e. where the actual message's // payload is claimed to disk (as with regular tracking) but also replaced by a token that needs to be // checked in and out. Message body's payload are claimed to the local disk and then brought asynchronously // to the central claim store by the ClaimStore.Agent. Because claims are brought asynchronously to the // central claim store, one has therefore to ensure a claim is available in the central claim store before // it could be redeemed. // The .chk and .trk extensions are there to allow the ClaimStore.Agent to distinguish these scenarios so // that it can, (1) bring claimed or tracked payloads to the central claim store and (2) make claims // available for redeem as soon as they have been brought to the central store. var extension = trackingModes.RequiresBodyClaimChecking() ? ".chk" : ".trk"; filePath = Path.Combine(CheckInDirectory, url.Replace("\\", "") + extension); } else { filePath = Path.Combine(CheckInDirectory, url); // ReSharper disable once AssignNullToNotNullAttribute Directory.CreateDirectory(Path.GetDirectoryName(filePath)); } return(FileTransacted.Create(filePath, 8192, transactionFactory.IfNotNull(ktf => ktf()))); }
public static bool RequiresBodyClaimChecking(this ActivityTrackingModes modes) { return((modes & ActivityTrackingModes.Claim) == ActivityTrackingModes.Claim); }
public static bool RequiresBodyTracking(this ActivityTrackingModes modes) { return((modes & ActivityTrackingModes.Body) == ActivityTrackingModes.Body); }
public static bool RequiresContextTracking(this ActivityTrackingModes modes) { return((modes & ActivityTrackingModes.Context) == ActivityTrackingModes.Context); }
public static bool RequiresStepTracking(this ActivityTrackingModes modes) { return((modes & ActivityTrackingModes.Step) == ActivityTrackingModes.Step); }
internal override void TrackActivity(ActivityTrackingModes trackingModes, TrackingStream trackingStream) { throw new NotSupportedException(); }