public static void Metrics_Not_Sent_If_Array_Is_Null_Or_Empty() { // Arrange var mock = new Mock <IStatsDTransport>(); var config = new StatsDConfiguration(); using (var publisher = new StatsDPublisher(config, mock.Object)) { // Act #nullable disable publisher.Decrement(-1, 1, null as string[]); publisher.Increment(-1, 1, null as string[]); publisher.Decrement(1, 1, null as string[]); publisher.Increment(1, 1, null as string[]); publisher.Decrement(1, 1, Array.Empty <string>()); publisher.Increment(1, 1, Array.Empty <string>()); publisher.Decrement(-1, 1, Array.Empty <string>()); publisher.Increment(-1, 1, Array.Empty <string>()); publisher.Decrement(-1, 1, new List <string>()); publisher.Increment(-1, 1, new List <string>()); publisher.Decrement(1, 1, null as IEnumerable <string>); publisher.Increment(1, 1, null as IEnumerable <string>); publisher.Decrement(1, 1, new[] { string.Empty }); publisher.Increment(1, 1, new[] { string.Empty }); #nullable enable }
public void ConfigurationIsNull() { StatsDConfiguration noConfig = null; Should.Throw <ArgumentNullException>( () => new StatsDPublisher(noConfig)); }
public static void Increment_Sends_Multiple_Metrics() { // Arrange var mock = new Mock <IStatsDTransport>(); var config = new StatsDConfiguration { Prefix = "red", }; using (var publisher = new StatsDPublisher(config, mock.Object)) { // Act publisher.Increment(10, "black"); publisher.Increment(-10, "yellow"); publisher.Increment(10, 1, "pink"); publisher.Increment(-10, 1, "orange"); publisher.Increment(10, 1, new[] { "white", "blue" }); publisher.Increment(10, 1, new List <string>() { "green", "red" }); publisher.Increment(10, 1, null as IEnumerable <string>); } // Assert mock.Verify((p) => p.Send(It.Ref <ArraySegment <byte> > .IsAny), Times.Exactly(8)); }
public static void Metrics_Not_Sent_If_Array_Is_Null_Or_Empty() { // Arrange var mock = new Mock <IStatsDTransport>(); var config = new StatsDConfiguration(); using (var publisher = new StatsDPublisher(config, mock.Object)) { // Act publisher.Decrement(-1, 1, null as string[]); publisher.Increment(-1, 1, null as string[]); publisher.Decrement(1, 1, null as string[]); publisher.Increment(1, 1, null as string[]); publisher.Decrement(1, 1, Array.Empty <string>()); publisher.Increment(1, 1, Array.Empty <string>()); publisher.Decrement(-1, 1, Array.Empty <string>()); publisher.Increment(-1, 1, Array.Empty <string>()); publisher.Decrement(-1, 1, new List <string>()); publisher.Increment(-1, 1, new List <string>()); publisher.Decrement(1, 1, null as IEnumerable <string>); publisher.Increment(1, 1, null as IEnumerable <string>); publisher.Decrement(1, 1, new[] { string.Empty }); publisher.Increment(1, 1, new[] { string.Empty }); } // Assert mock.Verify((p) => p.Send(It.IsAny <ArraySegment <byte> >()), Times.Never()); }
private static async Task AssertMetrics(StatsDConfiguration config, IStatsDPublisher publisher) { // Act - Create a counter publisher.Increment("apple"); // Act - Create and change a counter publisher.Increment("bear"); // 1 publisher.Increment(10, "bear"); // 11 publisher.Increment(10, 0, "bear"); // 11 publisher.Decrement("bear"); // 10 publisher.Decrement(5, "bear"); // 5 publisher.Decrement(5, 0, "bear"); // 5 // Act - Mark an event (which is a counter) publisher.Increment("fish"); // Act - Create a gauge publisher.Gauge(3.141, "circle"); // Act - Create and change a gauge publisher.Gauge(10, "dog"); publisher.Gauge(42, "dog"); // Act - Create a timer publisher.Timing(123, "elephant"); publisher.Timing(TimeSpan.FromSeconds(2), "fox"); publisher.Timing(456, 1, "goose"); publisher.Timing(TimeSpan.FromSeconds(3.5), 1, "hen"); // Act - Increment multiple counters publisher.Increment(7, 1, "green", "red"); // 7 publisher.Increment(2, 0, "green", "red"); // 7 publisher.Decrement(1, 0, "red", "green"); // 7 publisher.Decrement(4, 1, "red", "green"); // 3 // Allow enough time for metrics to be registered await Task.Delay(TimeSpan.FromSeconds(1.0)); // Assert var result = await SendCommandAsync("counters"); result.Value <int>(config.Prefix + ".apple").ShouldBe(1, result.ToString()); result.Value <int>(config.Prefix + ".bear").ShouldBe(5, result.ToString()); result.Value <int>(config.Prefix + ".fish").ShouldBe(1, result.ToString()); result.Value <int>(config.Prefix + ".green").ShouldBe(3, result.ToString()); result.Value <int>(config.Prefix + ".red").ShouldBe(3, result.ToString()); result = await SendCommandAsync("gauges"); result.Value <double>(config.Prefix + ".circle").ShouldBe(3.141, result.ToString()); result.Value <int>(config.Prefix + ".dog").ShouldBe(42, result.ToString()); result = await SendCommandAsync("timers"); result[config.Prefix + ".elephant"].Values <int>().ShouldBe(new[] { 123 }, result.ToString()); result[config.Prefix + ".fox"].Values <int>().ShouldBe(new[] { 2000 }, result.ToString()); result[config.Prefix + ".goose"].Values <int>().ShouldBe(new[] { 456 }, result.ToString()); result[config.Prefix + ".hen"].Values <int>().ShouldBe(new[] { 3500 }, result.ToString()); }
public void ConfigurationIsNull() { StatsDConfiguration configuration = null; Assert.Throws <ArgumentNullException>( "configuration", () => new StatsDPublisher(configuration)); }
public void ConfigurationIsValidWithHostIp() { var validConfig = new StatsDConfiguration { Host = "10.0.1.2" }; using var stats = new StatsDPublisher(validConfig); }
public void ConfigurationHasNoHost() { var badConfig = new StatsDConfiguration { Host = null }; Should.Throw <ArgumentNullException>( () => new StatsDPublisher(badConfig)); }
public static void Constructor_Throws_If_Transport_Is_Null() { // Arrange var configuration = new StatsDConfiguration(); IStatsDTransport transport = null; // Act and Assert Assert.Throws <ArgumentNullException>( "transport", () => new StatsDPublisher(configuration, transport)); }
public static void Constructor_Throws_If_Configuration_Is_Null() { // Arrange StatsDConfiguration configuration = null; var transport = Mock.Of <IStatsDTransport>(); // Act and Assert Assert.Throws <ArgumentNullException>( "configuration", () => new StatsDPublisher(configuration, transport)); }
public void ConfigurationHasNoHost() { var configuration = new StatsDConfiguration { Host = null }; Assert.Throws <ArgumentException>( "configuration", () => new StatsDPublisher(configuration)); }
public void ConfigurationHasNoCulture() { var badConfig = new StatsDConfiguration { Host = "someserver.somewhere.com", Culture = null }; Should.Throw <ArgumentNullException>( () => new StatsDPublisher(badConfig)); }
public StatsDPublisher(StatsDConfiguration configuration, IStatsDTransport transport) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } _transport = transport ?? throw new ArgumentNullException(nameof(transport)); _formatter = new StatsDMessageFormatter(configuration.Culture, configuration.Prefix); }
public void ConfigurationIsValidWithHostName() { var validConfig = new StatsDConfiguration { Host = "someserver.somewhere.com" }; using (new StatsDPublisher(validConfig)) { } }
public void ConfigurationIsValidWithHostName() { var validConfig = new StatsDConfiguration { Host = "someserver.somewhere.com" }; var stats = new StatsDPublisher(validConfig); stats.ShouldNotBeNull(); }
public void ConfigurationIsValidWithHostIp() { var validConfig = new StatsDConfiguration { Host = "10.0.1.2" }; var stats = new StatsDPublisher(validConfig); stats.ShouldNotBeNull(); }
public void ItShouldBeAbleToSendMessagesOfArbitraryLength(char ch, int count) { var config = new StatsDConfiguration { Host = "127.0.0.1" }; var fakeTransport = new FakeTransport(); var publisher = new BufferBasedStatsDPublisher(config, fakeTransport); publisher.Increment(new string(ch, count)); fakeTransport.TimesCalled.ShouldBe(1); }
public static void Metrics_Not_Sent_If_No_Metrics() { // Arrange var mock = new Mock <IStatsDTransport>(); var config = new StatsDConfiguration(); var publisher = new StatsDPublisher(config, mock.Object); // Act publisher.Decrement(1, 0, new[] { "foo" }); publisher.Increment(1, 0, new[] { "bar" }); // Assert mock.Verify((p) => p.Send(It.IsAny <ArraySegment <byte> >()), Times.Never()); }
/// <summary> /// Initializes a new instance of the <see cref="StatsDPublisher"/> class for the specified transport. /// </summary> /// <param name="configuration">The StatsD configuration to use.</param> /// <param name="transport">The transport implementation to use.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="configuration"/> or <paramref name="transport"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="configuration"/> is invalid, such as an invalid hostname or IP address. /// </exception> public StatsDPublisher(StatsDConfiguration configuration, IStatsDTransport transport) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (transport == null) { throw new ArgumentNullException(nameof(transport)); } _inner = new BufferBasedStatsDPublisher(configuration, transport); _transport = transport; _disposeTransport = false; }
public static void Decrement_Sends_Multiple_Metrics() { // Arrange var mock = new Mock <IStatsDTransport>(); var config = new StatsDConfiguration { Prefix = "red", }; var publisher = new StatsDPublisher(config, mock.Object); // Act publisher.Decrement(10, 1, "white", "blue"); // Assert mock.Verify((p) => p.Send(It.Ref <ArraySegment <byte> > .IsAny), Times.Exactly(2)); }
public static async Task Can_Send_Metrics_To_StatsD_Using_Udp( string host, SocketProtocol socketProtocol) { Skip.If(Environment.GetEnvironmentVariable("CI") == null, "By default, this test is only run during continuous integration."); // Arrange var config = new StatsDConfiguration { Host = host, Prefix = Guid.NewGuid().ToString().Replace("-", string.Empty, StringComparison.Ordinal), SocketProtocol = socketProtocol, }; using var publisher = new StatsDPublisher(config); // Act and Assert await AssertMetrics(config, publisher); }
public StatsDPublisher(StatsDConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (string.IsNullOrWhiteSpace(configuration.Host)) { throw new ArgumentNullException(nameof(configuration.Host)); } _formatter = new StatsDMessageFormatter(configuration.Culture, configuration.Prefix); var endpointSource = EndpointParser.MakeEndPointSource( configuration.Host, configuration.Port, configuration.DnsLookupInterval); _transport = new UdpTransport(endpointSource); }
public static void CanRegisterServicesWithNoConfiguratonIfConfigurationAlreadRegistered() { // Arrange var config = new StatsDConfiguration() { Host = "localhost" }; var provider = Configure( (services) => { services.AddSingleton(config); // Act services.AddStatsD(); }); try { // Assert var configuration = provider.GetRequiredService <StatsDConfiguration>(); configuration.ShouldNotBeNull(); configuration.ShouldBe(config); var source = provider.GetRequiredService <IPEndPointSource>(); source.ShouldNotBeNull(); var transport = provider.GetRequiredService <IStatsDTransport>(); transport.ShouldNotBeNull(); transport.ShouldBeOfType <UdpTransport>(); var publisher = provider.GetRequiredService <IStatsDPublisher>(); publisher.ShouldNotBeNull(); publisher.ShouldBeOfType <StatsDPublisher>(); } finally { if (provider is IDisposable disposable) { disposable.Dispose(); } } }
/// <summary> /// Initializes a new instance of the <see cref="StatsDPublisher"/> class using the default transport. /// </summary> /// <param name="configuration">The StatsD configuration to use.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="configuration"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="configuration"/> is invalid, such as an invalid hostname or IP address. /// </exception> public StatsDPublisher(StatsDConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (string.IsNullOrWhiteSpace(configuration.Host)) { throw new ArgumentException("No hostname or IP address is set.", nameof(configuration)); } var endpointSource = EndPointFactory.MakeEndPointSource( configuration.Host !, configuration.Port, configuration.DnsLookupInterval); var transport = new SocketTransport(endpointSource, configuration.SocketProtocol); _transport = transport; _disposeTransport = true; _inner = new BufferBasedStatsDPublisher(configuration, transport); }
public static void RegisteringServicesDoesNotOverwriteExistingRegistrations() { // Arrange var existingConfig = new StatsDConfiguration(); var existingSource = Mock.Of <IPEndPointSource>(); var existingTransport = Mock.Of <IStatsDTransport>(); var existingPublisher = Mock.Of <IStatsDPublisher>(); var provider = Configure( (services) => { services.AddSingleton(existingConfig); services.AddSingleton(existingSource); services.AddSingleton(existingTransport); services.AddSingleton(existingPublisher); // Act services.AddStatsD(); }); // Assert var configuration = provider.GetRequiredService <StatsDConfiguration>(); configuration.ShouldBe(existingConfig); var source = provider.GetRequiredService <IPEndPointSource>(); source.ShouldBe(existingSource); var transport = provider.GetRequiredService <IStatsDTransport>(); transport.ShouldBe(existingTransport); var publisher = provider.GetRequiredService <IStatsDPublisher>(); publisher.ShouldBe(existingPublisher); }
private static IStatsDPublisher MakeThrowingPublisher(StatsDConfiguration config) { return(new StatsDPublisher(config, new ThrowingTransport())); }
private static async Task AssertMetrics(StatsDConfiguration config, IStatsDPublisher publisher) { // Act - Create a counter publisher.Increment("apple"); // Act - Create and change a counter publisher.Increment("bear"); // 1 publisher.Increment(10, "bear"); // 11 publisher.Increment(10, 0, "bear", null); // 11 publisher.Decrement("bear"); // 10 publisher.Decrement(5, "bear"); // 5 publisher.Decrement(5, 0, "bear"); // 5 // Act - Create and change a counter with tags Dictionary<string, string> tags = new Dictionary<string, string>(); tags.Add("key", "value"); tags.Add("key2", "value2"); publisher.Increment("ant", tags); // 1 publisher.Increment(15, "ant", tags); // 16 publisher.Decrement(5,"ant", tags); // 11 // Act - Create multiple counters with tags and change them tags = new Dictionary<string, string>(); tags.Add("key", "value"); tags.Add("key2", "value2"); publisher.Increment(100, 1, tags, new string[] { "gmc", "ford" }); // 100 publisher.Decrement(5, 1, tags, new string[] { "gmc", "ford" }); // 95 // Act - Create multiple counters without tags and change them publisher.Increment(150, 1, null, new string[] { "jaguar", "kia" }); // 100 publisher.Decrement(20, 1, null, new string[] { "jaguar", "kia" }); // 130 // Act - Create a counter with tags tags = new Dictionary<string, string>(); tags.Add("key", "value"); tags.Add("key2", "value2"); publisher.Increment("orange", tags); // 1 publisher.Increment(50, "orange", tags); // 51 // Act - Create multiple counters with tags tags = new Dictionary<string, string>(); tags.Add("type", "vehicle"); publisher.Increment(60, 1, tags, new string[] { "mazda", "fiat" }); // Act - Create multiple counters without tags publisher.Increment(25, 1, null, new string[] { "ferrari", "jeep" }); // Act - Mark an event (which is a counter) publisher.Increment("fish"); // Act - Create a gauge publisher.Gauge(3.141, "circle", Operation.Set, null); // Act - Create and change a gauge publisher.Gauge(10, "dog", Operation.Set, null); publisher.Gauge(42, "dog", Operation.Set, null); // Act - Create a gauge with tags tags = new Dictionary<string, string>(); tags.Add("foo", "bar"); tags.Add("lorem", "ipsum"); publisher.Gauge(5.5, "square", Operation.Set, tags); // Act - Create a gauge and decrement it publisher.Gauge(2020, "year", Operation.Set, null); publisher.Gauge(10, "year", Operation.Decrement, null); // Act - Create a gauge and increment it publisher.Gauge(15, "score", Operation.Set, null); publisher.Gauge(2, "score", Operation.Increment, null); // Act - Create a timer publisher.Timing(123, "elephant"); publisher.Timing(TimeSpan.FromSeconds(2), "fox"); publisher.Timing(456, 1, "goose", null); publisher.Timing(TimeSpan.FromSeconds(3.5), 1, "hen"); // Act - Create a timer with tags tags = new Dictionary<string, string>(); tags.Add("class", "mammal"); tags.Add("genus", "panthera"); publisher.Timing(128, "leopard", tags); // Act - Increment multiple counters publisher.Increment(7, 1, new string[] { "green", "red" }); // 7 publisher.Increment(2, 0, new List<string>() { "green", "red" }); // 7 publisher.Decrement(1, 0, new string[] { "red", "green" }); // 7 publisher.Decrement(4, 1, new List<string>() { "red", "green" }); // 3 // Allow enough time for metrics to be registered await Task.Delay(TimeSpan.FromSeconds(1.0)); // Assert var result = await SendCommandAsync("counters"); result.Value<int>(config.Prefix + ".apple").ShouldBe(1, result.ToString()); result.Value<int>(config.Prefix + ".bear").ShouldBe(5, result.ToString()); result.Value<int>(config.Prefix + ".ant;key=value;key2=value2").ShouldBe(11, result.ToString()); result.Value<int>(config.Prefix + ".gmc;key=value;key2=value2").ShouldBe(95, result.ToString()); result.Value<int>(config.Prefix + ".ford;key=value;key2=value2").ShouldBe(95, result.ToString()); result.Value<int>(config.Prefix + ".jaguar").ShouldBe(130, result.ToString()); result.Value<int>(config.Prefix + ".kia").ShouldBe(130, result.ToString()); result.Value<int>(config.Prefix + ".orange;key=value;key2=value2").ShouldBe(51, result.ToString()); result.Value<int>(config.Prefix + ".mazda;type=vehicle").ShouldBe(60, result.ToString()); result.Value<int>(config.Prefix + ".fiat;type=vehicle").ShouldBe(60, result.ToString()); result.Value<int>(config.Prefix + ".ferrari").ShouldBe(25, result.ToString()); result.Value<int>(config.Prefix + ".jeep").ShouldBe(25, result.ToString()); result.Value<int>(config.Prefix + ".fish").ShouldBe(1, result.ToString()); result.Value<int>(config.Prefix + ".green").ShouldBe(3, result.ToString()); result.Value<int>(config.Prefix + ".red").ShouldBe(3, result.ToString()); result = await SendCommandAsync("gauges"); result.Value<double>(config.Prefix + ".circle").ShouldBe(3.141, result.ToString()); result.Value<int>(config.Prefix + ".dog").ShouldBe(42, result.ToString()); result.Value<double>(config.Prefix + ".square;foo=bar;lorem=ipsum").ShouldBe(5.5, result.ToString()); result.Value<int>(config.Prefix + ".year").ShouldBe(2010, result.ToString()); result.Value<int>(config.Prefix + ".score").ShouldBe(17, result.ToString()); result = await SendCommandAsync("timers"); result[config.Prefix + ".elephant"].Values<int>().ShouldBe(new[] { 123 }, result.ToString()); result[config.Prefix + ".leopard;class=mammal;genus=panthera"].Values<int>().ShouldBe(new[] { 128 }, result.ToString()); result[config.Prefix + ".fox"].Values<int>().ShouldBe(new[] { 2000 }, result.ToString()); result[config.Prefix + ".goose"].Values<int>().ShouldBe(new[] { 456 }, result.ToString()); result[config.Prefix + ".hen"].Values<int>().ShouldBe(new[] { 3500 }, result.ToString()); }