all the core support 🎉

This commit is contained in:
Tommy Parnell
2016-11-19 22:59:58 -05:00
parent 250f02caaf
commit aba7241dce
43 changed files with 582 additions and 976 deletions

3
.gitignore vendored
View File

@@ -14,7 +14,8 @@ TestResults
*.suo
*.user
*.sln.docstates
project.lock.json
.vs
# Build results
[Dd]ebug/
[Rr]elease/

View File

@@ -1,6 +1,6 @@
# statsd-csharp-client
# statsdcore.net
A simple c# client library for [statsd.net](https://github.com/lukevenediger/statsd.net/) and [statsd](https://github.com/etsy/statsd/).
A simple c# client library for [statsd.net](https://github.com/lukevenediger/statsd.net/) and [statsd](https://github.com/etsy/statsd/) compatible with dotnet core!!! This was originally a fork of [another client](https://github.com/lukevenediger/statsd.net).
# Features
* Log counts, timings, gauges, sets, calendargrams and raw metrics
@@ -75,12 +75,11 @@ The connection will attempt to reconnect if something goes wrong, and will try t
# Project Information
## Target Runtimes
* .Net 3.5
* .Net 4.0
* .Net 4.5
* netstandard1.3
## Authors
Luke Venediger - lukev@lukev.net and [@lukevenediger](http://twitter.com/lukevenediger)
Tommy Parnell - tommy@terribledev.io and [@TerribleDev](http://twitter.com/terribledev)
## See Also
* [statsd.net](https://github.com/lukevenediger/statsd.net/)

View File

@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace StatsdClient.ASPNET_MVC
{
public class LogLatencyAttribute : ActionFilterAttribute
{
private Stopwatch _stopwatch;
private string _name;
private IStatsd _statsd;
public LogLatencyAttribute(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("Name cannot be null or empty.", "name");
}
_name = name;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_stopwatch = Stopwatch.StartNew();
if (!filterContext.Controller.TempData.ContainsKey("statsdclient"))
{
throw new ArgumentNullException("statsdclient", "Could not find the statsdclient reference in the controller's TempData.");
}
_statsd = filterContext.Controller.TempData["statsdclient"] as IStatsd;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
_stopwatch.Stop();
_statsd.LogTiming(_name, (int)_stopwatch.ElapsedMilliseconds);
}
}
}

View File

@@ -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("StatsdClient.ASPNET-MVC")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StatsdClient.ASPNET-MVC")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("6c5d32a9-970e-4c4e-88e6-f57b3f219da0")]
// 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")]

View File

@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StatsdClient.ASPNET_MVC</RootNamespace>
<AssemblyName>StatsdClient.ASPNET-MVC</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="StatsdClient">
<HintPath>..\packages\StatsdCsharpClient.1.0.0.0\lib\net45\StatsdClient.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20715.0\lib\net40\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="LogLatencyAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="4.0.20710.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="StatsdCsharpClient" version="1.0.0.0" targetFramework="net45" />
</packages>

View File

@@ -1,6 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3981BC36-0C55-4127-827F-292024E6A8E9}"
ProjectSection(SolutionItems) = preProject
CHANGELOG.md = CHANGELOG.md
@@ -8,15 +10,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
nuget\StatsdClient.nuspec = nuget\StatsdClient.nuspec
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClient", "StatsdClient\StatsdClient.csproj", "{D9C7B372-074B-4649-B45E-01FE10724AF9}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StatsdCore.Net", "src\StatsdCore.Net\StatsdCore.Net.xproj", "{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClientTests", "StatsdClientTests\StatsdClientTests.csproj", "{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{415D2BEB-C25D-4B69-A308-835C93EDB2D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClient.ASPNET-MVC", "StatsdClient.ASPNET-MVC\StatsdClient.ASPNET-MVC.csproj", "{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClient-DotNet40", "StatsdClient\StatsdClient-DotNet40.csproj", "{4C053A87-70F9-4059-8A42-BC08626A8B22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClient-DotNet35", "StatsdClient\StatsdClient-DotNet35.csproj", "{BD729A99-C965-40F3-A69B-EFC81D6DA023}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "StatsdCore.Net.Tests", "src\StatsdCore.Net.Tests\StatsdCore.Net.Tests.xproj", "{92092AC3-65A9-44D4-A4B2-27502D139D22}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -24,26 +22,20 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D9C7B372-074B-4649-B45E-01FE10724AF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9C7B372-074B-4649-B45E-01FE10724AF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9C7B372-074B-4649-B45E-01FE10724AF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9C7B372-074B-4649-B45E-01FE10724AF9}.Release|Any CPU.Build.0 = Release|Any CPU
{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}.Release|Any CPU.Build.0 = Release|Any CPU
{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C01CFEE-CE8D-447F-9919-08FF7C548BF8}.Release|Any CPU.Build.0 = Release|Any CPU
{4C053A87-70F9-4059-8A42-BC08626A8B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4C053A87-70F9-4059-8A42-BC08626A8B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C053A87-70F9-4059-8A42-BC08626A8B22}.Release|Any CPU.Build.0 = Release|Any CPU
{BD729A99-C965-40F3-A69B-EFC81D6DA023}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD729A99-C965-40F3-A69B-EFC81D6DA023}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD729A99-C965-40F3-A69B-EFC81D6DA023}.Release|Any CPU.Build.0 = Release|Any CPU
{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1}.Release|Any CPU.Build.0 = Release|Any CPU
{92092AC3-65A9-44D4-A4B2-27502D139D22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92092AC3-65A9-44D4-A4B2-27502D139D22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92092AC3-65A9-44D4-A4B2-27502D139D22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92092AC3-65A9-44D4-A4B2-27502D139D22}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4F80CF24-D107-44CE-B9F7-EEF6C1E5B3A1} = {415D2BEB-C25D-4B69-A308-835C93EDB2D1}
{92092AC3-65A9-44D4-A4B2-27502D139D22} = {415D2BEB-C25D-4B69-A308-835C93EDB2D1}
EndGlobalSection
EndGlobal

View File

@@ -1,11 +0,0 @@
using System.Threading.Tasks;
namespace StatsdClient
{
internal sealed class NullOutputChannel : IOutputChannel
{
public async Task SendAsync(string line)
{
}
}
}

View File

@@ -1,10 +0,0 @@
namespace StatsdClient
{
public static class OutputChannelExtensions
{
public static void Send(this IOutputChannel outputChannel, string line)
{
outputChannel.SendAsync(line).Wait();
}
}
}

View File

@@ -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("StatsdClient")]
[assembly: AssemblyDescription("A statsd.net and statsd client for c#")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Luke Venediger")]
[assembly: AssemblyProduct("StatsdClient")]
[assembly: AssemblyCopyright("Copyright © Luke Venediger 2013")]
[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("8ac00668-c22c-4335-bc35-fc310f50d42a")]
// 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.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]

View File

@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BD729A99-C965-40F3-A69B-EFC81D6DA023}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StatsdClient</RootNamespace>
<AssemblyName>StatsdClient</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Nuget Releases\lib\net35\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>..\Nuget Releases\lib\net35\StatsdClient.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConnectionType.cs" />
<Compile Include="IOutputChannel.cs" />
<Compile Include="IStatsd.cs" />
<Compile Include="MetricType.cs" />
<Compile Include="NullOutputChannel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Statsd.cs" />
<Compile Include="StatsdClientExtensions.cs" />
<Compile Include="TcpOutputChannel.cs" />
<Compile Include="TimingToken.cs" />
<Compile Include="UdpOutputChannel.cs" />
</ItemGroup>
<ItemGroup>
<None Include="StatsdClient.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4C053A87-70F9-4059-8A42-BC08626A8B22}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StatsdClient</RootNamespace>
<AssemblyName>StatsdClient</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Nuget Releases\lib\net40\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>..\Nuget Releases\lib\net40\StatsdClient.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConnectionType.cs" />
<Compile Include="IOutputChannel.cs" />
<Compile Include="IStatsd.cs" />
<Compile Include="MetricType.cs" />
<Compile Include="NullOutputChannel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StatsdExtensions.cs" />
<Compile Include="Statsd.cs" />
<Compile Include="StatsdClientExtensions.cs" />
<Compile Include="TcpOutputChannel.cs" />
<Compile Include="TimingToken.cs" />
<Compile Include="UdpOutputChannel.cs" />
</ItemGroup>
<ItemGroup>
<None Include="StatsdClient.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D9C7B372-074B-4649-B45E-01FE10724AF9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StatsdClient</RootNamespace>
<AssemblyName>StatsdClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\Nuget Releases\lib\net45\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>..\Nuget Releases\lib\net45\StatsdClient.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AsyncLock.cs" />
<Compile Include="CalendargramRetentionPeriod.cs" />
<Compile Include="ConnectionType.cs" />
<Compile Include="IOutputChannel.cs" />
<Compile Include="IStatsd.cs" />
<Compile Include="MetricType.cs" />
<Compile Include="NullOutputChannel.cs" />
<Compile Include="OutputChannelExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StatsdExtensions.cs" />
<Compile Include="Statsd.cs" />
<Compile Include="StatsdClientExtensions.cs" />
<Compile Include="TcpOutputChannel.cs" />
<Compile Include="TimingToken.cs" />
<Compile Include="UdpOutputChannel.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,40 +0,0 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace StatsdClient
{
internal sealed class UdpOutputChannel : IOutputChannel
{
private readonly UdpClient _udpClient;
public Socket ClientSocket
{
get
{
return _udpClient.Client;
}
}
public UdpOutputChannel(string hostOrIPAddress, int port)
{
IPAddress ipAddress;
// Is this an IP address already?
if (!IPAddress.TryParse(hostOrIPAddress, out ipAddress))
{
// Convert to ipv4 address
ipAddress = Dns.GetHostAddresses(hostOrIPAddress).First(p => p.AddressFamily == AddressFamily.InterNetwork);
}
_udpClient = new UdpClient();
_udpClient.Connect(ipAddress, port);
}
public async Task SendAsync(string line)
{
var payload = Encoding.UTF8.GetBytes(line);
await _udpClient.SendAsync(payload, payload.Length);
}
}
}

View File

@@ -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("StatsdClientTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StatsdClientTests")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("90fef403-171b-449e-8400-5f2e6f8ffc7e")]
// 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")]

View File

@@ -1,98 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StatsdClientTests</RootNamespace>
<AssemblyName>StatsdClientTests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="System" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="StatsdExtensionsTests.cs" />
<Compile Include="StatsdTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestData.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\StatsdClient\StatsdClient.csproj">
<Project>{d9c7b372-074b-4649-b45e-01fe10724af9}</Project>
<Name>StatsdClient</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,60 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using StatsdClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StatsdClientTests
{
[TestClass]
public class StatsdExtensionsTests
{
private Mock<IOutputChannel> _outputChannel;
private Statsd _statsd;
private TestData _testData;
[TestInitialize]
public void Initialise()
{
_outputChannel = new Mock<IOutputChannel>();
_statsd = new Statsd("localhost", 12000, outputChannel : _outputChannel.Object);
_testData = new TestData();
}
[TestMethod]
public void count_SendToStatsd_Success()
{
_outputChannel.Setup(p => p.Send("foo.bar:1|c")).Verifiable();
_statsd.count().foo.bar += 1;
_outputChannel.VerifyAll();
}
[TestMethod]
public void gauge_SendToStatsd_Success()
{
_outputChannel.Setup(p => p.Send("foo.bar:1|g")).Verifiable();
_statsd.gauge().foo.bar += 1;
_outputChannel.VerifyAll();
}
[TestMethod]
public void timing_SendToStatsd_Success()
{
_outputChannel.Setup(p => p.Send("foo.bar:1|ms")).Verifiable();
_statsd.timing().foo.bar += 1;
_outputChannel.VerifyAll();
}
[TestMethod]
public void count_AddNamePartAsString_Success()
{
_outputChannel.Setup(p => p.Send("foo.bar:1|ms")).Verifiable();
_statsd.timing().foo._("bar")._ += 1;
_outputChannel.VerifyAll();
}
}
}

View File

@@ -1,186 +0,0 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StatsdClient;
using Moq;
namespace StatsdClientTests
{
[TestClass]
public class StatsdTests
{
private Mock<IOutputChannel> _outputChannel;
private Statsd _statsd;
private TestData _testData;
public StatsdTests()
{
_testData = new TestData();
}
[TestInitialize]
public void Initialise()
{
_outputChannel = new Mock<IOutputChannel>();
_statsd = new Statsd("localhost", 12000, outputChannel : _outputChannel.Object);
}
#region Parameter Checks
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void LogCount_NameIsNull_ExpectArgumentNullException()
{
_statsd.LogCount(null);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void LogCount_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
{
_statsd.LogCount("foo", -1);
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void LogGauge_NameIsNull_ExpectArgumentNullException()
{
_statsd.LogGauge(null, _testData.NextInteger);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void LogGauge_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
{
_statsd.LogGauge("foo", -1);
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void LogTiming_NameIsNull_ExpectArgumentNullException()
{
_statsd.LogTiming(null, _testData.NextInteger);
}
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void LogTiming_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
{
_statsd.LogTiming("foo", -1);
}
#endregion
[TestMethod]
public void LogCount_ValidInput_Success()
{
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.Send(stat + ":" + count.ToString() + "|c")).Verifiable();
_statsd.LogCount(stat, count);
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogTiming_ValidInput_Success()
{
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.Send(stat + ":" + count.ToString() + "|ms")).Verifiable();
_statsd.LogTiming(stat, count);
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogGauge_ValidInput_Success()
{
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.Send(stat + ":" + count.ToString() + "|g")).Verifiable();
_statsd.LogGauge(stat, count);
_outputChannel.VerifyAll();
}
[TestMethod]
public void Constructor_PrefixEndsInPeriod_RemovePeriod()
{
var statsd = new Statsd("localhost", 12000, "foo.", outputChannel : _outputChannel.Object);
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.Send("foo." + stat + ":" + count.ToString() + "|c")).Verifiable();
statsd.LogCount(stat, count);
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogCount_NullPrefix_DoesNotStartNameWithPeriod()
{
var statsd = new Statsd("localhost", 12000, prefix : null, outputChannel : _outputChannel.Object);
var inputStat = "some.stat:1|c";
_outputChannel.Setup(p => p.Send(It.Is<string>(q => q == inputStat)))
.Verifiable();
statsd.LogCount("some.stat");
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogCount_EmptyStringPrefix_DoesNotStartNameWithPeriod()
{
var statsd = new Statsd("localhost", 12000, prefix : "", outputChannel : _outputChannel.Object);
var inputStat = "some.stat:1|c";
_outputChannel.Setup(p => p.Send(It.Is<string>(q => q == inputStat)))
.Verifiable();
statsd.LogCount("some.stat");
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogRaw_WithoutEpoch_Valid()
{
var statsd = new Statsd("localhost", 12000, prefix : "", outputChannel : _outputChannel.Object);
var inputStat = "my.raw.stat:12934|r";
_outputChannel.Setup(p => p.Send(It.Is<String>(q => q == inputStat)))
.Verifiable();
statsd.LogRaw("my.raw.stat", 12934);
_outputChannel.VerifyAll();
}
[TestMethod]
public void LogRaw_WithEpoch_Valid()
{
var statsd = new Statsd("localhost", 12000, prefix : "", outputChannel : _outputChannel.Object);
var almostAnEpoch = DateTime.Now.Ticks;
var inputStat = "my.raw.stat:12934|r|" + almostAnEpoch;
_outputChannel.Setup(p => p.Send(It.Is<String>(q => q == inputStat)))
.Verifiable();
statsd.LogRaw("my.raw.stat", 12934, almostAnEpoch);
_outputChannel.VerifyAll();
}
[TestMethod]
public void CreateClient_WithInvalidHostName_DoesNotError()
{
var statsd = new Statsd("nowhere.here.or.anywhere", 12000);
statsd.LogCount("test.stat");
}
[TestMethod]
public void CreateClient_WithIPAddress_DoesNotError()
{
var statsd = new Statsd("127.0.0.1", 12000);
statsd.LogCount("test.stat");
}
[TestMethod]
public void CreateClient_WithInvalidCharactersInHostName_DoesNotError()
{
var statsd = new Statsd("@%)(F(FSDLKDEQ423t0-vbdfb", 12000);
statsd.LogCount("test.foo");
}
}
}

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Moq" version="4.0.10827" targetFramework="net45" />
</packages>

View File

@@ -1,38 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>StatsdCsharpClient</id>
<version>1.2.1.0</version>
<title>Simple Statsd Client for .Net 3.5, 4.0 and 4.5</title>
<authors>Luke Venediger</authors>
<owners>Luke Venediger</owners>
<projectUrl>https://github.com/lukevenediger/statsd-csharp-client/</projectUrl>
<summary>A simple c# client library for statsd and statsd.net</summary>
<description>
The simple statsd client for .Net is a robust, easy-to-use way of feeding metrics into a statsd-compatible server. You can use it to log counts, timings and gauges.
Features include:
* Log counts, timings, gauges, sets and raw metrics
* Has an additional API that uses dynamics to create and submit stats
* Fault-tolerant client that can be configured to fail silently (with a warning) if misconfigured
* IStatsdClient interface for easy mocking in unit tests
* Allows for customisation of every output stat to do things like screen metrics before sending
* Supports a user-defined prefix to prepend to every metric
* Outputs to UDP or TCP
.Net 4.0 and 4.5 Users:
* Use the StatsdExtensions to define metrics without having to manipulate strings
* The dynamic stats builder interface provides a cleaner alternative to creating and logging metrics
Licence: MIT
</description>
<releaseNotes>
* Fixed a bug in the tcp output channel's retry logic
* Skip DNS resolution on the UDP client if already an IP Address
* Fall back to the Null Output Channel if the client is created with an empty host name.
</releaseNotes>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<copyright>Copyright 2013 Luke Venediger</copyright>
<tags>statsd statsd.net graphite etsy metrics</tags>
</metadata>
</package>

View File

@@ -0,0 +1,19 @@
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StatsdCore.Net.Tests")]
[assembly: AssemblyTrademark("")]
// 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("92092ac3-65a9-44d4-a4b2-27502d139d22")]

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>92092ac3-65a9-44d4-a4b2-27502d139d22</ProjectGuid>
<RootNamespace>StatsdCore.Net.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,62 @@
using Moq;
using StatsdClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace StatsdClientTests
{
public class StatsdExtensionsTests
{
private Mock<IOutputChannel> _outputChannel;
private Statsd _statsd;
private TestData _testData;
public void Initialise()
{
_outputChannel = new Mock<IOutputChannel>();
_statsd = new Statsd("localhost", 12000, outputChannel: _outputChannel.Object);
_testData = new TestData();
}
[Fact]
public void count_SendToStatsd_Success()
{
Initialise();
_outputChannel.Setup(p => p.SendAsync("foo.bar:1|c")).Verifiable();
_statsd.count().foo.bar += 1;
_outputChannel.VerifyAll();
}
[Fact]
public void gauge_SendToStatsd_Success()
{
Initialise();
_outputChannel.Setup(p => p.SendAsync("foo.bar:1|g")).Verifiable();
_statsd.gauge().foo.bar += 1;
_outputChannel.VerifyAll();
}
[Fact]
public void timing_SendToStatsd_Success()
{
Initialise();
_outputChannel.Setup(p => p.SendAsync("foo.bar:1|ms")).Verifiable();
_statsd.timing().foo.bar += 1;
_outputChannel.VerifyAll();
}
[Fact]
public void count_AddNamePartAsString_Success()
{
Initialise();
_outputChannel.Setup(p => p.SendAsync("foo.bar:1|ms")).Verifiable();
_statsd.timing().foo._("bar")._ += 1;
_outputChannel.VerifyAll();
}
}
}

View File

@@ -0,0 +1,195 @@
using System;
using StatsdClient;
using Moq;
using Xunit;
namespace StatsdClientTests
{
public class StatsdTests
{
private Mock<IOutputChannel> _outputChannel;
private Statsd _statsd;
private TestData _testData;
public StatsdTests()
{
_testData = new TestData();
}
public void Initialise()
{
_outputChannel = new Mock<IOutputChannel>();
_statsd = new Statsd("localhost", 12000, outputChannel: _outputChannel.Object);
}
#region Parameter Checks
//[Fact]
//[ExpectedException(typeof(ArgumentNullException))]
//public void LogCount_NameIsNull_ExpectArgumentNullException()
//{
// _statsd.LogCount(null);
//}
//[Fact]
//[ExpectedException(typeof(ArgumentOutOfRangeException))]
//public void LogCount_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
//{
// _statsd.LogCount("foo", -1);
//}
//[Fact]
//[ExpectedException(typeof(ArgumentNullException))]
//public void LogGauge_NameIsNull_ExpectArgumentNullException()
//{
// _statsd.LogGauge(null, _testData.NextInteger);
//}
//[Fact]
//[ExpectedException(typeof(ArgumentOutOfRangeException))]
//public void LogGauge_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
//{
// _statsd.LogGauge("foo", -1);
//}
//[Fact]
//[ExpectedException(typeof(ArgumentNullException))]
//public void LogTiming_NameIsNull_ExpectArgumentNullException()
//{
// _statsd.LogTiming(null, _testData.NextInteger);
//}
//[Fact]
//[ExpectedException(typeof(ArgumentOutOfRangeException))]
//public void LogTiming_ValueIsLessThanZero_ExpectArgumentOutOfRangeException()
//{
// _statsd.LogTiming("foo", -1);
//}
#endregion
[Fact]
public void LogCount_ValidInput_Success()
{
Initialise();
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.SendAsync(stat + ":" + count.ToString() + "|c")).Verifiable();
_statsd.LogCount(stat, count);
_outputChannel.VerifyAll();
}
[Fact]
public void LogTiming_ValidInput_Success()
{
Initialise();
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.SendAsync(stat + ":" + count.ToString() + "|ms")).Verifiable();
_statsd.LogTiming(stat, count);
_outputChannel.VerifyAll();
}
[Fact]
public void LogGauge_ValidInput_Success()
{
Initialise();
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.SendAsync(stat + ":" + count.ToString() + "|g")).Verifiable();
_statsd.LogGauge(stat, count);
_outputChannel.VerifyAll();
}
[Fact]
public void Constructor_PrefixEndsInPeriod_RemovePeriod()
{
Initialise();
var statsd = new Statsd("localhost", 12000, "foo.", outputChannel: _outputChannel.Object);
var stat = _testData.NextStatName;
var count = _testData.NextInteger;
_outputChannel.Setup(p => p.SendAsync("foo." + stat + ":" + count.ToString() + "|c")).Verifiable();
statsd.LogCount(stat, count);
_outputChannel.VerifyAll();
}
[Fact]
public void LogCount_NullPrefix_DoesNotStartNameWithPeriod()
{
Initialise();
var statsd = new Statsd("localhost", 12000, prefix: null, outputChannel: _outputChannel.Object);
var inputStat = "some.stat:1|c";
_outputChannel.Setup(p => p.SendAsync(It.Is<string>(q => q == inputStat)))
.Verifiable();
statsd.LogCount("some.stat");
_outputChannel.VerifyAll();
}
[Fact]
public void LogCount_EmptyStringPrefix_DoesNotStartNameWithPeriod()
{
Initialise();
var statsd = new Statsd("localhost", 12000, prefix: "", outputChannel: _outputChannel.Object);
var inputStat = "some.stat:1|c";
_outputChannel.Setup(p => p.SendAsync(It.Is<string>(q => q == inputStat)))
.Verifiable();
statsd.LogCount("some.stat");
_outputChannel.VerifyAll();
}
[Fact]
public void LogRaw_WithoutEpoch_Valid()
{
Initialise();
var statsd = new Statsd("localhost", 12000, prefix: "", outputChannel: _outputChannel.Object);
var inputStat = "my.raw.stat:12934|r";
_outputChannel.Setup(p => p.SendAsync(It.Is<String>(q => q == inputStat)))
.Verifiable();
statsd.LogRaw("my.raw.stat", 12934);
_outputChannel.VerifyAll();
}
[Fact]
public void LogRaw_WithEpoch_Valid()
{
Initialise();
var statsd = new Statsd("localhost", 12000, prefix: "", outputChannel: _outputChannel.Object);
var almostAnEpoch = DateTime.Now.Ticks;
var inputStat = "my.raw.stat:12934|r|" + almostAnEpoch;
_outputChannel.Setup(p => p.SendAsync(It.Is<String>(q => q == inputStat)))
.Verifiable();
statsd.LogRaw("my.raw.stat", 12934, almostAnEpoch);
_outputChannel.VerifyAll();
}
[Fact]
public void CreateClient_WithInvalidHostName_DoesNotError()
{
var statsd = new Statsd("nowhere.here.or.anywhere", 12000);
statsd.LogCount("test.stat");
}
[Fact]
public void CreateClient_WithIPAddress_DoesNotError()
{
Initialise();
var statsd = new Statsd("127.0.0.1", 12000);
statsd.LogCount("test.stat");
}
[Fact]
public void CreateClient_WithInvalidCharactersInHostName_DoesNotError()
{
Initialise();
var statsd = new Statsd("@%)(F(FSDLKDEQ423t0-vbdfb", 12000);
statsd.LogCount("test.foo");
}
}
}

View File

@@ -0,0 +1,20 @@
{
"version": "1.0.0-*",
"testRunner": "xunit",
"dependencies": {
"xunit": "2.2.0-beta2-build3300",
"dotnet-test-xunit": "2.2.0-preview2-build1029",
"Moq": "4.6.38-alpha",
"StatsdCore.Net": "1.0.*"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatsdCore.Net
{
public class Class1
{
public Class1()
{
}
}
}

View File

@@ -1,11 +1,12 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace StatsdClient
{
/// <summary>
/// Contract for sending raw statds lines to the server
/// </summary>
public interface IOutputChannel
public interface IOutputChannel: IDisposable
{
/// <summary>
/// Sends a line of stats data to the server asynchronously.

View File

@@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
namespace StatsdClient
{
internal sealed class NullOutputChannel : IOutputChannel
{
public void Dispose(){}
public void Send(string line){}
public async Task SendAsync(string line){}
}
}

View File

@@ -0,0 +1,19 @@
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: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("StatsdCore.Net")]
[assembly: AssemblyTrademark("")]
// 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("4f80cf24-d107-44ce-b9f7-eef6c1e5b3a1")]

View File

@@ -81,13 +81,13 @@ namespace StatsdClient
private void InitialiseInternal(Func<IOutputChannel> createOutputChannel, string prefix, bool rethrowOnError)
{
_prefix = prefix;
if (_prefix != null && _prefix.EndsWith("."))
if (_prefix != null && _prefix.EndsWith(".", StringComparison.Ordinal))
{
_prefix = _prefix.Substring(0, _prefix.Length - 1);
}
try
{
_outputChannel = createOutputChannel();
_outputChannel = createOutputChannel?.Invoke();
}
catch (Exception ex)
{
@@ -105,30 +105,24 @@ namespace StatsdClient
/// </summary>
/// <param name="name">The metric name.</param>
/// <param name="count">The counter value (defaults to 1).</param>
public async Task LogCountAsync(string name, long count = 1)
{
await SendMetricAsync(MetricType.COUNT, name, _prefix, count);
}
public Task LogCountAsync(string name, long count = 1) => SendMetricAsync(MetricType.COUNT, name, _prefix, count);
/// <summary>
/// Log a timing / latency
/// </summary>
/// <param name="name">The metric name.</param>
/// <param name="milliseconds">The duration, in milliseconds, for this metric.</param>
public async Task LogTimingAsync(string name, long milliseconds)
{
await SendMetricAsync(MetricType.TIMING, name, _prefix, milliseconds);
}
public Task LogTimingAsync(string name, long milliseconds) => SendMetricAsync(MetricType.TIMING, name, _prefix, milliseconds);
/// <summary>
/// Log a gauge.
/// </summary>
/// <param name="name">The metric name</param>
/// <param name="value">The value for this gauge</param>
public async Task LogGaugeAsync(string name, long value)
{
await SendMetricAsync(MetricType.GAUGE, name, _prefix, value);
}
public Task LogGaugeAsync(string name, long value) => SendMetricAsync(MetricType.GAUGE, name, _prefix, value);
/// <summary>
/// Log to a set
@@ -139,10 +133,8 @@ namespace StatsdClient
/// Logging to a set is about counting the number
/// of occurrences of each event.
/// </remarks>
public async Task LogSetAsync(string name, long value)
{
await SendMetricAsync(MetricType.SET, name, _prefix, value);
}
public Task LogSetAsync(string name, long value) => SendMetricAsync(MetricType.SET, name, _prefix, value);
/// <summary>
/// Log a raw metric that will not get aggregated on the server.
@@ -150,10 +142,8 @@ namespace StatsdClient
/// <param name="name">The metric name.</param>
/// <param name="value">The metric value.</param>
/// <param name="epoch">(optional) The epoch timestamp. Leave this blank to have the server assign an epoch for you.</param>
public async Task LogRawAsync(string name, long value, long? epoch = null)
{
await SendMetricAsync(MetricType.RAW, name, String.Empty, value, epoch.HasValue ? epoch.ToString() : null);
}
public Task LogRawAsync(string name, long value, long? epoch = null) => SendMetricAsync(MetricType.RAW, name, String.Empty, value, epoch.HasValue ? epoch.ToString() : null);
/// <summary>
/// Log a calendargram metric
@@ -161,10 +151,8 @@ namespace StatsdClient
/// <param name="name">The metric namespace</param>
/// <param name="value">The unique value to be counted in the time period</param>
/// <param name="period">The time period, can be one of h,d,dow,w,m</param>
public async Task LogCalendargramAsync(string name, string value, string period)
{
await SendMetricAsync(MetricType.CALENDARGRAM, name, _prefix, value, period);
}
public Task LogCalendargramAsync(string name, string value, string period) => SendMetricAsync(MetricType.CALENDARGRAM, name, _prefix, value, period);
/// <summary>
/// Log a calendargram metric
@@ -172,28 +160,26 @@ namespace StatsdClient
/// <param name="name">The metric namespace</param>
/// <param name="value">The unique value to be counted in the time period</param>
/// <param name="period">The time period, can be one of h,d,dow,w,m</param>
public async Task LogCalendargramAsync(string name, long value, string period)
{
await SendMetricAsync(MetricType.CALENDARGRAM, name, _prefix, value, period);
}
public Task LogCalendargramAsync(string name, long value, string period) => SendMetricAsync(MetricType.CALENDARGRAM, name, _prefix, value, period);
private async Task SendMetricAsync(string metricType, string name, string prefix, long value, string postFix = null)
private Task SendMetricAsync(string metricType, string name, string prefix, long value, string postFix = null)
{
if (value < 0)
{
Trace.TraceWarning("Metric value for {0} was less than zero: {1}. Not sending.", name, value);
return;
return Task.FromResult(0);
}
await SendMetricAsync(metricType, name, prefix, value.ToString(), postFix);
return SendMetricAsync(metricType, name, prefix, value.ToString(), postFix);
}
private async Task SendMetricAsync(string metricType, string name, string prefix, string value, string postFix = null)
private Task SendMetricAsync(string metricType, string name, string prefix, string value, string postFix = null)
{
if (String.IsNullOrEmpty(name))
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
throw new ArgumentNullException(nameof(name));
}
await _outputChannel.SendAsync(PrepareMetric(metricType, name, prefix, value, postFix));
return _outputChannel.SendAsync(PrepareMetric(metricType, name, prefix, value, postFix));
}
/// <summary>

View File

@@ -12,9 +12,10 @@ namespace StatsdClient
/// </summary>
/// <param name="name">The metric name.</param>
/// <param name="count">The counter value (defaults to 1).</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogCount(this IStatsd client, string name, int count = 1)
{
client.LogCountAsync(name, count).Wait();
client.LogCountAsync(name, count)?.Wait();
}
/// <summary>
@@ -22,9 +23,10 @@ namespace StatsdClient
/// </summary>
/// <param name="name">The metric name.</param>
/// <param name="milliseconds">The duration, in milliseconds, for this metric.</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogTiming(this IStatsd client, string name, long milliseconds)
{
client.LogTimingAsync(name, milliseconds).Wait();
client.LogTimingAsync(name, milliseconds)?.Wait();
}
/// <summary>
@@ -32,9 +34,10 @@ namespace StatsdClient
/// </summary>
/// <param name="name">The metric name</param>
/// <param name="value">The value for this gauge</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogGauge(this IStatsd client, string name, int value)
{
client.LogGaugeAsync(name, value).Wait();
client.LogGaugeAsync(name, value)?.Wait();
}
/// <summary>
@@ -45,9 +48,10 @@ namespace StatsdClient
/// <remarks>
/// Logging to a set is about counting the number of occurrences of each event.
/// </remarks>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogSet(this IStatsd client, string name, int value)
{
client.LogSetAsync(name, value).Wait();
client.LogSetAsync(name, value)?.Wait();
}
/// <summary>
@@ -56,9 +60,10 @@ namespace StatsdClient
/// <param name="name">The metric name.</param>
/// <param name="value">The metric value.</param>
/// <param name="epoch">(optional) The epoch timestamp. Leave this blank to have the server assign an epoch for you.</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogRaw(this IStatsd client, string name, int value, long? epoch = null)
{
client.LogRawAsync(name, value, epoch).Wait();
client.LogRawAsync(name, value, epoch)?.Wait();
}
/// <summary>
@@ -67,9 +72,10 @@ namespace StatsdClient
/// <param name="name">The metric namespace</param>
/// <param name="value">The unique value to be counted in the time period</param>
/// <param name="period">The time period, can be one of h,d,dow,w,m</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogCalendargram(this IStatsd client, string name, string value, string period)
{
client.LogCalendargramAsync(name, value, period).Wait();
client.LogCalendargramAsync(name, value, period)?.Wait();
}
/// <summary>
@@ -78,9 +84,10 @@ namespace StatsdClient
/// <param name="name">The metric namespace</param>
/// <param name="value">The unique value to be counted in the time period</param>
/// <param name="period">The time period, can be one of h,d,dow,w,m</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogCalendargram(this IStatsd client, string name, long value, string period)
{
client.LogCalendargramAsync(name, value, period).Wait();
client.LogCalendargramAsync(name, value, period)?.Wait();
}
/// <summary>
@@ -89,6 +96,7 @@ namespace StatsdClient
/// <param name="client">The statsd client instance.</param>
/// <param name="name">The namespace of the timing metric.</param>
/// <param name="duration">The duration to log (will be converted into milliseconds)</param>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static void LogTiming(this IStatsd client, string name, TimeSpan duration)
{
client.LogTiming(name, (long)duration.TotalMilliseconds);
@@ -103,6 +111,7 @@ namespace StatsdClient
/// <remarks>
/// Wrap the code you want to measure in a using() {} block. The TimingToken instance will log the duration when it is disposed.
/// </remarks>
[Obsolete("This will go away, if you want to call this in a sync fashion you should just call this with ?.Wait()", false)]
public static TimingToken LogTiming(this IStatsd client, string name)
{
return new TimingToken(client, name);

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4f80cf24-d107-44ce-b9f7-eef6c1e5b3a1</ProjectGuid>
<RootNamespace>StatsdCore.Net</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -9,7 +9,7 @@ namespace StatsdClient
{
internal sealed class TcpOutputChannel : IOutputChannel
{
private readonly TcpClient _tcpClient;
private TcpClient _tcpClient;
private NetworkStream _stream;
private readonly string _host;
private readonly int _port;
@@ -26,7 +26,6 @@ namespace StatsdClient
_tcpClient = new TcpClient();
_asyncLock = new AsyncLock();
}
public async Task SendAsync(string line)
{
await SendWithRetryAsync(line, _reconnectEnabled ? _retryAttempts - 1 : 0);
@@ -83,5 +82,27 @@ namespace StatsdClient
}
}
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
void Dispose(bool disposing)
{
if(!disposedValue)
{
if(disposing)
{
_tcpClient.Dispose();
}
_tcpClient = null;
disposedValue = true;
}
}
public void Dispose()
{
Dispose(true);
}
#endregion
}
}

View File

@@ -29,7 +29,7 @@ namespace StatsdClient
public void Dispose()
{
_stopwatch.Stop();
_client.LogTiming(_name, (int)_stopwatch.ElapsedMilliseconds);
_client.LogTimingAsync(_name, (int)_stopwatch.ElapsedMilliseconds);
}
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace StatsdClient
{
internal sealed class UdpOutputChannel : IOutputChannel
{
private readonly UdpClient _udpClient = new UdpClient();
private IPEndPoint _ipEndpoint;
private string _hostOrIPAddress;
private int _port;
public Socket ClientSocket
{
get
{
return _udpClient.Client;
}
}
public UdpOutputChannel(string hostOrIPAddress, int port)
{
_hostOrIPAddress = hostOrIPAddress;
_port = port;
}
private async Task<IPEndPoint> GetIpAddress()
{
if(_ipEndpoint != null)
{
return _ipEndpoint;
}
IPAddress ipAddress;
// Is this an IP address already?
if(!IPAddress.TryParse(_hostOrIPAddress, out ipAddress))
{
try
{
ipAddress = (await Dns.GetHostAddressesAsync(_hostOrIPAddress).ConfigureAwait(false)).First(p => p.AddressFamily == AddressFamily.InterNetwork);
}
catch(Exception)
{
System.Diagnostics.Trace.TraceError("Failed to retrieve domain {0}", _hostOrIPAddress);
_ipEndpoint = null;
return null;
}
// Convert to ipv4 address
}
_ipEndpoint = new IPEndPoint(ipAddress, _port);
return _ipEndpoint;
}
public async Task SendAsync(string line)
{
var endpoint = await GetIpAddress().ConfigureAwait(false);
if(endpoint == null) return;
var payload = Encoding.UTF8.GetBytes(line);
await _udpClient.SendAsync(payload, payload.Length, endpoint).ConfigureAwait(false);
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
void Dispose(bool disposing)
{
if(!disposedValue)
{
if(disposing)
{
_udpClient.Dispose();
}
disposedValue = true;
}
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
Dispose(true);
}
#endregion
}
}

View File

@@ -0,0 +1,16 @@
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"System.Diagnostics.TraceSource": "4.0.0",
"System.Dynamic.Runtime": "4.0.11",
"System.Net.NameResolution": "4.0.0"
},
"frameworks": {
"netstandard1.3": {
"imports": "dnxcore50"
}
}
}