diff --git a/Metrics.sln b/Metrics.sln index 45d91b0a..229923d6 100644 --- a/Metrics.sln +++ b/Metrics.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics", "Src\Metrics\Metrics.csproj", "{95E29D40-DBEC-49E2-9CC5-26B88966DADE}" EndProject @@ -13,16 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{FE317A .nuget\NuGet.exe = .nuget\NuGet.exe EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{30108C17-0671-4786-90D0-0564718C3F70}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NancyFx.Sample", "Samples\NancyFx.Sample\NancyFx.Sample.csproj", "{B7C6EF21-0797-4B53-A917-1CFF8267CD67}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.Samples", "Samples\Metrics.Samples\Metrics.Samples.csproj", "{D08A63D0-F440-477C-9565-1264AE0879D0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.SamplesConsole", "Samples\Metrics.SamplesConsole\Metrics.SamplesConsole.csproj", "{7416F90D-FFD6-4E34-8638-5234C8B9EC39}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.StupidBenchmarks", "Samples\Metrics.StupidBenchmarks\Metrics.StupidBenchmarks.csproj", "{A9074D3E-3421-483D-AF98-4AAEEED11ECA}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Adapters", "Adapters", "{443860DA-6378-47D0-A4AE-4E79975C5E1C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Metrics", "Src\Adapters\Nancy.Metrics\Nancy.Metrics.csproj", "{FBFF51D8-52F4-4EEF-8498-122A14B37D6C}" @@ -30,30 +20,22 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9A42F567-91B0-4FFB-A9AD-DB0D158784EA}" ProjectSection(SolutionItems) = preProject .travis.yml = .travis.yml - build.bat = build.bat - build.sh = build.sh + build.net40.bat = build.net40.bat CHANGELOG.md = CHANGELOG.md create-nuget.bat = create-nuget.bat + Publishing\Metrics.NET.net40.nuspec = Publishing\Metrics.NET.net40.nuspec Publishing\Metrics.NET.nuspec = Publishing\Metrics.NET.nuspec Publishing\Nancy.Metrics.nuspec = Publishing\Nancy.Metrics.nuspec + Publishing\NancyFx.Metrics.net40.nuspec = Publishing\NancyFx.Metrics.net40.nuspec Publishing\Owin.Metrics.nuspec = Publishing\Owin.Metrics.nuspec + Publishing\push-nuget-40-influxdb1x.bat = Publishing\push-nuget-40-influxdb1x.bat Publishing\push-nuget.bat = Publishing\push-nuget.bat README.md = README.md SharedAssemblyInfo.cs = SharedAssemblyInfo.cs EndProjectSection EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Metrics.Samples.FSharp", "Samples\Metrics.Samples.FSharp\Metrics.Samples.FSharp.fsproj", "{DAF70394-CE63-4D2F-B52B-839941827B4E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.SampleReporter", "Samples\Metrics.SampleReporter\Metrics.SampleReporter.csproj", "{18E808CB-98F9-4754-9872-D3D00F9CE72B}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.NLog", "Src\Adapters\Metrics.NLog\Metrics.NLog.csproj", "{68F25A01-AF00-4D57-9D1A-81213E4EF56F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Metrics", "Src\Adapters\Owin.Metrics\Owin.Metrics.csproj", "{025CD6D0-1A1E-4B14-A7DB-AF5DFF887210}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Sample", "Samples\Owin.Sample\Owin.Sample.csproj", "{828188F9-26C2-4C93-A156-D9EA13D7E2FA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Metrics.Central", "Src\Metrics.Central\Metrics.Central.csproj", "{450184A4-9916-4AE5-87F8-A8067105CE40}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -68,55 +50,24 @@ Global {4E0F8CB9-6919-48B8-8212-BCE75D04E0D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E0F8CB9-6919-48B8-8212-BCE75D04E0D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E0F8CB9-6919-48B8-8212-BCE75D04E0D9}.Release|Any CPU.Build.0 = Release|Any CPU - {B7C6EF21-0797-4B53-A917-1CFF8267CD67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7C6EF21-0797-4B53-A917-1CFF8267CD67}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7C6EF21-0797-4B53-A917-1CFF8267CD67}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7C6EF21-0797-4B53-A917-1CFF8267CD67}.Release|Any CPU.Build.0 = Release|Any CPU - {D08A63D0-F440-477C-9565-1264AE0879D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D08A63D0-F440-477C-9565-1264AE0879D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D08A63D0-F440-477C-9565-1264AE0879D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D08A63D0-F440-477C-9565-1264AE0879D0}.Release|Any CPU.Build.0 = Release|Any CPU - {7416F90D-FFD6-4E34-8638-5234C8B9EC39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7416F90D-FFD6-4E34-8638-5234C8B9EC39}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7416F90D-FFD6-4E34-8638-5234C8B9EC39}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7416F90D-FFD6-4E34-8638-5234C8B9EC39}.Release|Any CPU.Build.0 = Release|Any CPU - {A9074D3E-3421-483D-AF98-4AAEEED11ECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9074D3E-3421-483D-AF98-4AAEEED11ECA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9074D3E-3421-483D-AF98-4AAEEED11ECA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9074D3E-3421-483D-AF98-4AAEEED11ECA}.Release|Any CPU.Build.0 = Release|Any CPU {FBFF51D8-52F4-4EEF-8498-122A14B37D6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBFF51D8-52F4-4EEF-8498-122A14B37D6C}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBFF51D8-52F4-4EEF-8498-122A14B37D6C}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBFF51D8-52F4-4EEF-8498-122A14B37D6C}.Release|Any CPU.Build.0 = Release|Any CPU - {DAF70394-CE63-4D2F-B52B-839941827B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DAF70394-CE63-4D2F-B52B-839941827B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DAF70394-CE63-4D2F-B52B-839941827B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DAF70394-CE63-4D2F-B52B-839941827B4E}.Release|Any CPU.Build.0 = Release|Any CPU - {18E808CB-98F9-4754-9872-D3D00F9CE72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18E808CB-98F9-4754-9872-D3D00F9CE72B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18E808CB-98F9-4754-9872-D3D00F9CE72B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18E808CB-98F9-4754-9872-D3D00F9CE72B}.Release|Any CPU.Build.0 = Release|Any CPU {68F25A01-AF00-4D57-9D1A-81213E4EF56F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {68F25A01-AF00-4D57-9D1A-81213E4EF56F}.Debug|Any CPU.Build.0 = Debug|Any CPU {68F25A01-AF00-4D57-9D1A-81213E4EF56F}.Release|Any CPU.ActiveCfg = Release|Any CPU {68F25A01-AF00-4D57-9D1A-81213E4EF56F}.Release|Any CPU.Build.0 = Release|Any CPU - {025CD6D0-1A1E-4B14-A7DB-AF5DFF887210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {025CD6D0-1A1E-4B14-A7DB-AF5DFF887210}.Debug|Any CPU.Build.0 = Debug|Any CPU - {025CD6D0-1A1E-4B14-A7DB-AF5DFF887210}.Release|Any CPU.ActiveCfg = Release|Any CPU - {025CD6D0-1A1E-4B14-A7DB-AF5DFF887210}.Release|Any CPU.Build.0 = Release|Any CPU - {828188F9-26C2-4C93-A156-D9EA13D7E2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {828188F9-26C2-4C93-A156-D9EA13D7E2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {828188F9-26C2-4C93-A156-D9EA13D7E2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {828188F9-26C2-4C93-A156-D9EA13D7E2FA}.Release|Any CPU.Build.0 = Release|Any CPU - {450184A4-9916-4AE5-87F8-A8067105CE40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {450184A4-9916-4AE5-87F8-A8067105CE40}.Debug|Any CPU.Build.0 = Debug|Any CPU - {450184A4-9916-4AE5-87F8-A8067105CE40}.Release|Any CPU.ActiveCfg = Release|Any CPU - {450184A4-9916-4AE5-87F8-A8067105CE40}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {FBFF51D8-52F4-4EEF-8498-122A14B37D6C} = {443860DA-6378-47D0-A4AE-4E79975C5E1C} + {68F25A01-AF00-4D57-9D1A-81213E4EF56F} = {443860DA-6378-47D0-A4AE-4E79975C5E1C} + EndGlobalSection + GlobalSection(CodealikeProperties) = postSolution + SolutionGuid = 169deccf-e8f8-4868-80f4-f7f0bb71cb4b {B7C6EF21-0797-4B53-A917-1CFF8267CD67} = {30108C17-0671-4786-90D0-0564718C3F70} {D08A63D0-F440-477C-9565-1264AE0879D0} = {30108C17-0671-4786-90D0-0564718C3F70} {7416F90D-FFD6-4E34-8638-5234C8B9EC39} = {30108C17-0671-4786-90D0-0564718C3F70} diff --git a/Publishing/Metrics.NET.net40.nuspec b/Publishing/Metrics.NET.net40.nuspec new file mode 100644 index 00000000..84e5c5bb --- /dev/null +++ b/Publishing/Metrics.NET.net40.nuspec @@ -0,0 +1,23 @@ + + + + Metrics.NET40.WithInfluxdbNewApiSupport + 0.4.7 + Metrics.NET40.WithInfluxdbNewApiSupport + shamork@163.com + Iulian Margarintescu + https://github.com/etishor/Metrics.NET/blob/master/LICENSE + https://github.com/etishor/Metrics.NET + http://www.erata.net/Metrics.NET/metrics_32.png + false + (Legacy .NET 4.0 Version) The library provides support for capturing: Gauges, Counters, Meters, Histograms and Timers + (Legacy .NET 4.0 Version) .NET Port of the Java Metrics Library, a library for collecting metrics. Library also provides Health Checks. Updated influxdb support to 1.x + Iulian Margarintescu + metrics, measurements, charts, timer, histogram, duration, graphite, health checks + + + + + + + \ No newline at end of file diff --git a/Publishing/NancyFx.Metrics.net40.nuspec b/Publishing/NancyFx.Metrics.net40.nuspec new file mode 100644 index 00000000..b618372d --- /dev/null +++ b/Publishing/NancyFx.Metrics.net40.nuspec @@ -0,0 +1,27 @@ + + + + NancyFx.Metrics-net40 + 0.2.15 + Nancy.Metrics-net40 + iulian.margarintescu + Iulian Margarintescu + false + (Legacy .NET 4.0 Version) The library provides support for integrating NancyFx with the Metrics.NET Library + (Legacy .NET 4.0 Version) NancyFx adapter for Metrics.NET + Iulian Margarintescu + https://github.com/etishor/Metrics.NET + https://github.com/etishor/Metrics.NET/blob/master/LICENSE + http://www.erata.net/Metrics.NET/metrics_32.png + nancy, nancyfx, metrics, measurements, charts, timer, histogram, duration, graphite, health checks + + + + + + + + + + + \ No newline at end of file diff --git a/Publishing/push-nuget-40-influxdb1x.bat b/Publishing/push-nuget-40-influxdb1x.bat new file mode 100644 index 00000000..5690f7fd --- /dev/null +++ b/Publishing/push-nuget-40-influxdb1x.bat @@ -0,0 +1 @@ +..\.nuget\NuGet.exe push Metrics.NET40.WithInfluxdbNewApiSupport.0.4.7.nupkg \ No newline at end of file diff --git a/Publishing/push-nuget.bat b/Publishing/push-nuget.bat index da6d7335..d96633fc 100644 --- a/Publishing/push-nuget.bat +++ b/Publishing/push-nuget.bat @@ -1,3 +1,2 @@ -..\.nuget\NuGet.exe push Metrics.NET.0.2.16.nupkg -..\.nuget\NuGet.exe push Nancy.Metrics.0.2.16.nupkg -..\.nuget\NuGet.exe push Owin.Metrics.0.1.19-alpha.nupkg \ No newline at end of file +..\.nuget\NuGet.exe push Metrics.NET-net40.0.2.16.nupkg +..\.nuget\NuGet.exe push NancyFx.Metrics-net40.0.2.16.nupkg \ No newline at end of file diff --git a/Publishing/push-nuget.bat.orig b/Publishing/push-nuget.bat.orig new file mode 100644 index 00000000..9fb6fc36 --- /dev/null +++ b/Publishing/push-nuget.bat.orig @@ -0,0 +1,8 @@ +<<<<<<< HEAD +..\.nuget\NuGet.exe push Metrics.NET-net40.0.2.10.nupkg +..\.nuget\NuGet.exe push NancyFx.Metrics-net40.0.2.10.nupkg +======= +..\.nuget\NuGet.exe push Metrics.NET.0.2.11.nupkg +..\.nuget\NuGet.exe push Nancy.Metrics.0.2.11.nupkg +..\.nuget\NuGet.exe push Owin.Metrics.0.1.15-alpha.nupkg +>>>>>>> master diff --git a/Samples/Metrics.SampleReporter/Metrics.SampleReporter.csproj b/Samples/Metrics.SampleReporter/Metrics.SampleReporter.csproj index 46b922fa..d3f762d7 100644 --- a/Samples/Metrics.SampleReporter/Metrics.SampleReporter.csproj +++ b/Samples/Metrics.SampleReporter/Metrics.SampleReporter.csproj @@ -9,6 +9,7 @@ Properties Metrics.SampleReporter Metrics.SampleReporter + v4.0 v4.5 512 ..\..\ @@ -39,7 +40,8 @@ 1591 - + + False ..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll diff --git a/Samples/Metrics.Samples/Metrics.Samples.csproj b/Samples/Metrics.Samples/Metrics.Samples.csproj index 1986911d..84e8c6b2 100644 --- a/Samples/Metrics.Samples/Metrics.Samples.csproj +++ b/Samples/Metrics.Samples/Metrics.Samples.csproj @@ -16,6 +16,7 @@ true full false + v4.0 ..\..\bin\Debug\ DEBUG;TRACE prompt @@ -23,6 +24,8 @@ pdbonly + true + v4.0 true ..\..\bin\Release\ TRACE diff --git a/Samples/Metrics.SamplesConsole/Metrics.SamplesConsole.csproj b/Samples/Metrics.SamplesConsole/Metrics.SamplesConsole.csproj index 4aa1be05..cb7f81f7 100644 --- a/Samples/Metrics.SamplesConsole/Metrics.SamplesConsole.csproj +++ b/Samples/Metrics.SamplesConsole/Metrics.SamplesConsole.csproj @@ -21,6 +21,7 @@ true full false + v4.0 ..\..\bin\Debug\ DEBUG;TRACE prompt @@ -30,6 +31,7 @@ AnyCPU pdbonly true + v4.0 ..\..\bin\Release\ TRACE prompt @@ -67,10 +69,6 @@ {18e808cb-98f9-4754-9872-d3d00f9ce72b} Metrics.SampleReporter - - {daf70394-ce63-4d2f-b52b-839941827b4e} - Metrics.Samples.FSharp - {d08a63d0-f440-477c-9565-1264ae0879d0} Metrics.Samples diff --git a/Samples/Metrics.StupidBenchmarks/Metrics.StupidBenchmarks.csproj b/Samples/Metrics.StupidBenchmarks/Metrics.StupidBenchmarks.csproj index 2445871e..e2be1c93 100644 --- a/Samples/Metrics.StupidBenchmarks/Metrics.StupidBenchmarks.csproj +++ b/Samples/Metrics.StupidBenchmarks/Metrics.StupidBenchmarks.csproj @@ -12,6 +12,7 @@ v4.5.1 512 true + ..\..\ true @@ -21,19 +22,46 @@ true full false + v4.0 ..\..\bin\Debug\ DEBUG;TRACE prompt 4 + false AnyCPU pdbonly true + v4.0 ..\..\bin\Release\ TRACE prompt 4 + false + + + AnyCPU + true + full + false + v4.5 + ..\..\bin\MonoDebug\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + pdbonly + true + v4.5.1 + ..\..\bin\MonoRelease\ + TRACE + prompt + 4 + true diff --git a/Samples/NancyFx.Sample/NancyFx.Sample.csproj b/Samples/NancyFx.Sample/NancyFx.Sample.csproj index dddeed76..488a2d21 100644 --- a/Samples/NancyFx.Sample/NancyFx.Sample.csproj +++ b/Samples/NancyFx.Sample/NancyFx.Sample.csproj @@ -21,19 +21,46 @@ true full false + v4.0 ..\..\bin\Debug\ DEBUG;TRACE prompt 4 + false AnyCPU pdbonly true + v4.0 ..\..\bin\Release\ TRACE prompt 4 + false + + + AnyCPU + true + full + false + v4.5 + ..\..\bin\MonoDebug\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + pdbonly + true + v4.5.1 + ..\..\bin\MonoRelease\ + TRACE + prompt + 4 + true diff --git a/Samples/Owin.Sample/Controllers/SampleController.cs b/Samples/Owin.Sample/Controllers/SampleController.cs deleted file mode 100644 index 7bc7a0cc..00000000 --- a/Samples/Owin.Sample/Controllers/SampleController.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Web.Http; - -namespace Owin.Sample.Controllers -{ - [RoutePrefix("sample")] - public class SampleController : ApiController - { - [Route("")] - public IEnumerable Get() - { - return new[] { "value1", "value2" }; - } - - [Route("withparams/{x}/{y}")] - public IEnumerable Get(int x, string y) - { - return new[] { "value1", "value2" }; - } - } -} diff --git a/Samples/Owin.Sample/Controllers/SampleIgnoreController.cs b/Samples/Owin.Sample/Controllers/SampleIgnoreController.cs deleted file mode 100644 index 882d5766..00000000 --- a/Samples/Owin.Sample/Controllers/SampleIgnoreController.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace Owin.Sample.Controllers -{ - using System.Web.Http; - - [RoutePrefix("sampleignore")] - public class SampleIgnoreController : ApiController - { - [Route("")] - public string Get() - { - return "get"; - } - } -} diff --git a/Samples/Owin.Sample/Program.cs b/Samples/Owin.Sample/Program.cs deleted file mode 100644 index 34aa9d72..00000000 --- a/Samples/Owin.Sample/Program.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Diagnostics; -using Metrics.Samples; -using Metrics.Utils; -using Microsoft.Owin.Hosting; - -namespace Owin.Sample -{ - public class Program - { - static void Main(string[] args) - { - const string url = "http://localhost:1235/"; - - using (var scheduler = new ActionScheduler()) - { - using (WebApp.Start(url)) - { - Console.WriteLine("Owin Running at {0}", url); - Console.WriteLine("Press any key to exit"); - Process.Start(string.Format("{0}metrics", url)); - - SampleMetrics.RunSomeRequests(); - - scheduler.Start(TimeSpan.FromMilliseconds(500), () => - { - SetCounterSample.RunSomeRequests(); - SetMeterSample.RunSomeRequests(); - UserValueHistogramSample.RunSomeRequests(); - UserValueTimerSample.RunSomeRequests(); - SampleMetrics.RunSomeRequests(); - }); - - HealthChecksSample.RegisterHealthChecks(); - - Console.ReadKey(); - } - } - } - } -} diff --git a/Samples/Owin.Sample/Properties/AssemblyInfo.cs b/Samples/Owin.Sample/Properties/AssemblyInfo.cs deleted file mode 100644 index b793163c..00000000 --- a/Samples/Owin.Sample/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("WebApi.Sample")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WebApi.Sample")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("4118530f-7ae9-4639-b9ce-6e64c404ea8f")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Samples/Owin.Sample/SetOwinRouteTemplateMessageHandler.cs b/Samples/Owin.Sample/SetOwinRouteTemplateMessageHandler.cs deleted file mode 100644 index 09677313..00000000 --- a/Samples/Owin.Sample/SetOwinRouteTemplateMessageHandler.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Web.Http.Routing; - -namespace Owin.Sample -{ - public class SetOwinRouteTemplateMessageHandler : DelegatingHandler - { - /// - /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation. - /// - /// The HTTP request message to send to the server. - /// A cancellation token to cancel operation. - /// - /// Returns . The task object representing the asynchronous operation. - /// - protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - var owinContext = request.GetOwinContext(); - - if (owinContext == null) return base.SendAsync(request, cancellationToken); - - var routes = request.GetConfiguration().Routes; - - if (routes == null) return base.SendAsync(request, cancellationToken); - - var routeData = routes.GetRouteData(request); - - if (routeData == null) return base.SendAsync(request, cancellationToken); - - var subRoutes = routeData.Values["MS_SubRoutes"] as IHttpRouteData[]; - - if (subRoutes == null) return base.SendAsync(request, cancellationToken); - - var routeTemplate = subRoutes[0].Route.RouteTemplate; - - owinContext.Environment.Add("metrics-net.routetemplate", routeTemplate); - - return base.SendAsync(request, cancellationToken); - } - } -} diff --git a/Samples/Owin.Sample/Startup.cs b/Samples/Owin.Sample/Startup.cs deleted file mode 100644 index abef397e..00000000 --- a/Samples/Owin.Sample/Startup.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Metrics; -using System; -using System.Text.RegularExpressions; -using System.Web.Http; -using Microsoft.Owin.Cors; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using Owin.Metrics; - -namespace Owin.Sample -{ - public class Startup - { - - public void Configuration(IAppBuilder app) - { - JsonConvert.DefaultSettings = () => new JsonSerializerSettings - { - Formatting = Formatting.Indented, - ContractResolver = new CamelCasePropertyNamesContractResolver() - }; - - app.UseCors(CorsOptions.AllowAll); - - var httpconfig = new HttpConfiguration(); - httpconfig.MapHttpAttributeRoutes(); - - // Sets the route template for the current request in the OWIN context - httpconfig.MessageHandlers.Add(new SetOwinRouteTemplateMessageHandler()); - - Metric.Config - .WithAllCounters() - .WithReporting(r => r.WithConsoleReport(TimeSpan.FromSeconds(30))) - .WithOwin(middleware => app.Use(middleware), config => config - .WithRequestMetricsConfig(c => c.WithAllOwinMetrics(), new[] - { - new Regex("(?i)^sampleignore"), - new Regex("(?i)^metrics"), - new Regex("(?i)^health"), - new Regex("(?i)^json") - }) - .WithMetricsEndpoint() - ); - - app.UseWebApi(httpconfig); - } - - } -} diff --git a/Src/Adapters/Metrics.NLog/Metrics.NLog.csproj b/Src/Adapters/Metrics.NLog/Metrics.NLog.csproj index a5a3b82f..59aaa0cb 100644 --- a/Src/Adapters/Metrics.NLog/Metrics.NLog.csproj +++ b/Src/Adapters/Metrics.NLog/Metrics.NLog.csproj @@ -9,10 +9,11 @@ Properties Metrics.NLog Metrics.NLog - v4.5 + v4.0 512 ..\..\..\ true + true @@ -42,7 +43,7 @@ False - ..\..\..\packages\NLog.3.2.0.0\lib\net45\NLog.dll + ..\..\..\packages\NLog.3.2.0.0\lib\net40\NLog.dll diff --git a/Src/Adapters/Metrics.NLog/packages.config b/Src/Adapters/Metrics.NLog/packages.config index 49932617..4155837b 100644 --- a/Src/Adapters/Metrics.NLog/packages.config +++ b/Src/Adapters/Metrics.NLog/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Src/Adapters/Nancy.Metrics/Nancy.Metrics.csproj b/Src/Adapters/Nancy.Metrics/Nancy.Metrics.csproj index 5466b931..aaedc68f 100644 --- a/Src/Adapters/Nancy.Metrics/Nancy.Metrics.csproj +++ b/Src/Adapters/Nancy.Metrics/Nancy.Metrics.csproj @@ -10,9 +10,11 @@ Nancy.Metrics Nancy.Metrics 512 - v4.5 + v4.0 + v4.0 ..\..\..\ true + true @@ -27,6 +29,7 @@ + false pdbonly @@ -38,6 +41,7 @@ true 1591 ..\..\..\bin\Release\Nancy.Metrics.XML + false diff --git a/Src/Adapters/Nancy.Metrics/packages.config b/Src/Adapters/Nancy.Metrics/packages.config index 4243dca3..8c07d575 100644 --- a/Src/Adapters/Nancy.Metrics/packages.config +++ b/Src/Adapters/Nancy.Metrics/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Src/Adapters/Nancy.Metrics/packages.config.orig b/Src/Adapters/Nancy.Metrics/packages.config.orig new file mode 100644 index 00000000..099350fe --- /dev/null +++ b/Src/Adapters/Nancy.Metrics/packages.config.orig @@ -0,0 +1,8 @@ + + +<<<<<<< HEAD + +======= + +>>>>>>> master + \ No newline at end of file diff --git a/Src/Adapters/Owin.Metrics/Owin.Metrics.csproj b/Src/Adapters/Owin.Metrics/Owin.Metrics.csproj index 7f3fe337..a2988e52 100644 --- a/Src/Adapters/Owin.Metrics/Owin.Metrics.csproj +++ b/Src/Adapters/Owin.Metrics/Owin.Metrics.csproj @@ -9,6 +9,7 @@ Properties Owin.Metrics Owin.Metrics + v4.0 v4.5 512 ..\..\..\ @@ -24,6 +25,7 @@ prompt 4 1591 + false true @@ -36,8 +38,45 @@ false ..\..\..\Release\Owin.Metrics.XML 1591 + false + + + AnyCPU + true + full + false + v4.5 + ..\..\..\bin\MonoDebug\ + DEBUG;TRACE + prompt + 4 + ..\..\..\bin\MonoDebug\Owin.Metrics.XML + 1591 + false + + + AnyCPU + pdbonly + true + v4.5.1 + ..\..\..\bin\MonoRelease\ + TRACE + prompt + 4 + ..\..\..\bin\MonoRelease\Owin.Metrics.XML + 1591 + false + + + False + ..\..\..\packages\Microsoft.Owin.2.1.0\lib\net40\Microsoft.Owin.dll + + + False + ..\..\..\packages\Owin.1.0\lib\net40\Owin.dll + diff --git a/Src/Metrics.Tests/Metrics.Tests.csproj b/Src/Metrics.Tests/Metrics.Tests.csproj index 92f6449b..94fe745f 100644 --- a/Src/Metrics.Tests/Metrics.Tests.csproj +++ b/Src/Metrics.Tests/Metrics.Tests.csproj @@ -10,20 +10,23 @@ Properties Metrics.Tests Metrics.Tests - v4.5 + v4.0 512 ..\..\ true + 97472c9d true full false + false ..\..\bin\Debug\Tests\ DEBUG;TRACE prompt 4 + false pdbonly @@ -32,6 +35,7 @@ TRACE prompt 4 + false @@ -40,23 +44,11 @@ False - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.dll + ..\..\packages\FluentAssertions.3.3.0\lib\net40\FluentAssertions.dll False - ..\..\packages\FluentAssertions.3.3.0\lib\net45\FluentAssertions.Core.dll - - - False - ..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - - - False - ..\..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll - - - False - ..\..\packages\Microsoft.Owin.Testing.3.0.1\lib\net45\Microsoft.Owin.Testing.dll + ..\..\packages\FluentAssertions.3.3.0\lib\net40\FluentAssertions.Core.dll False @@ -68,35 +60,21 @@ False - ..\..\packages\Newtonsoft.Json.6.0.6\lib\net45\Newtonsoft.Json.dll - - - False - ..\..\packages\Owin.1.0\lib\net40\Owin.dll + ..\..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll - - - False - ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll - - - False - ..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll - - - False - ..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll - + + - - ..\..\packages\xunit.1.9.2\lib\net20\xunit.dll + + ..\..\packages\xunit.runner.utility.2.0.0-beta5-build2785\lib\net35\xunit.runner.utility.dll + @@ -120,7 +98,6 @@ - @@ -139,10 +116,6 @@ {fbff51d8-52f4-4eef-8498-122a14b37d6c} Nancy.Metrics - - {025cd6d0-1a1e-4b14-a7db-af5dff887210} - Owin.Metrics - {95e29d40-dbec-49e2-9cc5-26b88966dade} Metrics @@ -152,9 +125,9 @@ + - diff --git a/Src/Metrics.Tests/OwinAdapter/OwinMiddlewareTests.cs b/Src/Metrics.Tests/OwinAdapter/OwinMiddlewareTests.cs deleted file mode 100644 index 94bf0aec..00000000 --- a/Src/Metrics.Tests/OwinAdapter/OwinMiddlewareTests.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.Owin.Testing; -using Owin; -using Owin.Metrics; -using Xunit; - -namespace Metrics.Tests.OwinAdapter -{ - public class OwinMiddlewareTests - { - private const int timePerRequest = 100; - - private readonly TestContext context = new TestContext(); - private readonly MetricsConfig config; - private readonly TestServer server; - - public OwinMiddlewareTests() - { - this.config = new MetricsConfig(this.context); - - this.server = TestServer.Create(app => - { - this.config.WithOwin(m => app.Use(m)); - - app.Run(ctx => - { - this.context.Clock.Advance(TimeUnit.Milliseconds, timePerRequest); - if (ctx.Request.Path.ToString() == "/test/action") - { - return ctx.Response.WriteAsync("response"); - } - - if (ctx.Request.Path.ToString() == "/test/error") - { - ctx.Response.StatusCode = 500; - return ctx.Response.WriteAsync("response"); - } - - if (ctx.Request.Path.ToString() == "/test/size") - { - return ctx.Response.WriteAsync("response"); - } - - if (ctx.Request.Path.ToString() == "/test/post") - { - return ctx.Response.WriteAsync("response"); - } - - ctx.Response.StatusCode = 404; - return ctx.Response.WriteAsync("not found"); - }); - - }); - } - - [Fact] - public async Task OwinMetrics_ShouldBeAbleToRecordErrors() - { - context.MeterValue("Owin", "Errors").Count.Should().Be(0); - (await server.HttpClient.GetAsync("http://local.test/test/error")).StatusCode.Should().Be(HttpStatusCode.InternalServerError); - context.MeterValue("Owin", "Errors").Count.Should().Be(1); - - (await server.HttpClient.GetAsync("http://local.test/test/error")).StatusCode.Should().Be(HttpStatusCode.InternalServerError); - context.MeterValue("Owin", "Errors").Count.Should().Be(2); - } - - [Fact] - public async Task OwinMetrics_ShouldBeAbleToRecordActiveRequestCounts() - { - context.TimerValue("Owin", "Requests").Rate.Count.Should().Be(0); - (await server.HttpClient.GetAsync("http://local.test/test/action")).StatusCode.Should().Be(HttpStatusCode.OK); - context.TimerValue("Owin", "Requests").Rate.Count.Should().Be(1); - (await server.HttpClient.GetAsync("http://local.test/test/action")).StatusCode.Should().Be(HttpStatusCode.OK); - context.TimerValue("Owin", "Requests").Rate.Count.Should().Be(2); - (await server.HttpClient.GetAsync("http://local.test/test/action")).StatusCode.Should().Be(HttpStatusCode.OK); - context.TimerValue("Owin", "Requests").Rate.Count.Should().Be(3); - (await server.HttpClient.GetAsync("http://local.test/test/action")).StatusCode.Should().Be(HttpStatusCode.OK); - context.TimerValue("Owin", "Requests").Rate.Count.Should().Be(4); - - var timer = context.TimerValue("Owin", "Requests"); - - timer.Histogram.Min.Should().Be(timePerRequest); - timer.Histogram.Max.Should().Be(timePerRequest); - timer.Histogram.Mean.Should().Be(timePerRequest); - } - - [Fact] - public async Task OwinMetrics_ShouldRecordHistogramMetricsForPostSizeAndTimePerRequest() - { - const string json = "{ 'id': '1'} "; - var postContent = new StringContent(json); - postContent.Headers.Add("Content-Length", json.Length.ToString()); - await server.HttpClient.PostAsync("http://local.test/test/post", postContent); - - var histogram = context.HistogramValue("Owin", "Post & Put Request Size"); - - histogram.Count.Should().Be(1); - histogram.LastValue.Should().Be(json.Length); - } - } -} diff --git a/Src/Metrics.Tests/app.config b/Src/Metrics.Tests/app.config index f072f570..e19dec93 100644 --- a/Src/Metrics.Tests/app.config +++ b/Src/Metrics.Tests/app.config @@ -1,3 +1,12 @@  + + + + + + + + + diff --git a/Src/Metrics.Tests/packages.config b/Src/Metrics.Tests/packages.config index b414efb4..5e2e1e77 100644 --- a/Src/Metrics.Tests/packages.config +++ b/Src/Metrics.Tests/packages.config @@ -1,17 +1,12 @@  - - - - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/Src/Metrics.Tests/packages.config.orig b/Src/Metrics.Tests/packages.config.orig new file mode 100644 index 00000000..fa67c8e2 --- /dev/null +++ b/Src/Metrics.Tests/packages.config.orig @@ -0,0 +1,25 @@ + + +<<<<<<< HEAD + + + + + + +======= + + + + + + + + + + + + + +>>>>>>> master + \ No newline at end of file diff --git a/Src/Metrics/ElasticSearch/ElasticSearchReport.cs b/Src/Metrics/ElasticSearch/ElasticSearchReport.cs index ac90ad8c..e3a28891 100644 --- a/Src/Metrics/ElasticSearch/ElasticSearchReport.cs +++ b/Src/Metrics/ElasticSearch/ElasticSearchReport.cs @@ -22,7 +22,7 @@ private class ESDocument public string ToJsonString() { var meta = string.Format("{{ \"index\" : {{ \"_index\" : \"{0}\", \"_type\" : \"{1}\"}} }}", this.Index, this.Type); - return meta + Environment.NewLine + this.Object.AsJson(false); + return meta + Environment.NewLine + this.Object.AsJson(false) + Environment.NewLine; } } @@ -46,7 +46,7 @@ protected override void EndReport(string contextName) base.EndReport(contextName); using (var client = new WebClient()) { - var json = string.Join(Environment.NewLine, this.data.Select(d => d.ToJsonString())); + var json = string.Join(string.Empty, this.data.Select(d => d.ToJsonString())); client.UploadString(this.elasticSearchUri, json); } } diff --git a/Src/Metrics/Graphite/GraphiteReport.cs b/Src/Metrics/Graphite/GraphiteReport.cs index 2f4e22fc..f680dc1d 100644 --- a/Src/Metrics/Graphite/GraphiteReport.cs +++ b/Src/Metrics/Graphite/GraphiteReport.cs @@ -12,6 +12,7 @@ namespace Metrics.Graphite public class GraphiteReport : BaseReport, IDisposable { private static readonly Regex invalid = new Regex(@"[^a-zA-Z0-9\-%&]+", RegexOptions.CultureInvariant | RegexOptions.Compiled); + private static readonly Regex invalidAllowDots = new Regex(@"[^a-zA-Z0-9\-%&.]+", RegexOptions.CultureInvariant | RegexOptions.Compiled); private static readonly Regex slash = new Regex(@"\s*/\s*", RegexOptions.CultureInvariant | RegexOptions.Compiled); private readonly GraphiteSender sender; @@ -133,7 +134,7 @@ protected virtual void Send(string name, string value) protected override string FormatContextName(IEnumerable contextStack, string contextName) { var parts = contextStack.Concat(new[] { contextName }) - .Select(GraphiteName); + .Select(_ => GraphiteName(_, true)); return string.Join(".", parts); } @@ -196,10 +197,12 @@ protected virtual string FormatUnit(string unit, string name) return string.Concat("-", clean); } - protected virtual string GraphiteName(string name) + protected virtual string GraphiteName(string name, bool allowDots = false) { var noSlash = slash.Replace(name, "-per-"); - return invalid.Replace(noSlash, "_").Trim('_'); + return allowDots ? + invalidAllowDots.Replace(noSlash, "_").Trim('_') : + invalid.Replace(noSlash, "_").Trim('_'); } public void Dispose() diff --git a/Src/Metrics/Influxdb/Influxdb1x/ConfigExtensions.cs b/Src/Metrics/Influxdb/Influxdb1x/ConfigExtensions.cs new file mode 100644 index 00000000..a6dd0a3d --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/ConfigExtensions.cs @@ -0,0 +1,134 @@ +using System; +using Metrics.Reports; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Metrics.NET.InfluxDB +{ + /// + /// Configure Metrics.NET to report data to InfluxDB 0.9+ + /// + public static class ConfigExtensions + { + /// + /// Push metrics into InfluxDB 0.9+ + /// + public static MetricsReports WithInflux(this MetricsReports reports, string host, int port, string user, string pass, string database, TimeSpan interval, ConfigOptions config = null) + { + var cfg = config ?? new ConfigOptions(); + + var uri = cfg.BuildUri(host, port, database); + + return reports.WithInflux(uri, user, pass, interval, cfg); + } + + /// + /// Push metrics into InfluxDB 0.9+ + /// + public static MetricsReports WithInflux(this MetricsReports reports, Uri influxdbUri, string username, string password, TimeSpan interval, ConfigOptions config = null) + { + return reports.WithReport(new InfluxDbReport(influxdbUri, username, password, config ?? new ConfigOptions()), interval); + } + } + + /// + /// Additional configuration options + /// + public class ConfigOptions + { + private static readonly Regex NonWord = new Regex("[^a-zA-Z0-9\\.]+"); + + /// + /// Export metric name as-is + /// + public static readonly Func IdentityConverter = name => name; + + /// + /// Compact and dot-ify metric name + /// + public static readonly Func CompactConverter = name => + { + if (name.StartsWith("[", StringComparison.InvariantCultureIgnoreCase)) + { + name = name.Substring(1); + } + + return NonWord.Replace(name, ".").ToLower(); + }; + + /// + /// Set whether or not to use SSL when posting data to InfluxDB + /// + /// true if use https; otherwise, false. + public bool UseHttps { get; set; } + + /// + /// Set the target retention policy for the write + /// + /// The retention policy. + public string RetentionPolicy { get; set; } + + /// + /// Set the number of nodes that must confirm the write + /// + /// One of: one,quorum,all,any + public string Consistency { get; set; } + + /// + /// Specify the acceptable error rate before a curcuit is + /// tripped which will temporarily prevent writing data to + /// InfluxDB, in the form of: EventCount / TimeSpan, eg: 3 / 00:00:30 + /// + /// + public string BreakerRate { get; set; } + + /// + /// Gets or sets the http timeout in milliseconds + /// + /// The http timeout. + public int HttpTimeoutMillis { get; set; } + + /// + /// Provide converter that takes a Metrics.NET name name returns the name that is sent to InfluxDB + /// + /// The metric name converter. + public Func MetricNameConverter { get; set; } + + /// + /// Enable InfluxDB integration debug-level output + /// + public bool Verbose { get; set; } + + /// + /// Instantiate a new config object + /// + public ConfigOptions() + { + BreakerRate = "3 / 00:00:30"; + HttpTimeoutMillis = 5000; + MetricNameConverter = IdentityConverter; + } + + internal Uri BuildUri(string host, int port, string database) + { + var parameters = new List + { + "db="+database + }; + + if (!string.IsNullOrEmpty(RetentionPolicy)) + { + parameters.Add("rp=" + RetentionPolicy); + } + + if (!string.IsNullOrEmpty(Consistency)) + { + parameters.Add("consistency=" + Consistency); + } + + var queryStringParams = string.Join("&", parameters); + + return new Uri(string.Format(@"{0}://{1}:{2}/write?{3}", UseHttps ? "https" : "http", host, port, queryStringParams)); + } + } +} diff --git a/Src/Metrics/Influxdb/Influxdb1x/InfluxDbRecord.cs b/Src/Metrics/Influxdb/Influxdb1x/InfluxDbRecord.cs new file mode 100644 index 00000000..c9d3b03f --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/InfluxDbRecord.cs @@ -0,0 +1,154 @@ +using System.Text; +using System.Linq; +using System.Collections.Generic; +using System; +using System.Diagnostics; +using System.Globalization; + +namespace Metrics.NET.InfluxDB +{ + /// + /// Influx db record. See: https://influxdb.com/docs/v0.9/write_protocols/write_syntax.html + /// + public class InfluxDbRecord + { + private static readonly CultureInfo _cultureEnUs = CultureInfo.CreateSpecificCulture("en-US"); + + private static readonly Func _integerFormatter = i => string.Format(_cultureEnUs, "{0:G}i", i); + + private static readonly Func _decimalFormatter = i => string.Format(_cultureEnUs, "{0:G}", i); + + private static readonly IDictionary> _typeFormatters = new Dictionary> + { + {typeof(short), _integerFormatter}, + {typeof(ushort), _integerFormatter}, + {typeof(int), _integerFormatter}, + {typeof(uint), _integerFormatter}, + {typeof(long), _integerFormatter}, + {typeof(ulong), _integerFormatter}, + {typeof(float), _decimalFormatter}, + {typeof(double), _decimalFormatter}, + {typeof(decimal), _decimalFormatter}, + {typeof(bool), i => i.ToString ().ToLower ()} + }; + + /// + /// The line protocol for a measurement(s) + /// + /// The line protocol. + public string LineProtocol { get; private set; } + + private readonly ConfigOptions _config; + + internal InfluxDbRecord(ConfigOptions config) + { + _config = config; + } + + internal InfluxDbRecord(string name, object data, MetricTags tags, ConfigOptions config, Tuple[] moreTags = null) + : this(config) + { + var record = BuildRecordPreamble(name, tags, moreTags); + + record.Append("value=").Append(StringifyValue(data)); + + LineProtocol = record.ToString(); + } + + internal InfluxDbRecord(string name, IEnumerable columns, IEnumerable data, MetricTags tags, ConfigOptions config, Tuple[] moreTags = null) + : this(config) + { + var record = BuildRecordPreamble(name, tags, moreTags); + + var fieldKeypairs = new List(); + + foreach (var pair in columns.Zip(data, (col, dat) => new { col, dat })) + { + fieldKeypairs.Add(string.Format("{0}={1}", Escape(pair.col), StringifyValue(pair.dat))); + } + + record.Append(string.Join(",", fieldKeypairs)); + + LineProtocol = record.ToString(); + } + + internal StringBuilder BuildRecordPreamble(string name, MetricTags tags, Tuple[] moreTags = null) + { + var record = new StringBuilder(); + record.Append(Escape(_config.MetricNameConverter(name))); + + var allTags = GetAllTags(tags); + + if (moreTags != null && moreTags.Length > 0) + { + allTags = allTags.Union(moreTags); + } + + if (allTags.Any()) + { + record.Append(","); + record.Append(string.Join(",", allTags.Select(t => string.Format("{0}={1}", Escape(t.Item1), Escape(t.Item2))))); + } + + record.Append(" "); + + return record; + } + + internal IEnumerable> GetAllTags(MetricTags tags) + { + var allTags = new List> + { + new Tuple("host", Environment.MachineName.ToLower ()), + new Tuple("user", Environment.UserName.ToLower ()), + new Tuple("pid", Process.GetCurrentProcess ().Id.ToString ()), + }; + + if (tags.Tags != null && tags.Tags.Length > 0) + { + allTags.AddRange(tags.Tags.Select(t => new Tuple(Escape(t), "true"))); + } + + return allTags; + } + + private static string Escape(string v) + { + // spaces, commas, and equals signs are escaped + return v.Replace(" ", "\\ ").Replace(",", "\\,").Replace("=", "\\="); + } + + /// + /// Return the value as an InfluxDB-parseable string. + /// See: https://docs.influxdata.com/influxdb/v0.9/write_protocols/line/ + /// + /// InfluxDB value + public static string StringifyValue(object val) + { + if (val == null) + { + return null; + } + + var t = val.GetType(); + + if (_typeFormatters.ContainsKey(t)) + { + return _typeFormatters[t](val); + } + else if (t == typeof(string) + && (string.Equals(val.ToString(), "true", StringComparison.InvariantCultureIgnoreCase) + || string.Equals(val.ToString(), "false", StringComparison.InvariantCultureIgnoreCase))) + { + return val.ToString().ToLower(); + } + else if (t == typeof(string)) + { + // surrounded by quoutes and escaped double quotes + return string.Format("\"{0}\"", val.ToString().Replace("\"", "\\\"")); + } + + return val.ToString(); + } + } +} diff --git a/Src/Metrics/Influxdb/Influxdb1x/InfluxDbReport.cs b/Src/Metrics/Influxdb/Influxdb1x/InfluxDbReport.cs new file mode 100644 index 00000000..7c4ac737 --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/InfluxDbReport.cs @@ -0,0 +1,109 @@ +using System; +using Metrics.Reporters; +using System.Collections.Generic; +using System.Linq; + +namespace Metrics.NET.InfluxDB +{ + internal class InfluxDbReport : BaseReport + { + private readonly InfluxDbHttpTransport _transport; + private readonly ConfigOptions _config; + private List _data; + + internal InfluxDbReport(Uri influxdb, string username, string password, ConfigOptions config) + { + _transport = new InfluxDbHttpTransport(influxdb, username, password, config); + _config = config; + } + + private void Pack(string name, object value, MetricTags tags) + { + _data.Add(new InfluxDbRecord(name, value, tags, _config)); + } + + private void Pack(string name, IEnumerable columns, IEnumerable values, MetricTags tags) + { + _data.Add(new InfluxDbRecord(name, columns, values, tags, _config)); + } + + protected override void StartReport(string contextName) + { + _data = new List(); + base.StartReport(contextName); + } + + protected override void EndReport(string contextName) + { + base.EndReport(contextName); + _transport.Send(_data); + _data = null; + } + + protected override void ReportGauge(string name, double value, Unit unit, MetricTags tags) + { + if (!double.IsNaN(value) && !double.IsInfinity(value)) + { + Pack(name, value, tags); + } + } + + protected override void ReportCounter(string name, MetricData.CounterValue value, Unit unit, MetricTags tags) + { + if (!value.Items.Any()) + { + Pack(name, value.Count, tags); + return; + } + + var cols = new List(new[] { "total" }); + cols.AddRange(value.Items.Select(x => x.Item)); + + var data = new List(new object[] { value.Count }); + data.AddRange(value.Items.Select(x => (object)x.Count)); + + Pack(name, cols, data, tags); + } + + protected override void ReportMeter(string name, MetricData.MeterValue value, Unit unit, TimeUnit rateUnit, MetricTags tags) + { + var data = new Dictionary(); + + value.AddMeterValues(data); + + var keys = data.Keys.ToList(); + var values = keys.Select(k => data[k]); + + Pack(name, keys, values, tags); + } + + protected override void ReportHistogram(string name, MetricData.HistogramValue value, Unit unit, MetricTags tags) + { + var data = new Dictionary(); + + value.AddHistogramValues(data); + + var keys = data.Keys.ToList(); + var values = keys.Select(k => data[k]); + + Pack(name, keys, values, tags); + } + + protected override void ReportTimer(string name, MetricData.TimerValue value, Unit unit, TimeUnit rateUnit, TimeUnit durationUnit, MetricTags tags) + { + var data = new Dictionary(); + + value.Rate.AddMeterValues(data); + value.Histogram.AddHistogramValues(data); + + var keys = data.Keys.ToList(); + var values = keys.Select(k => data[k]); + + Pack(name, keys, values, tags); + } + + protected override void ReportHealth(HealthStatus status) + { + } + } +} diff --git a/Src/Metrics/Influxdb/Influxdb1x/InfluxHttpTransport.cs b/Src/Metrics/Influxdb/Influxdb1x/InfluxHttpTransport.cs new file mode 100644 index 00000000..377bfef5 --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/InfluxHttpTransport.cs @@ -0,0 +1,102 @@ +using System; +using System.Net.Http; +using Polly; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net.Http.Headers; +using System.Threading; +using Metrics.Logging; + +namespace Metrics.NET.InfluxDB +{ + internal class InfluxDbHttpTransport + { + private static readonly ILog log = LogProvider.GetCurrentClassLogger(); + + private readonly HttpClient _client; + private readonly Policy _policy; + private readonly Uri _uri; + private readonly ConfigOptions _config; + + internal InfluxDbHttpTransport(Uri uri, string username, string password, ConfigOptions config) + { + _uri = uri; + _config = config; + + var byteArray = Encoding.ASCII.GetBytes(string.Format("{0}:{1}", username, password)); + + _client = new HttpClient() + { + DefaultRequestHeaders = + { + Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)) + } + }; + + _policy = new Rate(_config.BreakerRate).AsPolicy(); + } + + internal void Send(IEnumerable records) + { + if (_config.Verbose) + { + foreach (var rec in records) + { + log.DebugFormat("posting: {0}", rec.LineProtocol); + } + } + + _policy.ExecuteAndCapture(() => + { + var content = string.Join("\n", records.Select(d => d.LineProtocol)); + + var cts = new CancellationTokenSource(); + + try + { + Metric.Context("Metrics.NET").Meter("influxdb.post.meter", Unit.Events).Mark(); + + var task = _client.PostAsync(_uri, new StringContent(content), cts.Token); + + if (task.Wait(TimeSpan.FromMilliseconds(_config.HttpTimeoutMillis))) + { + if ((int)task.Result.StatusCode == 204) + { + Metric.Context("Metrics.NET").Meter("influxdb.success.meter", Unit.Events).Mark(); + } + else + { + Metric.Context("Metrics.NET").Meter("influxdb.fail.meter", Unit.Events).Mark(); + var response = task.Result.Content.ReadAsStringAsync().Result; + throw new Exception(string.Format("Error posting to [{0}] {1} {2}", _uri, task.Result.StatusCode, response)); + } + } + else + { + cts.Cancel(); + Metric.Context("Metrics.NET").Meter("influxdb.timeout.meter", Unit.Events).Mark(); + throw new TimeoutException(string.Format("Timed out after {0}ms posting to {1}", _config.HttpTimeoutMillis, _uri)); + } + } + catch (Exception e) + { + cts.Cancel(); + Metric.Context("Metrics.NET").Meter("influxdb.error.meter", Unit.Events).Mark(); + + var agg = e as AggregateException; + if (agg != null) + { + log.ErrorException(agg.InnerException.Message, agg.InnerException); + } + else + { + log.ErrorException(e.InnerException.Message, e.InnerException); + } + + throw; + } + }); + } + } +} diff --git a/Src/Metrics/Influxdb/Influxdb1x/MetricsDataCollectorExt.cs b/Src/Metrics/Influxdb/Influxdb1x/MetricsDataCollectorExt.cs new file mode 100644 index 00000000..d0796601 --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/MetricsDataCollectorExt.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; + +namespace Metrics.NET.InfluxDB +{ + /// + /// Extension methods to faciltate collecting data from Metrics.NET + /// + public static class MetricsDataCollectorExt + { + /// + /// Merge a Meter's metrics into a map of name/values + /// + /// + /// + public static void AddMeterValues(this MetricData.MeterValue meter, IDictionary values) + { + values.Add("count.meter", meter.Count); + values.Add("rate1m", meter.OneMinuteRate); + values.Add("rate5m", meter.FiveMinuteRate); + values.Add("rate15m", meter.FifteenMinuteRate); + values.Add("rate.mean", meter.MeanRate); + } + + /// + /// Merge a Histogram's metrics into a map of name/values + /// + /// + /// + public static void AddHistogramValues(this MetricData.HistogramValue hist, IDictionary values) + { + values.Add("samples", hist.SampleSize); + values.Add("last", hist.LastValue); + values.Add("count.hist", hist.Count); + values.Add("min", hist.Min); + values.Add("max", hist.Max); + values.Add("mean", hist.Mean); + values.Add("median", hist.Median); + values.Add("stddev", hist.StdDev); + values.Add("p999", hist.Percentile999); + values.Add("p99", hist.Percentile99); + values.Add("p98", hist.Percentile98); + values.Add("p95", hist.Percentile95); + values.Add("p75", hist.Percentile75); + + if (hist.LastUserValue != null) + { + values.Add("user.last", hist.LastUserValue); + } + + if (hist.MinUserValue != null) + { + values.Add("user.min", hist.MinUserValue); + } + + if (hist.MaxUserValue != null) + { + values.Add("user.max", hist.MaxUserValue); + } + } + } +} diff --git a/Src/Metrics/Influxdb/Influxdb1x/Rate.cs b/Src/Metrics/Influxdb/Influxdb1x/Rate.cs new file mode 100644 index 00000000..6f2e2520 --- /dev/null +++ b/Src/Metrics/Influxdb/Influxdb1x/Rate.cs @@ -0,0 +1,33 @@ +using System; +using Polly; + +namespace Metrics.NET.InfluxDB +{ + internal class Rate + { + internal int Events { get; private set; } + + internal TimeSpan Period { get; private set; } + + internal Rate (int events, TimeSpan period) + { + Events = events; + Period = period; + } + + /// + /// Rate specification in the form of: events / timeframe + /// + internal Rate (string specification) + { + var parts = specification.Split ('/'); + Events = int.Parse (parts [0].Trim ()); + Period = TimeSpan.Parse (parts [1].Trim ()); + } + + internal Policy AsPolicy () + { + return Policy.Handle ().CircuitBreaker (Events, Period); + } + } +} diff --git a/Src/Metrics/Metric.cs b/Src/Metrics/Metric.cs index 8f524472..51cde2e8 100644 --- a/Src/Metrics/Metric.cs +++ b/Src/Metrics/Metric.cs @@ -187,7 +187,7 @@ private static string GetGlobalContextName() try { var configName = ConfigurationManager.AppSettings["Metrics.GlobalContextName"]; - var name = string.IsNullOrEmpty(configName) ? Process.GetCurrentProcess().ProcessName : configName; + var name = string.IsNullOrEmpty(configName) ? Process.GetCurrentProcess().ProcessName.Replace('.', '_') : configName; log.Debug(() => "Metrics: GlobalContext Name set to " + name); return name; } diff --git a/Src/Metrics/Metrics.csproj b/Src/Metrics/Metrics.csproj index 496c8e59..d2c45724 100644 --- a/Src/Metrics/Metrics.csproj +++ b/Src/Metrics/Metrics.csproj @@ -9,7 +9,7 @@ Properties Metrics Metrics - v4.5 + v4.0 512 ..\..\ true @@ -40,9 +40,54 @@ + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll + True + + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll + True + + + ..\..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll + True + + + ..\..\packages\Polly.4.3.0\lib\net40\Polly.dll + True + + + ..\..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.IO.dll + True + + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.dll + True + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Extensions.dll + True + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.Primitives.dll + True + + + ..\..\packages\Microsoft.Net.Http.2.2.29\lib\net40\System.Net.Http.WebRequest.dll + True + + + ..\..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Runtime.dll + True + + + ..\..\packages\Microsoft.Bcl.1.1.10\lib\net40\System.Threading.Tasks.dll + True + @@ -64,6 +109,12 @@ + + + + + + @@ -168,6 +219,7 @@ + @@ -178,6 +230,11 @@ + + + + +