From f770c4857074015c659e40530ca6e37a0f54cce0 Mon Sep 17 00:00:00 2001 From: Luke Venediger Date: Thu, 18 Apr 2013 13:45:10 -0700 Subject: [PATCH 01/24] Initial commit --- .gitignore | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 ++ 2 files changed, 112 insertions(+) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bdc3535 --- /dev/null +++ b/.gitignore @@ -0,0 +1,108 @@ +# 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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9270390 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +statsd-csharp-client +==================== + +A c# client library for statsd and statsd.net \ No newline at end of file From caa66f9b411651a932901e1656870dd0f02bfc8e Mon Sep 17 00:00:00 2001 From: Luke Venediger Date: Sat, 20 Apr 2013 23:51:35 +0200 Subject: [PATCH 02/24] Added unit tests and beefed up the README file. --- README.md | 41 ++++++- StatsdClient.sln | 31 +++++ StatsdClient/IOutputChannel.cs | 13 ++ StatsdClient/IStatsd.cs | 10 ++ StatsdClient/MetricType.cs | 16 +++ StatsdClient/NullOutputChannel.cs | 16 +++ StatsdClient/Properties/AssemblyInfo.cs | 36 ++++++ StatsdClient/Statsd.cs | 77 ++++++++++++ StatsdClient/StatsdClient.csproj | 62 ++++++++++ StatsdClient/StatsdClientExtensions.cs | 21 ++++ StatsdClient/StatsdExtensions.cs | 94 +++++++++++++++ StatsdClient/TimingToken.cs | 29 +++++ StatsdClient/UdpOutputChannel.cs | 29 +++++ StatsdClient/_.cs | 12 ++ StatsdClientTests/Properties/AssemblyInfo.cs | 36 ++++++ StatsdClientTests/StatsdClientTests.csproj | 98 +++++++++++++++ StatsdClientTests/StatsdExtensionsTests.cs | 60 ++++++++++ StatsdClientTests/StatsdTests.cs | 120 +++++++++++++++++++ StatsdClientTests/TestData.cs | 53 ++++++++ StatsdClientTests/packages.config | 4 + 20 files changed, 855 insertions(+), 3 deletions(-) create mode 100644 StatsdClient.sln create mode 100644 StatsdClient/IOutputChannel.cs create mode 100644 StatsdClient/IStatsd.cs create mode 100644 StatsdClient/MetricType.cs create mode 100644 StatsdClient/NullOutputChannel.cs create mode 100644 StatsdClient/Properties/AssemblyInfo.cs create mode 100644 StatsdClient/Statsd.cs create mode 100644 StatsdClient/StatsdClient.csproj create mode 100644 StatsdClient/StatsdClientExtensions.cs create mode 100644 StatsdClient/StatsdExtensions.cs create mode 100644 StatsdClient/TimingToken.cs create mode 100644 StatsdClient/UdpOutputChannel.cs create mode 100644 StatsdClient/_.cs create mode 100644 StatsdClientTests/Properties/AssemblyInfo.cs create mode 100644 StatsdClientTests/StatsdClientTests.csproj create mode 100644 StatsdClientTests/StatsdExtensionsTests.cs create mode 100644 StatsdClientTests/StatsdTests.cs create mode 100644 StatsdClientTests/TestData.cs create mode 100644 StatsdClientTests/packages.config diff --git a/README.md b/README.md index 9270390..eed96b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,39 @@ -statsd-csharp-client -==================== +# statsd-csharp-client -A c# client library for statsd and statsd.net \ No newline at end of file +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 and gauges +* 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 + +## Coming soon +* batch-and-pump - collecting stats and sending them out in a batch at regular intervals +* Output to an HTTP endpoint + +## Usage + +Create an instance of StatsdClient to get started: +```csharp +var statsd = new StatsdClient( + +You can specify your metrics as a string: +```csharp +statsd.LogCount( "site.hits" ); +statsd.LogTiming( "site.pageLoad", 100 /* milliseconds */ ); +statsd.LogGauge( "site.activeUsers", numActiveUsers ); +``` + +You can also use the dynamic stats builder: + +```csharp +_.count.site.hits + 1 > statsd; +_.timing.site.pageLoad + 100 > statsd; +_.gauge.site.activeUsers + numActiveUsers > statsd; +''' + +[statsd]: https://github.com/etsy/statsd +[statsd.net]: https://github.com/lukevenediger/statsd.net \ No newline at end of file diff --git a/StatsdClient.sln b/StatsdClient.sln new file mode 100644 index 0000000..afdc54b --- /dev/null +++ b/StatsdClient.sln @@ -0,0 +1,31 @@ + +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 + README.md = README.md + 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 +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 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/StatsdClient/IOutputChannel.cs b/StatsdClient/IOutputChannel.cs new file mode 100644 index 0000000..cca80e2 --- /dev/null +++ b/StatsdClient/IOutputChannel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public interface IOutputChannel + { + void Send(string line); + } +} diff --git a/StatsdClient/IStatsd.cs b/StatsdClient/IStatsd.cs new file mode 100644 index 0000000..27e56e6 --- /dev/null +++ b/StatsdClient/IStatsd.cs @@ -0,0 +1,10 @@ +using System; +namespace StatsdClient +{ + public interface IStatsd + { + void LogCount(string name, int count = 1); + void LogGauge(string name, int value); + void LogTiming(string name, int milliseconds); + } +} diff --git a/StatsdClient/MetricType.cs b/StatsdClient/MetricType.cs new file mode 100644 index 0000000..1b1b197 --- /dev/null +++ b/StatsdClient/MetricType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public static class MetricType + { + public const string COUNT = "c"; + public const string TIMING = "ms"; + public const string GAUGE = "g"; + public const string SET = "s"; + } +} diff --git a/StatsdClient/NullOutputChannel.cs b/StatsdClient/NullOutputChannel.cs new file mode 100644 index 0000000..5f59441 --- /dev/null +++ b/StatsdClient/NullOutputChannel.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + internal sealed class NullOutputChannel : IOutputChannel + { + public void Send(string line) + { + // noop + } + } +} diff --git a/StatsdClient/Properties/AssemblyInfo.cs b/StatsdClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fa21966 --- /dev/null +++ b/StatsdClient/Properties/AssemblyInfo.cs @@ -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 and statsd.net client for c#")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[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.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/StatsdClient/Statsd.cs b/StatsdClient/Statsd.cs new file mode 100644 index 0000000..37f146e --- /dev/null +++ b/StatsdClient/Statsd.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public class Statsd : IStatsd + { + private string _prefix; + private IOutputChannel _outputChannel; + + public Statsd(string host, int port, string prefix = null, bool rethrowOnError = false, IOutputChannel outputChannel = null) + { + _prefix = prefix; + if (_prefix != null && _prefix.EndsWith(".")) + { + _prefix = _prefix.Substring(0, _prefix.Length - 1); + } + try + { + if (outputChannel != null) + { + _outputChannel = outputChannel; + } + else + { + _outputChannel = new UdpOutputChannel(host, port); + } + } + catch (Exception ex) + { + if (rethrowOnError) + { + throw; + } + Trace.TraceError("Could not initialise the Statsd client at {0}:{1} - {2}", host, port, ex.Message); + _outputChannel = new NullOutputChannel(); + } + } + + public void LogCount(string name, int count = 1) + { + SendMetric(MetricType.COUNT, name, _prefix, count); + } + + public void LogTiming(string name, int milliseconds) + { + SendMetric(MetricType.TIMING, name, _prefix, milliseconds); + } + + public void LogGauge(string name, int value) + { + SendMetric(MetricType.GAUGE, name, _prefix, value); + } + + private void SendMetric(string metricType, string name, string prefix, int value) + { + if (String.IsNullOrEmpty(name)) + { + throw new ArgumentNullException("name"); + } + if (value < 0) + { + throw new ArgumentOutOfRangeException("value", value, "Cannot be less than zero."); + } + _outputChannel.Send(PrepareMetric(metricType, name, prefix, value)); + } + + protected virtual string PrepareMetric(string metricType, string name, string prefix, int value) + { + return (prefix != null ? (prefix + "." + name) : name) + ":" + value + "|" + metricType; + } + } +} diff --git a/StatsdClient/StatsdClient.csproj b/StatsdClient/StatsdClient.csproj new file mode 100644 index 0000000..b48f50f --- /dev/null +++ b/StatsdClient/StatsdClient.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {D9C7B372-074B-4649-B45E-01FE10724AF9} + Library + Properties + StatsdClient + StatsdClient + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/StatsdClient/StatsdClientExtensions.cs b/StatsdClient/StatsdClientExtensions.cs new file mode 100644 index 0000000..3e9a2c1 --- /dev/null +++ b/StatsdClient/StatsdClientExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public static class StatsdClientExtensions + { + public static void LogTiming(this IStatsd client, string name, TimeSpan duration) + { + client.LogTiming(name, (int)duration.TotalMilliseconds); + } + + public static TimingToken LogTiming(this IStatsd client, string name) + { + return new TimingToken(client, name); + } + } +} diff --git a/StatsdClient/StatsdExtensions.cs b/StatsdClient/StatsdExtensions.cs new file mode 100644 index 0000000..4da7c73 --- /dev/null +++ b/StatsdClient/StatsdExtensions.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public static class StatsdExtensions + { + public static dynamic count(this IStatsd statsd) + { + return new StatsBuilderInternal(statsd, MetricType.COUNT); + } + + public static dynamic timing(this IStatsd statsd) + { + return new StatsBuilderInternal(statsd, MetricType.TIMING); + } + + public static dynamic gauge(this IStatsd statsd) + { + return new StatsBuilderInternal(statsd, MetricType.GAUGE); + } + + private class StatsBuilderInternal : DynamicObject + { + private IStatsd _statsd; + private List _parts; + private string _metricType; + + public StatsBuilderInternal(IStatsd statsd, string metricType) + { + _statsd = statsd; + _parts = new List(); + _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; + } + result = null; + return true; + } + result = null; + return false; + } + } + } +} diff --git a/StatsdClient/TimingToken.cs b/StatsdClient/TimingToken.cs new file mode 100644 index 0000000..8352f45 --- /dev/null +++ b/StatsdClient/TimingToken.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + 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; + } + + public void Dispose() + { + _stopwatch.Stop(); + _client.LogTiming(_name, (int)_stopwatch.ElapsedMilliseconds); + } + } +} diff --git a/StatsdClient/UdpOutputChannel.cs b/StatsdClient/UdpOutputChannel.cs new file mode 100644 index 0000000..0fc1e87 --- /dev/null +++ b/StatsdClient/UdpOutputChannel.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +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 UdpClient _udpClient; + + public UdpOutputChannel(string host, int port) + { + // Convert to ipv4 address + var ipv4Address = Dns.GetHostAddresses(host).First(p => p.AddressFamily == AddressFamily.InterNetwork); + _udpClient = new UdpClient(); + _udpClient.Connect(ipv4Address, port); + } + + public void Send(string line) + { + byte[] payload = Encoding.UTF8.GetBytes(line); + _udpClient.Send(payload, payload.Length); + } + } +} diff --git a/StatsdClient/_.cs b/StatsdClient/_.cs new file mode 100644 index 0000000..e6532c9 --- /dev/null +++ b/StatsdClient/_.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatsdClient +{ + public interface _ : IStatsd + { + } +} diff --git a/StatsdClientTests/Properties/AssemblyInfo.cs b/StatsdClientTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..29c09f4 --- /dev/null +++ b/StatsdClientTests/Properties/AssemblyInfo.cs @@ -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")] diff --git a/StatsdClientTests/StatsdClientTests.csproj b/StatsdClientTests/StatsdClientTests.csproj new file mode 100644 index 0000000..bb0b29d --- /dev/null +++ b/StatsdClientTests/StatsdClientTests.csproj @@ -0,0 +1,98 @@ + + + + Debug + AnyCPU + {15A2A9A7-D5A0-499D-A74B-2A06BD13B954} + Library + Properties + StatsdClientTests + StatsdClientTests + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\statsd-csharp-client\packages\Moq.4.0.10827\lib\NET40\Moq.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + {d9c7b372-074b-4649-b45e-01fe10724af9} + StatsdClient + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/StatsdClientTests/StatsdExtensionsTests.cs b/StatsdClientTests/StatsdExtensionsTests.cs new file mode 100644 index 0000000..f2c0973 --- /dev/null +++ b/StatsdClientTests/StatsdExtensionsTests.cs @@ -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 _outputChannel; + private Statsd _statsd; + private TestData _testData; + + [TestInitialize] + public void Initialise() + { + _outputChannel = new Mock(); + _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(); + } + } + +} diff --git a/StatsdClientTests/StatsdTests.cs b/StatsdClientTests/StatsdTests.cs new file mode 100644 index 0000000..d191d3a --- /dev/null +++ b/StatsdClientTests/StatsdTests.cs @@ -0,0 +1,120 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using StatsdClient; +using Moq; + +namespace StatsdClientTests +{ + [TestClass] + public class StatsdTests + { + private Mock _outputChannel; + private Statsd _statsd; + private TestData _testData; + + public StatsdTests() + { + _testData = new TestData(); + } + + [TestInitialize] + public void Initialise() + { + _outputChannel = new Mock(); + _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(); + } + } +} diff --git a/StatsdClientTests/TestData.cs b/StatsdClientTests/TestData.cs new file mode 100644 index 0000000..29c3343 --- /dev/null +++ b/StatsdClientTests/TestData.cs @@ -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)]; + } + } + } +} diff --git a/StatsdClientTests/packages.config b/StatsdClientTests/packages.config new file mode 100644 index 0000000..507a0f8 --- /dev/null +++ b/StatsdClientTests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 2daa84286ef349abca10363191b449e35bc5cba9 Mon Sep 17 00:00:00 2001 From: Luke Venediger Date: Mon, 22 Apr 2013 00:54:24 +0200 Subject: [PATCH 03/24] Prepared nuget package spec. Added a bit more documentation. --- .../StatsdCsharpClient.1.0.0.0.nupkg | Bin 0 -> 6763 bytes README.md | 42 +++++++++++------- StatsdClient/Properties/AssemblyInfo.cs | 4 +- StatsdClient/StatsdClient.csproj | 4 +- StatsdClient/StatsdClient.nuspec | 16 +++++++ StatsdClient/_.cs | 12 ----- 6 files changed, 47 insertions(+), 31 deletions(-) create mode 100644 Nuget Releases/StatsdCsharpClient.1.0.0.0.nupkg create mode 100644 StatsdClient/StatsdClient.nuspec delete mode 100644 StatsdClient/_.cs diff --git a/Nuget Releases/StatsdCsharpClient.1.0.0.0.nupkg b/Nuget Releases/StatsdCsharpClient.1.0.0.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..84732fed51d802fe2f2f409c7c170fe9fffcdffc GIT binary patch literal 6763 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index eed96b5..d806e63 100644 --- a/README.md +++ b/README.md @@ -11,29 +11,39 @@ A simple c# client library for [statsd.net](https://github.com/lukevenediger/sta * Supports a user-defined prefix to prepend to every metric ## Coming soon +* Support for sets and count sampling * batch-and-pump - collecting stats and sending them out in a batch at regular intervals * Output to an HTTP endpoint -## Usage - -Create an instance of StatsdClient to get started: -```csharp -var statsd = new StatsdClient( - -You can specify your metrics as a string: +## Quickstart +Assuming your statsd.net server is running on localhost and listening on port 12000: ```csharp +var statsd = new StatsdClient("localhost", 12000); +// Log a count statsd.LogCount( "site.hits" ); -statsd.LogTiming( "site.pageLoad", 100 /* milliseconds */ ); +// Log a gauge statsd.LogGauge( "site.activeUsers", numActiveUsers ); +// Log a timing +statsd.LogTiming( "site.pageLoad", 100 /* milliseconds */ ); ``` -You can also use the dynamic stats builder: - +You can also wrap your code in a `using` block to measure the latency: ```csharp -_.count.site.hits + 1 > statsd; -_.timing.site.pageLoad + 100 > statsd; -_.gauge.site.activeUsers + numActiveUsers > statsd; -''' +using (statsd.LogTiming( "site.db.fetchReport" )) +{ + // do some work +} +// At this point your latency has been sent to the server +``` -[statsd]: https://github.com/etsy/statsd -[statsd.net]: https://github.com/lukevenediger/statsd.net \ No newline at end of file +## 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 */ +``` \ No newline at end of file diff --git a/StatsdClient/Properties/AssemblyInfo.cs b/StatsdClient/Properties/AssemblyInfo.cs index fa21966..a78f2ec 100644 --- a/StatsdClient/Properties/AssemblyInfo.cs +++ b/StatsdClient/Properties/AssemblyInfo.cs @@ -6,9 +6,9 @@ using System.Runtime.InteropServices; // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("StatsdClient")] -[assembly: AssemblyDescription("A statsd and statsd.net client for c#")] +[assembly: AssemblyDescription("A statsd.net and statsd client for c#")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] +[assembly: AssemblyCompany("Luke Venediger")] [assembly: AssemblyProduct("StatsdClient")] [assembly: AssemblyCopyright("Copyright © Luke Venediger 2013")] [assembly: AssemblyTrademark("")] diff --git a/StatsdClient/StatsdClient.csproj b/StatsdClient/StatsdClient.csproj index b48f50f..6d492cf 100644 --- a/StatsdClient/StatsdClient.csproj +++ b/StatsdClient/StatsdClient.csproj @@ -49,7 +49,9 @@ - + + + + \ No newline at end of file diff --git a/StatsdClient.ASPNET-MVC/packages.config b/StatsdClient.ASPNET-MVC/packages.config new file mode 100644 index 0000000..ecb1c16 --- /dev/null +++ b/StatsdClient.ASPNET-MVC/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/StatsdClient.sln b/StatsdClient.sln index afdc54b..a018c41 100644 --- a/StatsdClient.sln +++ b/StatsdClient.sln @@ -4,12 +4,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3981BC36-0C55-4127-827F-292024E6A8E9}" ProjectSection(SolutionItems) = preProject 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 @@ -24,6 +31,16 @@ Global {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 diff --git a/StatsdClient/IOutputChannel.cs b/StatsdClient/IOutputChannel.cs index cca80e2..91635dc 100644 --- a/StatsdClient/IOutputChannel.cs +++ b/StatsdClient/IOutputChannel.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace StatsdClient { diff --git a/StatsdClient/IStatsd.cs b/StatsdClient/IStatsd.cs index 2e4cb0a..1e2c588 100644 --- a/StatsdClient/IStatsd.cs +++ b/StatsdClient/IStatsd.cs @@ -16,6 +16,10 @@ namespace StatsdClient /// void LogTiming(string name, int milliseconds); /// + /// Log a latency / Timing + /// + void LogTiming(string name, long milliseconds); + /// /// Log the number of unique occurrances of something /// /// diff --git a/StatsdClient/MetricType.cs b/StatsdClient/MetricType.cs index 1b1b197..3e6d489 100644 --- a/StatsdClient/MetricType.cs +++ b/StatsdClient/MetricType.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace StatsdClient { diff --git a/StatsdClient/NullOutputChannel.cs b/StatsdClient/NullOutputChannel.cs index 5f59441..713f30d 100644 --- a/StatsdClient/NullOutputChannel.cs +++ b/StatsdClient/NullOutputChannel.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace StatsdClient { diff --git a/StatsdClient/Properties/AssemblyInfo.cs b/StatsdClient/Properties/AssemblyInfo.cs index a78f2ec..e8591aa 100644 --- a/StatsdClient/Properties/AssemblyInfo.cs +++ b/StatsdClient/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // 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")] +[assembly: AssemblyVersion("1.0.1.0")] +[assembly: AssemblyFileVersion("1.0.1.0")] diff --git a/StatsdClient/Statsd.cs b/StatsdClient/Statsd.cs index abd8290..d2e8037 100644 --- a/StatsdClient/Statsd.cs +++ b/StatsdClient/Statsd.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace StatsdClient { @@ -51,6 +50,11 @@ namespace StatsdClient SendMetric(MetricType.TIMING, name, _prefix, milliseconds); } + public void LogTiming(string name, long milliseconds) + { + LogTiming(name, (int)milliseconds); + } + public void LogGauge(string name, int value) { SendMetric(MetricType.GAUGE, name, _prefix, value); diff --git a/StatsdClient/StatsdClient-DotNet35.csproj b/StatsdClient/StatsdClient-DotNet35.csproj new file mode 100644 index 0000000..41648ba --- /dev/null +++ b/StatsdClient/StatsdClient-DotNet35.csproj @@ -0,0 +1,64 @@ + + + + + Debug + AnyCPU + {BD729A99-C965-40F3-A69B-EFC81D6DA023} + Library + Properties + StatsdClient + StatsdClient + v3.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + ..\Nuget Releases\lib\net35\ + TRACE + prompt + 4 + ..\Nuget Releases\lib\net35\StatsdClient.XML + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/StatsdClient/StatsdClient-DotNet40.csproj b/StatsdClient/StatsdClient-DotNet40.csproj new file mode 100644 index 0000000..5a04d30 --- /dev/null +++ b/StatsdClient/StatsdClient-DotNet40.csproj @@ -0,0 +1,68 @@ + + + + + Debug + AnyCPU + {4C053A87-70F9-4059-8A42-BC08626A8B22} + Library + Properties + StatsdClient + StatsdClient + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + + + none + true + ..\Nuget Releases\lib\net40\ + TRACE + prompt + 4 + ..\Nuget Releases\lib\net40\StatsdClient.XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/StatsdClient/StatsdClient.csproj b/StatsdClient/StatsdClient.csproj index 6d492cf..8633d7d 100644 --- a/StatsdClient/StatsdClient.csproj +++ b/StatsdClient/StatsdClient.csproj @@ -22,12 +22,13 @@ 4 - pdbonly + none true - bin\Release\ + ..\Nuget Releases\lib\net45\ TRACE prompt 4 + ..\Nuget Releases\lib\net45\StatsdClient.XML @@ -50,9 +51,6 @@ - - -