async public Task SendDataAsyncThrowsHttpException() { const int expectedNumSendBatchAsyncCall = 1; var dataSender = new SpanDataSender(new TelemetryConfiguration().WithApiKey("123456")); dataSender.WithDelayFunction(async(uint milliSecondsDelay) => { await Task.Delay(0); return; }); var actualCountCallsSendData = 0; dataSender.WithCaptureSendDataAsyncDelegate((spanBatch, retryNum) => { actualCountCallsSendData++; }); dataSender.WithHttpHandlerImpl((json) => { throw new Exception("Server Error", new Exception("Inner exception message")); }); var spanBatch = SpanBatchBuilder.Create() .WithSpan(SpanBuilder.Create("Test Span").Build()) .Build(); var result = await dataSender.SendDataAsync(spanBatch); Assert.AreEqual(NewRelicResponseStatus.Failure, result.ResponseStatus); Assert.AreEqual("Inner exception message", result.Message); Assert.IsNull(result.HttpStatusCode); Assert.AreEqual(expectedNumSendBatchAsyncCall, actualCountCallsSendData, "Unexpected Number of SendDataAsync calls"); }
async public Task RetryOn429WithSpecificDate_429HappensOnce() { const int delayMs = 10000; // The actual retry delay will be slightly less than delayMs since UtcNow is recalculated in RetryWithServerDelay() var errorMargin = TimeSpan.FromMilliseconds(50).TotalMilliseconds; var actualResponseFromTestRun = new List <Response>(); uint actualDelayFromTestRun = 0; var dataSender = new SpanDataSender(new TelemetryConfiguration().WithApiKey("123456").WithMaxRetryAttempts(1)); dataSender.WithDelayFunction(async(uint milliSecondsDelay) => { actualDelayFromTestRun = milliSecondsDelay; await Task.Delay(0); return; }); dataSender.WithHttpHandlerImpl((json) => { var httpResponse = new HttpResponseMessage((HttpStatusCode)429); var retryOnSpecificTime = DateTimeOffset.UtcNow + TimeSpan.FromMilliseconds(delayMs); httpResponse.Headers.RetryAfter = new System.Net.Http.Headers.RetryConditionHeaderValue(retryOnSpecificTime); return(Task.FromResult(httpResponse)); }); var spanBatch = SpanBatchBuilder.Create() .WithSpan(SpanBuilder.Create("Test Span").Build()) .Build(); var response = await dataSender.SendDataAsync(spanBatch); Assert.IsTrue(actualDelayFromTestRun >= delayMs - errorMargin && actualDelayFromTestRun <= delayMs + errorMargin, $"Expected delay: {delayMs}, margin: +/-{errorMargin}, actual delay: {actualDelayFromTestRun}"); }
async public Task RetryOn429_RetriesExceeded() { const int delayMS = 10000; const int expectedNumSendBatchAsyncCall = 9; // 1 first call + 3 calls from retries var expectedBackoffSequenceFromTestRun = new List <int>() { delayMS, delayMS, delayMS, delayMS, delayMS, delayMS, delayMS, delayMS }; var actualBackoffSequenceFromTestRun = new List <uint>(); var dataSender = new SpanDataSender(new TelemetryConfiguration().WithApiKey("123456")); dataSender.WithDelayFunction(async(uint milliSecondsDelay) => { actualBackoffSequenceFromTestRun.Add(milliSecondsDelay); await Task.Delay(0); return; }); var actualCountCallsSendData = 0; dataSender.WithCaptureSendDataAsyncDelegate((spanBatch, retryNum) => { actualCountCallsSendData++; }); dataSender.WithHttpHandlerImpl((json) => { var httpResponse = new HttpResponseMessage((HttpStatusCode)429); httpResponse.Headers.RetryAfter = new System.Net.Http.Headers.RetryConditionHeaderValue(TimeSpan.FromMilliseconds(delayMS)); return(Task.FromResult(httpResponse)); }); var spanBatch = SpanBatchBuilder.Create() .WithSpan(SpanBuilder.Create("Test Span").Build()) .Build(); var result = await dataSender.SendDataAsync(spanBatch); Assert.AreEqual(NewRelicResponseStatus.Failure, result.ResponseStatus); Assert.AreEqual(expectedNumSendBatchAsyncCall, actualCountCallsSendData, "Unexpected Number of SendDataAsync calls"); CollectionAssert.AreEqual(expectedBackoffSequenceFromTestRun, actualBackoffSequenceFromTestRun); }
async public Task RetryBackoffSequence_IntermittentTimeoutEventuallySucceeds() { var expectedNumSendBatchAsyncCall = 4; // 1 first call + 3 calls from retries var expectedBackoffSequenceFromTestRun = new List <int>() { 5000, 10000, 20000, }; var actualBackoffSequenceFromTestRun = new List <uint>(); var dataSender = new SpanDataSender(new TelemetryConfiguration().WithApiKey("123456")); dataSender.WithDelayFunction(async(uint milliSecondsDelay) => { actualBackoffSequenceFromTestRun.Add(milliSecondsDelay); await Task.Delay(0); return; }); var actualCountCallsSendData = 0; dataSender.WithCaptureSendDataAsyncDelegate((spanBatch, retryNum) => { actualCountCallsSendData++; }); var callCount = 0; dataSender.WithHttpHandlerImpl((json) => { callCount++; if (callCount < 4) { return(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.RequestTimeout))); } return(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK))); }); var spanBatch = SpanBatchBuilder.Create() .WithSpan(SpanBuilder.Create("Test Span").Build()) .Build(); var result = await dataSender.SendDataAsync(spanBatch); Assert.AreEqual(NewRelicResponseStatus.Success, result.ResponseStatus); Assert.AreEqual(expectedNumSendBatchAsyncCall, actualCountCallsSendData, "Unexpected Number of SendDataAsync calls"); CollectionAssert.AreEqual(expectedBackoffSequenceFromTestRun, actualBackoffSequenceFromTestRun); }
async public Task SendDataAsyncThrowsNonHttpException() { const int expectedNumSendBatchAsyncCall = 1; const int expectedNumHttpHandlerCall = 0; var dataSender = new SpanDataSender(new TelemetryConfiguration().WithAPIKey("123456")); dataSender.WithDelayFunction(async(int milliSecondsDelay) => { await Task.Delay(0); return; }); var actualCountCallsSendData = 0; dataSender.WithCaptureSendDataAsyncDelegate((sb, retry) => { actualCountCallsSendData++; throw new Exception("Test Exception"); }); var actualCallsHttpHandler = 0; dataSender.WithHttpHandlerImpl((json) => { actualCallsHttpHandler++; return(Task.FromResult(new HttpResponseMessage() { StatusCode = HttpStatusCode.OK })); }); var spanBatch = SpanBatchBuilder.Create() .WithSpan(SpanBuilder.Create("Test Span").Build()) .Build(); var result = await dataSender.SendDataAsync(spanBatch); Assert.AreEqual(NewRelicResponseStatus.Failure, result.ResponseStatus); Assert.AreEqual("Test Exception", result.Message); Assert.IsNull(result.HttpStatusCode); Assert.AreEqual(expectedNumSendBatchAsyncCall, actualCountCallsSendData, "Unexpected Number of SendDataAsync calls"); Assert.AreEqual(expectedNumHttpHandlerCall, actualCallsHttpHandler, "Unexpected Number of Http Handler calls"); }
public void DateSpecificRetry_CorrectDelayDuration() { var traceId = "123"; var retryDuration = TimeSpan.FromSeconds(10); var retryDurationMs = retryDuration.TotalMilliseconds; var errorMargin = TimeSpan.FromMilliseconds(50).TotalMilliseconds; var spanBatch = SpanBatchBuilder.Create() .WithTraceId(traceId) .WithSpan(SpanBuilder.Create("TestSpan").Build()) .Build(); var config = new TelemetryConfiguration().WithAPIKey("12345"); var dataSender = new SpanDataSender(config); //Mock out the communication layer dataSender.WithHttpHandlerImpl((serializedJson) => { var response = new HttpResponseMessage((System.Net.HttpStatusCode) 429); var retryOnSpecificTime = DateTimeOffset.Now + retryDuration; response.Headers.RetryAfter = new System.Net.Http.Headers.RetryConditionHeaderValue(retryOnSpecificTime); return(Task.FromResult(response)); }); var capturedDelays = new List <int>(); dataSender.WithDelayFunction((delay) => { capturedDelays.Add(delay); return(Task.Delay(0)); }); var response = dataSender.SendDataAsync(spanBatch).Result; Assert.AreEqual(NewRelicResponseStatus.Failure, response.ResponseStatus); Assert.AreEqual(config.MaxRetryAttempts, capturedDelays.Count); Assert.AreEqual(System.Net.HttpStatusCode.RequestTimeout, response.HttpStatusCode); Assert.IsTrue(capturedDelays.All(x => x >= retryDurationMs - errorMargin && x <= retryDurationMs + errorMargin), "Expected duration out of range"); }