public async Task Can_write_payload_successfully()
        {
            // Arrange
            var httpMessageHandlerMock = new Mock <HttpMessageHandler>();

            httpMessageHandlerMock.Protected().Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()).Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));

            var settings = new MetricsReportingDatadogOptions
            {
                Datadog = new DatadogOptions
                {
                    BaseUri = new Uri("http://localhost"),
                    ApiKey  = "123"
                },
                HttpPolicy = new HttpPolicy()
            };

            var hostedMetricsClient = DatadogReporterBuilder.CreateClient(settings, settings.HttpPolicy, httpMessageHandlerMock.Object);

            // Act
            var response = await hostedMetricsClient.WriteAsync(Payload, CancellationToken.None);

            // Assert
            response.Success.Should().BeTrue();
        }
        /// <summary>
        ///     Add the <see cref="DatadogReporter" /> allowing metrics to be reported to Datadog.
        /// </summary>
        /// <param name="metricReporterProviderBuilder">
        ///     The <see cref="IMetricsReportingBuilder" /> used to configure metrics reporters.
        /// </param>
        /// <param name="url">The base url where metrics are written.</param>
        /// <param name="apiKey">The api key used for authentication</param>
        /// <param name="fieldsSetup">The metric fields to report as well as their names.</param>
        /// <param name="datadogOptionsSetup">The setup action to configure the <see cref="MetricsDatadogOptions"/> to use.</param>
        /// <returns>
        ///     An <see cref="IMetricsBuilder" /> that can be used to further configure App Metrics.
        /// </returns>
        public static IMetricsBuilder ToDatadogHttp(
            this IMetricsReportingBuilder metricReporterProviderBuilder,
            string url,
            string apiKey,
            Action <MetricFields> fieldsSetup = null,
            Action <MetricsDatadogOptions> datadogOptionsSetup = null)
        {
            if (metricReporterProviderBuilder == null)
            {
                throw new ArgumentNullException(nameof(metricReporterProviderBuilder));
            }

            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
            {
                throw new InvalidOperationException($"{nameof(url)} must be a valid absolute URI");
            }

            var datadogOptions = new MetricsDatadogOptions();

            var options = new MetricsReportingDatadogOptions
            {
                Datadog =
                {
                    BaseUri = uri,
                    ApiKey  = apiKey
                }
            };

            datadogOptionsSetup?.Invoke(datadogOptions);

            IMetricsOutputFormatter formatter;
            MetricFields            fields = null;

            if (fieldsSetup == null)
            {
                formatter = new MetricsDatadogJsonOutputFormatter(options.FlushInterval, datadogOptions);
            }
            else
            {
                fields = new MetricFields();
                fieldsSetup.Invoke(fields);
                formatter = new MetricsDatadogJsonOutputFormatter(options.FlushInterval, datadogOptions, fields);
            }

            options.MetricsOutputFormatter = formatter;

            var httpClient = CreateClient(options, options.HttpPolicy);
            var reporter   = new DatadogReporter(options, httpClient);

            var builder = metricReporterProviderBuilder.Using(reporter);

            builder.OutputMetrics.AsDatadogJson(datadogOptions, options.FlushInterval, fields);

            return(builder);
        }
        public async Task Should_back_off_when_reached_max_failures_then_retry_after_backoff_period()
        {
            var httpMessageHandlerMock = new Mock <HttpMessageHandler>();

            httpMessageHandlerMock.Protected().Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()).
            Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));
            var policy = new HttpPolicy {
                FailuresBeforeBackoff = 3, BackoffPeriod = TimeSpan.FromSeconds(1)
            };
            var settings = new MetricsReportingDatadogOptions
            {
                Datadog = new DatadogOptions
                {
                    BaseUri = new Uri("http://localhost"),
                    ApiKey  = "123"
                },
                HttpPolicy = new HttpPolicy()
            };
            var hostedMetricsClient = DatadogReporterBuilder.CreateClient(settings, policy, httpMessageHandlerMock.Object);

            foreach (var attempt in Enumerable.Range(0, 10))
            {
                await hostedMetricsClient.WriteAsync(Payload, CancellationToken.None);

                if (attempt <= policy.FailuresBeforeBackoff)
                {
                    httpMessageHandlerMock.Protected().Verify <Task <HttpResponseMessage> >(
                        "SendAsync",
                        Times.AtLeastOnce(),
                        ItExpr.IsAny <HttpRequestMessage>(),
                        ItExpr.IsAny <CancellationToken>());
                }
                else
                {
                    httpMessageHandlerMock.Protected().Verify <Task <HttpResponseMessage> >(
                        "SendAsync",
                        Times.AtMost(3),
                        ItExpr.IsAny <HttpRequestMessage>(),
                        ItExpr.IsAny <CancellationToken>());
                }
            }

            await Task.Delay(policy.BackoffPeriod);

            httpMessageHandlerMock = new Mock <HttpMessageHandler>();
            httpMessageHandlerMock.Protected().Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()).Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));

            hostedMetricsClient = DatadogReporterBuilder.CreateClient(settings, policy, httpMessageHandlerMock.Object);

            var response = await hostedMetricsClient.WriteAsync(Payload, CancellationToken.None);

            response.Success.Should().BeTrue();
        }
        public async Task Should_back_off_when_reached_max_failures()
        {
            // Arrange
            var httpMessageHandlerMock = new Mock <HttpMessageHandler>();

            httpMessageHandlerMock.Protected().Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()).
            Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));
            var policy = new HttpPolicy {
                FailuresBeforeBackoff = 3, BackoffPeriod = TimeSpan.FromMinutes(1)
            };
            var settings = new MetricsReportingDatadogOptions
            {
                Datadog = new DatadogOptions
                {
                    BaseUri = new Uri("http://localhost"),
                    ApiKey  = "123"
                },
                HttpPolicy = policy
            };
            var hostedMetricsClient = DatadogReporterBuilder.CreateClient(settings, policy, httpMessageHandlerMock.Object);

            // Act
            foreach (var attempt in Enumerable.Range(0, 10))
            {
                await hostedMetricsClient.WriteAsync(Payload, CancellationToken.None);

                // ReSharper disable ConvertIfStatementToConditionalTernaryExpression
                if (attempt <= policy.FailuresBeforeBackoff)
                {
                    // ReSharper restore ConvertIfStatementToConditionalTernaryExpression
                    // Assert
                    httpMessageHandlerMock.Protected().Verify <Task <HttpResponseMessage> >(
                        "SendAsync",
                        Times.AtLeastOnce(),
                        ItExpr.IsAny <HttpRequestMessage>(),
                        ItExpr.IsAny <CancellationToken>());
                }
                else
                {
                    // Assert
                    httpMessageHandlerMock.Protected().Verify <Task <HttpResponseMessage> >(
                        "SendAsync",
                        Times.AtMost(6), // TODO: Starting failing when running all tests with 2.0.0 upgrade, should be 3
                        ItExpr.IsAny <HttpRequestMessage>(),
                        ItExpr.IsAny <CancellationToken>());
                }
            }
        }
        /// <summary>
        ///     Add the <see cref="DatadogReporter" /> allowing metrics to be reported to Datadog.
        /// </summary>
        /// <param name="metricsReportingBuilder">
        ///     The <see cref="IMetricsReportingBuilder" /> used to configure metrics reporters.
        /// </param>
        /// <param name="options">The Datadog reporting options to use.</param>
        /// <returns>
        ///     An <see cref="IMetricsBuilder" /> that can be used to further configure App Metrics.
        /// </returns>
        public static IMetricsBuilder ToDatadogHttp(
            this IMetricsReportingBuilder metricsReportingBuilder,
            MetricsReportingDatadogOptions options)
        {
            if (metricsReportingBuilder == null)
            {
                throw new ArgumentNullException(nameof(metricsReportingBuilder));
            }

            var httpClient = CreateClient(options, options.HttpPolicy);
            var reporter   = new DatadogReporter(options, httpClient);

            return(metricsReportingBuilder.Using(reporter));
        }
        public static IDatadogClient CreateClient(
            MetricsReportingDatadogOptions options,
            HttpPolicy httpPolicy,
            HttpMessageHandler httpMessageHandler = null)
        {
            var httpClient = httpMessageHandler == null
                ? new HttpClient()
                : new HttpClient(httpMessageHandler);

            httpClient.BaseAddress = options.Datadog.BaseUri;
            httpClient.Timeout     = httpPolicy.Timeout;

            return(new DefaultDatadogHttpClient(
                       httpClient,
                       options.Datadog,
                       httpPolicy));
        }
        /// <summary>
        ///     Add the <see cref="DatadogReporter" /> allowing metrics to be reported to Datadog.
        /// </summary>
        /// <param name="metricReporterProviderBuilder">
        ///     The <see cref="IMetricsReportingBuilder" /> used to configure metrics reporters.
        /// </param>
        /// <param name="setupAction">The Datadog reporting options to use.</param>
        /// <returns>
        ///     An <see cref="IMetricsBuilder" /> that can be used to further configure App Metrics.
        /// </returns>
        public static IMetricsBuilder ToDatadogHttp(
            this IMetricsReportingBuilder metricReporterProviderBuilder,
            Action <MetricsReportingDatadogOptions> setupAction)
        {
            if (metricReporterProviderBuilder == null)
            {
                throw new ArgumentNullException(nameof(metricReporterProviderBuilder));
            }

            var options = new MetricsReportingDatadogOptions();

            setupAction?.Invoke(options);

            var httpClient = CreateClient(options, options.HttpPolicy);
            var reporter   = new DatadogReporter(options, httpClient);

            return(metricReporterProviderBuilder.Using(reporter));
        }
        public void Http_policy_is_required()
        {
            // Arrange
            Action action = () =>
            {
                var settings = new MetricsReportingDatadogOptions
                {
                    Datadog = new DatadogOptions
                    {
                        BaseUri = new Uri("http://localhost"),
                        ApiKey  = "123"
                    },
                    HttpPolicy = new HttpPolicy()
                };

                // Act
                var unused = new DefaultDatadogHttpClient(new HttpClient(), settings.Datadog, null);
            };

            // Assert
            action.Should().Throw <ArgumentNullException>();
        }
예제 #9
0
        public static IHost BuildWebHost(string[] args)
        {
            ConfigureLogging();

            var configuration = new ConfigurationBuilder()
                                .SetBasePath(Directory.GetCurrentDirectory())
                                .AddJsonFile(path: "appsettings.json", optional: false, reloadOnChange: true)
                                .Build();

            var datadogOptions = new MetricsReportingDatadogOptions();

            configuration.GetSection(nameof(MetricsReportingDatadogOptions)).Bind(datadogOptions);

            // Samples with weight of less than 10% of average should be discarded when rescaling
            const double minimumSampleWeight = 0.001;

            var metrics = AppMetrics.CreateDefaultBuilder()
                          .Configuration.ReadFrom(configuration)
                          .SampleWith.ForwardDecaying(
                AppMetricsReservoirSamplingConstants.DefaultSampleSize,
                AppMetricsReservoirSamplingConstants.DefaultExponentialDecayFactor,
                minimumSampleWeight: minimumSampleWeight)
                          .Report.ToDatadogHttp(datadogOptions)
                          .Build();

            return(Host.CreateDefaultBuilder(args)
                   .ConfigureMetrics(metrics)
                   .UseMetrics()
                   .UseSerilog()
                   .ConfigureWebHostDefaults(
                       webBuilder =>
            {
                webBuilder.UseStartup <Startup>();
            })
                   .Build());
        }