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>(); }
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()); }