diff --git a/AppMetrics.Extensions.InfluxDB.sln b/AppMetrics.Extensions.InfluxDB.sln index c3526df..700be71 100644 --- a/AppMetrics.Extensions.InfluxDB.sln +++ b/AppMetrics.Extensions.InfluxDB.sln @@ -44,6 +44,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "grafana-dashboards", "grafa visualization\grafana-dashbaords\App.Metrics.Sandbox-InfluxDB-GenericWebOAuth2.json = visualization\grafana-dashbaords\App.Metrics.Sandbox-InfluxDB-GenericWebOAuth2.json EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandbox", "sandbox", "{B0E330F2-942D-47DC-940D-692E01459A06}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.InfluxDB.Sandbox", "sandbox\App.Metrics.InfluxDB.Sandbox\App.Metrics.InfluxDB.Sandbox.csproj", "{4D15C49F-F4DC-4631-B8FA-1D307C461227}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -58,6 +62,10 @@ Global {84005F55-AF0E-40F4-A596-129E19C418CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {84005F55-AF0E-40F4-A596-129E19C418CE}.Release|Any CPU.ActiveCfg = Release|Any CPU {84005F55-AF0E-40F4-A596-129E19C418CE}.Release|Any CPU.Build.0 = Release|Any CPU + {4D15C49F-F4DC-4631-B8FA-1D307C461227}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D15C49F-F4DC-4631-B8FA-1D307C461227}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D15C49F-F4DC-4631-B8FA-1D307C461227}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D15C49F-F4DC-4631-B8FA-1D307C461227}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -69,5 +77,6 @@ Global {84005F55-AF0E-40F4-A596-129E19C418CE} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} {5BC3B2AF-AFC7-4C92-BD1E-D347E83B2497} = {31A4DDB1-952E-4EED-96EF-29C669279A86} {44E50731-4AE5-456F-A84C-CE3C4C977097} = {5BC3B2AF-AFC7-4C92-BD1E-D347E83B2497} + {4D15C49F-F4DC-4631-B8FA-1D307C461227} = {B0E330F2-942D-47DC-940D-692E01459A06} EndGlobalSection EndGlobal diff --git a/appveyor.yml b/appveyor.yml index 8b75b8a..ce4e07e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,9 +3,15 @@ image: Visual Studio 2017 environment: COVERALLS_REPO_TOKEN: secure: jE+uYnSDVrBExOFkaPPHpJeKfHxVuS+lYvS+8BlcKBTSioz25h+rBq3RxMGl9JBd - PreReleaseSuffix: alpha + PreReleaseSuffix: stable DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true DOTNET_CLI_TELEMETRY_OPTOUT: true + GitUser: + secure: zAdAOUUof3XGDsdOBRYg7J7wZS44iL4VjI/MVGw+JnU= + GitOwner: + secure: n6W5JZ7Q/xfZC7b2k3+ORA== + GitPassword: + secure: G1CZ0EzJTYjH60jzYYaitkieeslue7VdeeVW4vYS+msXQ9gSCf7KstBKEbXdI+W2 build_script: - ps: .\build.ps1 -Target AppVeyor test: off diff --git a/build.cake b/build.cake index ee12998..43181cc 100644 --- a/build.cake +++ b/build.cake @@ -8,6 +8,7 @@ #tool "nuget:?package=ReSharperReports" #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools" #tool "nuget:?package=coveralls.io" +#tool "nuget:?package=gitreleasemanager" ////////////////////////////////////////////////////////////////////// // ARGUMENTS @@ -19,12 +20,14 @@ var coverWith = HasArgument("CoverWith") ? Argument("CoverWith") : EnvironmentVariable("CoverWith") != null ? EnvironmentVariable("CoverWith") : "OpenCover"; // None, DotCover, OpenCover var skipReSharperCodeInspect = Argument("SkipCodeInspect", false) || !IsRunningOnWindows(); var preReleaseSuffix = HasArgument("PreReleaseSuffix") ? Argument("PreReleaseSuffix") : - (AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag) ? null : + (AppVeyor.IsRunningOnAppVeyor && EnvironmentVariable("PreReleaseSuffix") == null) ? null : EnvironmentVariable("PreReleaseSuffix") != null ? EnvironmentVariable("PreReleaseSuffix") : "ci"; var buildNumber = HasArgument("BuildNumber") ? Argument("BuildNumber") : AppVeyor.IsRunningOnAppVeyor ? AppVeyor.Environment.Build.Number : TravisCI.IsRunningOnTravisCI ? TravisCI.Environment.Build.BuildNumber : EnvironmentVariable("BuildNumber") != null ? int.Parse(EnvironmentVariable("BuildNumber")) : 0; +var gitUser = HasArgument("GitUser") ? Argument("GitUser") : EnvironmentVariable("GitUser"); +var gitPassword = HasArgument("GitPassword") ? Argument("GitPassword") : EnvironmentVariable("GitPassword"); ////////////////////////////////////////////////////////////////////// // DEFINE FILES & DIRECTORIES @@ -72,6 +75,30 @@ Task("Clean") CleanDirectory(testResultsDir); }); +Task("ReleaseNotes") + .IsDependentOn("Clean") + .WithCriteria(() => AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag && AppVeyor.Environment.Repository.Branch == "master") + .Does(() => +{ + var preRelease = preReleaseSuffix != null; + var milestone = AppVeyor.Environment.Repository.Tag.Name; + var owner = AppVeyor.Environment.Repository.Name.Split('/')[0]; + var repo = AppVeyor.Environment.Repository.Name.Split('/')[1]; + var tag = AppVeyor.Environment.Repository.Tag.Name; + + Context.Information("Creating release notes for Milestone " + milestone); + GitReleaseManagerCreate(gitUser, gitPassword, owner, repo, new GitReleaseManagerCreateSettings { + Milestone = milestone, + Prerelease = preRelease + }); + + Context.Information("Publishing Release Notes for Tag " + tag); + GitReleaseManagerPublish(gitUser, gitPassword, owner, repo, tag); + + Context.Information("Closing Milestone " + milestone); + GitReleaseManagerClose(gitUser, gitPassword, owner, repo, milestone); +}); + Task("Restore") .IsDependentOn("Clean") .Does(() => @@ -81,25 +108,24 @@ Task("Restore") Sources = new [] { "https://api.nuget.org/v3/index.json", "https://www.myget.org/F/alhardy/api/v3/index.json" } }; - var projects = solution.GetProjects(); - - foreach(var project in projects) - { - DotNetCoreRestore(project.Path.ToString(), settings); - } + DotNetCoreRestore(solutionFile, settings); }); Task("Build") .IsDependentOn("Restore") .Does(() => { - var projects = solution.GetProjects(); - var settings = new DotNetCoreBuildSettings { Configuration = configuration }; - foreach(var project in projects) - { - if (!IsRunningOnWindows()) + if (IsRunningOnWindows()) + { + DotNetCoreBuild(solutionFile, settings); + } + else + { + var projects = solution.GetProjects(); + + foreach(var project in projects) { // Ignore Net452 on non-windows environments if (project.Path.ToString().Contains("Net452")) @@ -109,7 +135,7 @@ Task("Build") var parsedProject = ParseProject(new FilePath(project.Path.ToString()), configuration); - if (parsedProject.IsLibrary() && !project.Path.ToString().Contains(".Facts") && !project.Path.ToString().Contains(".Benchmarks")) + if (parsedProject.IsLibrary() && !project.Path.ToString().Contains(".Sandbox")&& !project.Path.ToString().Contains(".Facts") && !project.Path.ToString().Contains(".Benchmarks")) { settings.Framework = "netstandard1.6"; } @@ -119,10 +145,11 @@ Task("Build") } Context.Information("Building as " + settings.Framework + ": " + project.Path.ToString()); - } - DotNetCoreBuild(project.Path.ToString(), settings); - } + DotNetCoreBuild(project.Path.ToString(), settings); + } + + } }); Task("Pack") @@ -367,19 +394,20 @@ Task("PublishCoverage") ////////////////////////////////////////////////////////////////////// Task("Default") - .IsDependentOn("Build") + .IsDependentOn("Build") .IsDependentOn("PublishTestResults") - .IsDependentOn("Pack") + .IsDependentOn("Pack") .IsDependentOn("HtmlCoverageReport") .IsDependentOn("RunInspectCode"); Task("AppVeyor") - .IsDependentOn("Build") + .IsDependentOn("Build") .IsDependentOn("PublishTestResults") - .IsDependentOn("Pack") + .IsDependentOn("Pack") .IsDependentOn("HtmlCoverageReport") .IsDependentOn("RunInspectCode") - .IsDependentOn("PublishCoverage"); + .IsDependentOn("PublishCoverage") + .IsDependentOn("ReleaseNotes"); ////////////////////////////////////////////////////////////////////// // EXECUTION diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/App.Metrics.InfluxDB.Sandbox.csproj b/sandbox/App.Metrics.InfluxDB.Sandbox/App.Metrics.InfluxDB.Sandbox.csproj new file mode 100644 index 0000000..909b4f4 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/App.Metrics.InfluxDB.Sandbox.csproj @@ -0,0 +1,34 @@ + + + + netcoreapp1.1 + ..\..\docker-compose.dcproj + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ExceptionThrowingController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ExceptionThrowingController.cs new file mode 100644 index 0000000..7626f40 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ExceptionThrowingController.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class ExceptionThrowingController : Controller + { + private readonly IMetrics _metrics; + + public ExceptionThrowingController(IMetrics metrics) + { + _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); + } + + [HttpGet] + public async Task Get() + { + await Task.Run(() => + { + throw new Exception(); + }); + + return 0; + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FileController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FileController.cs new file mode 100644 index 0000000..960bc91 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FileController.cs @@ -0,0 +1,22 @@ +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class FileController : Controller + { + [HttpPost] + public IActionResult Post(IFormFile file) + { + return Created(new Uri("http://localhost"), 0); + } + + [HttpPut] + public IActionResult Put(IFormFile file) + { + return Ok(); + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FrustratingController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FrustratingController.cs new file mode 100644 index 0000000..5f2cd8d --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/FrustratingController.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class FrustratingController : Controller + { + private readonly RequestDurationForApdexTesting _durationForApdexTesting; + + private readonly IMetrics _metrics; + + public FrustratingController(IMetrics metrics, RequestDurationForApdexTesting durationForApdexTesting) + { + _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); + _durationForApdexTesting = durationForApdexTesting; + } + + [HttpGet] + public async Task Get() + { + var duration = _durationForApdexTesting.NextFrustratingDuration; + + await Task.Delay(duration, HttpContext.RequestAborted); + + return duration; + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/RandomStatusCodeController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/RandomStatusCodeController.cs new file mode 100644 index 0000000..38c93cf --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/RandomStatusCodeController.cs @@ -0,0 +1,25 @@ +using System; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class RandomStatusCodeController : Controller + { + private readonly RandomStatusCodeForTesting _randomStatusCodeForTesting; + private readonly IMetrics _metrics; + + public RandomStatusCodeController(IMetrics metrics, RandomStatusCodeForTesting randomStatusCodeForTesting) + { + _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); + _randomStatusCodeForTesting = randomStatusCodeForTesting; + } + + [HttpGet] + public IActionResult Get() + { + return StatusCode(_randomStatusCodeForTesting.NextStatusCode); + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/SatisfyingController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/SatisfyingController.cs new file mode 100644 index 0000000..f778761 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/SatisfyingController.cs @@ -0,0 +1,65 @@ +using System; +using System.Threading.Tasks; +using App.Metrics.Core.Options; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + public static class Registry + { + public static HistogramOptions One = new HistogramOptions + { + Name = "test1", + MeasurementUnit = Unit.Bytes, + Context = "test" + }; + + public static HistogramOptions Two = new HistogramOptions + { + Name = "test2", + MeasurementUnit = Unit.Bytes, + Context = "test" + }; + + public static HistogramOptions Three = new HistogramOptions + { + Name = "test3", + MeasurementUnit = Unit.Bytes, + Context = "test" + }; + } + + [Route("api/[controller]")] + public class SatisfyingController : Controller + { + private readonly RequestDurationForApdexTesting _durationForApdexTesting; + private static readonly Random Rnd = new Random(); + private readonly IMetrics _metrics; + + public SatisfyingController(IMetrics metrics, RequestDurationForApdexTesting durationForApdexTesting) + { + _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); + _durationForApdexTesting = durationForApdexTesting; + } + + [HttpGet] + public async Task Get() + { + var duration = _durationForApdexTesting.NextSatisfiedDuration; + + //foreach (var i in Enumerable.Range(1, 500)) + //{ + // var tags = new MetricTags($"key{i}", $"value{i}"); + + // _metrics.Measure.Histogram.Update(Registry.One, tags, Rnd.Next(1, 500)); + // _metrics.Measure.Histogram.Update(Registry.Two, tags, Rnd.Next(1, 500)); + // _metrics.Measure.Histogram.Update(Registry.Three, tags, Rnd.Next(1, 500)); + //} + + await Task.Delay(duration, HttpContext.RequestAborted); + + return duration; + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/TestController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/TestController.cs new file mode 100644 index 0000000..0c05ca9 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/TestController.cs @@ -0,0 +1,14 @@ +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class TestController : Controller + { + [HttpGet] + public IActionResult Get() + { + return Ok(); + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ToleratingController.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ToleratingController.cs new file mode 100644 index 0000000..95109a4 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Controllers/ToleratingController.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading.Tasks; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; +using Microsoft.AspNetCore.Mvc; + +namespace App.Metrics.InfluxDB.Sandbox.Controllers +{ + [Route("api/[controller]")] + public class ToleratingController : Controller + { + private readonly RequestDurationForApdexTesting _durationForApdexTesting; + + private readonly IMetrics _metrics; + + public ToleratingController(IMetrics metrics, RequestDurationForApdexTesting durationForApdexTesting) + { + _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); + _durationForApdexTesting = durationForApdexTesting; + } + + [HttpGet] + public async Task Get() + { + var duration = _durationForApdexTesting.NextToleratingDuration; + + await Task.Delay(duration, HttpContext.RequestAborted); + + return duration; + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/HealthChecks/SampleHealthCheck.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/HealthChecks/SampleHealthCheck.cs new file mode 100644 index 0000000..4747e1c --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/HealthChecks/SampleHealthCheck.cs @@ -0,0 +1,31 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using App.Metrics.Health; + +namespace App.Metrics.InfluxDB.Sandbox.HealthChecks +{ + public class SampleHealthCheck : HealthCheck + { + /// + public SampleHealthCheck() : base("Random Health Check") + { + } + + /// + protected override Task CheckAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + if (DateTime.UtcNow.Second <= 20) + { + return Task.FromResult(HealthCheckResult.Degraded()); + } + + if (DateTime.UtcNow.Second >= 40) + { + return Task.FromResult(HealthCheckResult.Unhealthy()); + } + + return Task.FromResult(HealthCheckResult.Healthy()); + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomBufferGenerator.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomBufferGenerator.cs new file mode 100644 index 0000000..3adf845 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomBufferGenerator.cs @@ -0,0 +1,31 @@ +using System; + +namespace App.Metrics.InfluxDB.Sandbox.JustForTesting +{ + public class RandomBufferGenerator + { + private readonly int _maxBufferSize; + private readonly Random _random = new Random(); + private readonly byte[] _seedBuffer; + + public RandomBufferGenerator(int maxBufferSize) + { + _maxBufferSize = maxBufferSize; + _seedBuffer = new byte[maxBufferSize]; + + _random.NextBytes(_seedBuffer); + } + + public byte[] GenerateBufferFromSeed() + { + var size = _random.Next(_maxBufferSize); + var randomWindow = _random.Next(0, size); + var buffer = new byte[size]; + + Buffer.BlockCopy(_seedBuffer, randomWindow, buffer, 0, size - randomWindow); + Buffer.BlockCopy(_seedBuffer, 0, buffer, size - randomWindow, randomWindow); + + return buffer; + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomClientIdForTesting.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomClientIdForTesting.cs new file mode 100644 index 0000000..8296293 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomClientIdForTesting.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using Microsoft.AspNetCore.Http; + +namespace App.Metrics.InfluxDB.Sandbox.JustForTesting +{ + public static class RandomClientIdForTesting + { + private static readonly Random Rnd = new Random(); + + public static void SetTheFakeClaimsPrincipal(HttpContext context) + { + context.User = + new ClaimsPrincipal( + new List + { + new ClaimsIdentity( + new[] + { + new Claim("client_id", $"client-{Rnd.Next(1, 10)}") + }) + }); + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomStatusCodeForTesting.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomStatusCodeForTesting.cs new file mode 100644 index 0000000..67bec7e --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RandomStatusCodeForTesting.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace App.Metrics.InfluxDB.Sandbox.JustForTesting +{ + public class RandomStatusCodeForTesting + { + private static readonly Random Rnd = new Random(); + private static readonly List StatusCode = new List { 200, 401, 401, 404, 403, 500, 500, 500 }; + + public int NextStatusCode => StatusCode[Rnd.Next(0, StatusCode.Count - 1)]; + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RequestDurationForApdexTesting.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RequestDurationForApdexTesting.cs new file mode 100644 index 0000000..b52808e --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/RequestDurationForApdexTesting.cs @@ -0,0 +1,41 @@ +using System; + +namespace App.Metrics.InfluxDB.Sandbox.JustForTesting +{ + public class RequestDurationForApdexTesting + { + private const int MaxRequestDurationFactor = 1000; + private const int MinRequestDuration = 25; + private static readonly Random Rnd = new Random(); + + public RequestDurationForApdexTesting(double apdexTSeconds) + { + SatisfiedMinMilliseconds = MinRequestDuration; + SatisfiedMaxMilliseconds = (int)(apdexTSeconds * 1000); + + ToleratingMinMilliseconds = SatisfiedMaxMilliseconds + 1; + ToleratingMaxMilliseconds = 4 * SatisfiedMaxMilliseconds; + + FrustratingMinMilliseconds = ToleratingMaxMilliseconds + 1; + FrustratingMaxMilliseconds = ToleratingMaxMilliseconds + MaxRequestDurationFactor; + } + + public int FrustratingMaxMilliseconds { get; } + + public int FrustratingMinMilliseconds { get; } + + public int NextFrustratingDuration => Rnd.Next(FrustratingMinMilliseconds, FrustratingMaxMilliseconds); + + public int NextSatisfiedDuration => Rnd.Next(SatisfiedMinMilliseconds, SatisfiedMaxMilliseconds); + + public int NextToleratingDuration => Rnd.Next(ToleratingMinMilliseconds, ToleratingMaxMilliseconds); + + public int SatisfiedMaxMilliseconds { get; } + + public int SatisfiedMinMilliseconds { get; } + + public int ToleratingMaxMilliseconds { get; } + + public int ToleratingMinMilliseconds { get; } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/SampleRequests.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/SampleRequests.cs new file mode 100644 index 0000000..6a6e8f2 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/SampleRequests.cs @@ -0,0 +1,82 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using App.Metrics.Scheduling; + +namespace App.Metrics.InfluxDB.Sandbox.JustForTesting +{ + public static class SampleRequests + { + private static readonly Uri ApiBaseAddress = new Uri("http://localhost:1111/"); + + public static void Run(CancellationToken token) + { + var randomBufferGenerator = new RandomBufferGenerator(50000); + var scheduler = new DefaultTaskScheduler(); + var httpClient = new HttpClient + { + BaseAddress = ApiBaseAddress + }; + + Task.Run( + () => scheduler.Interval( + TimeSpan.FromSeconds(1), + TaskCreationOptions.None, + async () => + { + var satisfied = httpClient.GetAsync("api/satisfying", token); + var tolerating = httpClient.GetAsync("api/tolerating", token); + var frustrating = httpClient.GetAsync("api/frustrating", token); + + await Task.WhenAll(satisfied, tolerating, frustrating); + }, + token), + token); + + Task.Run( + () => scheduler.Interval( + TimeSpan.FromSeconds(3), + TaskCreationOptions.None, + async () => + { + var randomStatusCode = httpClient.GetAsync("api/randomstatuscode", token); + var exceptionThrower = httpClient.GetAsync("api/exceptionThrowing", token); + + await Task.WhenAll(randomStatusCode, exceptionThrower); + }, + token), + token); + + Task.Run( + () => scheduler.Interval( + TimeSpan.FromSeconds(3), + TaskCreationOptions.None, + async () => + { + await httpClient.GetAsync("api/test", token); + }, + token), + token); + + Task.Run( + () => scheduler.Interval( + TimeSpan.FromSeconds(2), + TaskCreationOptions.None, + async () => + { + var putBytes = new ByteArrayContent(randomBufferGenerator.GenerateBufferFromSeed()); + var putFormData = new MultipartFormDataContent { { putBytes, "put-file", "rnd-put" } }; + var putRequest = httpClient.PutAsync("api/file", putFormData, token); + + var postBytes = new ByteArrayContent(randomBufferGenerator.GenerateBufferFromSeed()); + var postFormData = new MultipartFormDataContent { { postBytes, "post-file", "rnd-post" } }; + var postRequest = httpClient.PostAsync("api/file", postFormData, token); + + await Task.WhenAll(putRequest, postRequest); + }, + token), + token); + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/ServiceCollectionExtensions.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..94921cb --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/JustForTesting/ServiceCollectionExtensions.cs @@ -0,0 +1,28 @@ +using System; +using App.Metrics.Extensions.Middleware.DependencyInjection.Options; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; + +// ReSharper disable CheckNamespace +namespace Microsoft.Extensions.DependencyInjection + // ReSharper restore CheckNamespace +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddTestStuff(this IServiceCollection services) + { + services.AddTransient>( + provider => { return apdexTSeconds => new RequestDurationForApdexTesting(apdexTSeconds); }); + + services.AddTransient(); + + services.AddTransient( + provider => + { + var options = provider.GetRequiredService(); + return new RequestDurationForApdexTesting(options.ApdexTSeconds); + }); + + return services; + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Program.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Program.cs new file mode 100644 index 0000000..a33b3d8 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Program.cs @@ -0,0 +1,19 @@ +using System.IO; +using Microsoft.AspNetCore.Hosting; + +namespace App.Metrics.InfluxDB.Sandbox +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup().Build(); + + host.Run(); + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Properties/launchSettings.json b/sandbox/App.Metrics.InfluxDB.Sandbox/Properties/launchSettings.json new file mode 100644 index 0000000..5261bf0 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:2222/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "metrics", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "App.Metrics.Sandbox": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "metrics", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:1111" + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/Startup.cs b/sandbox/App.Metrics.InfluxDB.Sandbox/Startup.cs new file mode 100644 index 0000000..7254d2a --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/Startup.cs @@ -0,0 +1,106 @@ +using System; +using App.Metrics.Configuration; +using App.Metrics.Extensions.Reporting.InfluxDB; +using App.Metrics.Extensions.Reporting.InfluxDB.Client; +using App.Metrics.Filtering; +using App.Metrics.InfluxDB.Sandbox.JustForTesting; +using App.Metrics.Reporting.Interfaces; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace App.Metrics.InfluxDB.Sandbox +{ + public class Startup + { + private static readonly bool HaveAppRunSampleRequests = true; + private static readonly string InfluxDbDatabase = "AppMetricsSandbox"; + private static readonly Uri InfluxDbUri = new Uri("http://127.0.0.1:8086"); + private static readonly bool RunSamplesWithClientId = true; + + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder().SetBasePath(env.ContentRootPath). + AddJsonFile("appsettings.json", optional: false, reloadOnChange: true). + AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true). + AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime) + { + if (RunSamplesWithClientId && HaveAppRunSampleRequests) + { + app.Use( + (context, func) => + { + RandomClientIdForTesting.SetTheFakeClaimsPrincipal(context); + return func(); + }); + } + + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + // loggerFactory.AddDebug(); + + app.UseMetrics(); + app.UseMetricsReporting(lifetime); + + app.UseMvc(); + + if (HaveAppRunSampleRequests) + { + SampleRequests.Run(lifetime.ApplicationStopping); + } + } + + public void ConfigureServices(IServiceCollection services) + { + services.AddTestStuff(); + services.AddLogging().AddRouting(options => { options.LowercaseUrls = true; }); + + services.AddMvc(options => options.AddMetricsResourceFilter()); + + var reportFilter = new DefaultMetricsFilter(); + reportFilter.WithHealthChecks(false); + + services.AddMetrics( + Configuration.GetSection("AppMetrics"), + options => + { + options.WithGlobalTags( + (globalTags, info) => { globalTags.Add("app", info.EntryAssemblyName); }); + }). + AddJsonSerialization(). + AddReporting( + factory => + { + factory.AddInfluxDb( + new InfluxDBReporterSettings + { + HttpPolicy = new HttpPolicy + { + FailuresBeforeBackoff = 3, + BackoffPeriod = TimeSpan.FromSeconds(30), + Timeout = TimeSpan.FromSeconds(10) + }, + InfluxDbSettings = new InfluxDBSettings(InfluxDbDatabase, InfluxDbUri), + ReportInterval = TimeSpan.FromSeconds(5) + }, + reportFilter); + }). + AddHealthChecks( + factory => + { + factory.RegisterPingHealthCheck("google ping", "google.com", TimeSpan.FromSeconds(10)); + factory.RegisterHttpGetHealthCheck("github", new Uri("https://github.com/"), TimeSpan.FromSeconds(10)); + }). + AddMetricsMiddleware(Configuration.GetSection("AspNetMetrics")); + } + } +} \ No newline at end of file diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.Development.json b/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.Development.json new file mode 100644 index 0000000..fa8ce71 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.json b/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.json new file mode 100644 index 0000000..6b80d09 --- /dev/null +++ b/sandbox/App.Metrics.InfluxDB.Sandbox/appsettings.json @@ -0,0 +1,29 @@ +{ + "AppMetrics": { + "DefaultContextLabel": "App.Metrics.Sandbox", + "DefaultSamplingType": "ExponentiallyDecaying", + "MetricsEnabled": true, + "ReportingEnabled": true, + "GlobalTags": { "env": "stage" }, + "ApdexTSeconds": 0.1, + "OAuth2TrackingEnabled": true + }, + "AspNetMetrics": { + "IgnoredHttpStatusCodes": [ 404 ], + "HealthEndpointEnabled": true, + "MetricsEndpointEnabled": true, + "MetricsTextEndpointEnabled": true, + "PingEndpointEnabled": true, + "OAuth2TrackingEnabled": true, + "HealthEndpoint": "/health", + "MetricsEndpoint": "/metrics", + "MetricsTextEndpoint": "/metrics-text", + "PingEndpoint": "/ping" + }, + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Warning" + } + } +} diff --git a/src/App.Metrics.Extensions.Reporting.Console/App.Metrics.Extensions.Reporting.Console.csproj b/src/App.Metrics.Extensions.Reporting.Console/App.Metrics.Extensions.Reporting.Console.csproj deleted file mode 100644 index 1b644a3..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/App.Metrics.Extensions.Reporting.Console.csproj +++ /dev/null @@ -1,68 +0,0 @@ - - - - - Provides console reporting capability to App Metrics - Allan Hardy 2016 - App.Metrics.Extensions.Reporting.Console - Allan Hardy - netstandard1.6;net452 - $(NoWarn);CS1591 - true - true - App.Metrics.Extensions.Reporting.Console - App.Metrics.Extensions.Reporting.Console - Metrics;Monitoring;Instrumentation;Reporting;Console - https://alhardy.github.io/app-metrics-docs/logo.png - https://alhardy.github.io/app-metrics-docs/getting-started/reporting/index.html#console-reporter - https://github.com/alhardy/AppMetrics.Reporting/blob/master/LICENSE - git - git://github.com/alhardy/AppMetrics.Reporting - false - false - false - false - ..\..\AppMetrics.ruleset - full - 1.1.0 - - - - bin\Release\netstandard1.6\App.Metrics.Extensions.Reporting.Console.xml - - - - bin\Debug\netstandard1.6\App.Metrics.Extensions.Reporting.Console.xml - - - - bin\Release\net452\App.Metrics.Extensions.Reporting.Console.xml - - - - bin\Debug\net452\App.Metrics.Extensions.Reporting.Console.xml - - - - - - - - - - - - All - - - - - $(DefineConstants);CLASSIC - - - - - - - - diff --git a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporter.cs b/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporter.cs deleted file mode 100644 index 4f50701..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporter.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Core.Abstractions; -using App.Metrics.Formatting.Humanize; -using App.Metrics.Health; -using App.Metrics.Infrastructure; -using App.Metrics.Tagging; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.Console -{ - public class ConsoleReporter : IMetricReporter - { - private static readonly string GlobalName = - $@"{CleanName(Environment.MachineName)}.{CleanName(Process.GetCurrentProcess().ProcessName)}"; - - private readonly ILogger _logger; - - public ConsoleReporter(TimeSpan reportInterval, ILoggerFactory loggerFactory) - : this(typeof(ConsoleReporter).Name, reportInterval, loggerFactory) { } - - public ConsoleReporter(string name, TimeSpan reportInterval, ILoggerFactory loggerFactory) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - Name = name; - ReportInterval = reportInterval; - - _logger = loggerFactory.CreateLogger(); - } - - public string Name { get; } - - public TimeSpan ReportInterval { get; } - - public void Dispose() { } - - public Task EndAndFlushReportRunAsync(IMetrics metrics) - { - _logger.LogTrace("Ending Console Report Run"); - - WriteLine( - string.Format( - Environment.NewLine + "-- End {0} Report: {1} - {2} --" + Environment.NewLine, - Name, - GlobalName, - metrics.Clock.FormatTimestamp(metrics.Clock.UtcDateTime))); - - return AppMetricsTaskCache.SuccessTask; - } - - public void EndMetricTypeReport(Type metricType) { } - - public void ReportEnvironment(EnvironmentInfo environmentInfo) - { - WriteLine(typeof(EnvironmentInfo).HumanzeStartMetricType()); - WriteLine(environmentInfo.Hummanize()); - WriteLine(typeof(EnvironmentInfo).HumanzeEndMetricType()); - } - - public void ReportHealth( - GlobalMetricTags globalTags, - IEnumerable healthyChecks, - IEnumerable degradedChecks, - IEnumerable unhealthyChecks) - { - WriteLine(typeof(HealthStatus).HumanzeStartMetricType()); - _logger.LogTrace("Writing Health Checks for Console"); - - var passed = healthyChecks.ToList(); - var failed = unhealthyChecks.ToList(); - var degraded = degradedChecks.ToList(); - var isHealthy = !failed.Any() && !degraded.Any(); - var isUnhealthy = failed.Any(); - - var status = "Degraded"; - - if (isHealthy) - { - status = "Healthy"; - } - - if (isUnhealthy) - { - status = "Unhealthy"; - } - - WriteLine(string.Format(Environment.NewLine + $"\tHealth Status = {status}" + Environment.NewLine)); - - WriteLine("\tPASSED CHECKS"); - - passed.ForEach(c => WriteLine(c.Hummanize())); - - WriteLine("\tDEGRADED CHECKS"); - - degraded.ForEach(c => WriteLine(c.Hummanize())); - - WriteLine("\tFAILED CHECKS"); - - failed.ForEach(c => WriteLine(c.Hummanize())); - - _logger.LogTrace("Writing Health Checks for Console"); - WriteLine(typeof(HealthStatus).HumanzeEndMetricType()); - } - - public void ReportMetric(string context, MetricValueSourceBase valueSource) - { - _logger.LogTrace("Writing Metric {T} for Console", typeof(T)); - - WriteLine(valueSource.HumanzizeName(context)); - - WriteLine(valueSource.Hummanize()); - - _logger.LogTrace("Writing Metric {T} for Console", typeof(T)); - } - - public void StartReportRun(IMetrics metrics) - { - _logger.LogTrace("Starting Console Report Run"); - - WriteLine( - string.Format( - Environment.NewLine + "-- Start {0} Report: {1} - {2} --" + Environment.NewLine, - Name, - GlobalName, - metrics.Clock.FormatTimestamp(metrics.Clock.UtcDateTime))); - } - - public void WriteLine(string message) { System.Console.WriteLine(message); } - - private static string CleanName(string name) { return name.Replace('.', '_'); } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterExtensions.cs b/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterExtensions.cs deleted file mode 100644 index 63d7008..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Reporting.Abstractions; - -namespace App.Metrics.Extensions.Reporting.Console -{ - public static class ConsoleReporterExtensions - { - public static IReportFactory AddConsole( - this IReportFactory factory, - ConsoleReporterSettings settings, - IFilterMetrics filter = null) - { - factory.AddProvider(new ConsoleReporterProvider(settings, filter)); - return factory; - } - - public static IReportFactory AddConsole( - this IReportFactory factory, - IFilterMetrics filter = null) - { - var settings = new ConsoleReporterSettings(); - factory.AddConsole(settings, filter); - return factory; - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterProvider.cs b/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterProvider.cs deleted file mode 100644 index 729c76e..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Abstractions.Reporting; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.Console -{ - public class ConsoleReporterProvider : IReporterProvider - { - private readonly ConsoleReporterSettings _settings; - - public ConsoleReporterProvider(ConsoleReporterSettings settings, IFilterMetrics filter) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - _settings = settings; - - Filter = filter; - } - - public IFilterMetrics Filter { get; } - - public IMetricReporter CreateMetricReporter(string name, ILoggerFactory loggerFactory) - { - return new ConsoleReporter(name, _settings.ReportInterval, loggerFactory); - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterSettings.cs b/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterSettings.cs deleted file mode 100644 index d56a79d..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/ConsoleReporterSettings.cs +++ /dev/null @@ -1,18 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Reporting; - -namespace App.Metrics.Extensions.Reporting.Console -{ - public class ConsoleReporterSettings : IReporterSettings - { - /// - public MetricValueDataKeys DataKeys { get; set; } - - public TimeSpan ReportInterval { get; set; } = TimeSpan.FromSeconds(30); - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.Console/Properties/AssemblyInfo.cs b/src/App.Metrics.Extensions.Reporting.Console/Properties/AssemblyInfo.cs deleted file mode 100644 index bacd3ed..0000000 --- a/src/App.Metrics.Extensions.Reporting.Console/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyProduct("App.Metrics")] -[assembly: AssemblyCompany("Allan Hardy.")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCopyright("© Allan Hardy. All rights reserved.")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("d6529db5-1812-4cc6-82d7-788df331d986")] \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/App.Metrics.Extensions.Reporting.ElasticSearch.csproj b/src/App.Metrics.Extensions.Reporting.ElasticSearch/App.Metrics.Extensions.Reporting.ElasticSearch.csproj deleted file mode 100644 index 0b2c6c5..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/App.Metrics.Extensions.Reporting.ElasticSearch.csproj +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - Provides ElasticSearch reporting capability to App Metrics - Allan Hardy 2016 - App.Metrics.Extensions.Reporting.ElasticSearch - Allan Hardy;Jenya Y. - netstandard1.6;net452 - $(NoWarn);CS1591 - true - true - App.Metrics.Extensions.Reporting.ElasticSearch - App.Metrics.Extensions.Reporting.ElasticSearch - Metrics;Monitoring;Instrumentation;Reporting;ElasticSearch - https://alhardy.github.io/app-metrics-docs/logo.png - https://alhardy.github.io/app-metrics-docs/getting-started/reporting/index.html#es-reporter - https://github.com/alhardy/AppMetrics.Reporting/blob/master/LICENSE - git - git://github.com/alhardy/AppMetrics.Reporting - false - false - false - false - ..\..\AppMetrics.ruleset - full - 1.1.0 - - - - bin\Release\netstandard1.6\App.Metrics.Extensions.Reporting.ElasticSearch.xml - - - - bin\Debug\netstandard1.6\App.Metrics.Extensions.Reporting.ElasticSearch.xml - - - - bin\Release\net452\App.Metrics.Extensions.Reporting.ElasticSearch.xml - - - - bin\Debug\net452\App.Metrics.Extensions.Reporting.ElasticSearch.xml - - - - - - - - - - - - - All - - - - - $(DefineConstants);CLASSIC - - - - - - - - diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkDocumentMetaData.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkDocumentMetaData.cs deleted file mode 100644 index 228d54c..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkDocumentMetaData.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using Newtonsoft.Json; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class BulkDocumentMetaData - { - [JsonProperty("index")] - public DocumentMetaData MetaData { get; set; } - - public BulkDocumentMetaData(string indexName, string typeName) - { - if (string.IsNullOrEmpty(indexName)) - { - throw new ArgumentNullException(nameof(indexName)); - } - - if (string.IsNullOrEmpty(typeName)) - { - throw new ArgumentNullException(nameof(typeName)); - } - - MetaData = new DocumentMetaData - { - IndexName = indexName, - TypeName = typeName, - DocumentId = Guid.NewGuid().ToString("D") - }; - } - - public class DocumentMetaData - { - [JsonProperty("_index")] - public string IndexName { get; set; } - - [JsonProperty("_type")] - public string TypeName { get; set; } - - [JsonProperty("_id")] - public string DocumentId { get; set; } - } - } -} diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayload.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayload.cs deleted file mode 100644 index 8925498..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayload.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.IO; -using Newtonsoft.Json; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class BulkPayload - { - private readonly List _documents; - private readonly string _indexName; - private readonly JsonSerializer _serializer; - - public BulkPayload(JsonSerializer serializer, string indexName) - { - _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); - _indexName = indexName ?? throw new ArgumentNullException(nameof(indexName)); - - if (string.IsNullOrWhiteSpace(indexName)) - { - throw new ArgumentException("Cannot be empty", nameof(indexName)); - } - - _documents = new List(); - } - - public void Add(MetricsDocument document) - { - if (document == null) - { - return; - } - - _documents.Add(document); - } - - public void Format(TextWriter textWriter) - { - if (textWriter == null) - { - return; - } - - foreach (var document in _documents) - { - _serializer.Serialize( - textWriter, - new BulkDocumentMetaData(_indexName, document.MeasurementType)); - textWriter.Write('\n'); - _serializer.Serialize(textWriter, document); - textWriter.Write('\n'); - } - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayloadBuilder.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayloadBuilder.cs deleted file mode 100644 index 70f0223..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/BulkPayloadBuilder.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using App.Metrics.Reporting.Abstractions; -using App.Metrics.Tagging; -using Newtonsoft.Json; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class BulkPayloadBuilder : IMetricPayloadBuilder - { - private readonly Func _metricTagValueFormatter; - private readonly JsonSerializer _serializer; - private readonly ElasticSearchSettings _settings; - private BulkPayload _payload; - - public BulkPayloadBuilder(ElasticSearchSettings settings, Func metricTagValueFormatter) - { - _settings = settings ?? throw new ArgumentNullException(nameof(settings)); - _metricTagValueFormatter = metricTagValueFormatter; - _serializer = JsonSerializer.Create(); - } - - public void Clear() { _payload = null; } - - public void Init() { _payload = new BulkPayload(_serializer, _settings.Index); } - - public void Pack(string name, object value, MetricTags tags) - { - var tagKeyValues = tags.ToDictionary(_metricTagValueFormatter); - - _payload.Add( - new MetricsDocument - { - MeasurementType = tagKeyValues["mtype"], - MeasurementName = name, - Fields = new Dictionary { { "value", value } }, - Tags = tagKeyValues - }); - } - - public void Pack( - string name, - IEnumerable columns, - IEnumerable values, - MetricTags tags) - { - var fields = columns.Zip(values, (column, data) => new { column, data }).ToDictionary(pair => pair.column, pair => pair.data); - var tagKeyValues = tags.ToDictionary(_metricTagValueFormatter); - - _payload.Add( - new MetricsDocument - { - MeasurementType = tagKeyValues["mtype"], - MeasurementName = name, - Fields = fields, - Tags = tagKeyValues - }); - } - - public BulkPayload Payload() { return _payload; } - - public string PayloadFormatted() - { - var result = new StringWriter(); - _payload.Format(result); - return result.ToString(); - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/Constants.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/Constants.cs deleted file mode 100644 index 0e12fef..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/Constants.cs +++ /dev/null @@ -1,15 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - internal static class Constants - { - public static readonly TimeSpan DefaultBackoffPeriod = TimeSpan.FromSeconds(30); - public static readonly int DefaultFailuresBeforeBackoff = 3; - public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30); - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchAuthorizationSchemes.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchAuthorizationSchemes.cs deleted file mode 100644 index 5418c59..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchAuthorizationSchemes.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public enum ElasticSearchAuthorizationSchemes - { - /// - /// Accessible without authorization - /// - Anonymous, - - /// - /// Basic HTTP authorization - /// - Basic, - - /// - /// Bearer token based authorization (e.g. JWT token) - /// - BearerToken - } -} diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchBulkClient.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchBulkClient.cs deleted file mode 100644 index 80a7d00..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchBulkClient.cs +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.IO; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class ElasticSearchBulkClient - { - private static TimeSpan _backOffPeriod; - private static long _backOffTicks; - private static long _failureAttempts; - private static long _failuresBeforeBackoff; - - private readonly HttpClient _httpClient; - private readonly ILogger _logger; - - public ElasticSearchBulkClient( - ILoggerFactory loggerFactory, - ElasticSearchSettings elasticSearchSettings) - : this( - loggerFactory, - elasticSearchSettings, - new HttpPolicy()) - { - } - - public ElasticSearchBulkClient( - ILoggerFactory loggerFactory, - ElasticSearchSettings elasticSearchSettings, - HttpPolicy httpPolicy, - HttpMessageHandler httpMessageHandler = null) - { - if (elasticSearchSettings == null) - { - throw new ArgumentNullException(nameof(elasticSearchSettings)); - } - - if (httpPolicy == null) - { - throw new ArgumentNullException(nameof(httpPolicy)); - } - - _httpClient = CreateClient(elasticSearchSettings, httpPolicy); - _backOffPeriod = httpPolicy.BackoffPeriod; - _failuresBeforeBackoff = httpPolicy.FailuresBeforeBackoff; - _failureAttempts = 0; - _logger = loggerFactory.CreateLogger(); - } - - public async Task WriteAsync( - BulkPayload payload, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (NeedToBackoff()) - { - _logger.LogTrace("Too many failures in writing to ElasticSearch, Circuit Opened"); - return false; - } - - var writer = new StringWriter(); - payload.Format(writer); - var content = new StringContent(writer.ToString(), Encoding.UTF8, "application/json"); - - try - { - var response = await _httpClient.PostAsync( - "/_bulk", - content, - cancellationToken). - ConfigureAwait(false); - - if (!response.IsSuccessStatusCode) - { - Interlocked.Increment(ref _failureAttempts); - - var body = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var errorMessage = $"Failed to write to ElasticSearch - StatusCode: {response.StatusCode} Reason: {body}"; - _logger.LogError(LoggingEvents.ElasticSearchWriteError, errorMessage); - - return false; - } - - _logger.LogTrace("Successful write to ElasticSearch"); - - return true; - } - catch (Exception ex) - { - Interlocked.Increment(ref _failureAttempts); - _logger.LogError(LoggingEvents.ElasticSearchWriteError, "Failed to write to ElasticSearch", ex); - return false; - } - } - - private HttpClient CreateClient(ElasticSearchSettings settings, HttpPolicy httpPolicy) - { - var httpClient = new HttpClient - { - BaseAddress = settings.Address, - Timeout = httpPolicy.Timeout - }; - - switch (settings.AuthorizationSchema) - { - case ElasticSearchAuthorizationSchemes.Anonymous: - httpClient.DefaultRequestHeaders.Authorization = - new AuthenticationHeaderValue("Bearer", settings.BearerToken); - break; - case ElasticSearchAuthorizationSchemes.Basic: - var byteArray = Encoding.ASCII.GetBytes($"{settings.UserName}:{settings.Password}"); - httpClient.DefaultRequestHeaders.Authorization = - new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); - break; - case ElasticSearchAuthorizationSchemes.BearerToken: - break; - default: - throw new NotImplementedException($"The specified schema {settings.AuthorizationSchema} is not implemented"); - } - - return httpClient; - } - - private bool NeedToBackoff() - { - if (Interlocked.Read(ref _failureAttempts) < _failuresBeforeBackoff) - { - return false; - } - - _logger.LogError($"ElasticSearch client write backoff for {_backOffPeriod.Seconds} seconds"); - - if (Interlocked.Read(ref _backOffTicks) == 0) - { - Interlocked.Exchange(ref _backOffTicks, DateTime.UtcNow.Add(_backOffPeriod).Ticks); - } - - if (DateTime.UtcNow.Ticks <= Interlocked.Read(ref _backOffTicks)) - { - return true; - } - - Interlocked.Exchange(ref _failureAttempts, 0); - Interlocked.Exchange(ref _backOffTicks, 0); - - return false; - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchSettings.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchSettings.cs deleted file mode 100644 index 50cf60a..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/ElasticSearchSettings.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class ElasticSearchSettings - { - public ElasticSearchSettings(Uri address, string indexName) - { - Address = address ?? throw new ArgumentNullException(nameof(address)); - Index = indexName ?? throw new ArgumentNullException(nameof(indexName)); - - if (string.IsNullOrWhiteSpace(indexName)) - { - throw new ArgumentException("Cannot be empty", nameof(indexName)); - } - - AuthorizationSchema = ElasticSearchAuthorizationSchemes.Basic; - } - - public ElasticSearchSettings(Uri address, string indexName, string userName, string password) - : this(address, indexName) - { - UserName = userName ?? throw new ArgumentNullException(nameof(userName)); - Password = password ?? throw new ArgumentNullException(nameof(password)); - - if (string.IsNullOrWhiteSpace(userName)) - { - throw new ArgumentException("Cannot be empty", nameof(userName)); - } - - if (string.IsNullOrWhiteSpace(password)) - { - throw new ArgumentException("Cannot be empty", nameof(password)); - } - - AuthorizationSchema = ElasticSearchAuthorizationSchemes.Anonymous; - } - - public ElasticSearchSettings(Uri address, string indexName, string bearerToken) - : this(address, indexName) - { - BearerToken = bearerToken ?? throw new ArgumentNullException(nameof(bearerToken)); - - if (string.IsNullOrWhiteSpace(bearerToken)) - { - throw new ArgumentException("Cannot be empty", nameof(bearerToken)); - } - - AuthorizationSchema = ElasticSearchAuthorizationSchemes.BearerToken; - } - - public Uri Address { get; } - - public ElasticSearchAuthorizationSchemes AuthorizationSchema { get; } - - public string BearerToken { get; } - - public string Index { get; } - - public string Password { get; } - - public string UserName { get; } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/MetricsDocument.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/MetricsDocument.cs deleted file mode 100644 index 62b003f..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Client/MetricsDocument.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch.Client -{ - public class MetricsDocument - { - [JsonProperty("name")] - public string MeasurementName { get; set; } - - [JsonIgnore] - public string MeasurementType { get; internal set; } - - [JsonProperty("fields")] - public IDictionary Fields { get; set; } - - [JsonProperty("tags")] - public IDictionary Tags { get; set; } - - [JsonProperty("@timestamp")] - public DateTime WrittenOn { get; set; } = DateTime.UtcNow; - } -} diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterExtensions.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterExtensions.cs deleted file mode 100644 index ea58b30..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Extensions.Reporting.ElasticSearch; -using App.Metrics.Extensions.Reporting.ElasticSearch.Client; -using App.Metrics.Reporting.Abstractions; - -// ReSharper disable CheckNamespace -namespace App.Metrics.Reporting.Interfaces - // ReSharper restore CheckNamespace -{ - public static class ElasticSearchReporterExtensions - { - public static IReportFactory AddElasticSearch( - this IReportFactory factory, - ElasticSearchReporterSettings settings, - IFilterMetrics filter = null) - { - factory.AddProvider(new ElasticSearchReporterProvider(settings, filter)); - return factory; - } - - public static IReportFactory AddElasticSearch( - this IReportFactory factory, - Uri address, - string indexName, - IFilterMetrics filter = null) - { - var settings = new ElasticSearchReporterSettings - { - ElasticSearchSettings = new ElasticSearchSettings(address, indexName) - }; - - factory.AddElasticSearch(settings, filter); - return factory; - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterProvider.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterProvider.cs deleted file mode 100644 index 5750c7a..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Extensions.Reporting.ElasticSearch.Client; -using App.Metrics.Internal; -using App.Metrics.Reporting; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch -{ - public class ElasticSearchReporterProvider : IReporterProvider - { - private readonly ElasticSearchReporterSettings _settings; - - public ElasticSearchReporterProvider(ElasticSearchReporterSettings settings) - { - _settings = settings ?? throw new ArgumentNullException(nameof(settings)); - Filter = new NoOpMetricsFilter(); - } - - public ElasticSearchReporterProvider(ElasticSearchReporterSettings settings, IFilterMetrics fitler) - { - _settings = settings ?? throw new ArgumentNullException(nameof(settings)); - Filter = fitler ?? new NoOpMetricsFilter(); - } - - public IFilterMetrics Filter { get; } - - public IMetricReporter CreateMetricReporter(string name, ILoggerFactory loggerFactory) - { - var lineProtocolClient = new ElasticSearchBulkClient( - loggerFactory, - _settings.ElasticSearchSettings, - _settings.HttpPolicy); - var payloadBuilder = new BulkPayloadBuilder(_settings.ElasticSearchSettings, _settings.MetricTagValueFormatter); - - return new ReportRunner( - async p => await lineProtocolClient.WriteAsync(p.Payload()), - payloadBuilder, - _settings.ReportInterval, - name, - loggerFactory, - _settings.MetricNameFormatter, - _settings.DataKeys); - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterSettings.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterSettings.cs deleted file mode 100644 index e8779fb..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/ElasticSearchReporterSettings.cs +++ /dev/null @@ -1,121 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Extensions.Reporting.ElasticSearch.Client; -using App.Metrics.Reporting; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch -{ - public class ElasticSearchReporterSettings : IReporterSettings - { - private static readonly string[] SpecialChars = { @"\", @"/", " ", "-", "+", "=", "{", "}", "[", "]", ":", "&", "^", "~", "?", "!", "," }; - - /// - /// Initializes a new instance of the class. - /// - public ElasticSearchReporterSettings() - { - var customHistogramDataKeys = new Dictionary - { - { HistogramValueDataKeys.Count, "countHist" }, - { HistogramValueDataKeys.UserLastValue, "userLast" }, - { HistogramValueDataKeys.UserMinValue, "userMin" }, - { HistogramValueDataKeys.UserMaxValue, "userMax" } - }; - - var customMeterDataKeys = new Dictionary - { - { MeterValueDataKeys.Count, "countMeter" }, - { MeterValueDataKeys.RateMean, "rateMean" } - }; - DataKeys = new MetricValueDataKeys(histogram: customHistogramDataKeys, meter: customMeterDataKeys); - - ElasticSearchSettings = new ElasticSearchSettings(new Uri("http://localhost:9200"), "metrics"); - HttpPolicy = new HttpPolicy - { - FailuresBeforeBackoff = Constants.DefaultFailuresBeforeBackoff, - BackoffPeriod = Constants.DefaultBackoffPeriod, - Timeout = Constants.DefaultTimeout - }; - ReportInterval = TimeSpan.FromSeconds(5); - MetricNameFormatter = (metricContext, metricName) => string.IsNullOrWhiteSpace(metricContext) - ? SpecialChars.Aggregate(metricName, (current, @char) => current.Replace(@char, "_")).ToLowerInvariant() - : SpecialChars.Aggregate($"{metricContext}__{metricName}", (current, @char) => current.Replace(@char, "_")).ToLowerInvariant(); - - MetricTagValueFormatter = tagValue => - { - return SpecialChars.Aggregate(tagValue, (current, @char) => current.Replace(@char, "_")).ToLowerInvariant(); - }; - } - - /// - // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global - // ReSharper disable MemberCanBePrivate.Global - public MetricValueDataKeys DataKeys { get; set; } - // ReSharper restore MemberCanBePrivate.Global - // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global - - /// - /// Gets or sets the ElasticSearch database settings. - /// - /// - /// The ElasticSearch database settings. - /// - public ElasticSearchSettings ElasticSearchSettings { get; set; } - - /// - /// Gets or sets the HTTP policy settings which allows circuit breaker configuration to be adjusted - /// - /// - /// The HTTP policy. - /// - // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global - // ReSharper disable MemberCanBePrivate.Global - public HttpPolicy HttpPolicy { get; set; } - // ReSharper restore MemberCanBePrivate.Global - // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global - - /// - /// Gets or sets the metric name formatter func which takes the metric context and name and returns a formatted string - /// which will be reported to ElasticSearch as the measurement - /// - /// - /// The metric name formatter. - /// - // ReSharper disable MemberCanBePrivate.Global - // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global - public Func MetricNameFormatter { get; set; } - // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global - // ReSharper restore MemberCanBePrivate.Global - - /// - /// Gets or sets the metric tag value formatter func which takes the metric name and returns a formatted string - /// which will be used when reporting tag values to elasicsearch - /// - /// - /// The metric tag value formatter. - /// - // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global - // ReSharper disable MemberCanBePrivate.Global - public Func MetricTagValueFormatter { get; set; } - // ReSharper restore MemberCanBePrivate.Global - // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global - - /// - /// Gets or sets the report interval for which to flush metrics to ElasticSearch. - /// - /// - /// The report interval. - /// - // ReSharper disable AutoPropertyCanBeMadeGetOnly.Global - // ReSharper disable MemberCanBePrivate.Global - public TimeSpan ReportInterval { get; set; } - // ReSharper restore MemberCanBePrivate.Global - // ReSharper restore AutoPropertyCanBeMadeGetOnly.Global - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/HttpPolicy.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/HttpPolicy.cs deleted file mode 100644 index e201538..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/HttpPolicy.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Extensions.Reporting.ElasticSearch.Client; - -namespace App.Metrics.Extensions.Reporting.ElasticSearch -{ - public class HttpPolicy - { - public HttpPolicy() - { - FailuresBeforeBackoff = Constants.DefaultFailuresBeforeBackoff; - BackoffPeriod = Constants.DefaultBackoffPeriod; - Timeout = Constants.DefaultTimeout; - } - - public TimeSpan BackoffPeriod { get; set; } - - public int FailuresBeforeBackoff { get; set; } - - public TimeSpan Timeout { get; set; } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/LoggingEvents.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/LoggingEvents.cs deleted file mode 100644 index c96ee6b..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/LoggingEvents.cs +++ /dev/null @@ -1,11 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -namespace App.Metrics.Extensions.Reporting.ElasticSearch -{ - public class LoggingEvents - { - public const int ElasticSearchWriteError = 6000; - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Properties/AssemblyInfo.cs b/src/App.Metrics.Extensions.Reporting.ElasticSearch/Properties/AssemblyInfo.cs deleted file mode 100644 index 0ea129c..0000000 --- a/src/App.Metrics.Extensions.Reporting.ElasticSearch/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyProduct("App.Metrics")] -[assembly: AssemblyCompany("Allan Hardy.")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCopyright("© Allan Hardy. All rights reserved.")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("681a90a6-ce3b-41d0-93fe-5c57849a120d")] diff --git a/src/App.Metrics.Extensions.Reporting.InfluxDB/App.Metrics.Extensions.Reporting.InfluxDB.csproj b/src/App.Metrics.Extensions.Reporting.InfluxDB/App.Metrics.Extensions.Reporting.InfluxDB.csproj index 584f6e2..486d608 100644 --- a/src/App.Metrics.Extensions.Reporting.InfluxDB/App.Metrics.Extensions.Reporting.InfluxDB.csproj +++ b/src/App.Metrics.Extensions.Reporting.InfluxDB/App.Metrics.Extensions.Reporting.InfluxDB.csproj @@ -18,7 +18,7 @@ https://alhardy.github.io/app-metrics-docs/getting-started/reporting/index.html#influxdb-reporter https://github.com/alhardy/AppMetrics.Reporting/blob/master/LICENSE git - git://github.com/alhardy/AppMetrics.Reporting + git://github.com/alhardy/AppMetrics.Extensions.InfluxDB false false false @@ -49,8 +49,8 @@ - - + + All diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/App.Metrics.Extensions.Reporting.TextFile.csproj b/src/App.Metrics.Extensions.Reporting.TextFile/App.Metrics.Extensions.Reporting.TextFile.csproj deleted file mode 100644 index dc00d33..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/App.Metrics.Extensions.Reporting.TextFile.csproj +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - Provides text file reporting capability to App Metrics - Allan Hardy 2016 - App.Metrics.Extensions.Reporting.TextFile - Allan Hardy - netstandard1.6;net452 - $(NoWarn);CS1591 - true - true - App.Metrics.Extensions.Reporting.TextFile - App.Metrics.Extensions.Reporting.TextFile - Metrics;Monitoring;Instrumentation;Reporting;TextFile - https://alhardy.github.io/app-metrics-docs/logo.png - https://alhardy.github.io/app-metrics-docs/getting-started/reporting/index.html#text-file-reporter - https://github.com/alhardy/AppMetrics.Reporting/blob/master/LICENSE - git - git://github.com/alhardy/AppMetrics.Reporting - $(PackageTargetFallback);dotnet5.6;portable-net45+win8 - false - false - false - false - ..\..\AppMetrics.ruleset - full - 1.1.0 - - - - bin\Release\netstandard1.6\App.Metrics.Extensions.Reporting.TextFile.xml - - - - bin\Debug\netstandard1.6\App.Metrics.Extensions.Reporting.TextFile.xml - - - - bin\Release\net452\App.Metrics.Extensions.Reporting.TextFile.xml - - - - bin\Debug\net452\App.Metrics.Extensions.Reporting.TextFile.xml - - - - - - - - - - - All - - - - - $(DefineConstants);CLASSIC - - - - - - - - diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/Properties/AssemblyInfo.cs b/src/App.Metrics.Extensions.Reporting.TextFile/Properties/AssemblyInfo.cs deleted file mode 100644 index 87b3086..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyProduct("App.Metrics")] -[assembly: AssemblyCompany("Allan Hardy.")] -[assembly: NeutralResourcesLanguage("en-us")] -[assembly: AssemblyCopyright("© Allan Hardy. All rights reserved.")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("c29e2ef1-077d-43c8-9144-d998ed3a7bb3")] \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporter.cs b/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporter.cs deleted file mode 100644 index 918baa4..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporter.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Core.Abstractions; -using App.Metrics.Health; -using App.Metrics.Infrastructure; -using App.Metrics.Reporting; -using App.Metrics.Tagging; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.TextFile -{ - public class TextFileReporter : IMetricReporter - { - private readonly string _file; - private readonly ILogger _logger; - private readonly StringReporter _stringReporter; - private bool _disposed; - - public TextFileReporter(string file, TimeSpan interval, ILoggerFactory loggerFactory) - : this(typeof(TextFileReporter).Name, file, interval, loggerFactory) - { - } - - public TextFileReporter(string name, string file, TimeSpan interval, ILoggerFactory loggerFactory) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (file == null) - { - throw new ArgumentNullException(nameof(file)); - } - - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _file = file; - _logger = loggerFactory.CreateLogger(); - _stringReporter = new StringReporter(name); - Name = name; - ReportInterval = interval; - } - - public string Name { get; } - - public TimeSpan ReportInterval { get; } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - // Free any other managed objects here. - - _stringReporter?.Dispose(); - } - } - - _disposed = true; - } - - public async Task EndAndFlushReportRunAsync(IMetrics metrics) - { - await _stringReporter.EndAndFlushReportRunAsync(metrics); - - _logger.LogTrace($"End {Name} Run"); - - var file = new FileInfo(_file); - file.Directory.Create(); - File.WriteAllText(_file, _stringReporter.Result); - - return true; - } - - public void ReportEnvironment(EnvironmentInfo environmentInfo) { _stringReporter.ReportEnvironment(environmentInfo); } - - public void ReportHealth( - GlobalMetricTags globalMetrics, - IEnumerable healthyChecks, - IEnumerable degradedChecks, - IEnumerable unhealthyChecks) - { - _logger.LogTrace($"Writing Health Checks for {Name}"); - - _stringReporter.ReportHealth(globalMetrics, healthyChecks, degradedChecks, unhealthyChecks); - - _logger.LogTrace($"Writing Health Checks for {Name}"); - } - - public void ReportMetric(string context, MetricValueSourceBase valueSource) - { - _logger.LogTrace($"Start Writing Metric {typeof(T)} for {Name}"); - - _stringReporter.ReportMetric(context, valueSource); - - _logger.LogTrace($"End Writing Metric {typeof(T)} for {Name}"); - } - - public void StartReportRun(IMetrics metrics) - { - _logger.LogTrace($"Starting {Name} Run"); - - _stringReporter.StartReportRun(metrics); - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterExtensions.cs b/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterExtensions.cs deleted file mode 100644 index 4e17a76..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterExtensions.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Reporting.Abstractions; - -namespace App.Metrics.Extensions.Reporting.TextFile -{ - public static class TextFileReporterExtensions - { - public static IReportFactory AddTextFile( - this IReportFactory factory, - TextFileReporterSettings settings, - IFilterMetrics filter = null) - { - factory.AddProvider(new TextFileReporterProvider(settings, filter)); - return factory; - } - - public static IReportFactory AddTextFile(this IReportFactory factory, IFilterMetrics filter = null) - { - var settings = new TextFileReporterSettings(); - factory.AddTextFile(settings, filter); - return factory; - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterProvider.cs b/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterProvider.cs deleted file mode 100644 index bad4947..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Filtering; -using App.Metrics.Abstractions.Reporting; -using Microsoft.Extensions.Logging; - -namespace App.Metrics.Extensions.Reporting.TextFile -{ - public class TextFileReporterProvider : IReporterProvider - { - private readonly TextFileReporterSettings _settings; - - public TextFileReporterProvider(TextFileReporterSettings settings, IFilterMetrics fitler) - { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } - - _settings = settings; - Filter = fitler; - } - - public IFilterMetrics Filter { get; } - - public IMetricReporter CreateMetricReporter(string name, ILoggerFactory loggerFactory) - { - return new TextFileReporter(name, _settings.FileName, _settings.ReportInterval, loggerFactory); - } - } -} \ No newline at end of file diff --git a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterSettings.cs b/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterSettings.cs deleted file mode 100644 index 7e892ad..0000000 --- a/src/App.Metrics.Extensions.Reporting.TextFile/TextFileReporterSettings.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. -// - -using System; -using App.Metrics.Abstractions.Reporting; -using App.Metrics.Reporting; - -namespace App.Metrics.Extensions.Reporting.TextFile -{ - public class TextFileReporterSettings : IReporterSettings - { - public string FileName { get; set; } - - /// - public MetricValueDataKeys DataKeys { get; set; } - - public TimeSpan ReportInterval { get; set; } = TimeSpan.FromSeconds(5); - } -} \ No newline at end of file