diff --git a/.travis.yml b/.travis.yml index 85fdc6a..4c4160e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ notifications: - al_hardy@live.com.au language: csharp -dotnet: 2.0.0-preview1-005977 +dotnet: 2.1.300 os: # - osx - linux diff --git a/README.md b/README.md index 75e09db..6f04278 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# App Metrics Reporting App Metrics +# App Metrics Reporting App Metrics [![Official Site](https://img.shields.io/badge/site-appmetrics-blue.svg?style=flat-square)](http://app-metrics.io/getting-started/intro.html) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square)](https://opensource.org/licenses/Apache-2.0) ## What is it? @@ -7,16 +7,17 @@ The repo contains reporting extension packages to [App Metrics](https://github.c ## Latest Builds, Packages & Repo Stats -|Branch|AppVeyor|Travis|Coverage| -|------|:--------:|:--------:|:--------:| -|dev|[![AppVeyor](https://img.shields.io/appveyor/ci/alhardy/reporting/dev.svg?style=flat-square&label=appveyor%20build)](https://ci.appveyor.com/project/alhardy/reporting/branch/dev)|[![Travis](https://img.shields.io/travis/alhardy/AppMetrics.Reporters/dev.svg?style=flat-square&label=travis%20build)](https://travis-ci.org/alhardy/AppMetrics.Reporters)|[![Coveralls](https://img.shields.io/coveralls/AppMetrics/Reporting/dev.svg?style=flat-square)](https://coveralls.io/github/AppMetrics/Reporting?branch=dev) -|master|[![AppVeyor](https://img.shields.io/appveyor/ci/alhardy/reporting/master.svg?style=flat-square&label=appveyor%20build)](https://ci.appveyor.com/project/alhardy/reporting/branch/master)| [![Travis](https://img.shields.io/travis/alhardy/AppMetrics.Reporters/master.svg?style=flat-square&label=travis%20build)](https://travis-ci.org/AppMetrics.Reporters)| [![Coveralls](https://img.shields.io/coveralls/AppMetrics/Reporters/master.svg?style=flat-square)](https://coveralls.io/github/AppMetrics/Reporters?branch=master)| +|Branch|AppVeyor|Travis| +|------|:--------:|:--------:| +|dev|[![AppVeyor](https://img.shields.io/appveyor/ci/alhardy/reporting/dev.svg?style=flat-square&label=appveyor%20build)](https://ci.appveyor.com/project/alhardy/reporting/branch/dev)|[![Travis](https://img.shields.io/travis/alhardy/AppMetrics.Reporters/dev.svg?style=flat-square&label=travis%20build)](https://travis-ci.org/alhardy/AppMetrics.Reporters) +|master|[![AppVeyor](https://img.shields.io/appveyor/ci/alhardy/reporting/master.svg?style=flat-square&label=appveyor%20build)](https://ci.appveyor.com/project/alhardy/reporting/branch/master)| [![Travis](https://img.shields.io/travis/alhardy/AppMetrics.Reporters/master.svg?style=flat-square&label=travis%20build)](https://travis-ci.org/AppMetrics.Reporters)|| |Package|Dev Release|Pre-Release|Release| |------|:--------:|:--------:|:--------:| |App.Metrics.Reporting.Console|[![MyGet Status](https://img.shields.io/myget/appmetrics/v/App.Metrics.Reporting.Console.svg?style=flat-square)](https://www.myget.org/feed/appmetrics/package/nuget/App.Metrics.Reporting.Console)|[![NuGet Status](https://img.shields.io/nuget/vpre/App.Metrics.Reporting.Console.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Console/)|[![NuGet Status](https://img.shields.io/nuget/v/App.Metrics.Reporting.Console.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Console/) |App.Metrics.Reporting.TextFile|[![MyGet Status](https://img.shields.io/myget/appmetrics/v/App.Metrics.Reporting.TextFile.svg?style=flat-square)](https://www.myget.org/feed/alhardy/package/nuget/App.Metrics.Reporting.TextFile)|[![NuGet Status](https://img.shields.io/nuget/vpre/App.Metrics.Reporting.TextFile.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.TextFile/)|[![NuGet Status](https://img.shields.io/nuget/v/App.Metrics.Reporting.TextFile.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.TextFile/) -|App.Metrics.Reporting.Http|[![MyGet Status](https://img.shields.io/myget/appmetrics/v/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.myget.org/feed/alhardy/package/nuget/App.Metrics.Reporting.Http)|[![NuGet Status](https://img.shields.io/nuget/vpre/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Http/)|[![NuGet Status](https://img.shields.io/nuget/v/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Http/)| +|App.Metrics.Reporting.Http|[![MyGet Status](https://img.shields.io/myget/appmetrics/v/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.myget.org/feed/alhardy/package/nuget/App.Metrics.Reporting.Http)|[![NuGet Status](https://img.shields.io/nuget/vpre/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Http/)|[![NuGet Status](https://img.shields.io/nuget/v/App.Metrics.Reporting.Http.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Http/) +|App.Metrics.Reporting.Socket|[![MyGet Status](https://img.shields.io/myget/appmetrics/v/App.Metrics.Reporting.Socket.svg?style=flat-square)](https://www.myget.org/feed/alhardy/package/nuget/App.Metrics.Reporting.Socket)|[![NuGet Status](https://img.shields.io/nuget/vpre/App.Metrics.Reporting.Socket.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Socket/)|[![NuGet Status](https://img.shields.io/nuget/v/App.Metrics.Reporting.Socket.svg?style=flat-square)](https://www.nuget.org/packages/App.Metrics.Reporting.Socket/)| ## Other Reporters for App Metrics @@ -84,7 +85,7 @@ See the [contribution guidlines](https://github.com/alhardy/AppMetrics/blob/mast ***Thanks for providing free open source licensing*** -* [Jetbrains](https://www.jetbrains.com/dotnet/) +* [Jetbrains](https://www.jetbrains.com/dotnet/) * [AppVeyor](https://www.appveyor.com/) * [Travis CI](https://travis-ci.org/) * [Coveralls](https://coveralls.io/) diff --git a/Reporting.sln b/Reporting.sln index 29db1e8..3acaf9f 100644 --- a/Reporting.sln +++ b/Reporting.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2D805782-756E-4C98-B22E-F502BEE95318}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{31A4DDB1-952E-4EED-96EF-29C669279A86}" ProjectSection(SolutionItems) = preProject @@ -16,6 +19,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DD2E4647-7125-4CE3-9BA5-B45A26113A31}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cake", "Cake", "{E1A943F7-5493-4B64-A448-3E9EEA582E20}" ProjectSection(SolutionItems) = preProject @@ -48,6 +54,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{82BE5E48 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.Http", "src\App.Metrics.Reporting.Http\App.Metrics.Reporting.Http.csproj", "{A4FCA5FE-5866-419D-B2BE-AAF31751C476}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.Socket", "src\App.Metrics.Reporting.Socket\App.Metrics.Reporting.Socket.csproj", "{7DA4DF65-A890-4ACD-8981-AFAAF344C2C0}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReportingSandbox", "sandbox\ReportingSandbox\ReportingSandbox.csproj", "{96B005A1-B339-408F-BAAE-5C95566A7DF1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.Console.Facts", "test\App.Metrics.Reporting.Console.Facts\App.Metrics.Reporting.Console.Facts.csproj", "{5A9AEB7B-FB2A-4933-96D3-DBAF9E25A9B0}" @@ -58,7 +66,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.TextF EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.FactsCommon", "test\App.Metrics.Reporting.FactsCommon\App.Metrics.Reporting.FactsCommon.csproj", "{CEC70E9D-D384-4473-910B-4E96936B3B7D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetricsReceiveSanboxApi", "sandbox\MetricsReceiveSanboxApi\MetricsReceiveSanboxApi.csproj", "{9D0AE951-114B-4590-85D5-56C06652A19A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetricsReceiveSanboxApi", "sandbox\MetricsReceiveSanboxApi\MetricsReceiveSanboxApi.csproj", "{9D0AE951-114B-4590-85D5-56C06652A19A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "App.Metrics.Reporting.Socket.Facts", "test\App.Metrics.Reporting.Socket.Facts\App.Metrics.Reporting.Socket.Facts.csproj", "{F168E7F2-D0BE-4010-B30D-C95990225F32}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -78,6 +88,10 @@ Global {A4FCA5FE-5866-419D-B2BE-AAF31751C476}.Debug|Any CPU.Build.0 = Debug|Any CPU {A4FCA5FE-5866-419D-B2BE-AAF31751C476}.Release|Any CPU.ActiveCfg = Release|Any CPU {A4FCA5FE-5866-419D-B2BE-AAF31751C476}.Release|Any CPU.Build.0 = Release|Any CPU + {7DA4DF65-A890-4ACD-8981-AFAAF344C2C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7DA4DF65-A890-4ACD-8981-AFAAF344C2C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7DA4DF65-A890-4ACD-8981-AFAAF344C2C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7DA4DF65-A890-4ACD-8981-AFAAF344C2C0}.Release|Any CPU.Build.0 = Release|Any CPU {96B005A1-B339-408F-BAAE-5C95566A7DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {96B005A1-B339-408F-BAAE-5C95566A7DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {96B005A1-B339-408F-BAAE-5C95566A7DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -102,6 +116,10 @@ Global {9D0AE951-114B-4590-85D5-56C06652A19A}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D0AE951-114B-4590-85D5-56C06652A19A}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D0AE951-114B-4590-85D5-56C06652A19A}.Release|Any CPU.Build.0 = Release|Any CPU + {F168E7F2-D0BE-4010-B30D-C95990225F32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F168E7F2-D0BE-4010-B30D-C95990225F32}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F168E7F2-D0BE-4010-B30D-C95990225F32}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F168E7F2-D0BE-4010-B30D-C95990225F32}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -113,12 +131,14 @@ Global {2B01FDF8-8E73-4904-9B2C-5BFA505BFF5F} = {2D805782-756E-4C98-B22E-F502BEE95318} {82BE5E48-3A8F-4B09-8A3A-03448C6D2B4D} = {31A4DDB1-952E-4EED-96EF-29C669279A86} {A4FCA5FE-5866-419D-B2BE-AAF31751C476} = {2D805782-756E-4C98-B22E-F502BEE95318} + {7DA4DF65-A890-4ACD-8981-AFAAF344C2C0} = {2D805782-756E-4C98-B22E-F502BEE95318} {96B005A1-B339-408F-BAAE-5C95566A7DF1} = {887BC5A0-8ED7-4460-851D-5EFC4AE828DE} {5A9AEB7B-FB2A-4933-96D3-DBAF9E25A9B0} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} {457CACEF-A3DB-4A0B-8665-A5E20AA925E0} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} {9032C810-1ABC-4631-AE3F-0F9A3482BA6B} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} {CEC70E9D-D384-4473-910B-4E96936B3B7D} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} {9D0AE951-114B-4590-85D5-56C06652A19A} = {887BC5A0-8ED7-4460-851D-5EFC4AE828DE} + {F168E7F2-D0BE-4010-B30D-C95990225F32} = {DD2E4647-7125-4CE3-9BA5-B45A26113A31} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {492C97B1-706A-4357-B3F7-EFB6AFB1F6C6} diff --git a/appveyor.yml b/appveyor.yml index 53bed38..d03ee6b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -33,8 +33,8 @@ deploy: skip_symbols: true symbol_server: https://www.myget.org/F/appmetrics/symbol install: - - cmd: curl -O https://download.microsoft.com/download/0/F/D/0FD852A4-7EA1-4E2A-983A-0484AC19B92C/dotnet-sdk-2.0.0-win-x64.exe - - cmd: dotnet-sdk-2.0.0-win-x64.exe /install /quiet /norestart /log install.log + - cmd: curl -O https://download.microsoft.com/download/8/8/5/88544F33-836A-49A5-8B67-451C24709A8F/dotnet-sdk-2.1.300-win-x64.exe + - cmd: dotnet-sdk-2.1.300-win-x64.exe /install /quiet /norestart /log install.log skip_commits: files: - '**/*.md' \ No newline at end of file diff --git a/build.cake b/build.cake index eddb262..5607646 100644 --- a/build.cake +++ b/build.cake @@ -14,34 +14,35 @@ // ARGUMENTS ////////////////////////////////////////////////////////////////////// var packageRelease = HasArgument("packageRelease") ? Argument("packageRelease") : - EnvironmentVariable("packageRelease") != null ? bool.Parse(EnvironmentVariable("packageRelease")) : false; + EnvironmentVariable("packageRelease") != null ? bool.Parse(EnvironmentVariable("packageRelease")) : false; var target = Argument("target", "Default"); var configuration = HasArgument("BuildConfiguration") ? Argument("BuildConfiguration") : - EnvironmentVariable("BuildConfiguration") != null ? EnvironmentVariable("BuildConfiguration") : "Release"; + EnvironmentVariable("BuildConfiguration") != null ? EnvironmentVariable("BuildConfiguration") : "Release"; var coverWith = HasArgument("CoverWith") ? Argument("CoverWith") : - EnvironmentVariable("CoverWith") != null ? EnvironmentVariable("CoverWith") : "DotCover"; // None, DotCover, OpenCover + EnvironmentVariable("CoverWith") != null ? EnvironmentVariable("CoverWith") : "DotCover"; // None, DotCover, OpenCover var skipReSharperCodeInspect = HasArgument("SkipCodeInspect") ? Argument("SkipCodeInspect", false) || !IsRunningOnWindows(): true; var preReleaseSuffix = HasArgument("PreReleaseSuffix") ? Argument("PreReleaseSuffix") : - (AppVeyor.IsRunningOnAppVeyor && EnvironmentVariable("PreReleaseSuffix") == null) || (AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag && !packageRelease) + (AppVeyor.IsRunningOnAppVeyor && EnvironmentVariable("PreReleaseSuffix") == null) || (AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag && !packageRelease) ? 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; + 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"); var skipHtmlCoverageReport = HasArgument("SkipHtmlCoverageReport") ? Argument("SkipHtmlCoverageReport", true) || !IsRunningOnWindows() : true; var linkSources = HasArgument("LinkSources") ? Argument("LinkSources") : - EnvironmentVariable("LinkSources") != null ? bool.Parse(EnvironmentVariable("LinkSources")) : true; + EnvironmentVariable("LinkSources") != null ? bool.Parse(EnvironmentVariable("LinkSources")) : true; ////////////////////////////////////////////////////////////////////// // DEFINE FILES & DIRECTORIES ////////////////////////////////////////////////////////////////////// -var packDirs = new [] - { +var packDirs = new [] + { Directory("./src/App.Metrics.Reporting.Console"), - Directory("./src/App.Metrics.Reporting.TextFile"), - Directory("./src/App.Metrics.Reporting.Http") + Directory("./src/App.Metrics.Reporting.Http"), + Directory("./src/App.Metrics.Reporting.Socket"), + Directory("./src/App.Metrics.Reporting.TextFile") }; var artifactsDir = (DirectoryPath) Directory("./artifacts"); var testResultsDir = (DirectoryPath) artifactsDir.Combine("test-results"); @@ -69,44 +70,57 @@ var coverExcludeFilter = "-:*.Facts"; var excludeFromCoverage = "*.ExcludeFromCodeCoverage*"; string versionSuffix = null; -if (!string.IsNullOrEmpty(preReleaseSuffix)) +if (AppVeyor.IsRunningOnAppVeyor) { - if (packageRelease && AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag) + if (AppVeyor.Environment.Repository.Tag.IsTag) { - versionSuffix = preReleaseSuffix; + // Stable release package, pushed to nuget + } + else if (string.IsNullOrEmpty(preReleaseSuffix)) + { + // Next stable release development package, not pushed to nuget + versionSuffix = buildNumber.ToString("D4"); } else { - versionSuffix = preReleaseSuffix + "-" + buildNumber.ToString("D4"); + if (packageRelease) + { + // Pre-release package, set version suffix without build number, not tagged until stable release but pushed to nuget + versionSuffix = preReleaseSuffix; + } + else + { + // Pre-release development package, set version suffix with build number, not pushed to nuget + versionSuffix = preReleaseSuffix + "-" + buildNumber.ToString("D4"); + } } } -else if (AppVeyor.IsRunningOnAppVeyor && !AppVeyor.Environment.Repository.Tag.IsTag && !packageRelease) +else { - versionSuffix = buildNumber.ToString("D4"); + versionSuffix = preReleaseSuffix + "-" + buildNumber.ToString("D4"); } - ////////////////////////////////////////////////////////////////////// // TASKS ////////////////////////////////////////////////////////////////////// Task("Clean") - .Does(() => + .Does(() => { Context.Information("Cleaning files *.trx"); var rootDir = new System.IO.DirectoryInfo("./"); rootDir.GetFiles("*.trx", SearchOption.AllDirectories).ToList().ForEach(file=>file.Delete()); - CleanDirectory(artifactsDir); + CleanDirectory(artifactsDir); CleanDirectory(coverageResultsDir); CleanDirectory(testResultsDir); }); Task("ReleaseNotes") - .IsDependentOn("Clean") + .IsDependentOn("Clean") .WithCriteria(() => AppVeyor.IsRunningOnAppVeyor && AppVeyor.Environment.Repository.Tag.IsTag) - .Does(() => -{ + .Does(() => +{ var preRelease = preReleaseSuffix != null; var milestone = AppVeyor.Environment.Repository.Tag.Name; var owner = AppVeyor.Environment.Repository.Name.Split('/')[0]; @@ -127,21 +141,21 @@ Task("ReleaseNotes") }); Task("Restore") - .IsDependentOn("Clean") - .Does(() => -{ + .IsDependentOn("Clean") + .Does(() => +{ var settings = new DotNetCoreRestoreSettings - { - Sources = new [] { "https://api.nuget.org/v3/index.json", "https://www.myget.org/F/appmetrics/api/v3/index.json" } - }; + { + Sources = new [] { "https://api.nuget.org/v3/index.json", "https://www.myget.org/F/appmetrics/api/v3/index.json" } + }; DotNetCoreRestore(solutionFile, settings); }); -Task("Build") - .IsDependentOn("Restore") - .Does(() => -{ +Task("Build") + .IsDependentOn("Restore") + .Does(() => +{ var settings = new DotNetCoreBuildSettings { Configuration = configuration, VersionSuffix = versionSuffix }; Context.Information("Building using preReleaseSuffix: " + preReleaseSuffix); @@ -152,9 +166,9 @@ Task("Build") args.Append("/t:Restore /p:RestoreSources=https://api.nuget.org/v3/index.json;https://www.myget.org/F/appmetrics/api/v3/index.json;"); if (linkSources) { args.Append("/p:SourceLinkCreate=true"); - } + } return args; - }; + }; if (IsRunningOnWindows()) @@ -164,23 +178,23 @@ Task("Build") else { // var projects = solution.GetProjects(); - // + // // foreach(var project in projects) - // { + // { // var parsedProject = ParseProject(new FilePath(project.Path.ToString()), configuration); - // + // // if (parsedProject.IsLibrary() && !project.Path.ToString().Contains(".Sandbox")&& !project.Path.ToString().Contains(".Facts") && !project.Path.ToString().Contains(".Benchmarks")) - // { + // { // settings.Framework = "netstandard2.0"; - // + // // } // else // { // settings.Framework = "netcoreapp2.0"; // } - // + // // Context.Information("Building as " + settings.Framework + ": " + project.Path.ToString()); - // + // // DotNetCoreBuild(project.Path.ToString(), settings); // } @@ -188,9 +202,9 @@ Task("Build") }); Task("Pack") - .IsDependentOn("Restore") - .IsDependentOn("Clean") - .Does(() => + .IsDependentOn("Restore") + .IsDependentOn("Clean") + .Does(() => { if (!IsRunningOnWindows()) { @@ -201,66 +215,66 @@ Task("Pack") Context.Information("Packing using preReleaseSuffix: " + preReleaseSuffix); Context.Information("Packing using versionSuffix: " + versionSuffix); - var settings = new DotNetCorePackSettings - { - Configuration = configuration, - OutputDirectory = packagesDir, - VersionSuffix = versionSuffix, + var settings = new DotNetCorePackSettings + { + Configuration = configuration, + OutputDirectory = packagesDir, + VersionSuffix = versionSuffix, NoBuild = true, // Workaround to fixing pre-release version package references - https://github.com/NuGet/Home/issues/4337 ArgumentCustomization = args=>args.Append("/p:RestoreSources=https://api.nuget.org/v3/index.json;https://www.myget.org/F/appmetrics/api/v3/index.json;") - }; - - foreach(var packDir in packDirs) - { - DotNetCorePack(packDir, settings); - } + }; + + foreach(var packDir in packDirs) + { + DotNetCorePack(packDir, settings); + } }); Task("RunInspectCode") .WithCriteria(() => !skipReSharperCodeInspect) - .Does(() => + .Does(() => { InspectCode(solutionFile, new InspectCodeSettings { SolutionWideAnalysis = true, Profile = resharperSettings, OutputFile = inspectCodeXml }); - ReSharperReports(inspectCodeXml, inspectCodeHtml); + ReSharperReports(inspectCodeXml, inspectCodeHtml); }); Task("RunTests") .WithCriteria(() => coverWith == "None" || !IsRunningOnWindows()) - .IsDependentOn("Build") - .Does(() => + .IsDependentOn("Build") + .Does(() => { - var projects = GetFiles("./test/**/*.csproj"); + var projects = GetFiles("./test/**/*.csproj"); - CreateDirectory(coverageResultsDir); + CreateDirectory(coverageResultsDir); - Context.Information("Found " + projects.Count() + " projects"); + Context.Information("Found " + projects.Count() + " projects"); - foreach (var project in projects) - { - var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; - var settings = new DotNetCoreTestSettings + foreach (var project in projects) + { + var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; + var settings = new DotNetCoreTestSettings { Configuration = configuration, // Workaround to fixing pre-release version package references - https://github.com/NuGet/Home/issues/4337 ArgumentCustomization = args=>args.Append("--logger:trx /t:Restore /p:RestoreSources=https://api.nuget.org/v3/index.json;https://www.myget.org/F/appmetrics/api/v3/index.json;") }; - + if (!IsRunningOnWindows()) - { + { settings.Framework = "netcoreapp2.0"; - } + } DotNetCoreTest(project.FullPath, settings); - } + } }); -Task("HtmlCoverageReport") - .WithCriteria(() => IsRunningOnWindows() && FileExists(testOCoverageOutputFilePath) && coverWith != "None" && !skipHtmlCoverageReport) - .IsDependentOn("RunTests") - .Does(() => +Task("HtmlCoverageReport") + .WithCriteria(() => IsRunningOnWindows() && FileExists(testOCoverageOutputFilePath) && coverWith != "None" && !skipHtmlCoverageReport) + .IsDependentOn("RunTests") + .Does(() => { - if (coverWith == "DotCover") + if (coverWith == "DotCover") { DotCoverReport( mergedCoverageSnapshots, @@ -277,29 +291,29 @@ Task("HtmlCoverageReport") Task("RunTestsWithOpenCover") .WithCriteria(() => coverWith == "OpenCover" && IsRunningOnWindows()) - .IsDependentOn("Build") - .Does(() => + .IsDependentOn("Build") + .Does(() => { var projects = GetFiles("./test/**/*.csproj"); - CreateDirectory(coverageResultsDir); + CreateDirectory(coverageResultsDir); - Context.Information("Found " + projects.Count() + " projects"); + Context.Information("Found " + projects.Count() + " projects"); var settings = new DotNetCoreTestSettings - { - Configuration = configuration, + { + Configuration = configuration, // Workaround to fixing pre-release version package references - https://github.com/NuGet/Home/issues/4337 ArgumentCustomization = args=>args.Append("--logger:trx /t:Restore /p:RestoreSources=https://api.nuget.org/v3/index.json;https://www.myget.org/F/appmetrics/api/v3/index.json;") - }; + }; + + foreach (var project in projects) + { + var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; - foreach (var project in projects) - { - var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; - Action testAction = tool => { tool.DotNetCoreTest(project.ToString(), settings); }; - var openCoverSettings = new OpenCoverSettings { + var openCoverSettings = new OpenCoverSettings { ReturnTargetCodeOffset = 1, SkipAutoProps = true, Register = "user", @@ -312,25 +326,25 @@ Task("RunTestsWithOpenCover") openCoverSettings.ExcludeByAttribute(excludeFromCoverage); openCoverSettings.ExcludeByFile(openCoverExcludeFile); - OpenCover(testAction, testOCoverageOutputFilePath, openCoverSettings); - } + OpenCover(testAction, testOCoverageOutputFilePath, openCoverSettings); + } }); Task("PublishTestResults") .IsDependentOn("RunTestsWithDotCover") .IsDependentOn("RunTestsWithOpenCover") .IsDependentOn("RunTests") - .Does(() => + .Does(() => { if (IsRunningOnWindows()) - { + { CreateDirectory(testResultsDir); var projects = GetFiles("./test/**/*.csproj"); - + foreach (var project in projects) - { - var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; + { + var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; IEnumerable filePaths = GetFiles(System.IO.Path.GetDirectoryName(project.ToString()) + "/TestResults" + "/*.trx"); @@ -348,59 +362,59 @@ Task("PublishTestResults") catch(Exception ex) { Context.Information(ex.ToString()); - } + } } - } + } } }); Task("RunTestsWithDotCover") .WithCriteria(() => coverWith == "DotCover" && IsRunningOnWindows()) - .IsDependentOn("Build") - .Does(() => + .IsDependentOn("Build") + .Does(() => { var projects = GetFiles("./test/**/*.csproj"); - - CreateDirectory(coverageResultsDir); - Context.Information("Found " + projects.Count() + " projects"); + CreateDirectory(coverageResultsDir); + + Context.Information("Found " + projects.Count() + " projects"); var settings = new DotNetCoreTestSettings - { - Configuration = configuration, + { + Configuration = configuration, // Workaround to fixing pre-release version package references - https://github.com/NuGet/Home/issues/4337 ArgumentCustomization = args=>args.Append("--logger:trx /t:Restore /p:RestoreSources=https://api.nuget.org/v3/index.json;https://www.myget.org/F/appmetrics/api/v3/index.json;") - }; + }; + + foreach (var project in projects) + { + var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; - foreach (var project in projects) - { - var folderName = new System.IO.DirectoryInfo(System.IO.Path.GetDirectoryName(project.ToString())).Name; - Action testAction = tool => { tool.DotNetCoreTest(project.ToString(), settings); }; - var dotCoverSettings = new DotCoverCoverSettings + var dotCoverSettings = new DotCoverCoverSettings { ArgumentCustomization = args => args.Append(@"/HideAutoProperties") .Append(@"/AttributeFilters=System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute") .Append(@"/Filters=+:module=App.Metrics*;-:module=*.Facts*;") - .Append(@"/ReturnTargetExitCode") + .Append(@"/ReturnTargetExitCode") }; - + dotCoverSettings.WithFilter(coverIncludeFilter).WithFilter(coverExcludeFilter); - var coverageFile = coverageResultsDir.FullPath + folderName + ".dcvr"; + var coverageFile = coverageResultsDir.FullPath + folderName + ".dcvr"; - DotCoverCover(testAction, new FilePath(coverageFile), dotCoverSettings); + DotCoverCover(testAction, new FilePath(coverageFile), dotCoverSettings); - MoveFiles(coverageFile, coverageResultsDir); - } + MoveFiles(coverageFile, coverageResultsDir); + } - var snapshots = GetFiles(coverageResultsDir.FullPath + "/*.dcvr"); + var snapshots = GetFiles(coverageResultsDir.FullPath + "/*.dcvr"); - if (snapshots != null && snapshots.Any()) + if (snapshots != null && snapshots.Any()) { DotCoverMerge(snapshots, - new FilePath(mergedCoverageSnapshots), null); + new FilePath(mergedCoverageSnapshots), null); DotCoverReport( mergedCoverageSnapshots, @@ -410,42 +424,42 @@ Task("RunTestsWithDotCover") }); -Task("PublishCoverage") - .WithCriteria(() => FileExists(testOCoverageOutputFilePath)) - .WithCriteria(() => !BuildSystem.IsLocalBuild) +Task("PublishCoverage") + .WithCriteria(() => FileExists(testOCoverageOutputFilePath)) + .WithCriteria(() => !BuildSystem.IsLocalBuild) .WithCriteria(() => coverWith == "OpenCover") - .WithCriteria(() => !string.IsNullOrEmpty(coverallsToken)) - .IsDependentOn("RunTests") - .Does(() => + .WithCriteria(() => !string.IsNullOrEmpty(coverallsToken)) + .IsDependentOn("RunTests") + .Does(() => { - CoverallsIo(testOCoverageOutputFilePath, new CoverallsIoSettings() - { - RepoToken = coverallsToken - }); + CoverallsIo(testOCoverageOutputFilePath, new CoverallsIoSettings() + { + RepoToken = coverallsToken + }); }); ////////////////////////////////////////////////////////////////////// // TASK TARGETS ////////////////////////////////////////////////////////////////////// -Task("Default") - .IsDependentOn("Build") - .IsDependentOn("PublishTestResults") - .IsDependentOn("Pack") +Task("Default") + .IsDependentOn("Build") + .IsDependentOn("PublishTestResults") + .IsDependentOn("Pack") .IsDependentOn("HtmlCoverageReport") - .IsDependentOn("RunInspectCode"); + .IsDependentOn("RunInspectCode"); -Task("AppVeyor") - .IsDependentOn("Build") - .IsDependentOn("PublishTestResults") - .IsDependentOn("Pack") +Task("AppVeyor") + .IsDependentOn("Build") + .IsDependentOn("PublishTestResults") + .IsDependentOn("Pack") .IsDependentOn("HtmlCoverageReport") - .IsDependentOn("RunInspectCode") - .IsDependentOn("PublishCoverage") + .IsDependentOn("RunInspectCode") + .IsDependentOn("PublishCoverage") .IsDependentOn("ReleaseNotes"); ////////////////////////////////////////////////////////////////////// // EXECUTION ////////////////////////////////////////////////////////////////////// -RunTarget(target); \ No newline at end of file +RunTarget(target); diff --git a/build/common.props b/build/common.props index 309b34c..3987dbc 100644 --- a/build/common.props +++ b/build/common.props @@ -13,7 +13,7 @@ https://www.app-metrics.io/reporting/ https://github.com/AppMetrics/Reporting/blob/master/LICENSE git - git://github.com/AppMetrics/AppMetricsReporting + git://github.com/AppMetrics/Reporting false false false @@ -23,7 +23,7 @@ $(MSBuildThisFileDirectory)Key.snk true true - embedded + full diff --git a/build/dependencies.props b/build/dependencies.props index fc10ac4..f6a841f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -1,18 +1,18 @@ - 2.0.0-* - 2.0.0-* - 2.0.0-* - 4.4.0-* - 2.0.0-* - 4.8.2 - 10.0.2 - 2.0.0-* - 2.0.0-* - 15.5.0 - 2.3.1 - 5.2.0 - 5.2.0 + 3.0.0-* + 3.0.0-* + 2.1.6 + 2.1.3 + 4.4.0 + 2.1.1 + 2.1.1 + 4.10.0 + 11.0.2 + 15.9.0 + 2.4.1 + 5.5.3 + 5.0.0 1.0.0 \ No newline at end of file diff --git a/global.json b/global.json index 2df97a2..92ef4c7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { - "projects": [ "src", "test", "benchmarks", "sandbox" ], + "projects": [ "src", "test", "sandbox" ], "sdk": { - "version": "2.0.0" + "version": "2.1.300" } } \ No newline at end of file diff --git a/sandbox/MetricsReceiveSanboxApi/Controllers/MetricsController.cs b/sandbox/MetricsReceiveSanboxApi/Controllers/MetricsController.cs index 13b2728..503a55b 100644 --- a/sandbox/MetricsReceiveSanboxApi/Controllers/MetricsController.cs +++ b/sandbox/MetricsReceiveSanboxApi/Controllers/MetricsController.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using Microsoft.AspNetCore.Mvc; @@ -7,7 +7,7 @@ namespace MetricsReceiveSanboxApi.Controllers { [Route("api/[controller]")] - public class MetricsController : Controller + public class MetricsController : ControllerBase { [HttpPost] public void Post([FromBody] MetricsModel metrics) diff --git a/sandbox/MetricsReceiveSanboxApi/MetricsModel.cs b/sandbox/MetricsReceiveSanboxApi/MetricsModel.cs index b7e1b02..3b866e6 100644 --- a/sandbox/MetricsReceiveSanboxApi/MetricsModel.cs +++ b/sandbox/MetricsReceiveSanboxApi/MetricsModel.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj b/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj index 2caa9ce..4705803 100644 --- a/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj +++ b/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj @@ -1,10 +1,10 @@ - + - netcoreapp2.0;net461 - netcoreapp2.0 + netcoreapp2.1 + $(TargetFrameworks);net461 @@ -14,10 +14,10 @@ - - - - + + + + diff --git a/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj.DotSettings b/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/sandbox/MetricsReceiveSanboxApi/MetricsReceiveSanboxApi.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/sandbox/MetricsReceiveSanboxApi/Program.cs b/sandbox/MetricsReceiveSanboxApi/Program.cs index a19b62a..dfa7f77 100644 --- a/sandbox/MetricsReceiveSanboxApi/Program.cs +++ b/sandbox/MetricsReceiveSanboxApi/Program.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System.Threading.Tasks; @@ -12,7 +12,7 @@ namespace MetricsReceiveSanboxApi { public static class Program { - public static IMetricsRoot Metrics { get; private set; } + public static IMetricsRoot Metrics => null; public static Task Main() { diff --git a/sandbox/MetricsReceiveSanboxApi/Startup.cs b/sandbox/MetricsReceiveSanboxApi/Startup.cs index 87dfb82..77a4e90 100644 --- a/sandbox/MetricsReceiveSanboxApi/Startup.cs +++ b/sandbox/MetricsReceiveSanboxApi/Startup.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using Microsoft.AspNetCore.Builder; @@ -27,6 +27,6 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) } // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } + public void ConfigureServices(IServiceCollection services) { services.AddMvcCore(); } } } \ No newline at end of file diff --git a/sandbox/ReportingSandbox/JustForTesting/AppMetricsRegistry.cs b/sandbox/ReportingSandbox/JustForTesting/AppMetricsRegistry.cs index 86ed6b2..2937907 100644 --- a/sandbox/ReportingSandbox/JustForTesting/AppMetricsRegistry.cs +++ b/sandbox/ReportingSandbox/JustForTesting/AppMetricsRegistry.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using App.Metrics; diff --git a/sandbox/ReportingSandbox/JustForTesting/CpuUsage.cs b/sandbox/ReportingSandbox/JustForTesting/CpuUsage.cs index c082544..6b527cd 100644 --- a/sandbox/ReportingSandbox/JustForTesting/CpuUsage.cs +++ b/sandbox/ReportingSandbox/JustForTesting/CpuUsage.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/MultiContextInstanceMetrics.cs b/sandbox/ReportingSandbox/JustForTesting/MultiContextInstanceMetrics.cs index 4c076c4..00e328f 100644 --- a/sandbox/ReportingSandbox/JustForTesting/MultiContextInstanceMetrics.cs +++ b/sandbox/ReportingSandbox/JustForTesting/MultiContextInstanceMetrics.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using App.Metrics; diff --git a/sandbox/ReportingSandbox/JustForTesting/MultiContextMetrics.cs b/sandbox/ReportingSandbox/JustForTesting/MultiContextMetrics.cs index 25f98a6..8c6c9dc 100644 --- a/sandbox/ReportingSandbox/JustForTesting/MultiContextMetrics.cs +++ b/sandbox/ReportingSandbox/JustForTesting/MultiContextMetrics.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using App.Metrics; diff --git a/sandbox/ReportingSandbox/JustForTesting/ProcessSample.cs b/sandbox/ReportingSandbox/JustForTesting/ProcessSample.cs index c5f4821..931d1c7 100644 --- a/sandbox/ReportingSandbox/JustForTesting/ProcessSample.cs +++ b/sandbox/ReportingSandbox/JustForTesting/ProcessSample.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System.Diagnostics; diff --git a/sandbox/ReportingSandbox/JustForTesting/SampleMetrics.cs b/sandbox/ReportingSandbox/JustForTesting/SampleMetrics.cs index ebcb7be..e6d5890 100644 --- a/sandbox/ReportingSandbox/JustForTesting/SampleMetrics.cs +++ b/sandbox/ReportingSandbox/JustForTesting/SampleMetrics.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRegistry.cs b/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRegistry.cs index e4b9934..3f636ff 100644 --- a/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRegistry.cs +++ b/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRegistry.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using App.Metrics; diff --git a/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRunner.cs b/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRunner.cs index 06d3568..f8db138 100644 --- a/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRunner.cs +++ b/sandbox/ReportingSandbox/JustForTesting/SampleMetricsRunner.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/SetCounterSample.cs b/sandbox/ReportingSandbox/JustForTesting/SetCounterSample.cs index 2fdf4b5..1d8ce1c 100644 --- a/sandbox/ReportingSandbox/JustForTesting/SetCounterSample.cs +++ b/sandbox/ReportingSandbox/JustForTesting/SetCounterSample.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/SetMeterSample.cs b/sandbox/ReportingSandbox/JustForTesting/SetMeterSample.cs index 0f948c6..33c0fee 100644 --- a/sandbox/ReportingSandbox/JustForTesting/SetMeterSample.cs +++ b/sandbox/ReportingSandbox/JustForTesting/SetMeterSample.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/UserValueHistogramSample.cs b/sandbox/ReportingSandbox/JustForTesting/UserValueHistogramSample.cs index a8e8abb..bc58d72 100644 --- a/sandbox/ReportingSandbox/JustForTesting/UserValueHistogramSample.cs +++ b/sandbox/ReportingSandbox/JustForTesting/UserValueHistogramSample.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/JustForTesting/UserValueTimerSample.cs b/sandbox/ReportingSandbox/JustForTesting/UserValueTimerSample.cs index ad56790..a1b2c00 100644 --- a/sandbox/ReportingSandbox/JustForTesting/UserValueTimerSample.cs +++ b/sandbox/ReportingSandbox/JustForTesting/UserValueTimerSample.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/sandbox/ReportingSandbox/Program.cs b/sandbox/ReportingSandbox/Program.cs index 4b679e9..bcb0b40 100644 --- a/sandbox/ReportingSandbox/Program.cs +++ b/sandbox/ReportingSandbox/Program.cs @@ -1,10 +1,11 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; using System.Threading.Tasks; using App.Metrics; +using App.Metrics.Formatters.InfluxDB; using Microsoft.AspNetCore.Hosting; using ReportingSandbox.JustForTesting; using Serilog; @@ -48,6 +49,9 @@ private static void Init() .Report.ToTextFile(@"C:\metrics\sample.txt", TimeSpan.FromSeconds(5)) .Report.OverHttp("http://localhost:50001/metrics-receive", TimeSpan.FromSeconds(10)) .Report.OverHttp("http://localhost:50002/api/metrics", TimeSpan.FromSeconds(10)) + // .Report.OverTcp(new MetricsInfluxDbLineProtocolOutputFormatter(), "localhost", 8094) + .Report.OverUdp(new MetricsInfluxDbLineProtocolOutputFormatter(), "localhost", 8094) + // .Report.OverUds(new MetricsInfluxDbLineProtocolOutputFormatter(), "/tmp/telegraf.sock") .Build(); } } diff --git a/sandbox/ReportingSandbox/ReportingSandbox.csproj b/sandbox/ReportingSandbox/ReportingSandbox.csproj index 36f296f..0cf1084 100644 --- a/sandbox/ReportingSandbox/ReportingSandbox.csproj +++ b/sandbox/ReportingSandbox/ReportingSandbox.csproj @@ -3,23 +3,26 @@ - netcoreapp2.0;net461 - netcoreapp2.0 + netcoreapp2.1 + $(TargetFrameworks);net461 - + + + - - - - + + + + + diff --git a/sandbox/ReportingSandbox/ReportingSandbox.csproj.DotSettings b/sandbox/ReportingSandbox/ReportingSandbox.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/sandbox/ReportingSandbox/ReportingSandbox.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/sandbox/ReportingSandbox/Startup.cs b/sandbox/ReportingSandbox/Startup.cs index 763284f..83335ae 100644 --- a/sandbox/ReportingSandbox/Startup.cs +++ b/sandbox/ReportingSandbox/Startup.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System.IO; @@ -19,9 +19,7 @@ public class Startup public void ConfigureServices(IServiceCollection services) // ReSharper restore UnusedMember.Global { - // TODO: At the moment using the IHostedService implemented in App.Metrics.AspNetCore.Reporting, - // similar will be provided when the "Generic Host" is available - https://github.com/aspnet/Hosting/issues/1163 - services.AddMetricsReportScheduler(); + services.AddMetricsReportingHostedService(); services.AddMetrics(Program.Metrics); } diff --git a/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj b/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj index 92efc25..592dcfc 100644 --- a/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj +++ b/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj @@ -1,11 +1,12 @@  - + Provides console reporting capability to App Metrics App.Metrics.Reporting.Console - netstandard1.6;net452 + netstandard1.6 + $(TargetFrameworks);net452 appmetrics;reporting;console diff --git a/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj.DotSettings b/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/src/App.Metrics.Reporting.Console/App.Metrics.Reporting.Console.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/src/App.Metrics.Reporting.Console/Builder/MetricsConsoleReporterBuilder.cs b/src/App.Metrics.Reporting.Console/Builder/MetricsConsoleReporterBuilder.cs index ae275f4..eb9435b 100644 --- a/src/App.Metrics.Reporting.Console/Builder/MetricsConsoleReporterBuilder.cs +++ b/src/App.Metrics.Reporting.Console/Builder/MetricsConsoleReporterBuilder.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Console/ConsoleMetricsReporter.cs b/src/App.Metrics.Reporting.Console/ConsoleMetricsReporter.cs index 6e33468..80396ff 100644 --- a/src/App.Metrics.Reporting.Console/ConsoleMetricsReporter.cs +++ b/src/App.Metrics.Reporting.Console/ConsoleMetricsReporter.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Console/MetricsReportingConsoleOptions.cs b/src/App.Metrics.Reporting.Console/MetricsReportingConsoleOptions.cs index 8f557f8..06437e4 100644 --- a/src/App.Metrics.Reporting.Console/MetricsReportingConsoleOptions.cs +++ b/src/App.Metrics.Reporting.Console/MetricsReportingConsoleOptions.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj b/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj index cb85848..40d1bcf 100644 --- a/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj +++ b/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj @@ -4,8 +4,8 @@ Provides HTTP reporting capability to App Metrics - App.Metrics.Reporting.Http - netstandard1.6;net452 + netstandard1.6 + $(TargetFrameworks);net452 appmetrics;reporting;http @@ -14,4 +14,9 @@ + + + + + diff --git a/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj.DotSettings b/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/src/App.Metrics.Reporting.Http/App.Metrics.Reporting.Http.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/src/App.Metrics.Reporting.Http/Builder/MetricsHttpReporterBuilder.cs b/src/App.Metrics.Reporting.Http/Builder/MetricsHttpReporterBuilder.cs index e8f3660..bb89b6a 100644 --- a/src/App.Metrics.Reporting.Http/Builder/MetricsHttpReporterBuilder.cs +++ b/src/App.Metrics.Reporting.Http/Builder/MetricsHttpReporterBuilder.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/Client/Constants.cs b/src/App.Metrics.Reporting.Http/Client/Constants.cs index eb88aee..2e2d2b8 100644 --- a/src/App.Metrics.Reporting.Http/Client/Constants.cs +++ b/src/App.Metrics.Reporting.Http/Client/Constants.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/Client/DefaultHttpClient.cs b/src/App.Metrics.Reporting.Http/Client/DefaultHttpClient.cs index 22af97f..d980383 100644 --- a/src/App.Metrics.Reporting.Http/Client/DefaultHttpClient.cs +++ b/src/App.Metrics.Reporting.Http/Client/DefaultHttpClient.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/Client/HttpPolicy.cs b/src/App.Metrics.Reporting.Http/Client/HttpPolicy.cs index f670db0..973bf75 100644 --- a/src/App.Metrics.Reporting.Http/Client/HttpPolicy.cs +++ b/src/App.Metrics.Reporting.Http/Client/HttpPolicy.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/Client/HttpSettings.cs b/src/App.Metrics.Reporting.Http/Client/HttpSettings.cs index 5b0b4d8..7a64743 100644 --- a/src/App.Metrics.Reporting.Http/Client/HttpSettings.cs +++ b/src/App.Metrics.Reporting.Http/Client/HttpSettings.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/Client/HttpWriteResult.cs b/src/App.Metrics.Reporting.Http/Client/HttpWriteResult.cs index 501dea5..2cd6b78 100644 --- a/src/App.Metrics.Reporting.Http/Client/HttpWriteResult.cs +++ b/src/App.Metrics.Reporting.Http/Client/HttpWriteResult.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // namespace App.Metrics.Reporting.Http.Client diff --git a/src/App.Metrics.Reporting.Http/HttpMetricsReporter.cs b/src/App.Metrics.Reporting.Http/HttpMetricsReporter.cs index 55d0350..17c1e10 100644 --- a/src/App.Metrics.Reporting.Http/HttpMetricsReporter.cs +++ b/src/App.Metrics.Reporting.Http/HttpMetricsReporter.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Http/MetricsReportingHttpOptions.cs b/src/App.Metrics.Reporting.Http/MetricsReportingHttpOptions.cs index f3a5135..d5a53e8 100644 --- a/src/App.Metrics.Reporting.Http/MetricsReportingHttpOptions.cs +++ b/src/App.Metrics.Reporting.Http/MetricsReportingHttpOptions.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.Socket/App.Metrics.Reporting.Socket.csproj b/src/App.Metrics.Reporting.Socket/App.Metrics.Reporting.Socket.csproj new file mode 100644 index 0000000..5d01bd2 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/App.Metrics.Reporting.Socket.csproj @@ -0,0 +1,21 @@ + + + + + + Provides reporting capability to App Metrics via sockets + netstandard1.6 + $(TargetFrameworks);net452 + appmetrics;reporting;socket;tcp;udp;uds + + + + + + + + + + + + diff --git a/src/App.Metrics.Reporting.Socket/Builder/MetricsTcpReporterBuilder.cs b/src/App.Metrics.Reporting.Socket/Builder/MetricsTcpReporterBuilder.cs new file mode 100644 index 0000000..2b2c133 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Builder/MetricsTcpReporterBuilder.cs @@ -0,0 +1,155 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Net.Sockets; +using App.Metrics.Builder; +using App.Metrics.Formatters; +using App.Metrics.Reporting.Socket; +using App.Metrics.Reporting.Socket.Client; + +// ReSharper disable CheckNamespace +namespace App.Metrics + // ReSharper restore CheckNamespace +{ + /// + /// Builder for configuring metrics TCP reporting using an + /// . + /// + public static class MetricsTcpReporterBuilder + { + /// + /// Add the allowing metrics to be reported over TCP. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverTcp( + this IMetricsReportingBuilder reportingBuilder, + MetricsReportingSocketOptions options) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + options.SocketSettings.ProtocolType = ProtocolType.Tcp; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over TCP. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverTcp( + this IMetricsReportingBuilder reportingBuilder, + Action setupAction) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions(); + + setupAction?.Invoke(options); + + options.SocketSettings.ProtocolType = ProtocolType.Tcp; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over TCP. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics output formatter. + /// + /// The TCP endpoint address where metrics are POSTed. + /// The TCP endpoint port where metrics are POSTed. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverTcp( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address, + int port) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.Tcp, address, port), + MetricsOutputFormatter = metricsOutputFormatter + }; + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over TCP. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics reporters. + /// + /// The TCP endpoint address where metrics are POSTed. + /// The TCP endpoint port where metrics are POSTed. + /// + /// The interval used if intended to schedule metrics + /// reporting. + /// + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverTcp( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address, + int port, + TimeSpan flushInterval) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.Tcp, address, port), + MetricsOutputFormatter = metricsOutputFormatter, + FlushInterval = flushInterval + }; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Builder/MetricsUdpReporterBuilder.cs b/src/App.Metrics.Reporting.Socket/Builder/MetricsUdpReporterBuilder.cs new file mode 100644 index 0000000..41bf7c2 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Builder/MetricsUdpReporterBuilder.cs @@ -0,0 +1,155 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Net.Sockets; +using App.Metrics.Builder; +using App.Metrics.Formatters; +using App.Metrics.Reporting.Socket; +using App.Metrics.Reporting.Socket.Client; + +// ReSharper disable CheckNamespace +namespace App.Metrics + // ReSharper restore CheckNamespace +{ + /// + /// Builder for configuring metrics UDP reporting using an + /// . + /// + public static class MetricsUdpReporterBuilder + { + /// + /// Add the allowing metrics to be reported over UDP. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUdp( + this IMetricsReportingBuilder reportingBuilder, + MetricsReportingSocketOptions options) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + options.SocketSettings.ProtocolType = ProtocolType.Udp; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over UDP. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUdp( + this IMetricsReportingBuilder reportingBuilder, + Action setupAction) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions(); + + setupAction?.Invoke(options); + + options.SocketSettings.ProtocolType = ProtocolType.Udp; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over UDP. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics output formatter. + /// + /// The UDP endpoint address where metrics are POSTed. + /// The UDP endpoint port where metrics are POSTed. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUdp( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address, + int port) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.Udp, address, port), + MetricsOutputFormatter = metricsOutputFormatter + }; + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over UDP. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics reporters. + /// + /// The UDP endpoint address where metrics are POSTed. + /// The UDP endpoint port where metrics are POSTed. + /// + /// The interval used if intended to schedule metrics + /// reporting. + /// + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUdp( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address, + int port, + TimeSpan flushInterval) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.Udp, address, port), + MetricsOutputFormatter = metricsOutputFormatter, + FlushInterval = flushInterval + }; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Builder/MetricsUdsReporterBuilder.cs b/src/App.Metrics.Reporting.Socket/Builder/MetricsUdsReporterBuilder.cs new file mode 100644 index 0000000..e2ebacd --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Builder/MetricsUdsReporterBuilder.cs @@ -0,0 +1,151 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Net.Sockets; +using App.Metrics.Builder; +using App.Metrics.Formatters; +using App.Metrics.Reporting.Socket; +using App.Metrics.Reporting.Socket.Client; + +// ReSharper disable CheckNamespace +namespace App.Metrics + // ReSharper restore CheckNamespace +{ + /// + /// Builder for configuring metrics UDS reporting using an + /// . + /// + public static class MetricsUdsReporterBuilder + { + /// + /// Add the allowing metrics to be reported over Unix Domain Sockets. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUds( + this IMetricsReportingBuilder reportingBuilder, + MetricsReportingSocketOptions options) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + options.SocketSettings.ProtocolType = ProtocolType.IP; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over Unix Domain Sockets. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Socket reporting options to use. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUds( + this IMetricsReportingBuilder reportingBuilder, + Action setupAction) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions(); + + setupAction?.Invoke(options); + + options.SocketSettings.ProtocolType = ProtocolType.IP; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over Unix Domain Sockets. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics output formatter. + /// + /// The Unix Domain Socket endpoint address where metrics are POSTed. + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUds( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.IP, address, 0), + MetricsOutputFormatter = metricsOutputFormatter + }; + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + + /// + /// Add the allowing metrics to be reported over Unix Domain Sockets. + /// + /// + /// The used to configure metrics reporters. + /// + /// + /// The used to configure metrics reporters. + /// + /// The Unix Domain Socket endpoint address where metrics are POSTed. + /// + /// The interval used if intended to schedule metrics + /// reporting. + /// + /// + /// An that can be used to further configure App Metrics. + /// + public static IMetricsBuilder OverUds( + this IMetricsReportingBuilder reportingBuilder, + IMetricsOutputFormatter metricsOutputFormatter, + string address, + TimeSpan flushInterval) + { + if (reportingBuilder == null) + { + throw new ArgumentNullException(nameof(reportingBuilder)); + } + + var options = new MetricsReportingSocketOptions + { + SocketSettings = new SocketSettings(ProtocolType.IP, address, 0), + MetricsOutputFormatter = metricsOutputFormatter, + FlushInterval = flushInterval + }; + + var provider = new SocketMetricsReporter(options); + + return reportingBuilder.Using(provider); + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/Constants.cs b/src/App.Metrics.Reporting.Socket/Client/Constants.cs new file mode 100644 index 0000000..42b83dd --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/Constants.cs @@ -0,0 +1,15 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; + +namespace App.Metrics.Reporting.Socket.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); + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/DefaultSocketClient.cs b/src/App.Metrics.Reporting.Socket/Client/DefaultSocketClient.cs new file mode 100644 index 0000000..da161a2 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/DefaultSocketClient.cs @@ -0,0 +1,110 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Threading; +using System.Threading.Tasks; +using App.Metrics.Logging; + +namespace App.Metrics.Reporting.Socket.Client +{ + public class DefaultSocketClient + { + private static readonly ILog Logger = LogProvider.For(); + + private static long _backoffTicks; + private static long _failureAttempts; + private readonly SocketClient _socketClient; + private readonly SocketPolicy _socketPolicy; + + public string Endpoint + { + get + { + return _socketClient.Endpoint; + } + } + + public DefaultSocketClient(MetricsReportingSocketOptions options) + { + _socketClient = CreateSocketClient(options.SocketSettings); + _socketPolicy = options.SocketPolicy; + _failureAttempts = 0; + } + + public async Task WriteAsync( + string payload, + CancellationToken cancellationToken = default) + { + if (NeedToBackoff()) + { + return new SocketWriteResult(false, $"Too many failures when attempting to write to {Endpoint}, circuit is open"); + } + + if (!_socketClient.IsConnected()) + { + Logger.Debug($"Trying to connect to {Endpoint}"); + await _socketClient.Reconnect(); + } + + try + { + var response = await _socketClient.WriteAsync(payload, cancellationToken); + + if (!response.Success) + { + Interlocked.Increment(ref _failureAttempts); + + var errorMessage = + $"Failed to write {payload.Length} bytes to {Endpoint} ({response.ErrorMessage})"; + Logger.Error(errorMessage); + + return new SocketWriteResult(false, errorMessage); + } + + Logger.Trace($"Successful write to {Endpoint}"); + + return new SocketWriteResult(true); + } + catch (Exception ex) + { + Interlocked.Increment(ref _failureAttempts); + Logger.Error(ex, $"Failed to write to {Endpoint}"); + return new SocketWriteResult(false, ex.ToString()); + } + } + + private static SocketClient CreateSocketClient( + SocketSettings socketSettings) + { + var client = new SocketClient(socketSettings); + return client; + } + + private bool NeedToBackoff() + { + if (Interlocked.Read(ref _failureAttempts) < _socketPolicy.FailuresBeforeBackoff) + { + return false; + } + + Logger.Error($"{Endpoint} write backoff for {_socketPolicy.BackoffPeriod.Seconds} seconds"); + + if (Interlocked.Read(ref _backoffTicks) == 0) + { + Interlocked.Exchange(ref _backoffTicks, DateTime.UtcNow.Add(_socketPolicy.BackoffPeriod).Ticks); + } + + if (DateTime.UtcNow.Ticks <= Interlocked.Read(ref _backoffTicks)) + { + return true; + } + + Interlocked.Exchange(ref _failureAttempts, 0); + Interlocked.Exchange(ref _backoffTicks, 0); + + return false; + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/SocketClient.cs b/src/App.Metrics.Reporting.Socket/Client/SocketClient.cs new file mode 100644 index 0000000..c6e337e --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/SocketClient.cs @@ -0,0 +1,134 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace App.Metrics.Reporting.Socket.Client +{ + public class SocketClient + { + private readonly SocketSettings _socketSettings; + + // Implementation for UDP protocol + private readonly UdpClient _udpClient; + + // Implementation for Unix Domain Sockets + private readonly UnixEndPoint _unixEndpoint; + + private System.Net.Sockets.Socket _unixClient; + + // Implementation for TCP protocol + private TcpClient _tcpClient; + + public SocketClient(SocketSettings socketSettings) + { + SocketSettings.Validate(socketSettings.ProtocolType, socketSettings.Address, socketSettings.Port); + + if (socketSettings.ProtocolType == ProtocolType.Tcp) + { + _tcpClient = new TcpClient(); + } + + if (socketSettings.ProtocolType == ProtocolType.Udp) + { + _udpClient = new UdpClient(); + } + + if (socketSettings.ProtocolType == ProtocolType.IP) + { + _unixClient = new System.Net.Sockets.Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); + _unixEndpoint = new UnixEndPoint(socketSettings.Address); + } + + _socketSettings = socketSettings; + } + + public string Endpoint => _socketSettings.Endpoint; + + public bool IsConnected() + { + if (_tcpClient != null) + { + if (!_tcpClient.Connected + || !_tcpClient.Client.Poll(0, SelectMode.SelectWrite) + || _tcpClient.Client.Poll(0, SelectMode.SelectError)) + { + return false; + } + + return true; + } + + if (_udpClient != null) + { + return true; + } + + if (_unixClient != null) + { + return _unixClient.Connected; + } + + return false; + } + + public async Task Reconnect() + { + if (_tcpClient != null) + { + _tcpClient.Client.Dispose(); + _tcpClient = new TcpClient(); + await _tcpClient.ConnectAsync(_socketSettings.Address, _socketSettings.Port); + } + + if (_unixClient != null) + { + _unixClient.Dispose(); + _unixClient = new System.Net.Sockets.Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); + _unixClient.Connect(_unixEndpoint); + } + } + + public async Task WriteAsync( + string payload, + CancellationToken cancellationToken = default) + { + var output = Encoding.UTF8.GetBytes(payload); + + if (_tcpClient != null) + { + NetworkStream stream = _tcpClient.GetStream(); + await stream.WriteAsync(output, 0, output.Length, cancellationToken); + return new SocketWriteResult(true); + } + + if (_udpClient != null) + { + var sended = await _udpClient.SendAsync( + output, + output.Length, + _socketSettings.Address, + _socketSettings.Port); + var success = sended == output.Length; + return new SocketWriteResult(success); + } + + if (_unixClient != null) + { + using (var stream = new NetworkStream(_unixClient)) + { + await stream.WriteAsync(output, 0, output.Length, cancellationToken); + } + + return new SocketWriteResult(true); + } + + return new SocketWriteResult(false, "There is no socket instance!"); + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/SocketPolicy.cs b/src/App.Metrics.Reporting.Socket/Client/SocketPolicy.cs new file mode 100644 index 0000000..d2bdcd9 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/SocketPolicy.cs @@ -0,0 +1,24 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; + +namespace App.Metrics.Reporting.Socket.Client +{ + public class SocketPolicy + { + public SocketPolicy() + { + FailuresBeforeBackoff = Constants.DefaultFailuresBeforeBackoff; + BackoffPeriod = Constants.DefaultBackoffPeriod; + Timeout = Constants.DefaultTimeout; + } + + public TimeSpan BackoffPeriod { get; set; } + + public int FailuresBeforeBackoff { get; set; } + + public TimeSpan Timeout { get; set; } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/SocketSettings.cs b/src/App.Metrics.Reporting.Socket/Client/SocketSettings.cs new file mode 100644 index 0000000..e0ebc5b --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/SocketSettings.cs @@ -0,0 +1,114 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Net; +using System.Net.Sockets; + +namespace App.Metrics.Reporting.Socket.Client +{ + public class SocketSettings + { + public SocketSettings(ProtocolType protocolType, string address, int port) + { + Validate(protocolType, address, port); + ProtocolType = protocolType; + Address = address; + Port = port; + } + + public SocketSettings() { } + + /// + /// Gets or sets Protocol to send data. + /// + /// + /// Possible variants are TCP and UDP. + /// + public ProtocolType ProtocolType { get; set; } + + /// + /// Gets or sets Address to send data. + /// + /// + /// Name of remote host. + /// + public string Address { get; set; } + + /// + /// Gets or sets Port to send data. + /// + /// + /// The remote port. + /// + public int Port { get; set; } + + public string Endpoint + { + get + { + if (ProtocolType == ProtocolType.Tcp) + { + return $"tcp://{Address}:{Port}"; + } + + if (ProtocolType == ProtocolType.Udp) + { + return $"udp://{Address}:{Port}"; + } + + if (ProtocolType == ProtocolType.IP) + { + return $"unix://{Address}"; + } + + return "Wrong Settings Instance"; + } + } + + public static void Validate( + ProtocolType protocolType, + string address, + int port) + { + if (protocolType != ProtocolType.Tcp + && protocolType != ProtocolType.Udp + && protocolType != ProtocolType.IP) + { + throw new ArgumentOutOfRangeException(nameof(protocolType), "Only TCP/IP/UDP protocols are available. IP only for Unix domain sockets"); + } + + if (string.IsNullOrWhiteSpace(address)) + { + throw new ArgumentNullException(nameof(address)); + } + + if (protocolType == ProtocolType.IP) + { + if (port != 0) + { + throw new ArgumentException( + $"Port must be 0 when Unix domain socket is used", + nameof(port)); + } + + return; + } + + if (port <= IPEndPoint.MinPort || port > IPEndPoint.MaxPort) + { + throw new ArgumentOutOfRangeException( + nameof(port), + port, + $"Port must be in ({IPEndPoint.MinPort}; {IPEndPoint.MaxPort}) range."); + } + + string endpoint = $"{address}:{port}"; + if (!Uri.TryCreate(endpoint, UriKind.Absolute, out var uri)) + { + throw new InvalidOperationException($"{endpoint} must be a valid absolute URI."); + } + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/SocketWriteResult.cs b/src/App.Metrics.Reporting.Socket/Client/SocketWriteResult.cs new file mode 100644 index 0000000..419a015 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/SocketWriteResult.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +namespace App.Metrics.Reporting.Socket.Client +{ + public struct SocketWriteResult + { + public SocketWriteResult(bool success) + { + Success = success; + ErrorMessage = null; + } + + public SocketWriteResult(bool success, string errorMessage) + { + Success = success; + ErrorMessage = errorMessage; + } + + public string ErrorMessage { get; } + + public bool Success { get; } + } +} diff --git a/src/App.Metrics.Reporting.Socket/Client/UnixEndPoint.cs b/src/App.Metrics.Reporting.Socket/Client/UnixEndPoint.cs new file mode 100644 index 0000000..9d2a8fa --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/Client/UnixEndPoint.cs @@ -0,0 +1,155 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +// Copied from https://github.com/mono/mono/blob/master/mcs/class/Mono.Posix/Mono.Unix/UnixEndPoint.cs + +// +// Mono.Unix.UnixEndPoint: EndPoint derived class for AF_UNIX family sockets. +// +// Authors: +// Gonzalo Paniagua Javier (gonzalo@ximian.com) +// +// (C) 2003 Ximian, Inc (http://www.ximian.com) +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System.Net.Sockets; +using System.Text; + +// ReSharper disable CheckNamespace +namespace System.Net + // ReSharper restore CheckNamespace +{ + public class UnixEndPoint : EndPoint + { + private string filename; + + public UnixEndPoint(string filename) + { + if (filename == null) + { + throw new ArgumentNullException("filename"); + } + + if (filename == string.Empty) + { + throw new ArgumentException("Cannot be empty.", "filename"); + } + + this.filename = filename; + } + + public string Filename + { + get + { + return filename; + } + + set + { + filename = value; + } + } + + public override AddressFamily AddressFamily + { + get { return AddressFamily.Unix; } + } + + public override EndPoint Create(SocketAddress socketAddress) + { + /* + * Should also check this + * + int addr = (int) AddressFamily.Unix; + if (socketAddress [0] != (addr & 0xFF)) + throw new ArgumentException ("socketAddress is not a unix socket address."); + if (socketAddress [1] != ((addr & 0xFF00) >> 8)) + throw new ArgumentException ("socketAddress is not a unix socket address."); + */ + + if (socketAddress.Size == 2) + { + // Empty filename. + // Probably from RemoteEndPoint which on linux does not return the file name. + UnixEndPoint uep = new UnixEndPoint("a"); + uep.filename = string.Empty; + return uep; + } + + int size = socketAddress.Size - 2; + byte[] bytes = new byte[size]; + for (int i = 0; i < bytes.Length; i++) + { + bytes[i] = socketAddress[i + 2]; + // There may be junk after the null terminator, so ignore it all. + if (bytes[i] == 0) + { + size = i; + break; + } + } + + string name = Encoding.UTF8.GetString(bytes, 0, size); + return new UnixEndPoint(name); + } + + public override SocketAddress Serialize() + { + byte[] bytes = Encoding.UTF8.GetBytes(filename); + SocketAddress sa = new SocketAddress(AddressFamily, 2 + bytes.Length + 1); + // sa [0] -> family low byte, sa [1] -> family high byte + for (int i = 0; i < bytes.Length; i++) + { + sa[2 + i] = bytes[i]; + } + + // NULL suffix for non-abstract path + sa[2 + bytes.Length] = 0; + + return sa; + } + + public override string ToString() + { + return filename; + } + + public override int GetHashCode() + { + return filename.GetHashCode(); + } + + public override bool Equals(object o) + { + UnixEndPoint other = o as UnixEndPoint; + if (other == null) + { + return false; + } + + return other.filename == filename; + } + } +} diff --git a/src/App.Metrics.Reporting.Socket/MetricsReportingSocketOptions.cs b/src/App.Metrics.Reporting.Socket/MetricsReportingSocketOptions.cs new file mode 100644 index 0000000..505dd82 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/MetricsReportingSocketOptions.cs @@ -0,0 +1,60 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using App.Metrics.Filters; +using App.Metrics.Formatters; +using App.Metrics.Reporting.Socket.Client; + +namespace App.Metrics.Reporting.Socket +{ + /// + /// Provides programmatic configuration of Socket Reporting in the App Metrics framework. + /// + public class MetricsReportingSocketOptions + { + public MetricsReportingSocketOptions() + { + SocketSettings = new SocketSettings(); + SocketPolicy = new SocketPolicy(); + } + + /// + /// Gets or sets the Socket policy settings which allows circuit breaker configuration to be adjusted + /// + /// + /// The Socket policy. + /// + public SocketPolicy SocketPolicy { get; set; } + + /// + /// Gets or sets the Socket client related settings. + /// + /// + /// The Socket client settings. + /// + public SocketSettings SocketSettings { get; set; } + + /// + /// Gets or sets the to use for just this reporter. + /// + /// + /// The to use for this reporter. + /// + public IFilterMetrics Filter { get; set; } + + /// + /// Gets or sets the used to write metrics. + /// + /// + /// The used to write metrics. + /// + public IMetricsOutputFormatter MetricsOutputFormatter { get; set; } + + /// + /// Gets or sets the interval between flushing metrics. + /// + public TimeSpan FlushInterval { get; set; } + } +} diff --git a/src/App.Metrics.Reporting.Socket/SocketMetricsReporter.cs b/src/App.Metrics.Reporting.Socket/SocketMetricsReporter.cs new file mode 100644 index 0000000..6d8e614 --- /dev/null +++ b/src/App.Metrics.Reporting.Socket/SocketMetricsReporter.cs @@ -0,0 +1,86 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using App.Metrics.Filters; +using App.Metrics.Formatters; +using App.Metrics.Logging; +using App.Metrics.Reporting.Socket.Client; + +namespace App.Metrics.Reporting.Socket +{ + public class SocketMetricsReporter : IReportMetrics + { + private static readonly ILog Logger = LogProvider.For(); + private readonly DefaultSocketClient _socketClient; + + public SocketMetricsReporter(MetricsReportingSocketOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (options.MetricsOutputFormatter == null) + { + throw new ArgumentNullException(nameof(options.MetricsOutputFormatter)); + } + + if (options.FlushInterval < TimeSpan.Zero) + { + throw new InvalidOperationException($"{nameof(MetricsReportingSocketOptions.FlushInterval)} must not be less than zero"); + } + + Formatter = options.MetricsOutputFormatter; + + FlushInterval = options.FlushInterval > TimeSpan.Zero + ? options.FlushInterval + : AppMetricsConstants.Reporting.DefaultFlushInterval; + + Filter = options.Filter; + + _socketClient = new DefaultSocketClient(options); + + Logger.Info($"Using Metrics Reporter {this}. Output: {_socketClient.Endpoint} FlushInterval: {FlushInterval}"); + } + + /// + public IFilterMetrics Filter { get; set; } + + /// + public TimeSpan FlushInterval { get; set; } + + /// + public IMetricsOutputFormatter Formatter { get; set; } + + /// + public async Task FlushAsync(MetricsDataValueSource metricsData, CancellationToken cancellationToken = default) + { + Logger.Trace("Flushing metrics snapshot"); + + using (var stream = new MemoryStream()) + { + await Formatter.WriteAsync(stream, metricsData, cancellationToken); + + var output = Encoding.UTF8.GetString(stream.ToArray()); + + var result = await _socketClient.WriteAsync(output, cancellationToken); + + if (result.Success) + { + Logger.Trace("Successfully flushed metrics snapshot"); + return true; + } + + Logger.Error(result.ErrorMessage); + + return false; + } + } + } +} diff --git a/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj b/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj index 1d87578..0b4785f 100644 --- a/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj +++ b/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj @@ -1,11 +1,10 @@  - - Provides text file reporting capability to App Metrics App.Metrics.Reporting.TextFile - netstandard1.6;net452 + netstandard1.6 + $(TargetFrameworks);net452 appmetrics;reporting;influxdb diff --git a/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj.DotSettings b/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/src/App.Metrics.Reporting.TextFile/App.Metrics.Reporting.TextFile.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/src/App.Metrics.Reporting.TextFile/Builder/MetricsTextFileReporterBuilder.cs b/src/App.Metrics.Reporting.TextFile/Builder/MetricsTextFileReporterBuilder.cs index 496774a..addf2cf 100644 --- a/src/App.Metrics.Reporting.TextFile/Builder/MetricsTextFileReporterBuilder.cs +++ b/src/App.Metrics.Reporting.TextFile/Builder/MetricsTextFileReporterBuilder.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.TextFile/MetricsReportingTextFileOptions.cs b/src/App.Metrics.Reporting.TextFile/MetricsReportingTextFileOptions.cs index 0b35740..3660e00 100644 --- a/src/App.Metrics.Reporting.TextFile/MetricsReportingTextFileOptions.cs +++ b/src/App.Metrics.Reporting.TextFile/MetricsReportingTextFileOptions.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/src/App.Metrics.Reporting.TextFile/TextFileMetricsReporter.cs b/src/App.Metrics.Reporting.TextFile/TextFileMetricsReporter.cs index b443659..9f300a2 100644 --- a/src/App.Metrics.Reporting.TextFile/TextFileMetricsReporter.cs +++ b/src/App.Metrics.Reporting.TextFile/TextFileMetricsReporter.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; @@ -61,7 +61,7 @@ public TextFileMetricsReporter(MetricsReportingTextFileOptions options) var fileInfo = new FileInfo(options.OutputPathAndFileName); - if (!fileInfo.Directory.Exists) + if (fileInfo.Directory != null && !fileInfo.Directory.Exists) { Directory.CreateDirectory(fileInfo.Directory.FullName); } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ad660fa..036aa4f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,5 +1,9 @@ + + + - + + \ No newline at end of file diff --git a/stylecop.json b/stylecop.json index 6d82cf0..55ae462 100644 --- a/stylecop.json +++ b/stylecop.json @@ -8,7 +8,7 @@ "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", "settings": { "documentationRules": { - "companyName": "Allan Hardy", + "companyName": "App Metrics Contributors", "xmlHeader": true } } diff --git a/test/App.Metrics.Reporting.Console.Facts/App.Metrics.Reporting.Console.Facts.csproj b/test/App.Metrics.Reporting.Console.Facts/App.Metrics.Reporting.Console.Facts.csproj index a955f28..26e7887 100644 --- a/test/App.Metrics.Reporting.Console.Facts/App.Metrics.Reporting.Console.Facts.csproj +++ b/test/App.Metrics.Reporting.Console.Facts/App.Metrics.Reporting.Console.Facts.csproj @@ -1,23 +1,11 @@  - - - + - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTest) - - - - - - - - - - + diff --git a/test/App.Metrics.Reporting.Console.Facts/ConsoleMetricsReporterTests.cs b/test/App.Metrics.Reporting.Console.Facts/ConsoleMetricsReporterTests.cs index b25d518..9e5d4f4 100644 --- a/test/App.Metrics.Reporting.Console.Facts/ConsoleMetricsReporterTests.cs +++ b/test/App.Metrics.Reporting.Console.Facts/ConsoleMetricsReporterTests.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/test/App.Metrics.Reporting.Console.Facts/MetricsConsoleReporterBuilderTests.cs b/test/App.Metrics.Reporting.Console.Facts/MetricsConsoleReporterBuilderTests.cs index 2c6475c..df71cde 100644 --- a/test/App.Metrics.Reporting.Console.Facts/MetricsConsoleReporterBuilderTests.cs +++ b/test/App.Metrics.Reporting.Console.Facts/MetricsConsoleReporterBuilderTests.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj b/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj index 1dfecdc..7340076 100644 --- a/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj +++ b/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj @@ -1,23 +1,11 @@  - - - + - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTest) - - - - - - - - - diff --git a/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj.DotSettings b/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj.DotSettings new file mode 100644 index 0000000..58ad6c8 --- /dev/null +++ b/test/App.Metrics.Reporting.FactsCommon/App.Metrics.Reporting.FactsCommon.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp71 \ No newline at end of file diff --git a/test/App.Metrics.Reporting.FactsCommon/TestMetricsFormatter.cs b/test/App.Metrics.Reporting.FactsCommon/TestMetricsFormatter.cs index dfe1e1c..f84036c 100644 --- a/test/App.Metrics.Reporting.FactsCommon/TestMetricsFormatter.cs +++ b/test/App.Metrics.Reporting.FactsCommon/TestMetricsFormatter.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System.IO; @@ -14,6 +14,7 @@ public class TestMetricsFormatter : IMetricsOutputFormatter public TestMetricsFormatter() { MediaType = new MetricsMediaTypeValue("test", "test", "v1", "format"); + MetricFields = new MetricFields(); } public Task WriteAsync(Stream output, MetricsDataValueSource metricsData, CancellationToken cancellationToken = default) @@ -22,5 +23,8 @@ public Task WriteAsync(Stream output, MetricsDataValueSource metricsData, Cancel } public MetricsMediaTypeValue MediaType { get; } + + /// + public MetricFields MetricFields { get; set; } } } diff --git a/test/App.Metrics.Reporting.Http.Facts/App.Metrics.Reporting.Http.Facts.csproj b/test/App.Metrics.Reporting.Http.Facts/App.Metrics.Reporting.Http.Facts.csproj index d413f81..559d5c6 100644 --- a/test/App.Metrics.Reporting.Http.Facts/App.Metrics.Reporting.Http.Facts.csproj +++ b/test/App.Metrics.Reporting.Http.Facts/App.Metrics.Reporting.Http.Facts.csproj @@ -1,23 +1,11 @@  - - - + - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTest) - - - - - - - - - - + diff --git a/test/App.Metrics.Reporting.Http.Facts/MetricsHttpReporterBuilderTests.cs b/test/App.Metrics.Reporting.Http.Facts/MetricsHttpReporterBuilderTests.cs index a9d8618..3a687db 100644 --- a/test/App.Metrics.Reporting.Http.Facts/MetricsHttpReporterBuilderTests.cs +++ b/test/App.Metrics.Reporting.Http.Facts/MetricsHttpReporterBuilderTests.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/test/App.Metrics.Reporting.Socket.Facts/App.Metrics.Reporting.Socket.Facts.csproj b/test/App.Metrics.Reporting.Socket.Facts/App.Metrics.Reporting.Socket.Facts.csproj new file mode 100644 index 0000000..fa2cb74 --- /dev/null +++ b/test/App.Metrics.Reporting.Socket.Facts/App.Metrics.Reporting.Socket.Facts.csproj @@ -0,0 +1,16 @@ + + + + $(StandardTest) + + + + + + + + + + + + diff --git a/test/App.Metrics.Reporting.Socket.Facts/MetricsSocketReporterBuilderTests.cs b/test/App.Metrics.Reporting.Socket.Facts/MetricsSocketReporterBuilderTests.cs new file mode 100644 index 0000000..bb0b77a --- /dev/null +++ b/test/App.Metrics.Reporting.Socket.Facts/MetricsSocketReporterBuilderTests.cs @@ -0,0 +1,363 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Linq; +using System.Net.Sockets; +using App.Metrics.Filtering; +using App.Metrics.Formatters.Ascii; +using App.Metrics.Internal.NoOp; +using App.Metrics.Reporting.FactsCommon; +using App.Metrics.Reporting.Socket.Client; +using FluentAssertions; +using Xunit; + +namespace App.Metrics.Reporting.Socket.Facts +{ + public class MetricsSocketReporterBuilderTests + { + private static ProtocolType defaultProtocol = ProtocolType.Udp; + private static string defaultAddress = "localhost"; + private static string defaultUnixAddress = "//path/to/socket.file"; + private static int defaultPort = 8094; + + [Fact] + public void Can_use_tcp_socket_reporter() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var builder = new MetricsBuilder().Report.OverTcp(formatter, defaultAddress, defaultPort); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(AppMetricsConstants.Reporting.DefaultFlushInterval); + metrics.Reporters.First().Filter.Should().BeOfType(); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void Can_use_udp_socket_reporter() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var builder = new MetricsBuilder().Report.OverUdp(formatter, defaultAddress, defaultPort); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(AppMetricsConstants.Reporting.DefaultFlushInterval); + metrics.Reporters.First().Filter.Should().BeOfType(); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact(Skip = "Test should work only on unix platform")] + public void Can_use_uds_socket_reporter() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var builder = new MetricsBuilder().Report.OverUds(formatter, defaultUnixAddress); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(AppMetricsConstants.Reporting.DefaultFlushInterval); + metrics.Reporters.First().Filter.Should().BeOfType(); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void Cannot_use_tcp_socket_reporter_without_formatter() + { + // Arrange + Action action = () => + { + // Act + var builder = new MetricsBuilder().Report.OverTcp(null, defaultAddress, defaultPort); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Cannot_use_udp_socket_reporter_without_formatter() + { + // Arrange + Action action = () => + { + // Act + var builder = new MetricsBuilder().Report.OverUdp(null, defaultAddress, defaultPort); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Cannot_use_uds_socket_reporter_without_formatter() + { + // Arrange + Action action = () => + { + // Act + var builder = new MetricsBuilder().Report.OverUds(null, defaultUnixAddress); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Can_use_tcp_socket_reporter_with_options() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var options = new MetricsReportingSocketOptions(); + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + var builder = new MetricsBuilder().Report.OverTcp(options); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void Can_use_udp_socket_reporter_with_options() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var options = new MetricsReportingSocketOptions(); + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + var builder = new MetricsBuilder().Report.OverUdp(options); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact(Skip = "Test should work only on unix platform")] + public void Can_use_uds_socket_reporter_with_options() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(); + settings.Address = defaultUnixAddress; + var options = new MetricsReportingSocketOptions(); + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + var builder = new MetricsBuilder().Report.OverUds(options); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void Can_use_tcp_socket_reporter_with_setup_actions() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var builder = new MetricsBuilder().Report.OverTcp( + options => + { + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + }); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void Can_use_udp_socket_reporter_with_setup_actions() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var builder = new MetricsBuilder().Report.OverUdp( + options => + { + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + }); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact(Skip = "Test should work only on unix platform")] + public void Can_use_uds_socket_reporter_with_setup_actions() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var flushInterval = TimeSpan.FromDays(1); + var settings = new SocketSettings(); + settings.Address = defaultUnixAddress; + var builder = new MetricsBuilder().Report.OverUds( + options => + { + options.Filter = filter; + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + }); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + metrics.Reporters.First().Filter.Should().BeSameAs(filter); + metrics.Reporters.First().Formatter.Should().BeOfType(); + } + + [Fact] + public void When_using_socket_reporter_with_setu_actions_flush_interval_equal_to_zero_should_apply_default_interval() + { + // Arrange + var flushInterval = TimeSpan.Zero; + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var builder = new MetricsBuilder().Report.OverTcp( + options => + { + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + }); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.First().FlushInterval.Should().Be(AppMetricsConstants.Reporting.DefaultFlushInterval); + } + + [Fact] + public void When_using_socket_reporter_with_setup_actions_flush_interval_less_than_zero_should_throw() + { + // Arrange + Action action = () => + { + // Act + var flushInterval = TimeSpan.FromSeconds(-1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var builder = new MetricsBuilder().Report.OverTcp( + options => + { + options.FlushInterval = flushInterval; + options.MetricsOutputFormatter = new TestMetricsFormatter(); + options.SocketSettings = settings; + }); + + var unused = builder.Build(); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Can_use_tcp_socket_reporter_overriding_flush_interval() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var flushInterval = TimeSpan.FromDays(1); + var builder = new MetricsBuilder().Report.OverTcp(formatter, defaultAddress, defaultPort, flushInterval); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + } + + [Fact] + public void Can_use_udp_socket_reporter_overriding_flush_interval() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var flushInterval = TimeSpan.FromDays(1); + var builder = new MetricsBuilder().Report.OverUdp(formatter, defaultAddress, defaultPort, flushInterval); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + } + + [Fact(Skip = "Test should work only on unix platform")] + public void Can_use_uds_socket_reporter_overriding_flush_interval() + { + // Arrange + var formatter = new TestMetricsFormatter(); + var flushInterval = TimeSpan.FromDays(1); + var builder = new MetricsBuilder().Report.OverUds(formatter, defaultAddress, flushInterval); + + // Act + var metrics = builder.Build(); + + // Assert + metrics.Reporters.Should().Contain(reportMetrics => reportMetrics is SocketMetricsReporter); + metrics.Reporters.First().FlushInterval.Should().Be(flushInterval); + } + } +} diff --git a/test/App.Metrics.Reporting.Socket.Facts/SocketMetricsReporterTests.cs b/test/App.Metrics.Reporting.Socket.Facts/SocketMetricsReporterTests.cs new file mode 100644 index 0000000..3257a97 --- /dev/null +++ b/test/App.Metrics.Reporting.Socket.Facts/SocketMetricsReporterTests.cs @@ -0,0 +1,168 @@ +// +// Copyright (c) App Metrics Contributors. All rights reserved. +// + +using System; +using System.Linq; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using App.Metrics.Filtering; +using App.Metrics.Reporting.FactsCommon; +using App.Metrics.Reporting.Socket.Client; +using FluentAssertions; +using Xunit; + +namespace App.Metrics.Reporting.Socket.Facts +{ + public class SocketMetricsReporterTests + { + private static ProtocolType defaultProtocol = ProtocolType.Udp; + private static string defaultAddress = "localhost"; + private static int defaultPort = 8094; + + [Fact] + public void Socket_metrics_reporter_expect_options() + { + // Arrange + Action action = () => + { + // Act + var reporter = new SocketMetricsReporter(null); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_metrics_reporter_expect_output_formatter() + { + // Arrange + Action action = () => + { + var options = new MetricsReportingSocketOptions(); + + // Act + var reporter = new SocketMetricsReporter(options); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_metrics_reporter_expect_socket_settings() + { + // Arrange + Action action = () => + { + var formatter = new TestMetricsFormatter(); + var options = new MetricsReportingSocketOptions + { + MetricsOutputFormatter = formatter + }; + // Act + var reporter = new SocketMetricsReporter(options); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_settings_expect_supported_protocol() + { + // Arrange + Action action = () => + { + // Act + var settings = new SocketSettings(ProtocolType.Ipx, defaultAddress, defaultPort); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_settings_expect_non_empty_address() + { + // Arrange + Action action = () => + { + // Act + var settings = new SocketSettings(defaultProtocol, string.Empty, defaultPort); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_settings_expect_port_greater_than_zero() + { + // Arrange + Action action = () => + { + // Act + var settings = new SocketSettings(defaultProtocol, defaultAddress, 0); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_settings_expect_port_less_than_maxium_available_port() + { + // Arrange + Action action = () => + { + // Act + var settings = new SocketSettings(defaultProtocol, defaultAddress, 97531); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public void Socket_settings_expect_using_unix_domain_sockets_with_null_port() + { + // Arrange + Action action = () => + { + // Act + var settings = new SocketSettings(ProtocolType.IP, defaultAddress, defaultPort); + }; + + // Assert + action.Should().Throw(); + } + + [Fact] + public async Task Can_flush_metrics_via_sockets_with_options() + { + // Arrange + var filter = new MetricsFilter().WhereType(MetricType.Apdex); + var formatter = new TestMetricsFormatter(); + var interval = TimeSpan.FromDays(1); + var settings = new SocketSettings(defaultProtocol, defaultAddress, defaultPort); + var options = new MetricsReportingSocketOptions + { + Filter = filter, + FlushInterval = interval, + MetricsOutputFormatter = formatter, + SocketSettings = settings + }; + var reporter = new SocketMetricsReporter(options); + var snapshot = new MetricsDataValueSource(DateTime.Now, Enumerable.Empty()); + + // Act + var result = await reporter.FlushAsync(snapshot, CancellationToken.None); + + // Assert + result.Should().BeTrue(); + } + } +} diff --git a/test/App.Metrics.Reporting.TextFile.Facts/App.Metrics.Reporting.TextFile.Facts.csproj b/test/App.Metrics.Reporting.TextFile.Facts/App.Metrics.Reporting.TextFile.Facts.csproj index 9ed1525..703ff17 100644 --- a/test/App.Metrics.Reporting.TextFile.Facts/App.Metrics.Reporting.TextFile.Facts.csproj +++ b/test/App.Metrics.Reporting.TextFile.Facts/App.Metrics.Reporting.TextFile.Facts.csproj @@ -1,23 +1,11 @@  - - - + - netcoreapp2.0;net461 - netcoreapp2.0 + $(StandardTest) - - - - - - - - - - + diff --git a/test/App.Metrics.Reporting.TextFile.Facts/MetricsTextFileReporterBuilderTests.cs b/test/App.Metrics.Reporting.TextFile.Facts/MetricsTextFileReporterBuilderTests.cs index 24abe63..d7d0340 100644 --- a/test/App.Metrics.Reporting.TextFile.Facts/MetricsTextFileReporterBuilderTests.cs +++ b/test/App.Metrics.Reporting.TextFile.Facts/MetricsTextFileReporterBuilderTests.cs @@ -1,5 +1,5 @@ -// -// Copyright (c) Allan Hardy. All rights reserved. +// +// Copyright (c) App Metrics Contributors. All rights reserved. // using System; diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000..f97e5e7 --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,23 @@ + + + + + netcoreapp2.1 + $(DeveloperBuildTest) + $(StandardTest);netcoreapp2.0 + $(StandardTest);net461 + + + + + + + + + + + + + + + diff --git a/version.props b/version.props index 33185a8..3918c42 100644 --- a/version.props +++ b/version.props @@ -1,7 +1,7 @@ - 2.0.0 + 3.0.0 \ No newline at end of file