public async Task SingleBatch() { // expect a single batch of events to be posted to CloudWatch Logs var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); Assert.Single(putLogEventsCalls); var request = putLogEventsCalls.First().Request; Assert.Equal(options.LogGroupName, request.LogGroupName); Assert.Null(request.SequenceToken); Assert.Equal(10, request.LogEvents.Count); for (var i = 0; i < events.Length; i++) { Assert.Equal(events[i].MessageTemplate.Text, request.LogEvents.ElementAt(i).Message); } client.VerifyAll(); }
public async Task LargeMessage() { // expect an event with a length beyond the MaxLogEventSize will be truncated to the MaxLogEventSize var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var largeEventMessage = CreateMessage(CloudWatchLogSink.MaxLogEventSize + 1); var events = new LogEvent[] { new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(largeEventMessage), Enumerable.Empty <LogEventProperty>()) }; client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); Assert.Single(putLogEventsCalls); var request = putLogEventsCalls.First().Request; Assert.Equal(options.LogGroupName, request.LogGroupName); Assert.Null(request.SequenceToken); Assert.Single(request.LogEvents); Assert.Equal(largeEventMessage.Substring(0, CloudWatchLogSink.MaxLogEventSize), request.LogEvents.First().Message); client.VerifyAll(); }
public async Task DataAlreadyAccepted() { // expect update of sequence token and successful retry var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.DescribeLogStreamsAsync(It.IsAny <DescribeLogStreamsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogStreamsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextToken = Guid.NewGuid().ToString() }); List <CreateLogStreamRequest> createLogStreamRequests = new List <CreateLogStreamRequest>(); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .Callback <CreateLogStreamRequest, CancellationToken>((createLogStreamRequest, cancellationToken) => createLogStreamRequests.Add(createLogStreamRequest)) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.SetupSequence(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new DataAlreadyAcceptedException("data already accepted")) .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); client.Verify(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.DescribeLogStreamsAsync(It.Is <DescribeLogStreamsRequest>(req => req.LogGroupName == options.LogGroupName && req.LogStreamNamePrefix == createLogStreamRequests.First().LogStreamName), It.IsAny <CancellationToken>()), Times.Once); client.Verify(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>()), Times.Once); client.VerifyAll(); }
public async Task ServiceUnavailable() { // expect retries until exhausted var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ThrowsAsync(new ServiceUnavailableException("unavailable")); await sink.EmitBatchAsync(events); Assert.Equal(options.RetryAttempts + 1, putLogEventsCalls.Count); TimeSpan lastInterval = TimeSpan.Zero; for (var i = 1; i < putLogEventsCalls.Count; i++) { // ensure retry attempts are throttled properly var interval = putLogEventsCalls[i].DateTime.Subtract(putLogEventsCalls[i - 1].DateTime); Assert.True(interval.TotalMilliseconds >= (CloudWatchLogSink.ErrorBackoffStartingInterval.Milliseconds * Math.Pow(2, i - 1)), $"{interval.TotalMilliseconds} >= {CloudWatchLogSink.ErrorBackoffStartingInterval.Milliseconds * Math.Pow(2, i - 1)}"); lastInterval = interval; } client.VerifyAll(); }
public async Task ResourceNotFound() { // expect failure, creation of log group/stream, and evenutal success var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); List <CreateLogStreamRequest> createLogStreamRequests = new List <CreateLogStreamRequest>(); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .Callback <CreateLogStreamRequest, CancellationToken>((createLogStreamRequest, cancellationToken) => createLogStreamRequests.Add(createLogStreamRequest)) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.SetupSequence(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new ResourceNotFoundException("no resource")) .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); client.Verify(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.CreateLogGroupAsync(It.Is <CreateLogGroupRequest>(req => req.LogGroupName == options.LogGroupName), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); Assert.Equal(createLogStreamRequests.ElementAt(0).LogStreamName, createLogStreamRequests.ElementAt(1).LogStreamName); client.VerifyAll(); }
public async Task ResourceNotFound_CannotCreateResource() { // expect failure with failure to successfully create resources upon retries var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.SetupSequence(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }) .ThrowsAsync(new Exception("can't create a new log stream")); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new ResourceNotFoundException("no resource")); await sink.EmitBatchAsync(events); client.Verify(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(1)); client.Verify(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.CreateLogGroupAsync(It.Is <CreateLogGroupRequest>(req => req.LogGroupName == options.LogGroupName), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.VerifyAll(); }
public async Task InvalidParameter() { // expect batch dropped var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ThrowsAsync(new InvalidParameterException("invalid param")); await sink.EmitBatchAsync(events); Assert.Single(putLogEventsCalls); client.VerifyAll(); }
public async Task ServiceUnavailable_WithEventualSuccess() { // expect successful posting of batch after retry var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.SetupSequence(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new ServiceUnavailableException("unavailable")) .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); client.Verify(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.VerifyAll(); }
public async Task InvalidSequenceToken_CannotUpdateSequenceToken() { // expect update of sequence token and success on a new log stream var logStreamNameProvider = new Mock <ILogStreamNameProvider>(); logStreamNameProvider.SetupSequence(mock => mock.GetLogStreamName()) .Returns("a") .Returns("b"); var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions { LogStreamNameProvider = logStreamNameProvider.Object }; var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 10) .Select(_ => // create 10 events with message length of 12 new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.DescribeLogStreamsAsync(It.IsAny <DescribeLogStreamsRequest>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new Exception("no describe log stream")); List <CreateLogStreamRequest> createLogStreamRequests = new List <CreateLogStreamRequest>(); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .Callback <CreateLogStreamRequest, CancellationToken>((createLogStreamRequest, cancellationToken) => createLogStreamRequests.Add(createLogStreamRequest)) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.PutLogEventsAsync(It.Is <PutLogEventsRequest>(req => req.LogStreamName == "a"), It.IsAny <CancellationToken>())) .ThrowsAsync(new InvalidSequenceTokenException("invalid sequence")); client.Setup(mock => mock.PutLogEventsAsync(It.Is <PutLogEventsRequest>(req => req.LogStreamName == "b"), It.IsAny <CancellationToken>())) .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); client.Verify(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); client.Verify(mock => mock.DescribeLogStreamsAsync(It.Is <DescribeLogStreamsRequest>(req => req.LogGroupName == options.LogGroupName && req.LogStreamNamePrefix == createLogStreamRequests.First().LogStreamName), It.IsAny <CancellationToken>()), Times.Once); client.Verify(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(2)); Assert.Equal(2, createLogStreamRequests.Count); Assert.NotEqual(createLogStreamRequests.ElementAt(0).LogStreamName, createLogStreamRequests.ElementAt(1).LogStreamName); client.VerifyAll(); }
public async Task MoreThanMaxBatchSize() { // expect multiple batches, all having a batch size less than the maximum var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 256) // 256 4 KB messages matches our max batch size, but we want to test a "less nice" scenario, so we'll create 256 5 KB messages .Select(i => new LogEvent( DateTimeOffset.UtcNow, LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(1024 * 5)), // 5 KB messages Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); Assert.Equal(2, putLogEventsCalls.Count); for (var i = 0; i < putLogEventsCalls.Count; i++) { var call = putLogEventsCalls[i]; var request = call.Request; Assert.Equal(options.LogGroupName, request.LogGroupName); if (i == 0) // first call { Assert.Null(request.SequenceToken); Assert.Equal(203, request.LogEvents.Count); // expect 203 of the 256 messages in the first batch } else { Assert.NotNull(request.SequenceToken); Assert.Equal(53, request.LogEvents.Count); // expect 53 of the 256 messages in the second batch } } client.VerifyAll(); }
public async Task MultipleDays() { // expect a batch to be posted for each 24-hour period var client = new Mock <IAmazonCloudWatchLogs>(MockBehavior.Strict); var options = new CloudWatchSinkOptions(); var sink = new CloudWatchLogSink(client.Object, options); var events = Enumerable.Range(0, 20) .Select(i => // create multipe events with message length of 12 new LogEvent( DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays((i % 2) * 2)), // split the events into two days LogEventLevel.Information, null, new MessageTemplateParser().Parse(CreateMessage(12)), Enumerable.Empty <LogEventProperty>())) .ToArray(); client.Setup(mock => mock.DescribeLogGroupsAsync(It.IsAny <DescribeLogGroupsRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new DescribeLogGroupsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogGroupAsync(It.IsAny <CreateLogGroupRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogGroupResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); client.Setup(mock => mock.CreateLogStreamAsync(It.IsAny <CreateLogStreamRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync(new CreateLogStreamResponse { HttpStatusCode = System.Net.HttpStatusCode.OK }); var putLogEventsCalls = new List <RequestCall <PutLogEventsRequest> >(); client.Setup(mock => mock.PutLogEventsAsync(It.IsAny <PutLogEventsRequest>(), It.IsAny <CancellationToken>())) .Callback <PutLogEventsRequest, CancellationToken>((putLogEventsRequest, cancellationToken) => putLogEventsCalls.Add(new RequestCall <PutLogEventsRequest>(putLogEventsRequest))) // keep track of the requests made .ReturnsAsync(new PutLogEventsResponse { HttpStatusCode = System.Net.HttpStatusCode.OK, NextSequenceToken = Guid.NewGuid().ToString() }); await sink.EmitBatchAsync(events); Assert.Equal(2, putLogEventsCalls.Count); for (var i = 0; i < putLogEventsCalls.Count; i++) { var call = putLogEventsCalls[i]; var request = call.Request; Assert.Equal(options.LogGroupName, request.LogGroupName); Assert.Equal(events.Length / putLogEventsCalls.Count, request.LogEvents.Count); // make sure the events are ordered for (var index = 1; index < call.Request.LogEvents.Count; index++) { Assert.True(call.Request.LogEvents.ElementAt(index).Timestamp >= call.Request.LogEvents.ElementAt(index - 1).Timestamp); } if (i == 0) // first call { Assert.Null(request.SequenceToken); } else { Assert.NotNull(request.SequenceToken); } } client.VerifyAll(); }
/// <summary> /// Extension method to call protected EmitBatchAsync method. /// </summary> /// <param name="sink">The sink.</param> /// <param name="events">The events to be published.</param> /// <returns>The task to wait on.</returns> public static Task EmitBatchAsync(this CloudWatchLogSink sink, IEnumerable <LogEvent> events) { var emitMethod = sink.GetType().GetMethod("EmitBatchAsync", BindingFlags.NonPublic | BindingFlags.Instance); return(emitMethod.Invoke(sink, new object[] { events }) as Task); }