diff --git a/src/Http.Tests/RequestActivityEventSourceTests.cs b/src/Http.Tests/RequestActivityEventSourceTests.cs index 7326045..3cbb08a 100644 --- a/src/Http.Tests/RequestActivityEventSourceTests.cs +++ b/src/Http.Tests/RequestActivityEventSourceTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Diagnostics.Tracing; using System.Linq; using Thor.Analyzer; @@ -242,6 +243,34 @@ public void Stop_HttpResponse_Null() #endregion + #region Outer Activity Warning + + [Fact(DisplayName = "OuterActivityNotAllowed: Should log a outer activity is not allowed")] + public void OuterActivityNotAllowed() + { + RequestActivityEventSource.Log.Listen((listener) => + { + // arrange + const string expectedMessage = "Outer activities are not allowed when creating a server-side message activity."; + Guid activityId = Guid.NewGuid(); + + // act + RequestActivityEventSource.Log.OuterActivityNotAllowed(activityId); + + // assert + TelemetryEvent firstItem = listener + .OrderedEvents + .Select(e => e.Map("7778")) + .FirstOrDefault(e => e.Message == expectedMessage); + + Assert.NotNull(firstItem); + Assert.Equal(EventLevel.Warning, firstItem.Level); + AssertItem(firstItem, 0, activityId, expectedMessage); + }); + } + + #endregion + #region Begin/End Transfer Events [Fact(DisplayName = "BeginTransfer: Should log a begin transfer")] @@ -296,6 +325,44 @@ public void EndTransfer() #endregion + #region Internal Server Error + + [Fact(DisplayName = "InternalServerErrorOccurred: Should log a internal server error exception")] + public void InternalServerErrorOccurred() + { + RequestActivityEventSource.Log.Listen((listener) => + { + // arrange + ConcurrentQueue attachments = new ConcurrentQueue(); + const string expectedMessage = "Internal server error occurred."; + Exception exception = new Exception(); + AttachmentDispatcher.Instance.Attach(d => attachments.Enqueue(d)); + + // act + RequestActivityEventSource.Log.InternalServerErrorOccurred(exception); + + // assert + AttachmentDispatcher.Instance.Detach(d => attachments.Enqueue(d)); + TelemetryEvent firstItem = listener + .OrderedEvents + .Select(e => e.Map("7779")) + .FirstOrDefault(e => e.Message == expectedMessage); + + Assert.NotNull(firstItem); + Assert.Equal(EventLevel.Error, firstItem.Level); + AssertItem(firstItem, 0, Guid.Empty, expectedMessage); + Assert.Collection(attachments, + d => + { + Assert.Matches("^\\d{8}\\-[a-f\\d]{32}$", d.Id); + Assert.Equal("exception", d.Name); + Assert.Equal(nameof(Exception), d.TypeName); + }); + }); + } + + #endregion + private static void AssertItem(TelemetryEvent item, int expectedCount, Guid expectedActivityId, Guid? expectedUserId, string expectedMessage) { diff --git a/src/Http/RequestActivityEventSource.cs b/src/Http/RequestActivityEventSource.cs index 25fb9e4..dc164cb 100644 --- a/src/Http/RequestActivityEventSource.cs +++ b/src/Http/RequestActivityEventSource.cs @@ -15,6 +15,7 @@ internal sealed class RequestActivityEventSource private const int _beginTransferEventId = 5; private const int _endTransferEventId = 6; private const int _outerActivityWarningEventId = 7; + private const int _internalServerErrorEventId = 8; public static RequestActivityEventSource Log { get; } = new RequestActivityEventSource(); @@ -143,7 +144,8 @@ private void Stop(int applicationId, Guid activityId, Guid userId, int statusCod #region Outer Activity Warning /// - /// A warning regarding outer activities which were not allowed when opening a new server-side message activity. + /// A warning regarding outer activities which are not allowed when opening a new + /// server-side message activity. /// [NonEvent] public void OuterActivityNotAllowed(Guid activityId) @@ -201,6 +203,58 @@ private void EndTransfer(Guid relatedActivityId, int applicationId, Guid activit #endregion + #region Internal Server Error + + /// + /// A internal server error occurred during request/response processing. + /// + [NonEvent] + public void InternalServerErrorOccurred(Exception exception) + { + if (IsEnabled()) + { + AttachmentId attachmentId = AttachmentId.NewId(); + ExceptionAttachment attachment = AttachmentFactory.Create(attachmentId, + nameof(exception), exception); + + AttachmentDispatcher.Instance.Dispatch(attachment); + InternalServerErrorOccurred(Application.Id, ActivityStack.Id, attachmentId); + } + } + + [Event(_internalServerErrorEventId, Level = EventLevel.Error, + Message = "Internal server error occurred.", Version = 1)] + private void InternalServerErrorOccurred(int applicationId, Guid activityId, + string attachmentId) + { + InternalServerErrorOccurredCore(_internalServerErrorEventId, applicationId, activityId, + attachmentId); + } + + [NonEvent] + private unsafe void InternalServerErrorOccurredCore(int eventId, int applicationId, + Guid activityId, string attachmentId) + { + StringExtensions.SetToEmptyIfNull(ref attachmentId); + + fixed (char* attachmentIdBytes = attachmentId) + { + const short dataCount = 3; + EventData* data = stackalloc EventData[dataCount]; + + data[0].DataPointer = (IntPtr)(&applicationId); + data[0].Size = 4; + data[1].DataPointer = (IntPtr)(&activityId); + data[1].Size = 16; + data[2].DataPointer = (IntPtr)attachmentIdBytes; + data[2].Size = ((attachmentId.Length + 1) * 2); + + WriteEventCore(eventId, dataCount, data); + } + } + + #endregion + #region Tasks and Opcodes public static class Tasks