Click here to Skip to main content
15,896,154 members
Articles / Desktop Programming / XAML

Diagnostic Explorer

Rate me:
Please Sign up or sign in to vote.
4.93/5 (41 votes)
29 Nov 2010LGPL315 min read 82.7K   1.5K   120  
A .NET library and website which allows developers to expose and view arbitrary diagnostic information about their .NET processes.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Diagnostics;
using System.Timers;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Configuration;
using System.Reflection;

namespace DiagnosticExplorer
{
	public static class DiagnosticHostingService
	{
		private static ServiceHost _host;
		private static DiagnosticService _diagService;
		private static System.Timers.Timer _registrationTimer;
		private static System.Timers.Timer _openHostTimer;
		private static bool _isStarted = false;
		private static Registration _registration;

		public static void Start()
		{
			_isStarted = true;
			Trace.WriteLine("DiagnosticHostingService.Start()");
			DiagnosticConfig config = (DiagnosticConfig)ConfigurationManager.GetSection("diagnosticExplorer");
			if (config == null)
				config = new DiagnosticConfig { PortMode = PortMode.Auto, AutoRegister = true };

			_registration = new Registration();
			_registration.ProcessId = Process.GetCurrentProcess().Id;
			_registration.UserDomain = Environment.UserDomainName;
			_registration.UserName = Environment.UserName;
			_registration.ProcessName = Process.GetCurrentProcess().ProcessName;

			int portNumber = config.Port;
			if (config.PortMode == PortMode.Auto)
				portNumber = GetFreePort();

			_registration.Uri = string.Format("net.tcp://{0}:{1}/Diagnostics", Environment.MachineName, portNumber);
			_registration.InstanceName = "Dev";

			_openHostTimer = new System.Timers.Timer();
			_openHostTimer.Interval = 100;
			_openHostTimer.Elapsed += OpenHostTick;
			_openHostTimer.Start();

			_registrationTimer = new System.Timers.Timer();
			_registrationTimer.Interval = 100;
			_registrationTimer.Elapsed += RegisterTick;
			if (config.AutoRegister)
				_registrationTimer.Start();
		}

		private static int GetFreePort()
		{
			TcpListener l = new TcpListener(IPAddress.Parse("127.0.0.1"), 0);
			l.Start();
			int port = ((IPEndPoint)l.LocalEndpoint).Port;
			l.Stop();
			return port;
		}

		private static void RegisterTick(object sender, ElapsedEventArgs e)
		{
			if (!_isStarted) 
				return;

			_registrationTimer.Enabled = false;
			try
			{
				Trace.WriteLine("DiagnosticHostingService registering");
				RegistrationClient client = CreateRegistrationClient();
				Trace.WriteLine(string.Format("Created client at {0}, registering {1}", client.Endpoint.Address, _registration));
				RegistrationResponse response = client.Register(_registration);
				Trace.WriteLine(response);
				_registrationTimer.Interval = response.RenewTime.TotalMilliseconds;
				client.Close();
			}
			catch (Exception ex)
			{
				Trace.WriteLine("Diagnostics registration failed: ");
				Trace.WriteLine(ex);
			}
			finally
			{
				if (_isStarted)
				{
					if (_registrationTimer.Interval <= 5000)
						_registrationTimer.Interval = 5000;

					_registrationTimer.Start();
				}
			}
		}

		private static RegistrationClient CreateRegistrationClient()
		{
			RegistrationClient client = new RegistrationClient();
			client.Open();
			return client;
		}

		private static void OpenHostTick(object sender, ElapsedEventArgs e)
		{
			_openHostTimer.Enabled = false;

			if (_host == null)
			{
				try
				{
					if (_diagService == null)
						_diagService = new DiagnosticService();

					_host = new ServiceHost(typeof(DiagnosticService));
					_host.Faulted += HandleHostFaulted;
					NetTcpBinding binding = new NetTcpBinding();
					binding.Security.Mode = SecurityMode.None;
					_host.AddServiceEndpoint(typeof(IDiagnosticService), binding, _registration.Uri);
					Trace.WriteLine("DiagnosticHostingService opening host");
					_host.Open();
					Trace.WriteLine("DiagnosticHostingService host opened");
				}
				catch (Exception ex)
				{
					Trace.WriteLine(ex);
				}
			}
		}

		private static void HandleHostFaulted(object sender, EventArgs e)
		{
			if (_isStarted)
			{
				_host = null;
				_openHostTimer.Interval = 5000;
				_openHostTimer.Start();

				Trace.WriteLine("DiagnosticManager service host faulted, trying again in 5 seconds");
			}
		}

		public static void Stop()
		{
			_isStarted = false;
			_registrationTimer.Stop();
			_openHostTimer.Stop();
			Deregister();
			
			try
			{
				if (_host != null)
					_host.Close();
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex);
			}
		}

		private static void Deregister()
		{
			try
			{
				_isStarted = false;
				_registrationTimer.Stop();

				RegistrationClient client = CreateRegistrationClient();
				client.Deregister(_registration);
				client.Close();
				Trace.WriteLine("Deregistered");
			}
			catch (Exception ex)
			{
				Trace.WriteLine(ex);
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer
United Kingdom United Kingdom
I am a software developer originally from Auckland, New Zealand. I have lived and worked in London since 2005.

Comments and Discussions