Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » C# » General » Downloads
 
Add your own
alternative version

LOG4NET WebServiceAppender

, 27 Dec 2006
Introducing a small appender that logs to a web service within the LOG4NET logging framework
log4netwebserviceappender_demo.zip
References
ClickOnceButton.dll
de
ZetaLib.Core.resources.dll
ZetaLib.Web.resources.dll
ZetaLib.Windows.resources.dll
ICSharpCode.SharpZipLib.dll
Interop.ADODB.dll
Interop.JRO.dll
log4net.dll
ZetaLib.Core.dll
ZetaLib.Web.dll
ZetaLib.Windows.dll
Runtime
bin
Debug
de
obj
Debug
Refactor
TempPE
Properties
Settings.settings
Runtime.csproj.user
Web References
Logging
LoggingService.disco
LoggingService.wsdl
Reference.map
TestClient
bin
Debug
de
ZetaLib.Core.resources.dll
ZetaLib.Windows.resources.dll
ICSharpCode.SharpZipLib.dll
Interop.ADODB.dll
Interop.JRO.dll
log4net.dll
TestClient.exe
TestClient.vshost.exe
ZetaLib.Core.dll
ZetaLib.Windows.dll
ZetaWebServiceAppender.dll
obj
Debug
Refactor
TempPE
Properties
Settings.settings
Web
App_Code
Bin
ClickOnceButton.dll
de
ZetaLib.Core.resources.dll
ZetaLib.Web.resources.dll
ICSharpCode.SharpZipLib.dll
Interop.ADODB.dll
Interop.JRO.dll
log4net.dll
ZetaLib.Core.dll
ZetaLib.Core.dll.refresh
ZetaLib.Web.dll
ZetaLib.Web.dll.refresh
Global.asax
namespace Zeta
{
	#region Using directives.
	// ----------------------------------------------------------------------

	using System;
	using System.Collections.Generic;
	using System.Text;
	using log4net.Core;
	using log4net.Appender;
	using log4net.Util;
	using ZetaLib.Core.Common;
	using System.ComponentModel;
	using log4net.Layout;
	using System.Net;
	using log4net.Filter;
	using System.Diagnostics;
	using ZetaLib.Core.Logging;

	// ----------------------------------------------------------------------
	#endregion

	/////////////////////////////////////////////////////////////////////////

	/// <summary>
	/// An appender for LOG4NET that is capable of appending to a web service.
	/// </summary>
	/// <remarks>
	/// See http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/tpage/1/view/topic/postid/17080/Default.aspx#17919
	///
	/// Available configuration options:
	/// 
	/// 	&lt;appender name="WebServiceAppender" type="Zeta.WebServiceAppender"&gt;
	/// 		&lt;!-- LOG4NET parameters. --&gt;
	/// 		&lt;filter type="log4net.Filter.LevelRangeFilter"&gt;
	/// 			&lt;param name="LevelMin" value="DEBUG"/&gt;
	/// 			&lt;param name="LevelMax" value="FATAL"/&gt;
	/// 		&lt;/filter&gt;
	/// 
	/// 		&lt;!-- General parameters. --&gt;
	/// 		&lt;param name="ApiKey" value="{0E12B21A-95B9-11DB-96C0-005056C00008}" /&gt;
	/// 
	/// 		&lt;!-- WebService parameters. --&gt;
	/// 		&lt;param name="Url" value="http://www.myserver.com/LoggingService.asmx" /&gt;
	/// 		&lt;param name="TimeoutSeconds" value="60" /&gt;
	/// 
	/// 		&lt;!-- Proxy parameters. --&gt;
	/// 		&lt;param name="UseProxy" value="false" /&gt;
	/// 		&lt;param name="ProxyUrl" value="http://myproxy:3128" /&gt;
	/// 		&lt;param name="ProxyBypassOnLocal" value="true" /&gt;
	/// 		&lt;param name="ProxyUseDefaultCredentials" value="true" /&gt;
	/// 		&lt;param name="ProxyCredentialsDomain" value="OFFICE" /&gt;
	/// 		&lt;param name="ProxyCredentialsUserName" value="MyUser" /&gt;
	/// 		&lt;param name="ProxyCredentialsPassword" value="MyPassword" /&gt;
	/// 	&lt;/appender&gt;
	/// </remarks>
	public class WebServiceAppender :
		AppenderSkeleton
	{
		#region Public properties, setable from the configuration file.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		public LevelRangeFilter Filter
		{
			get
			{
				return filter;
			}
			set
			{
				filter = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ApiKey
		{
			get
			{
				return apiKey;
			}
			set
			{
				apiKey = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string Url
		{
			get
			{
				return url;
			}
			set
			{
				url = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public int TimeoutSeconds
		{
			get
			{
				return timeoutSeconds;
			}
			set
			{
				timeoutSeconds = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public bool UseProxy
		{
			get
			{
				return useProxy;
			}
			set
			{
				useProxy = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ProxyUrl
		{
			get
			{
				return proxyUrl;
			}
			set
			{
				proxyUrl = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public bool ProxyBypassOnLocal
		{
			get
			{
				return proxyBypassOnLocal.GetValueOrDefault( true );
			}
			set
			{
				proxyBypassOnLocal = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public bool ProxyUseDefaultCredentials
		{
			get
			{
				return proxyUseDefaultCredentials.GetValueOrDefault( true );
			}
			set
			{
				proxyUseDefaultCredentials = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ProxyCredentialsDomain
		{
			get
			{
				return proxyCredentialsDomain;
			}
			set
			{
				proxyCredentialsDomain = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ProxyCredentialsUserName
		{
			get
			{
				return proxyCredentialsUserName;
			}
			set
			{
				proxyCredentialsUserName = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public string ProxyCredentialsPassword
		{
			get
			{
				return proxyCredentialsPassword;
			}
			set
			{
				proxyCredentialsPassword = value;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Implementation of IOptionHandler.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		public override void ActivateOptions()
		{
			base.ActivateOptions();

			//Provide any checks based on Service config properties, if Service
			//config properties are valid initialize WebServiceAppender.

			InitializeServiceConnection();
		}


		// ------------------------------------------------------------------
		#endregion

		#region Override implementation of AppenderSkeleton.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		protected override void Append(
			LoggingEvent loggingEvent )
		{
			try
			{
				// Call the web service, but only if filtered correctly.
				if ( filter == null ||
					(loggingEvent.Level >= filter.LevelMin &&
					loggingEvent.Level <= filter.LevelMax) )
				{
					string message = loggingEvent.RenderedMessage;

					if ( !string.IsNullOrEmpty( message ) )
					{
						message = message.Trim();
					}

					Logging.WebServiceCommunicationInformation info =
						new Zeta.Logging.WebServiceCommunicationInformation();

					info.ApiKey = apiKey;
					info.ExceptionSerializedAsString =
						StringHelper.SerializeToString(
						loggingEvent.ExceptionObject );
					info.Level = loggingEvent.Level.Name;
					info.Message = message;

					// Provide additional context information.
					info.ContextInformation = 
						ZetaLib.Core.Logging.LoggingInformation.All;

					// Call the web service.
					_serviceLogging.LogAsync(
						info,
						Guid.NewGuid() );
				}
			}
			catch ( Exception exc )
			{
				ErrorHandler.Error(
					"Unable to send loggingEvent to Logging Service",
					exc,
					ErrorCode.WriteFailure );
			}
		}

		/// <summary>
		/// 
		/// </summary>
		protected override bool RequiresLayout
		{
			get
			{
				return false;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		protected override void OnClose()
		{
			base.OnClose();

			//Release any resource that were needed.
			if ( _serviceLogging != null )
			{
				_serviceLogging.Dispose();
				_serviceLogging = null;
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private methods.
		// ------------------------------------------------------------------

		/// <summary>
		/// 
		/// </summary>
		private void InitializeServiceConnection()
		{
			try
			{
				//Code any Service initialization needed for WebServiceAppender to work.
				//This is called from ActiveOptions.
				//Instantiate the WebService.
				if ( _serviceLogging == null )
				{
					_serviceLogging = new Zeta.Logging.LoggingService();

					_serviceLogging.LogCompleted +=
						new Zeta.Logging.LogCompletedEventHandler(
						_serviceLogging_LogCompleted );

					// --

					if ( !string.IsNullOrEmpty( url ) )
					{
						_serviceLogging.Url = url;
					}

					if ( timeoutSeconds > 0 )
					{
						_serviceLogging.Timeout = timeoutSeconds * 1000;
					}

					if ( useProxy )
					{
						WebProxy proxy = new WebProxy();

						proxy.Address = new Uri( proxyUrl );

						proxy.BypassProxyOnLocal =
							proxyBypassOnLocal.GetValueOrDefault(
							proxy.BypassProxyOnLocal );
						proxy.UseDefaultCredentials =
							proxyUseDefaultCredentials.GetValueOrDefault(
							proxy.UseDefaultCredentials );

						if ( !proxy.UseDefaultCredentials )
						{
							NetworkCredential credentials =
								new NetworkCredential();

							credentials.Domain = proxyCredentialsDomain;
							credentials.UserName = proxyCredentialsUserName;
							credentials.Password = proxyCredentialsPassword;

							proxy.Credentials = credentials;
						}

						_serviceLogging.Proxy = proxy;
					}
				}
			}
			catch ( Exception exc )
			{
				// TODO: Add Service name to error message.
				ErrorHandler.Error(
					"Could not initialize the service",
					exc,
					ErrorCode.GenericFailure );

				// TODO: Reset the Service object to a known state if needed.
			}
		}

		/// <summary>
		/// Event handler.
		/// </summary>
		private void _serviceLogging_LogCompleted(
			object sender,
			AsyncCompletedEventArgs e )
		{
			if ( e.Error != null )
			{
				ErrorHandler.Error(
					"Unable to send loggingEvent to Logging Service",
					e.Error,
					ErrorCode.WriteFailure );
			}
		}

		// ------------------------------------------------------------------
		#endregion

		#region Private variables.
		// ------------------------------------------------------------------

		private string apiKey;
		private string url;
		private int timeoutSeconds;
		private bool useProxy = false;

		private string proxyUrl;
		private bool? proxyBypassOnLocal;
		private bool? proxyUseDefaultCredentials;
		private string proxyCredentialsDomain;
		private string proxyCredentialsUserName;
		private string proxyCredentialsPassword;

		private Logging.LoggingService _serviceLogging = null;

		private LevelRangeFilter filter;

		// ------------------------------------------------------------------
		#endregion
	}

	/////////////////////////////////////////////////////////////////////////
}

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 Code Project Open License (CPOL)

About the Author

Uwe Keim
Chief Technology Officer Zeta Producer Desktop CMS
Germany Germany
Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.
 
In his free time, he does climbing, running and mountain biking. Recently he became a father of a cute boy.
 
Some cool, free software from us:
 
Free Test Management Software - Intuitive, competitive, Test Plans. Download now!  
Homepage erstellen - Intuitive, very easy to use. Download now!  
Send large Files online for free by Email
Offline-Homepage-Baukasten

| Advertise | Privacy | Mobile
Web04 | 2.8.140718.1 | Last Updated 27 Dec 2006
Article Copyright 2006 by Uwe Keim
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid