Question

I'm using Graphite.NET for logging to statsD. Underneath the hood, it uses UdpClient to write to the statD server. Source. I think makes sense to create this as a singleton because I will be logging frequently and it seems that there will be a lot of overhead in creating this client and connecting every time I want to log. Is there any downside to doing this? What happens if the connection gets interrupted: will an exception be thrown? Will my logger be recreated by StuctureMap next time I try to use the logger? Here's what my SM configuration looks like:

x.For<IStatsDClientAdapter>()
                 .Singleton()
                 .Use<StatsDClientAdapter>()
                 .Ctor<string>("hostname").EqualToAppSetting("GraphiteHostname")
                 .Ctor<int>("port").EqualToAppSetting("GraphitePort")
                 .Ctor<string>("keyPrefix").EqualToAppSetting("GraphiteKeyPrefix");
Was it helpful?

Solution

Because the Graphite.NET StatsDClient instantiates and calls Connect on UdpClient in it's constructor, your ability to recover from initial connection exceptions are limited if you only make this call once (e.g. at application startup via depencency injected singleton - as you've done).

Using a Singleton with this StatsDClient means you'd need to catch and re-instantiate the StatsDClient if a connection issue occurred in order to insure that your application was initialized correctly (i.e. with a working StatsDClient)... because, again, Connect is run in the constructor.

That said, if the StatsDClient initializes successfully (i.e. Connect doesn't throw an exception) then you should be OK even if the server goes down afterward because UDP is connectionless and StatsDClient is handling/catching any exception that occurs on Send(). The client should just keep right on firing Sends at the Ip and Port that was established in the default connection with no knowledge of whether the server is good/bad.

Too bad the Graphite.NET StatsDClient doesn't pass the ip and port to UdpClient.Send() - http://msdn.microsoft.com/en-us/library/acf44a1a.aspx) instead of using a default connection via the constructor... as this would make using a static member possible (as you'd be able to construct usable StatsDClients under any conditions).

Long story short, in order to avoid getting your application into a bad state, I'd instantiate at usage time. As follows:

using(var statsdclient = new StatsDClient("my.statsd.host", 8125, "whatever.blah"))
{
    statsdclient.Increment("asdf"); 
}

Or, alternatively, fork StatsDClient and modify it to pass the IP and Port on the Send().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top