Ejemplo n.º 1
0
        public void SendANonEmptySpanBatch()
        {
            var traceId = "123";

            var span = new NewRelicSpan(
                traceId: null,
                spanId: "Span1",
                timestamp: DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                parentSpanId: null,
                attributes: new Dictionary <string, object>()
            {
                { NewRelicConsts.Tracing.AttribNameName, "TestSpan" },
            });

            var spanBatch = new NewRelicSpanBatch(
                spans: new[] { span },
                commonProperties: new NewRelicSpanBatchCommonProperties(traceId));

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            dataSender.WithHttpHandlerImpl((serializedJson) =>
            {
                var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                return(Task.FromResult(response));
            });

            var response = dataSender.SendDataAsync(spanBatch).Result;

            Assert.Equal(NewRelicResponseStatus.Success, response.ResponseStatus);
        }
Ejemplo n.º 2
0
        public WeatherForecastController()
        {
            // Obtain the API from the Web.Config file
            var apiKey = ConfigurationManager.AppSettings["NewRelic.Telemetry.ApiKey"];

            // Create a Logger Factory using settings in the Web.Config File
            var loggerConfig = new LoggerConfiguration()
                               .ReadFrom.AppSettings();

            var loggerFactory = new LoggerFactory()
                                .AddSerilog(loggerConfig.CreateLogger());

            _logger = loggerFactory.CreateLogger <WeatherForecastController>();

            // Create a new Telemetry Configuration Object with the API Key retrieved
            // from the Web.Config
            var telemetryConfig = new TelemetryConfiguration()
            {
                ApiKey = apiKey
            };

            // Instantiate the SpanDataSender which manages the communication with New
            // Relic endpoints
            _spanDataSender = new TraceDataSender(telemetryConfig, loggerFactory);
        }
Ejemplo n.º 3
0
        public async Task RetryBackoffSequence_RetriesExceeded()
        {
            var expectedNumSendBatchAsyncCall      = 9; // 1 first call + 8 calls from retries
            var expectedBackoffSequenceFromTestRun = new List <uint>()
            {
                5000,
                10000,
                20000,
                40000,
                80000,
                80000,
                80000,
                80000,
            };
            var actualBackoffSequenceFromTestRun = new List <uint>();
            var actualCountCallsSendData         = 0;

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            dataSender.WithDelayFunction(async(uint milliSecondsDelay) =>
            {
                actualBackoffSequenceFromTestRun.Add(milliSecondsDelay);
                await Task.Delay(0);
                return;
            });

            dataSender.WithCaptureSendDataAsyncDelegate((newRelicSpanBatch, retryNum) =>
            {
                actualCountCallsSendData++;
            });

            dataSender.WithHttpHandlerImpl((json) =>
            {
                return(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.RequestTimeout)));
            });

            var spans = new List <NewRelicSpan>()
            {
                new NewRelicSpan(
                    traceId: null,
                    spanId: "Test Span",
                    timestamp: 12345,
                    parentSpanId: null,
                    attributes: null),
            };

            var spanBatch = new NewRelicSpanBatch(spans);

            var result = await dataSender.SendDataAsync(spanBatch);

            Assert.Equal(NewRelicResponseStatus.Failure, result.ResponseStatus);
            Assert.Equal(HttpStatusCode.RequestTimeout, result.HttpStatusCode);
            Assert.Equal(expectedNumSendBatchAsyncCall, actualCountCallsSendData);
            Assert.Equal(expectedBackoffSequenceFromTestRun, actualBackoffSequenceFromTestRun);
        }
Ejemplo n.º 4
0
        internal NewRelicTraceExporter(TraceDataSender spanDataSender, NewRelicExporterOptions options, ITelemetryLogger logger)
        {
            _spanDataSender = spanDataSender;
            spanDataSender.AddVersionInfo(ProductInfo.Name, ProductInfo.Version);

            _config = options.TelemetryConfiguration;

            _logger = logger;
        }
Ejemplo n.º 5
0
        public async Task SendDataAsyncThrowsNonHttpException()
        {
            const int expectedNumSendBatchAsyncCall = 1;
            const int expectedNumHttpHandlerCall    = 0;

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            dataSender.WithDelayFunction(async(uint 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 spans = new List <NewRelicSpan>()
            {
                new NewRelicSpan(
                    traceId: null,
                    spanId: "Test Span",
                    timestamp: 12345,
                    parentSpanId: null,
                    attributes: null),
            };

            var spanBatch = new NewRelicSpanBatch(spans);

            var result = await dataSender.SendDataAsync(spanBatch);

            Assert.Equal(NewRelicResponseStatus.Failure, result.ResponseStatus);
            Assert.Equal("Test Exception", result.Message);
            Assert.Null(result.HttpStatusCode);

            Assert.Equal(expectedNumSendBatchAsyncCall, actualCountCallsSendData);
            Assert.Equal(expectedNumHttpHandlerCall, actualCallsHttpHandler);
        }
        /// <summary>
        /// At startup, read configuration settings and instantiate the data service
        /// which will communicate with the New Relic endpoint.
        /// </summary>
        private static void Configuration()
        {
            // obtain application settings from appsettings.json file
            // Most importantly, the config file will contain the New Relic API Key
            var config = new ConfigurationBuilder()
                         .SetBasePath(Directory.GetCurrentDirectory())
                         .AddJsonFile("appsettings.json")
                         .Build();

            var telemetryConfiguration = new TelemetryConfiguration(config);

            Console.WriteLine($"{telemetryConfiguration.TraceUrl}");

            // The SpanDataSender handles all communication with the New Relic end point
            _dataSvc = new TraceDataSender(telemetryConfiguration, null);
        }
Ejemplo n.º 7
0
        public async 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(1000).TotalMilliseconds;
            var actualResponseFromTestRun = new List <Response>();

            uint actualDelayFromTestRun = 0;

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456", MaxRetryAttempts = 1
            }, null);

            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 spans = new List <NewRelicSpan>()
            {
                new NewRelicSpan(
                    traceId: null,
                    spanId: "Test Span",
                    timestamp: 12345,
                    parentSpanId: null,
                    attributes: null),
            };

            var spanBatch = new NewRelicSpanBatch(spans);

            var result = await dataSender.SendDataAsync(spanBatch);

            Assert.True(actualDelayFromTestRun >= delayMs - errorMargin && actualDelayFromTestRun <= delayMs + errorMargin, $"Expected delay: {delayMs}, margin: +/-{errorMargin}, actual delay: {actualDelayFromTestRun}");
        }
Ejemplo n.º 8
0
        public void AddVersionInfo(string productName, string productVersion)
        {
            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            var expectedUserAgentValue = dataSender.UserAgent;

            if (!string.IsNullOrEmpty(productName) && !string.IsNullOrEmpty(productVersion))
            {
                expectedUserAgentValue += " " + $@"{productName}/{productVersion}";
            }

            dataSender.AddVersionInfo(productName, productVersion);

            var userAgentValueAfter = dataSender.UserAgent;

            Assert.Equal(expectedUserAgentValue, userAgentValueAfter);
        }
Ejemplo n.º 9
0
        public void SendAnEmptySpanBatch()
        {
            var traceId   = "123";
            var spanBatch = new NewRelicSpanBatch(
                spans: new NewRelicSpan[0],
                commonProperties: new NewRelicSpanBatchCommonProperties(traceId));

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            dataSender.WithHttpHandlerImpl((serializedJson) =>
            {
                var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
                return(Task.FromResult(response));
            });

            var response = dataSender.SendDataAsync(spanBatch).Result;

            Assert.Equal(NewRelicResponseStatus.DidNotSend_NoData, response.ResponseStatus);
        }
Ejemplo n.º 10
0
 /// <summary>
 /// Use dependency injection in the constructor to pass in the Logger Factory and
 /// the Configuration Provider.
 /// </summary>
 public WeatherForecastController(ILoggerFactory loggerFactory, TraceDataSender spanDataSender)
 {
     _spanDataSender = spanDataSender;
     _logger         = loggerFactory.CreateLogger <WeatherForecastController>();
 }
Ejemplo n.º 11
0
        public async Task RetryOn429WithDuration_429HappensOnce()
        {
            const int delayMS = 10000;
            const int expectedNumSendBatchAsyncCall      = 2;
            var       expectedBackoffSequenceFromTestRun = new List <uint>()
            {
                delayMS,
            };

            var actualBackoffSequenceFromTestRun = new List <uint>();

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            dataSender.WithDelayFunction(async(uint milliSecondsDelay) =>
            {
                actualBackoffSequenceFromTestRun.Add(milliSecondsDelay);
                await Task.Delay(0);
                return;
            });

            var actualCountCallsSendData = 0;

            dataSender.WithCaptureSendDataAsyncDelegate((newRelicSpanBatch, retryNum) =>
            {
                actualCountCallsSendData++;
            });

            dataSender.WithHttpHandlerImpl((json) =>
            {
                if (actualCountCallsSendData < 2)
                {
                    var httpResponse = new HttpResponseMessage((HttpStatusCode)429);
                    httpResponse.Headers.RetryAfter = new System.Net.Http.Headers.RetryConditionHeaderValue(TimeSpan.FromMilliseconds(delayMS));

                    return(Task.FromResult(httpResponse));
                }

                return(Task.FromResult(new HttpResponseMessage(System.Net.HttpStatusCode.OK)));
            });

            var spans = new List <NewRelicSpan>()
            {
                new NewRelicSpan(
                    traceId: null,
                    spanId: "Test Span",
                    timestamp: 12345,
                    parentSpanId: null,
                    attributes: null),
            };

            var spanBatch = new NewRelicSpanBatch(spans);

            var result = await dataSender.SendDataAsync(spanBatch);

            Assert.Equal(NewRelicResponseStatus.Success, result.ResponseStatus);
            Assert.Equal(expectedNumSendBatchAsyncCall, actualCountCallsSendData);
            Assert.Equal(expectedBackoffSequenceFromTestRun, actualBackoffSequenceFromTestRun);
        }
Ejemplo n.º 12
0
        public async Task RequestTooLarge_SplitSuccess()
        {
            const int    expectedCountSpans                 = 9;
            const int    expectedCountCallsSendData         = 7;
            const int    expectedCountSuccessfulSpanBatches = 4;
            const string expectedTraceID = "TestTrace";

            var actualCountCallsSendData = 0;

            // Arrange
            var successfulSpanBatches = new List <NewRelicSpanBatch>();

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            var okJsons = new List <string>();

            // Mock the behavior to return EntityTooLarge for any span batch with 4 or more spans.
            // Anything with less than 4 will return success.
            dataSender.WithCaptureSendDataAsyncDelegate((spanBatch, retryNum) =>
            {
                actualCountCallsSendData++;

                if (spanBatch.Spans.Count() < 4)
                {
                    okJsons.Add(spanBatch.ToJson());
                    successfulSpanBatches.Add(spanBatch);
                }
            });

            dataSender.WithHttpHandlerImpl((json) =>
            {
                var response = okJsons.Contains(json)
                    ? new HttpResponseMessage(System.Net.HttpStatusCode.OK)
                    : new HttpResponseMessage(System.Net.HttpStatusCode.RequestEntityTooLarge);

                return(Task.FromResult(response));
            });

            var attribs = new Dictionary <string, object>()
            {
                { "testAttrib1", "testAttribValue1" },
            };

            var spans = new List <NewRelicSpan>();

            for (var i = 0; i < expectedCountSpans; i++)
            {
                spans.Add(new NewRelicSpan(null, i.ToString(), i, null, null));
            }

            var spanBatch = new NewRelicSpanBatch(spans, new NewRelicSpanBatchCommonProperties(expectedTraceID, attribs));

            // Act
            await dataSender.SendDataAsync(spanBatch);

            // Assert
            Assert.Equal(expectedCountCallsSendData, actualCountCallsSendData);

            // Test the Spans
            Assert.Equal(expectedCountSuccessfulSpanBatches, successfulSpanBatches.Count);
            Assert.Equal(expectedCountSpans, successfulSpanBatches.SelectMany(x => x.Spans).Count());
            Assert.Equal(expectedCountSpans, successfulSpanBatches.SelectMany(x => x.Spans).Select(x => x.Id).Distinct().Count());

            // Test the attributes on the NewRelicSpanBatch
            Assert.Single(successfulSpanBatches.Select(x => x.CommonProperties.TraceId).Distinct());
            Assert.Equal(expectedTraceID, successfulSpanBatches.FirstOrDefault().CommonProperties.TraceId);
            Assert.Single(successfulSpanBatches.Select(x => x.CommonProperties.Attributes).Distinct());
            Assert.Equal(attribs, successfulSpanBatches.Select(x => x.CommonProperties.Attributes).FirstOrDefault());
        }
Ejemplo n.º 13
0
        public async Task RequestTooLarge_SplitFail()
        {
            const int    expectedCountCallsSendData = 7;
            const string traceID_Success            = "OK";
            const string traceID_SplitBatch_Prefix  = "TooLarge";

            var actualCountCallsSendData = 0;
            var successfulSpans          = new List <NewRelicSpan>();

            var dataSender = new TraceDataSender(new TelemetryConfiguration()
            {
                ApiKey = "123456"
            }, null);

            var shouldSplitJsons = new List <string>();

            // Mock the behavior to return EntityTooLarge for any span batch that has a span with an
            // id that starts with TooLarge.
            dataSender.WithCaptureSendDataAsyncDelegate((newRelicSpanBatch, retryNum) =>
            {
                actualCountCallsSendData++;

                if (newRelicSpanBatch.Spans == null)
                {
                    return;
                }

                if (newRelicSpanBatch.Spans.Any(x => x.Id.StartsWith(traceID_SplitBatch_Prefix)))
                {
                    shouldSplitJsons.Add(newRelicSpanBatch.ToJson());
                }
                else
                {
                    successfulSpans.AddRange(newRelicSpanBatch.Spans);
                }
            });

            dataSender.WithHttpHandlerImpl((json) =>
            {
                var response = shouldSplitJsons.Contains(json)
                    ? new HttpResponseMessage(System.Net.HttpStatusCode.RequestEntityTooLarge)
                    : new HttpResponseMessage(System.Net.HttpStatusCode.OK);

                return(Task.FromResult(response));
            });

            var spans = new List <NewRelicSpan>();

            spans.Add(new NewRelicSpan(null, $"{traceID_SplitBatch_Prefix}1", 0, null, null));
            spans.Add(new NewRelicSpan(null, $"{traceID_SplitBatch_Prefix}2", 0, null, null));
            spans.Add(new NewRelicSpan(null, $"{traceID_SplitBatch_Prefix}3", 0, null, null));
            spans.Add(new NewRelicSpan(null, traceID_Success, 0, null, null));

            // Act
            var result = await dataSender.SendDataAsync(spans);

            // Assert
            Assert.Equal(NewRelicResponseStatus.Failure, result.ResponseStatus);
            Assert.Equal(expectedCountCallsSendData, actualCountCallsSendData);
            Assert.Single(successfulSpans);
            Assert.Equal(traceID_Success, successfulSpans[0].Id);
        }