Initial commit
This commit is contained in:
112
.gitignore
vendored
Normal file
112
.gitignore
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
nuget/lib
|
||||
|
||||
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# mstest test results
|
||||
TestResults
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
[Tt]est[Rr]esult*
|
||||
*.Cache
|
||||
ClientBin
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
Nuget Releases/
|
||||
26
CHANGELOG.md
Normal file
26
CHANGELOG.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# statsd-csharp-client Changelog
|
||||
|
||||
## v1.3.0.0
|
||||
* Added support for Calendargrams
|
||||
|
||||
## v1.2.1.0
|
||||
* 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.
|
||||
|
||||
## v1.2.0.0
|
||||
* Support the Raw metric format
|
||||
* A few more unit tests
|
||||
* Fixed a bug where you couldn't start up if the host could not be resolved
|
||||
|
||||
## v1.1.0.0
|
||||
* Added a TCP output channel
|
||||
* Added a simpler default constructor for connecting via UDP
|
||||
|
||||
## v1.0.1.0
|
||||
* Added support for .net 3.5 and .net 4.0 users
|
||||
|
||||
## v1.0.0.0
|
||||
* First upload of the client library
|
||||
* Supports counts, gauges and timers
|
||||
* Can output to any statsd-compatible service
|
||||
7
LICENCE.txt
Normal file
7
LICENCE.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2013 Luke Venediger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
89
README.md
Normal file
89
README.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# statsd-csharp-client
|
||||
|
||||
A simple c# client library for [statsd.net](https://github.com/lukevenediger/statsd.net/) and [statsd](https://github.com/etsy/statsd/).
|
||||
|
||||
# Features
|
||||
* Log counts, timings, gauges, sets, calendargrams 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
|
||||
* Send metrics over a UDP or TCP connection
|
||||
|
||||
Coming soon:
|
||||
* Support for count sampling and histograms
|
||||
* batch-and-pump - collecting stats and sending them out in a batch at regular intervals
|
||||
* Output to an HTTP endpoint
|
||||
|
||||
# Download and Install
|
||||
Install the [StatsdCsharpClient](https://nuget.org/packages/StatsdCsharpClient/) via nuget:
|
||||
```bash
|
||||
PM> Install-Package StatsdCsharpClient
|
||||
```
|
||||
|
||||
# Quickstart
|
||||
Assuming your server is running on localhost and listening on port 12000:
|
||||
```csharp
|
||||
using StatsdClient;
|
||||
...
|
||||
var statsd = new Statsd("localhost", 12000);
|
||||
// Log a count
|
||||
statsd.LogCount( "site.hits" );
|
||||
// Log a gauge
|
||||
statsd.LogGauge( "site.activeUsers", numActiveUsers );
|
||||
// Log a timing
|
||||
statsd.LogTiming( "site.pageLoad", 100 /* milliseconds */ );
|
||||
// Log a raw metric
|
||||
statsd.LogRaw ("already.aggregated", 982, 1885837485 /* epoch timestamp */ );
|
||||
// Log a calendargram
|
||||
statsd.LogCalendargram("order.completed", "user_13143", CalendargramRetentionPeriod.HOUR);
|
||||
```
|
||||
|
||||
You can also wrap your code in a `using` block to measure the latency by using the LogTiming(string) extension method:
|
||||
```csharp
|
||||
using StatsdClient;
|
||||
...
|
||||
using (statsd.LogTiming( "site.db.fetchReport" ))
|
||||
{
|
||||
// do some work
|
||||
}
|
||||
// At this point your latency has been sent to the server
|
||||
```
|
||||
|
||||
## Dynamic Stats Builder
|
||||
There's also a nifty set of extension methods that let you define your stats without using strings. Using the example provided above, but now using the builder:
|
||||
```csharp
|
||||
var statsd = new StatsdClient("localhost", 12000);
|
||||
// Log a count
|
||||
statsd.count.site.hits += 1;
|
||||
// Log a gauge
|
||||
statsd.gauge.site.activeUsers += numActiveUsers;
|
||||
// Log a timing
|
||||
statsd.site.pageLoad += 100; /* milliseconds */
|
||||
```
|
||||
|
||||
## TCP Output Channel
|
||||
Metrics can be delivered over a TCP connection by specifying ConnectionType.Tcp during construction:
|
||||
```csharp
|
||||
var statsd = new Statsd("localhost", 12001);
|
||||
// Continue as normal
|
||||
```
|
||||
|
||||
The connection will attempt to reconnect if something goes wrong, and will try three times before giving up. Use the retryOnDisconnect parameter to enable/disable this, and the retryAttempts parameter to specify the number of times to try the request again.
|
||||
|
||||
# Project Information
|
||||
|
||||
## Target Runtimes
|
||||
* .Net 3.5
|
||||
* .Net 4.0
|
||||
* .Net 4.5
|
||||
|
||||
## Authors
|
||||
Luke Venediger - lukev@lukev.net and [@lukevenediger](http://twitter.com/lukevenediger)
|
||||
|
||||
## See Also
|
||||
* [statsd.net](https://github.com/lukevenediger/statsd.net/)
|
||||
* [statsd](https://github.com/etsy/statsd)
|
||||
* [graphite](https://github.com/graphite-project)
|
||||
* [StatsdCsharpClient on nuget.org](https://nuget.org/packages/StatsdCsharpClient/)
|
||||
42
StatsdClient.ASPNET-MVC/LogLatencyAttribute.cs
Normal file
42
StatsdClient.ASPNET-MVC/LogLatencyAttribute.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
StatsdClient.ASPNET-MVC/Properties/AssemblyInfo.cs
Normal file
36
StatsdClient.ASPNET-MVC/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
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")]
|
||||
87
StatsdClient.ASPNET-MVC/StatsdClient.ASPNET-MVC.csproj
Normal file
87
StatsdClient.ASPNET-MVC/StatsdClient.ASPNET-MVC.csproj
Normal file
@@ -0,0 +1,87 @@
|
||||
<?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>
|
||||
8
StatsdClient.ASPNET-MVC/packages.config
Normal file
8
StatsdClient.ASPNET-MVC/packages.config
Normal file
@@ -0,0 +1,8 @@
|
||||
<?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>
|
||||
49
StatsdClient.sln
Normal file
49
StatsdClient.sln
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3981BC36-0C55-4127-827F-292024E6A8E9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CHANGELOG.md = CHANGELOG.md
|
||||
README.md = README.md
|
||||
nuget\StatsdClient.nuspec = nuget\StatsdClient.nuspec
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClient", "StatsdClient\StatsdClient.csproj", "{D9C7B372-074B-4649-B45E-01FE10724AF9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsdClientTests", "StatsdClientTests\StatsdClientTests.csproj", "{15A2A9A7-D5A0-499D-A74B-2A06BD13B954}"
|
||||
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}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
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
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
18
StatsdClient/CalendargramRetentionPeriod.cs
Normal file
18
StatsdClient/CalendargramRetentionPeriod.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
public sealed class CalendargramRetentionPeriod
|
||||
{
|
||||
public const string ONE_MINUTE = "1min";
|
||||
public const string FIVE_MINUTE = "5min";
|
||||
public const string HOUR = "h";
|
||||
public const string DAY = "d";
|
||||
public const string WEEK = "w";
|
||||
public const string DAY_OF_WEEK = "dow";
|
||||
public const string MONTH = "m";
|
||||
}
|
||||
}
|
||||
22
StatsdClient/ConnectionType.cs
Normal file
22
StatsdClient/ConnectionType.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// The network connection type
|
||||
/// </summary>
|
||||
public enum ConnectionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Udp (recommended)
|
||||
/// </summary>
|
||||
Udp,
|
||||
/// <summary>
|
||||
/// Tcp
|
||||
/// </summary>
|
||||
Tcp
|
||||
}
|
||||
}
|
||||
18
StatsdClient/IOutputChannel.cs
Normal file
18
StatsdClient/IOutputChannel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for sending raw statds lines to the server
|
||||
/// </summary>
|
||||
public interface IOutputChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a line of stats data to the server.
|
||||
/// </summary>
|
||||
void Send(string line);
|
||||
}
|
||||
}
|
||||
53
StatsdClient/IStatsd.cs
Normal file
53
StatsdClient/IStatsd.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for the statsd.net client
|
||||
/// </summary>
|
||||
public interface IStatsd
|
||||
{
|
||||
/// <summary>
|
||||
/// Log a count for a metric
|
||||
/// </summary>
|
||||
void LogCount(string name, int count = 1);
|
||||
/// <summary>
|
||||
/// Log a gauge value
|
||||
/// </summary>
|
||||
void LogGauge(string name, int value);
|
||||
/// <summary>
|
||||
/// Log a latency / Timing
|
||||
/// </summary>
|
||||
void LogTiming(string name, int milliseconds);
|
||||
/// <summary>
|
||||
/// Log a latency / Timing
|
||||
/// </summary>
|
||||
void LogTiming(string name, long milliseconds);
|
||||
/// <summary>
|
||||
/// Log the number of unique occurrances of something
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
void LogSet(string name, int value);
|
||||
/// <summary>
|
||||
/// Log a calendargram metric
|
||||
/// </summary>
|
||||
/// <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>
|
||||
void LogCalendargram(string name, string value, string period);
|
||||
/// <summary>
|
||||
/// Log a calendargram metric
|
||||
/// </summary>
|
||||
/// <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>
|
||||
void LogCalendargram(string name, int value, string period);
|
||||
/// <summary>
|
||||
/// Log a raw metric that will not get aggregated on the server.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
void LogRaw(string name, int value, long? epoch = null);
|
||||
}
|
||||
}
|
||||
38
StatsdClient/MetricType.cs
Normal file
38
StatsdClient/MetricType.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of metric types that statsd.net supports
|
||||
/// </summary>
|
||||
public static class MetricType
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of times something happened.
|
||||
/// </summary>
|
||||
public const string COUNT = "c";
|
||||
/// <summary>
|
||||
/// The time it took for something to happen.
|
||||
/// </summary>
|
||||
public const string TIMING = "ms";
|
||||
/// <summary>
|
||||
/// The value of some measurement at this very moment.
|
||||
/// </summary>
|
||||
public const string GAUGE = "g";
|
||||
/// <summary>
|
||||
/// The number of times each event has been seen.
|
||||
/// </summary>
|
||||
public const string SET = "s";
|
||||
/// <summary>
|
||||
/// A raw metric that won't be aggregated on the server.
|
||||
/// </summary>
|
||||
public const string RAW = "r";
|
||||
/// <summary>
|
||||
/// A metric that calculates unique hits per hour, day, day-of-week, week or month
|
||||
/// </summary>
|
||||
public const string CALENDARGRAM = "cg";
|
||||
}
|
||||
}
|
||||
15
StatsdClient/NullOutputChannel.cs
Normal file
15
StatsdClient/NullOutputChannel.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
internal sealed class NullOutputChannel : IOutputChannel
|
||||
{
|
||||
public void Send(string line)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
36
StatsdClient/Properties/AssemblyInfo.cs
Normal file
36
StatsdClient/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
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")]
|
||||
226
StatsdClient/Statsd.cs
Normal file
226
StatsdClient/Statsd.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// The statsd client library.
|
||||
/// </summary>
|
||||
public class Statsd : IStatsd
|
||||
{
|
||||
private string _prefix;
|
||||
private IOutputChannel _outputChannel;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the Statsd client.
|
||||
/// </summary>
|
||||
/// <param name="host">The statsd or statsd.net server.</param>
|
||||
/// <param name="port"></param>
|
||||
public Statsd(string host, int port)
|
||||
{
|
||||
if ( String.IsNullOrEmpty( host ) )
|
||||
{
|
||||
Trace.TraceWarning( "Statsd client initialised with empty host address. Dropping back to NullOutputChannel." );
|
||||
InitialiseInternal( () => new NullOutputChannel(), "", false );
|
||||
}
|
||||
else
|
||||
{
|
||||
InitialiseInternal( () => new UdpOutputChannel( host, port ), "", false );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the Statsd client.
|
||||
/// </summary>
|
||||
/// <param name="host">The statsd or statsd.net server.</param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="prefix">A string prefix to prepend to every metric.</param>
|
||||
/// <param name="rethrowOnError">If True, rethrows any exceptions caught due to bad configuration.</param>
|
||||
/// <param name="connectionType">Choose between a UDP (recommended) or TCP connection.</param>
|
||||
/// <param name="retryOnDisconnect">Retry the connection if it fails (TCP only).</param>
|
||||
/// <param name="retryAttempts">Number of times to retry before giving up (TCP only).</param>
|
||||
public Statsd(string host,
|
||||
int port,
|
||||
ConnectionType connectionType = ConnectionType.Udp,
|
||||
string prefix = null,
|
||||
bool rethrowOnError = false,
|
||||
bool retryOnDisconnect = true,
|
||||
int retryAttempts = 3)
|
||||
{
|
||||
InitialiseInternal(() =>
|
||||
{
|
||||
return connectionType == ConnectionType.Tcp
|
||||
? (IOutputChannel)new TcpOutputChannel(host, port, retryOnDisconnect, retryAttempts)
|
||||
: (IOutputChannel)new UdpOutputChannel(host, port);
|
||||
},
|
||||
prefix,
|
||||
rethrowOnError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the Statsd client.
|
||||
/// </summary>
|
||||
/// <param name="host">The statsd or statsd.net server.</param>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="prefix">A string prefix to prepend to every metric.</param>
|
||||
/// <param name="rethrowOnError">If True, rethrows any exceptions caught due to bad configuration.</param>
|
||||
/// <param name="outputChannel">Optional output channel (useful for mocking / testing).</param>
|
||||
public Statsd(string host, int port, string prefix = null, bool rethrowOnError = false, IOutputChannel outputChannel = null)
|
||||
{
|
||||
if (outputChannel == null)
|
||||
{
|
||||
InitialiseInternal(() => new UdpOutputChannel(host, port), prefix, rethrowOnError);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitialiseInternal(() => outputChannel, prefix, rethrowOnError);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitialiseInternal(Func<IOutputChannel> createOutputChannel, string prefix, bool rethrowOnError)
|
||||
{
|
||||
_prefix = prefix;
|
||||
if (_prefix != null && _prefix.EndsWith("."))
|
||||
{
|
||||
_prefix = _prefix.Substring(0, _prefix.Length - 1);
|
||||
}
|
||||
try
|
||||
{
|
||||
_outputChannel = createOutputChannel();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (rethrowOnError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
Trace.TraceError("Could not initialise the Statsd client: {0} - falling back to NullOutputChannel.", ex.Message);
|
||||
_outputChannel = new NullOutputChannel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a counter.
|
||||
/// </summary>
|
||||
/// <param name="name">The metric name.</param>
|
||||
/// <param name="count">The counter value (defaults to 1).</param>
|
||||
public void LogCount(string name, int count = 1)
|
||||
{
|
||||
SendMetric(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 void LogTiming(string name, int milliseconds)
|
||||
{
|
||||
SendMetric(MetricType.TIMING, name, _prefix, milliseconds);
|
||||
}
|
||||
|
||||
/// <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 void LogTiming(string name, long milliseconds)
|
||||
{
|
||||
LogTiming(name, (int)milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a gauge.
|
||||
/// </summary>
|
||||
/// <param name="name">The metric name</param>
|
||||
/// <param name="value">The value for this gauge</param>
|
||||
public void LogGauge(string name, int value)
|
||||
{
|
||||
SendMetric(MetricType.GAUGE, name, _prefix, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log to a set
|
||||
/// </summary>
|
||||
/// <param name="name">The metric name.</param>
|
||||
/// <param name="value">The value to log.</param>
|
||||
/// <remarks>Logging to a set is about counting the number
|
||||
/// of occurrences of each event.</remarks>
|
||||
public void LogSet(string name, int value)
|
||||
{
|
||||
SendMetric(MetricType.SET, name, _prefix, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a calendargram metric
|
||||
/// </summary>
|
||||
/// <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 void LogCalendargram(string name, string value, string period)
|
||||
{
|
||||
SendMetric(MetricType.CALENDARGRAM, name, _prefix, value, period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a calendargram metric
|
||||
/// </summary>
|
||||
/// <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 void LogCalendargram(string name, int value, string period)
|
||||
{
|
||||
SendMetric(MetricType.CALENDARGRAM, name, _prefix, value, period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a raw metric that will not get aggregated on the server.
|
||||
/// </summary>
|
||||
/// <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 void LogRaw(string name, int value, long? epoch = null)
|
||||
{
|
||||
SendMetric(MetricType.RAW, name, String.Empty, value, epoch.HasValue ? epoch.ToString() : (string)null);
|
||||
}
|
||||
|
||||
private void SendMetric(string metricType, string name, string prefix, int value, string postFix = null)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
Trace.TraceWarning(String.Format("Metric value for {0} was less than zero: {1}. Not sending.", name, value));
|
||||
return;
|
||||
}
|
||||
SendMetric(metricType, name, prefix, value.ToString(), postFix);
|
||||
}
|
||||
|
||||
private void SendMetric(string metricType, string name, string prefix, string value, string postFix = null)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
_outputChannel.Send(PrepareMetric(metricType, name, prefix, value, postFix));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare a metric prior to sending it off ot the Graphite server.
|
||||
/// </summary>
|
||||
/// <param name="metricType"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="prefix"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="postFix">A value to append to the end of the line.</param>
|
||||
/// <returns>The formatted metric</returns>
|
||||
protected virtual string PrepareMetric(string metricType, string name, string prefix, string value, string postFix = null)
|
||||
{
|
||||
return (String.IsNullOrEmpty(prefix) ? name : (prefix + "." + name))
|
||||
+ ":" + value
|
||||
+ "|" + metricType
|
||||
+ (postFix == null ? String.Empty : "|" + postFix);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
StatsdClient/StatsdClient-DotNet35.csproj
Normal file
66
StatsdClient/StatsdClient-DotNet35.csproj
Normal file
@@ -0,0 +1,66 @@
|
||||
<?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>
|
||||
70
StatsdClient/StatsdClient-DotNet40.csproj
Normal file
70
StatsdClient/StatsdClient-DotNet40.csproj
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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>
|
||||
65
StatsdClient/StatsdClient.csproj
Normal file
65
StatsdClient/StatsdClient.csproj
Normal file
@@ -0,0 +1,65 @@
|
||||
<?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="CalendargramRetentionPeriod.cs" />
|
||||
<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>
|
||||
<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>
|
||||
35
StatsdClient/StatsdClientExtensions.cs
Normal file
35
StatsdClient/StatsdClientExtensions.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using StatsdClient;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// A set of extensions for use with the StatsdClient library.
|
||||
/// </summary>
|
||||
public static class StatsdClientExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Log a timing metric
|
||||
/// </summary>
|
||||
/// <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>
|
||||
public static void LogTiming(this IStatsd client, string name, TimeSpan duration)
|
||||
{
|
||||
client.LogTiming(name, (int)duration.TotalMilliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a timing metric that will be logged when the TimingToken is disposed.
|
||||
/// </summary>
|
||||
/// <param name="client">The statsd clien instance.</param>
|
||||
/// <param name="name">The namespace of the timing metric.</param>
|
||||
/// <returns>A timing token that has been initialised with a start datetime.</returns>
|
||||
/// <remarks>Wrap the code you want to measure in a using() {} block. The
|
||||
/// TimingToken instance will log the duration when it is disposed.</remarks>
|
||||
public static TimingToken LogTiming(this IStatsd client, string name)
|
||||
{
|
||||
return new TimingToken(client, name);
|
||||
}
|
||||
}
|
||||
116
StatsdClient/StatsdExtensions.cs
Normal file
116
StatsdClient/StatsdExtensions.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// A set of extensions for building up metrics using dynamic objects.
|
||||
/// </summary>
|
||||
public static class StatsdExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Start logging a count
|
||||
/// </summary>
|
||||
public static dynamic count(this IStatsd statsd)
|
||||
{
|
||||
return new StatsBuilderInternal(statsd, MetricType.COUNT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start logging a timing / latency
|
||||
/// </summary>
|
||||
public static dynamic timing(this IStatsd statsd)
|
||||
{
|
||||
return new StatsBuilderInternal(statsd, MetricType.TIMING);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start logging a gauge
|
||||
/// </summary>
|
||||
public static dynamic gauge(this IStatsd statsd)
|
||||
{
|
||||
return new StatsBuilderInternal(statsd, MetricType.GAUGE);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start logging a set
|
||||
/// </summary>
|
||||
public static dynamic set(this IStatsd statsd)
|
||||
{
|
||||
return new StatsBuilderInternal(statsd, MetricType.SET);
|
||||
}
|
||||
|
||||
private class StatsBuilderInternal : DynamicObject
|
||||
{
|
||||
private IStatsd _statsd;
|
||||
private List<string> _parts;
|
||||
private string _metricType;
|
||||
|
||||
public StatsBuilderInternal(IStatsd statsd, string metricType)
|
||||
{
|
||||
_statsd = statsd;
|
||||
_parts = new List<string>();
|
||||
_metricType = metricType;
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
if (binder.Name != "_")
|
||||
{
|
||||
_parts.Add(binder.Name);
|
||||
}
|
||||
result = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
|
||||
{
|
||||
if (binder.Name == "_" && args.Length == 1)
|
||||
{
|
||||
_parts.Add(args[0].ToString());
|
||||
result = this;
|
||||
return true;
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
|
||||
{
|
||||
if (binder.Operation == ExpressionType.AddAssign)
|
||||
{
|
||||
var quantity = (int)arg;
|
||||
var name = String.Join(".", _parts);
|
||||
switch (_metricType)
|
||||
{
|
||||
case MetricType.COUNT:
|
||||
_statsd.LogCount(name, quantity);
|
||||
break;
|
||||
case MetricType.GAUGE:
|
||||
_statsd.LogGauge(name, quantity);
|
||||
break;
|
||||
case MetricType.TIMING:
|
||||
_statsd.LogTiming(name, quantity);
|
||||
break;
|
||||
case MetricType.SET:
|
||||
_statsd.LogSet(name, quantity);
|
||||
break;
|
||||
}
|
||||
result = null;
|
||||
return true;
|
||||
}
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
StatsdClient/TcpOutputChannel.cs
Normal file
85
StatsdClient/TcpOutputChannel.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
internal sealed class TcpOutputChannel : IOutputChannel
|
||||
{
|
||||
private TcpClient _tcpClient;
|
||||
private NetworkStream _stream;
|
||||
private object _reconnectLock;
|
||||
private string _host;
|
||||
private int _port;
|
||||
private bool _reconnectEnabled;
|
||||
private int _retryAttempts;
|
||||
|
||||
public TcpOutputChannel(string host, int port, bool reconnectEnabled = true, int retryAttempts = 3)
|
||||
{
|
||||
_host = host;
|
||||
_port = port;
|
||||
_reconnectEnabled = reconnectEnabled;
|
||||
_retryAttempts = retryAttempts;
|
||||
_tcpClient = new TcpClient();
|
||||
_reconnectLock = new object();
|
||||
}
|
||||
|
||||
public void Send(string line)
|
||||
{
|
||||
SendWithRetry(line, _reconnectEnabled ? _retryAttempts - 1 : 0);
|
||||
}
|
||||
|
||||
private void SendWithRetry(string line, int attemptsLeft)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( !_tcpClient.Connected )
|
||||
{
|
||||
RestoreConnection();
|
||||
}
|
||||
var bytesToSend = Encoding.UTF8.GetBytes( line + Environment.NewLine );
|
||||
_stream.Write( bytesToSend, 0, bytesToSend.Length );
|
||||
}
|
||||
catch ( IOException ex )
|
||||
{
|
||||
if ( attemptsLeft > 0 )
|
||||
{
|
||||
SendWithRetry( line, --attemptsLeft );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more attempts left, so log it and continue
|
||||
Trace.TraceWarning( "Sending metrics via TCP failed with an IOException: {0}", ex.Message );
|
||||
}
|
||||
}
|
||||
catch ( SocketException ex )
|
||||
{
|
||||
if ( attemptsLeft > 0 )
|
||||
{
|
||||
SendWithRetry( line, --attemptsLeft );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more attempts left, so log it and continue
|
||||
Trace.TraceWarning( "Sending metrics via TCP failed with a SocketException: {0}, code: {1}", ex.Message, ex.SocketErrorCode.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RestoreConnection()
|
||||
{
|
||||
lock (_reconnectLock)
|
||||
{
|
||||
if (!_tcpClient.Connected)
|
||||
{
|
||||
_tcpClient.Connect(_host, _port);
|
||||
_stream = _tcpClient.GetStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
StatsdClient/TimingToken.cs
Normal file
35
StatsdClient/TimingToken.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
/// <summary>
|
||||
/// A class that is used to measure a latency wrapped in a using block.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{_name} - IsActive = {_stopwatch.IsRunning}")]
|
||||
public sealed class TimingToken : IDisposable
|
||||
{
|
||||
private IStatsd _client;
|
||||
private string _name;
|
||||
private Stopwatch _stopwatch;
|
||||
|
||||
internal TimingToken(IStatsd client, string name)
|
||||
{
|
||||
_stopwatch = Stopwatch.StartNew();
|
||||
_client = client;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the internal timer and logs a latency metric.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
_client.LogTiming(_name, (int)_stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
StatsdClient/UdpOutputChannel.cs
Normal file
34
StatsdClient/UdpOutputChannel.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace StatsdClient
|
||||
{
|
||||
internal sealed class UdpOutputChannel : IOutputChannel
|
||||
{
|
||||
private 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 void Send(string line)
|
||||
{
|
||||
byte[] payload = Encoding.UTF8.GetBytes(line);
|
||||
_udpClient.Send(payload, payload.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
StatsdClientTests/Properties/AssemblyInfo.cs
Normal file
36
StatsdClientTests/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
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")]
|
||||
98
StatsdClientTests/StatsdClientTests.csproj
Normal file
98
StatsdClientTests/StatsdClientTests.csproj
Normal file
@@ -0,0 +1,98 @@
|
||||
<?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>
|
||||
60
StatsdClientTests/StatsdExtensionsTests.cs
Normal file
60
StatsdClientTests/StatsdExtensionsTests.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
186
StatsdClientTests/StatsdTests.cs
Normal file
186
StatsdClientTests/StatsdTests.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
53
StatsdClientTests/TestData.cs
Normal file
53
StatsdClientTests/TestData.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StatsdClientTests
|
||||
{
|
||||
public class TestData
|
||||
{
|
||||
private static string[] WORDS = "Lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua Ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum".Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
private Random _random;
|
||||
private int _lastInteger;
|
||||
|
||||
public TestData()
|
||||
{
|
||||
_random = new Random();
|
||||
}
|
||||
|
||||
public int NextInteger
|
||||
{
|
||||
get { return (_lastInteger = _random.Next(0, Int32.MaxValue)); }
|
||||
}
|
||||
|
||||
public int LastInteger
|
||||
{
|
||||
get { return _lastInteger; }
|
||||
}
|
||||
|
||||
public string NextStatName
|
||||
{
|
||||
get
|
||||
{
|
||||
var length = _random.Next(1, 5);
|
||||
var stat = new string[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
stat[i] = WORDS[_random.Next(0, WORDS.Length - 1)];
|
||||
}
|
||||
return String.Join(".", stat);
|
||||
}
|
||||
}
|
||||
|
||||
public string NextWord
|
||||
{
|
||||
get
|
||||
{
|
||||
return WORDS[_random.Next(0, WORDS.Length - 1)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4
StatsdClientTests/packages.config
Normal file
4
StatsdClientTests/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Moq" version="4.0.10827" targetFramework="net45" />
|
||||
</packages>
|
||||
38
nuget/StatsdClient.nuspec
Normal file
38
nuget/StatsdClient.nuspec
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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>
|
||||
Reference in New Issue
Block a user