RemoteLoggingServerPlugin.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #region Apache License
  2. //
  3. // Licensed to the Apache Software Foundation (ASF) under one or more
  4. // contributor license agreements. See the NOTICE file distributed with
  5. // this work for additional information regarding copyright ownership.
  6. // The ASF licenses this file to you under the Apache License, Version 2.0
  7. // (the "License"); you may not use this file except in compliance with
  8. // the License. You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. //
  18. #endregion
  19. // .NET Compact Framework 1.0 has no support for System.Runtime.Remoting
  20. #if !NETCF
  21. using System;
  22. using System.Runtime.Remoting;
  23. using log4net.Util;
  24. using log4net.Repository;
  25. using log4net.Core;
  26. using IRemoteLoggingSink = log4net.Appender.RemotingAppender.IRemoteLoggingSink;
  27. namespace log4net.Plugin
  28. {
  29. /// <summary>
  30. /// Plugin that listens for events from the <see cref="log4net.Appender.RemotingAppender"/>
  31. /// </summary>
  32. /// <remarks>
  33. /// <para>
  34. /// This plugin publishes an instance of <see cref="IRemoteLoggingSink"/>
  35. /// on a specified <see cref="SinkUri"/>. This listens for logging events delivered from
  36. /// a remote <see cref="log4net.Appender.RemotingAppender"/>.
  37. /// </para>
  38. /// <para>
  39. /// When an event is received it is relogged within the attached repository
  40. /// as if it had been raised locally.
  41. /// </para>
  42. /// </remarks>
  43. /// <author>Nicko Cadell</author>
  44. /// <author>Gert Driesen</author>
  45. public class RemoteLoggingServerPlugin : PluginSkeleton
  46. {
  47. #region Public Instance Constructors
  48. /// <summary>
  49. /// Default constructor
  50. /// </summary>
  51. /// <remarks>
  52. /// <para>
  53. /// Initializes a new instance of the <see cref="RemoteLoggingServerPlugin" /> class.
  54. /// </para>
  55. /// <para>
  56. /// The <see cref="SinkUri"/> property must be set.
  57. /// </para>
  58. /// </remarks>
  59. public RemoteLoggingServerPlugin() : base("RemoteLoggingServerPlugin:Unset URI")
  60. {
  61. }
  62. /// <summary>
  63. /// Construct with sink Uri.
  64. /// </summary>
  65. /// <param name="sinkUri">The name to publish the sink under in the remoting infrastructure.
  66. /// See <see cref="SinkUri"/> for more details.</param>
  67. /// <remarks>
  68. /// <para>
  69. /// Initializes a new instance of the <see cref="RemoteLoggingServerPlugin" /> class
  70. /// with specified name.
  71. /// </para>
  72. /// </remarks>
  73. public RemoteLoggingServerPlugin(string sinkUri) : base("RemoteLoggingServerPlugin:"+sinkUri)
  74. {
  75. m_sinkUri = sinkUri;
  76. }
  77. #endregion Public Instance Constructors
  78. #region Public Instance Properties
  79. /// <summary>
  80. /// Gets or sets the URI of this sink.
  81. /// </summary>
  82. /// <value>
  83. /// The URI of this sink.
  84. /// </value>
  85. /// <remarks>
  86. /// <para>
  87. /// This is the name under which the object is marshaled.
  88. /// <see cref="M:RemotingServices.Marshal(MarshalByRefObject,String,Type)"/>
  89. /// </para>
  90. /// </remarks>
  91. public virtual string SinkUri
  92. {
  93. get { return m_sinkUri; }
  94. set { m_sinkUri = value; }
  95. }
  96. #endregion Public Instance Properties
  97. #region Override implementation of PluginSkeleton
  98. /// <summary>
  99. /// Attaches this plugin to a <see cref="ILoggerRepository"/>.
  100. /// </summary>
  101. /// <param name="repository">The <see cref="ILoggerRepository"/> that this plugin should be attached to.</param>
  102. /// <remarks>
  103. /// <para>
  104. /// A plugin may only be attached to a single repository.
  105. /// </para>
  106. /// <para>
  107. /// This method is called when the plugin is attached to the repository.
  108. /// </para>
  109. /// </remarks>
  110. #if NET_4_0 || MONO_4_0
  111. [System.Security.SecuritySafeCritical]
  112. #endif
  113. override public void Attach(ILoggerRepository repository)
  114. {
  115. base.Attach(repository);
  116. // Create the sink and marshal it
  117. m_sink = new RemoteLoggingSinkImpl(repository);
  118. try
  119. {
  120. RemotingServices.Marshal(m_sink, m_sinkUri, typeof(IRemoteLoggingSink));
  121. }
  122. catch(Exception ex)
  123. {
  124. LogLog.Error(declaringType, "Failed to Marshal remoting sink", ex);
  125. }
  126. }
  127. /// <summary>
  128. /// Is called when the plugin is to shutdown.
  129. /// </summary>
  130. /// <remarks>
  131. /// <para>
  132. /// When the plugin is shutdown the remote logging
  133. /// sink is disconnected.
  134. /// </para>
  135. /// </remarks>
  136. #if NET_4_0 || MONO_4_0
  137. [System.Security.SecuritySafeCritical]
  138. #endif
  139. override public void Shutdown()
  140. {
  141. // Stops the sink from receiving messages
  142. RemotingServices.Disconnect(m_sink);
  143. m_sink = null;
  144. base.Shutdown();
  145. }
  146. #endregion Override implementation of PluginSkeleton
  147. #region Private Instance Fields
  148. private RemoteLoggingSinkImpl m_sink;
  149. private string m_sinkUri;
  150. #endregion Private Instance Fields
  151. #region Private Static Fields
  152. /// <summary>
  153. /// The fully qualified type of the RemoteLoggingServerPlugin class.
  154. /// </summary>
  155. /// <remarks>
  156. /// Used by the internal logger to record the Type of the
  157. /// log message.
  158. /// </remarks>
  159. private readonly static Type declaringType = typeof(RemoteLoggingServerPlugin);
  160. #endregion Private Static Fields
  161. /// <summary>
  162. /// Delivers <see cref="LoggingEvent"/> objects to a remote sink.
  163. /// </summary>
  164. /// <remarks>
  165. /// <para>
  166. /// Internal class used to listen for logging events
  167. /// and deliver them to the local repository.
  168. /// </para>
  169. /// </remarks>
  170. private class RemoteLoggingSinkImpl : MarshalByRefObject, IRemoteLoggingSink
  171. {
  172. #region Public Instance Constructors
  173. /// <summary>
  174. /// Constructor
  175. /// </summary>
  176. /// <param name="repository">The repository to log to.</param>
  177. /// <remarks>
  178. /// <para>
  179. /// Initializes a new instance of the <see cref="RemoteLoggingSinkImpl"/> for the
  180. /// specified <see cref="ILoggerRepository"/>.
  181. /// </para>
  182. /// </remarks>
  183. public RemoteLoggingSinkImpl(ILoggerRepository repository)
  184. {
  185. m_repository = repository;
  186. }
  187. #endregion Public Instance Constructors
  188. #region Implementation of IRemoteLoggingSink
  189. /// <summary>
  190. /// Logs the events to the repository.
  191. /// </summary>
  192. /// <param name="events">The events to log.</param>
  193. /// <remarks>
  194. /// <para>
  195. /// The events passed are logged to the <see cref="ILoggerRepository"/>
  196. /// </para>
  197. /// </remarks>
  198. public void LogEvents(LoggingEvent[] events)
  199. {
  200. if (events != null)
  201. {
  202. foreach(LoggingEvent logEvent in events)
  203. {
  204. if (logEvent != null)
  205. {
  206. m_repository.Log(logEvent);
  207. }
  208. }
  209. }
  210. }
  211. #endregion Implementation of IRemoteLoggingSink
  212. #region Override implementation of MarshalByRefObject
  213. /// <summary>
  214. /// Obtains a lifetime service object to control the lifetime
  215. /// policy for this instance.
  216. /// </summary>
  217. /// <returns><c>null</c> to indicate that this instance should live forever.</returns>
  218. /// <remarks>
  219. /// <para>
  220. /// Obtains a lifetime service object to control the lifetime
  221. /// policy for this instance. This object should live forever
  222. /// therefore this implementation returns <c>null</c>.
  223. /// </para>
  224. /// </remarks>
  225. #if NET_4_0 || MONO_4_0
  226. [System.Security.SecurityCritical]
  227. #endif
  228. public override object InitializeLifetimeService()
  229. {
  230. return null;
  231. }
  232. #endregion Override implementation of MarshalByRefObject
  233. #region Private Instance Fields
  234. /// <summary>
  235. /// The underlying <see cref="ILoggerRepository" /> that events should
  236. /// be logged to.
  237. /// </summary>
  238. private readonly ILoggerRepository m_repository;
  239. #endregion Private Instance Fields
  240. }
  241. }
  242. }
  243. #endif // !NETCF