Skip to content

Commit 6f57e26

Browse files
committed
Merge branch 'dotnet4'
2 parents aecda26 + f5f2ac4 commit 6f57e26

File tree

14 files changed

+145
-53
lines changed

14 files changed

+145
-53
lines changed

Readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ var opt = new StatsdOptions(){
8484

8585
By default the various logging metric functions return Tasks. **You do not need to await on these** If you await on these and you have buffered metrics off , you will return after the bytes have been added to the network stream. If you await, and buffered metrics are on then your await will return when your metric has been added to the Queue of metrics to be sent.
8686

87+
88+
## dotnet 4.0
89+
90+
While this project does target dotnet 4.0, the unit tests do not run in 4.0. The support is limited (new features may not come to dotnet 4.S), but bugs will be addressed.
91+
92+
8793
## Dev setup
8894

8995
If you plan on playing around with the code, be sure to download and install [.NET core sdk](https://www.microsoft.com/net/core).

src/StatsN.IntergrationTests/project.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"dependencies": {
55
"xunit": "2.2.0-beta2-build3300",
66
"dotnet-test-xunit": "2.2.0-preview2-build1029",
7-
"Moq": "4.6.38-alpha",
87
"StatsN": "1.0.*"
98
},
109
"frameworks": {

src/StatsN.UnitTests/StastdTests.cs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -96,60 +96,68 @@ public void ConfirmMetricsBuffered()
9696
var mockedMetric = new Mock<NullChannel>();
9797
mockedMetric.Setup(a => a.IsConnected).Returns(true);
9898
mockedMetric.Setup(a => a.SendAsync(It.Is<byte[]>(param => param.Length > 200 && param.Length < 512))).Verifiable();
99-
var statsd = new Statsd(new StatsdOptions() { BufferMetrics = true }, mockedMetric.Object);
100-
for (int i = 0; i < 100000; i++)
99+
using (var statsd = new Statsd(new StatsdOptions() { BufferMetrics = true }, mockedMetric.Object))
101100
{
102-
statsd.CountAsync("fun");
101+
for (int i = 0; i < 100000; i++)
102+
{
103+
statsd.CountAsync("fun");
104+
}
105+
while (mockedMetric.Object.worker.IsBusy) { }
106+
mockedMetric.Verify();
103107
}
104-
while (mockedMetric.Object.worker.IsBusy) { }
105-
mockedMetric.Verify();
106108
}
107109
[Fact]
108110
public void ConfirmMetricsNotBuffered()
109111
{
110112
var mockedMetric = new Mock<NullChannel>();
111113
mockedMetric.Setup(a => a.IsConnected).Returns(true);
112114
mockedMetric.Setup(a => a.SendAsync(It.Is<byte[]>(param => param.Length < 50))).Verifiable();
113-
var statsd = new Statsd(new StatsdOptions() {}, mockedMetric.Object);
114-
for (int i = 0; i < 100000; i++)
115+
using (var statsd = new Statsd(new StatsdOptions() { }, mockedMetric.Object))
115116
{
116-
statsd.CountAsync("fun");
117+
for (int i = 0; i < 100000; i++)
118+
{
119+
statsd.CountAsync("fun");
120+
}
121+
while (mockedMetric.Object.worker.IsBusy) { }
122+
mockedMetric.Verify();
117123
}
118-
while (mockedMetric.Object.worker.IsBusy) { }
119-
mockedMetric.Verify();
120124
}
121125
[Fact]
122126
public void ConfirmUdpSendBuffTime()
123127
{
124128
var client = new Udp();
125129
var options = new StatsdOptions() { BufferMetrics = true, OnExceptionGenerated = (exception)=> { throw exception; } };
126-
var statsd = new Statsd(options, client);
127-
var stopwatch = new Stopwatch();
128-
stopwatch.Start();
129-
for (int i = 0; i < 100000; i++)
130+
using (var statsd = new Statsd(options, client))
130131
{
131-
statsd.CountAsync("fun");
132+
var stopwatch = new Stopwatch();
133+
stopwatch.Start();
134+
for (int i = 0; i < 100000; i++)
135+
{
136+
statsd.CountAsync("fun");
137+
}
138+
while (client.worker.IsBusy) { }
139+
stopwatch.Stop();
140+
//we shouldn't cost more than 1 milisecond a metric buffered or not
141+
Assert.InRange(stopwatch.ElapsedMilliseconds, 0, 100000);
132142
}
133-
while (client.worker.IsBusy) { }
134-
stopwatch.Stop();
135-
//we shouldn't cost more than 1 milisecond a metric buffered or not
136-
Assert.InRange(stopwatch.ElapsedMilliseconds, 0, 100000);
137143
}
138144
[Fact]
139145
public void ConfirmUdpSendNoBufferedTime()
140146
{
141147
var client = new Udp();
142-
var statsd = new Statsd(new StatsdOptions() { BufferMetrics = false, OnExceptionGenerated = (exception) => { throw exception; } }, client);
143-
var stopwatch = new Stopwatch();
144-
stopwatch.Start();
145-
for (int i = 0; i < 100000; i++)
148+
using (var statsd = new Statsd(new StatsdOptions() { BufferMetrics = false, OnExceptionGenerated = (exception) => { throw exception; } }, client))
146149
{
147-
statsd.CountAsync("fun");
150+
var stopwatch = new Stopwatch();
151+
stopwatch.Start();
152+
for (int i = 0; i < 100000; i++)
153+
{
154+
statsd.CountAsync("fun");
155+
}
156+
while (client.worker.IsBusy) { }
157+
stopwatch.Stop();
158+
//we shouldn't cost more than 1 milisecond a metric buffered or not
159+
Assert.InRange(stopwatch.ElapsedMilliseconds, 0, 100000);
148160
}
149-
while (client.worker.IsBusy) { }
150-
stopwatch.Stop();
151-
//we shouldn't cost more than 1 milisecond a metric buffered or not
152-
Assert.InRange(stopwatch.ElapsedMilliseconds, 0, 100000);
153161
}
154162
}
155163
}

src/StatsN.UnitTests/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"StatsN": "1.0.*"
99
},
1010
"frameworks": {
11-
"net461":{},
11+
"net461": {},
1212
"netcoreapp1.0": {
1313
"dependencies": {
1414
"Microsoft.NETCore.App": {

src/StatsN/BaseCommunicationProvider.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ namespace StatsN
1313
{
1414
public abstract class BaseCommunicationProvider : IDisposable
1515
{
16+
/// <summary>
17+
/// User Options
18+
/// </summary>
1619
protected StatsdOptions Options { get; private set; }
1720
internal BackgroundWorker worker { get; set; }
1821
private ConcurrentQueue<byte[]> Queue { get; } = new ConcurrentQueue<byte[]>();
@@ -58,24 +61,43 @@ internal BaseCommunicationProvider Construct(StatsdOptions options)
5861
this.Options = options;
5962
return this;
6063
}
64+
/// <summary>
65+
/// Connect the socket
66+
/// </summary>
67+
/// <returns></returns>
6168
public abstract Task<bool> Connect();
69+
/// <summary>
70+
/// Is the socket connected?
71+
/// </summary>
6272
public abstract bool IsConnected { get; }
63-
73+
/// <summary>
74+
/// Send metric to inherited provider
75+
/// </summary>
76+
/// <param name="metric"></param>
77+
/// <returns></returns>
6478
internal Task SendMetric(string metric)
6579
{
6680
var payload = Encoding.ASCII.GetBytes(metric + Environment.NewLine);
6781
if (Options.BufferMetrics)
6882
{
6983
Queue.Enqueue(payload);
7084
if (!worker.IsBusy) worker.RunWorkerAsync();
71-
return Task.FromResult(0);
85+
return TplFactory.FromResult();
7286
}
7387
return SendAsync(payload);
7488
}
7589
public abstract Task SendAsync(byte[] payload);
76-
77-
protected Task<IPEndPoint> GetIpAddressAsync() => GetIpAddressAsync(this.Options.HostOrIp, this.Options.Port);
78-
90+
/// <summary>
91+
/// Get the IPEndpoint for the Options object, will return null if it cannot be established
92+
/// </summary>
93+
/// <returns></returns>
94+
protected Task<IPEndPoint> GetIpAddressAsync() => GetIpAddressAsync(this.Options.HostOrIp, this.Options.Port);
95+
/// <summary>
96+
/// Get the IPEndpoint for the Options object, will return null if it cannot be established
97+
/// </summary>
98+
/// <param name="hostOrIPAddress"></param>
99+
/// <param name="port"></param>
100+
/// <returns></returns>
79101
protected async Task<IPEndPoint> GetIpAddressAsync(string hostOrIPAddress, int port)
80102
{
81103
IPAddress ipAddress;
@@ -84,7 +106,12 @@ protected async Task<IPEndPoint> GetIpAddressAsync(string hostOrIPAddress, int p
84106
{
85107
try
86108
{
109+
#if net40
110+
ipAddress = await TaskEx.Run(()=>Dns.GetHostAddresses(hostOrIPAddress).First(p => p.AddressFamily == AddressFamily.InterNetwork)).ConfigureAwait(false);
111+
#else
87112
ipAddress = (await Dns.GetHostAddressesAsync(hostOrIPAddress).ConfigureAwait(false)).First(p => p.AddressFamily == AddressFamily.InterNetwork);
113+
#endif
114+
88115
}
89116
catch (Exception)
90117
{

src/StatsN/Constants.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
namespace StatsN
88
{
9-
internal class Constants
9+
internal static class Constants
1010
{
1111
internal const char colon = ':';
1212
internal const char pipe = '|';
1313
internal const char dot = '.';
1414
internal const string Localhost = "127.0.0.1";
15-
internal const string Statsd = "Statsd";
15+
internal const string StatsN = "StatsN";
1616

1717
internal static class Metrics
1818
{

src/StatsN/Exceptions/StatsdLogMessage.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ public class StatsdLogMessage
88
{
99
public string Message { get; set; }
1010
public EventType Weight { get; set; }
11-
1211
public StatsdLogMessage(string message, EventType weight)
1312
{
14-
this.Message = message;
13+
this.Message = message ?? string.Empty;
1514
Weight = weight;
1615
}
1716
}

src/StatsN/NullChannel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ public override bool IsConnected
1717

1818
public override Task<bool> Connect()
1919
{
20-
return Task.FromResult(true);
20+
return TplFactory.FromResult(true);
2121
}
2222

2323
public override void OnDispose(){}
2424

2525
public override Task SendAsync(byte[] payload)
2626
{
27-
return Task.FromResult(0);
27+
return TplFactory.FromResult(0);
2828
}
2929
}
3030
}

src/StatsN/Statsd.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ internal async Task LogMetricAsync(string metricName, string value, string metri
8686
return;
8787
}
8888
var calculateMetric = BuildMetric(metricName, value, metricType, options.Prefix, postfix);
89+
options.LogEvent(calculateMetric, EventType.Info);
8990
if (string.IsNullOrWhiteSpace(calculateMetric))
9091
{
9192
options.LogEvent($"Unable to generate metric for {metricType} value {value}", EventType.Error);

src/StatsN/StatsdOptions.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class StatsdOptions
1111
{
1212
public Action<System.Exception> OnExceptionGenerated;
1313
public Action<StatsdLogMessage> OnLogEventGenerated;
14-
14+
public TraceSource TraceSource { get; private set; } = new TraceSource(Constants.StatsN, SourceLevels.Warning);
1515
public bool BufferMetrics { get; set; } = false;
1616
public int BufferSize { get; set; } = 512;
1717
public string HostOrIp { get; set; } = Constants.Localhost;
@@ -30,7 +30,7 @@ public string Prefix
3030
}
3131
}
3232

33-
internal void LogException(System.Exception exception)
33+
internal void LogException(Exception exception)
3434
{
3535
if(OnExceptionGenerated == null)
3636
{
@@ -39,25 +39,23 @@ internal void LogException(System.Exception exception)
3939
}
4040
OnExceptionGenerated.Invoke(exception);
4141

42-
4342
}
4443
internal void LogEvent(string message, EventType weight) => this.LogEvent(new StatsdLogMessage(message, weight));
4544

4645
internal void LogEvent(StatsdLogMessage logMessage)
4746
{
48-
if(OnLogEventGenerated == null)
47+
if (OnLogEventGenerated == null)
4948
{
50-
var traceMessage = $"{Constants.Statsd}: {logMessage.Message}";
5149
switch (logMessage.Weight)
5250
{
5351
case EventType.Info:
54-
Trace.TraceInformation(traceMessage);
52+
TraceSource.TraceEvent(TraceEventType.Information, 1, logMessage.Message);
5553
break;
5654
case EventType.Warning:
57-
Trace.TraceWarning(traceMessage);
55+
TraceSource.TraceEvent(TraceEventType.Warning, 2, logMessage.Message);
5856
break;
5957
case EventType.Error:
60-
Trace.TraceError(traceMessage);
58+
TraceSource.TraceEvent(TraceEventType.Error, 1, logMessage.Message);
6159
break;
6260
}
6361
}

0 commit comments

Comments
 (0)