Logger.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  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. using System;
  20. using System.Collections;
  21. using log4net.Appender;
  22. using log4net.Util;
  23. using log4net.Core;
  24. namespace log4net.Repository.Hierarchy
  25. {
  26. /// <summary>
  27. /// Implementation of <see cref="ILogger"/> used by <see cref="Hierarchy"/>
  28. /// </summary>
  29. /// <remarks>
  30. /// <para>
  31. /// Internal class used to provide implementation of <see cref="ILogger"/>
  32. /// interface. Applications should use <see cref="LogManager"/> to get
  33. /// logger instances.
  34. /// </para>
  35. /// <para>
  36. /// This is one of the central classes in the log4net implementation. One of the
  37. /// distinctive features of log4net are hierarchical loggers and their
  38. /// evaluation. The <see cref="Hierarchy"/> organizes the <see cref="Logger"/>
  39. /// instances into a rooted tree hierarchy.
  40. /// </para>
  41. /// <para>
  42. /// The <see cref="Logger"/> class is abstract. Only concrete subclasses of
  43. /// <see cref="Logger"/> can be created. The <see cref="ILoggerFactory"/>
  44. /// is used to create instances of this type for the <see cref="Hierarchy"/>.
  45. /// </para>
  46. /// </remarks>
  47. /// <author>Nicko Cadell</author>
  48. /// <author>Gert Driesen</author>
  49. /// <author>Aspi Havewala</author>
  50. /// <author>Douglas de la Torre</author>
  51. public abstract class Logger : IAppenderAttachable, ILogger
  52. {
  53. #region Protected Instance Constructors
  54. /// <summary>
  55. /// This constructor created a new <see cref="Logger" /> instance and
  56. /// sets its name.
  57. /// </summary>
  58. /// <param name="name">The name of the <see cref="Logger" />.</param>
  59. /// <remarks>
  60. /// <para>
  61. /// This constructor is protected and designed to be used by
  62. /// a subclass that is not abstract.
  63. /// </para>
  64. /// <para>
  65. /// Loggers are constructed by <see cref="ILoggerFactory"/>
  66. /// objects. See <see cref="DefaultLoggerFactory"/> for the default
  67. /// logger creator.
  68. /// </para>
  69. /// </remarks>
  70. protected Logger(string name)
  71. {
  72. #if NETCF || NETSTANDARD1_3
  73. // NETCF: String.Intern causes Native Exception
  74. m_name = name;
  75. #else
  76. m_name = string.Intern(name);
  77. #endif
  78. }
  79. #endregion Protected Instance Constructors
  80. #region Public Instance Properties
  81. /// <summary>
  82. /// Gets or sets the parent logger in the hierarchy.
  83. /// </summary>
  84. /// <value>
  85. /// The parent logger in the hierarchy.
  86. /// </value>
  87. /// <remarks>
  88. /// <para>
  89. /// Part of the Composite pattern that makes the hierarchy.
  90. /// The hierarchy is parent linked rather than child linked.
  91. /// </para>
  92. /// </remarks>
  93. virtual public Logger Parent
  94. {
  95. get { return m_parent; }
  96. set { m_parent = value; }
  97. }
  98. /// <summary>
  99. /// Gets or sets a value indicating if child loggers inherit their parent's appenders.
  100. /// </summary>
  101. /// <value>
  102. /// <c>true</c> if child loggers inherit their parent's appenders.
  103. /// </value>
  104. /// <remarks>
  105. /// <para>
  106. /// Additivity is set to <c>true</c> by default, that is children inherit
  107. /// the appenders of their ancestors by default. If this variable is
  108. /// set to <c>false</c> then the appenders found in the
  109. /// ancestors of this logger are not used. However, the children
  110. /// of this logger will inherit its appenders, unless the children
  111. /// have their additivity flag set to <c>false</c> too. See
  112. /// the user manual for more details.
  113. /// </para>
  114. /// </remarks>
  115. virtual public bool Additivity
  116. {
  117. get { return m_additive; }
  118. set { m_additive = value; }
  119. }
  120. /// <summary>
  121. /// Gets the effective level for this logger.
  122. /// </summary>
  123. /// <returns>The nearest level in the logger hierarchy.</returns>
  124. /// <remarks>
  125. /// <para>
  126. /// Starting from this logger, searches the logger hierarchy for a
  127. /// non-null level and returns it. Otherwise, returns the level of the
  128. /// root logger.
  129. /// </para>
  130. /// <para>The Logger class is designed so that this method executes as
  131. /// quickly as possible.</para>
  132. /// </remarks>
  133. virtual public Level EffectiveLevel
  134. {
  135. get
  136. {
  137. for(Logger c = this; c != null; c = c.m_parent)
  138. {
  139. Level level = c.m_level;
  140. // Casting level to Object for performance, otherwise the overloaded operator is called
  141. if ((object)level != null)
  142. {
  143. return level;
  144. }
  145. }
  146. return null; // If reached will cause an NullPointerException.
  147. }
  148. }
  149. /// <summary>
  150. /// Gets or sets the <see cref="Hierarchy"/> where this
  151. /// <c>Logger</c> instance is attached to.
  152. /// </summary>
  153. /// <value>The hierarchy that this logger belongs to.</value>
  154. /// <remarks>
  155. /// <para>
  156. /// This logger must be attached to a single <see cref="Hierarchy"/>.
  157. /// </para>
  158. /// </remarks>
  159. virtual public Hierarchy Hierarchy
  160. {
  161. get { return m_hierarchy; }
  162. set { m_hierarchy = value; }
  163. }
  164. /// <summary>
  165. /// Gets or sets the assigned <see cref="Level"/>, if any, for this Logger.
  166. /// </summary>
  167. /// <value>
  168. /// The <see cref="Level"/> of this logger.
  169. /// </value>
  170. /// <remarks>
  171. /// <para>
  172. /// The assigned <see cref="Level"/> can be <c>null</c>.
  173. /// </para>
  174. /// </remarks>
  175. virtual public Level Level
  176. {
  177. get { return m_level; }
  178. set { m_level = value; }
  179. }
  180. #endregion Public Instance Properties
  181. #region Implementation of IAppenderAttachable
  182. /// <summary>
  183. /// Add <paramref name="newAppender"/> to the list of appenders of this
  184. /// Logger instance.
  185. /// </summary>
  186. /// <param name="newAppender">An appender to add to this logger</param>
  187. /// <remarks>
  188. /// <para>
  189. /// Add <paramref name="newAppender"/> to the list of appenders of this
  190. /// Logger instance.
  191. /// </para>
  192. /// <para>
  193. /// If <paramref name="newAppender"/> is already in the list of
  194. /// appenders, then it won't be added again.
  195. /// </para>
  196. /// </remarks>
  197. virtual public void AddAppender(IAppender newAppender)
  198. {
  199. if (newAppender == null)
  200. {
  201. throw new ArgumentNullException("newAppender");
  202. }
  203. m_appenderLock.AcquireWriterLock();
  204. try
  205. {
  206. if (m_appenderAttachedImpl == null)
  207. {
  208. m_appenderAttachedImpl = new log4net.Util.AppenderAttachedImpl();
  209. }
  210. m_appenderAttachedImpl.AddAppender(newAppender);
  211. }
  212. finally
  213. {
  214. m_appenderLock.ReleaseWriterLock();
  215. }
  216. }
  217. /// <summary>
  218. /// Get the appenders contained in this logger as an
  219. /// <see cref="System.Collections.ICollection"/>.
  220. /// </summary>
  221. /// <returns>A collection of the appenders in this logger</returns>
  222. /// <remarks>
  223. /// <para>
  224. /// Get the appenders contained in this logger as an
  225. /// <see cref="System.Collections.ICollection"/>. If no appenders
  226. /// can be found, then a <see cref="EmptyCollection"/> is returned.
  227. /// </para>
  228. /// </remarks>
  229. virtual public AppenderCollection Appenders
  230. {
  231. get
  232. {
  233. m_appenderLock.AcquireReaderLock();
  234. try
  235. {
  236. if (m_appenderAttachedImpl == null)
  237. {
  238. return AppenderCollection.EmptyCollection;
  239. }
  240. else
  241. {
  242. return m_appenderAttachedImpl.Appenders;
  243. }
  244. }
  245. finally
  246. {
  247. m_appenderLock.ReleaseReaderLock();
  248. }
  249. }
  250. }
  251. /// <summary>
  252. /// Look for the appender named as <c>name</c>
  253. /// </summary>
  254. /// <param name="name">The name of the appender to lookup</param>
  255. /// <returns>The appender with the name specified, or <c>null</c>.</returns>
  256. /// <remarks>
  257. /// <para>
  258. /// Returns the named appender, or null if the appender is not found.
  259. /// </para>
  260. /// </remarks>
  261. virtual public IAppender GetAppender(string name)
  262. {
  263. m_appenderLock.AcquireReaderLock();
  264. try
  265. {
  266. if (m_appenderAttachedImpl == null || name == null)
  267. {
  268. return null;
  269. }
  270. return m_appenderAttachedImpl.GetAppender(name);
  271. }
  272. finally
  273. {
  274. m_appenderLock.ReleaseReaderLock();
  275. }
  276. }
  277. /// <summary>
  278. /// Remove all previously added appenders from this Logger instance.
  279. /// </summary>
  280. /// <remarks>
  281. /// <para>
  282. /// Remove all previously added appenders from this Logger instance.
  283. /// </para>
  284. /// <para>
  285. /// This is useful when re-reading configuration information.
  286. /// </para>
  287. /// </remarks>
  288. virtual public void RemoveAllAppenders()
  289. {
  290. m_appenderLock.AcquireWriterLock();
  291. try
  292. {
  293. if (m_appenderAttachedImpl != null)
  294. {
  295. m_appenderAttachedImpl.RemoveAllAppenders();
  296. m_appenderAttachedImpl = null;
  297. }
  298. }
  299. finally
  300. {
  301. m_appenderLock.ReleaseWriterLock();
  302. }
  303. }
  304. /// <summary>
  305. /// Remove the appender passed as parameter form the list of appenders.
  306. /// </summary>
  307. /// <param name="appender">The appender to remove</param>
  308. /// <returns>The appender removed from the list</returns>
  309. /// <remarks>
  310. /// <para>
  311. /// Remove the appender passed as parameter form the list of appenders.
  312. /// The appender removed is not closed.
  313. /// If you are discarding the appender you must call
  314. /// <see cref="IAppender.Close"/> on the appender removed.
  315. /// </para>
  316. /// </remarks>
  317. virtual public IAppender RemoveAppender(IAppender appender)
  318. {
  319. m_appenderLock.AcquireWriterLock();
  320. try
  321. {
  322. if (appender != null && m_appenderAttachedImpl != null)
  323. {
  324. return m_appenderAttachedImpl.RemoveAppender(appender);
  325. }
  326. }
  327. finally
  328. {
  329. m_appenderLock.ReleaseWriterLock();
  330. }
  331. return null;
  332. }
  333. /// <summary>
  334. /// Remove the appender passed as parameter form the list of appenders.
  335. /// </summary>
  336. /// <param name="name">The name of the appender to remove</param>
  337. /// <returns>The appender removed from the list</returns>
  338. /// <remarks>
  339. /// <para>
  340. /// Remove the named appender passed as parameter form the list of appenders.
  341. /// The appender removed is not closed.
  342. /// If you are discarding the appender you must call
  343. /// <see cref="IAppender.Close"/> on the appender removed.
  344. /// </para>
  345. /// </remarks>
  346. virtual public IAppender RemoveAppender(string name)
  347. {
  348. m_appenderLock.AcquireWriterLock();
  349. try
  350. {
  351. if (name != null && m_appenderAttachedImpl != null)
  352. {
  353. return m_appenderAttachedImpl.RemoveAppender(name);
  354. }
  355. }
  356. finally
  357. {
  358. m_appenderLock.ReleaseWriterLock();
  359. }
  360. return null;
  361. }
  362. #endregion
  363. #region Implementation of ILogger
  364. /// <summary>
  365. /// Gets the logger name.
  366. /// </summary>
  367. /// <value>
  368. /// The name of the logger.
  369. /// </value>
  370. /// <remarks>
  371. /// <para>
  372. /// The name of this logger
  373. /// </para>
  374. /// </remarks>
  375. virtual public string Name
  376. {
  377. get { return m_name; }
  378. }
  379. /// <summary>
  380. /// This generic form is intended to be used by wrappers.
  381. /// </summary>
  382. /// <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
  383. /// the stack boundary into the logging system for this call.</param>
  384. /// <param name="level">The level of the message to be logged.</param>
  385. /// <param name="message">The message object to log.</param>
  386. /// <param name="exception">The exception to log, including its stack trace.</param>
  387. /// <remarks>
  388. /// <para>
  389. /// Generate a logging event for the specified <paramref name="level"/> using
  390. /// the <paramref name="message"/> and <paramref name="exception"/>.
  391. /// </para>
  392. /// <para>
  393. /// This method must not throw any exception to the caller.
  394. /// </para>
  395. /// </remarks>
  396. virtual public void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception)
  397. {
  398. try
  399. {
  400. if (IsEnabledFor(level))
  401. {
  402. ForcedLog((callerStackBoundaryDeclaringType != null) ? callerStackBoundaryDeclaringType : declaringType, level, message, exception);
  403. }
  404. }
  405. catch (Exception ex)
  406. {
  407. log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
  408. }
  409. #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3
  410. catch
  411. {
  412. log4net.Util.LogLog.Error(declaringType, "Exception while logging");
  413. }
  414. #endif
  415. }
  416. /// <summary>
  417. /// This is the most generic printing method that is intended to be used
  418. /// by wrappers.
  419. /// </summary>
  420. /// <param name="logEvent">The event being logged.</param>
  421. /// <remarks>
  422. /// <para>
  423. /// Logs the specified logging event through this logger.
  424. /// </para>
  425. /// <para>
  426. /// This method must not throw any exception to the caller.
  427. /// </para>
  428. /// </remarks>
  429. virtual public void Log(LoggingEvent logEvent)
  430. {
  431. try
  432. {
  433. if (logEvent != null)
  434. {
  435. if (IsEnabledFor(logEvent.Level))
  436. {
  437. ForcedLog(logEvent);
  438. }
  439. }
  440. }
  441. catch (Exception ex)
  442. {
  443. log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
  444. }
  445. #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3
  446. catch
  447. {
  448. log4net.Util.LogLog.Error(declaringType, "Exception while logging");
  449. }
  450. #endif
  451. }
  452. /// <summary>
  453. /// Checks if this logger is enabled for a given <see cref="Level"/> passed as parameter.
  454. /// </summary>
  455. /// <param name="level">The level to check.</param>
  456. /// <returns>
  457. /// <c>true</c> if this logger is enabled for <c>level</c>, otherwise <c>false</c>.
  458. /// </returns>
  459. /// <remarks>
  460. /// <para>
  461. /// Test if this logger is going to log events of the specified <paramref name="level"/>.
  462. /// </para>
  463. /// <para>
  464. /// This method must not throw any exception to the caller.
  465. /// </para>
  466. /// </remarks>
  467. virtual public bool IsEnabledFor(Level level)
  468. {
  469. try
  470. {
  471. if (level != null)
  472. {
  473. if (m_hierarchy.IsDisabled(level))
  474. {
  475. return false;
  476. }
  477. return level >= this.EffectiveLevel;
  478. }
  479. }
  480. catch (Exception ex)
  481. {
  482. log4net.Util.LogLog.Error(declaringType, "Exception while logging", ex);
  483. }
  484. #if !NET_2_0 && !MONO_2_0 && !MONO_3_5 && !MONO_4_0 && !NETSTANDARD1_3
  485. catch
  486. {
  487. log4net.Util.LogLog.Error(declaringType, "Exception while logging");
  488. }
  489. #endif
  490. return false;
  491. }
  492. /// <summary>
  493. /// Gets the <see cref="ILoggerRepository"/> where this
  494. /// <c>Logger</c> instance is attached to.
  495. /// </summary>
  496. /// <value>
  497. /// The <see cref="ILoggerRepository" /> that this logger belongs to.
  498. /// </value>
  499. /// <remarks>
  500. /// <para>
  501. /// Gets the <see cref="ILoggerRepository"/> where this
  502. /// <c>Logger</c> instance is attached to.
  503. /// </para>
  504. /// </remarks>
  505. public ILoggerRepository Repository
  506. {
  507. get { return m_hierarchy; }
  508. }
  509. #endregion Implementation of ILogger
  510. /// <summary>
  511. /// Deliver the <see cref="LoggingEvent"/> to the attached appenders.
  512. /// </summary>
  513. /// <param name="loggingEvent">The event to log.</param>
  514. /// <remarks>
  515. /// <para>
  516. /// Call the appenders in the hierarchy starting at
  517. /// <c>this</c>. If no appenders could be found, emit a
  518. /// warning.
  519. /// </para>
  520. /// <para>
  521. /// This method calls all the appenders inherited from the
  522. /// hierarchy circumventing any evaluation of whether to log or not
  523. /// to log the particular log request.
  524. /// </para>
  525. /// </remarks>
  526. virtual protected void CallAppenders(LoggingEvent loggingEvent)
  527. {
  528. if (loggingEvent == null)
  529. {
  530. throw new ArgumentNullException("loggingEvent");
  531. }
  532. int writes = 0;
  533. for(Logger c=this; c != null; c=c.m_parent)
  534. {
  535. if (c.m_appenderAttachedImpl != null)
  536. {
  537. // Protected against simultaneous call to addAppender, removeAppender,...
  538. c.m_appenderLock.AcquireReaderLock();
  539. try
  540. {
  541. if (c.m_appenderAttachedImpl != null)
  542. {
  543. writes += c.m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent);
  544. }
  545. }
  546. finally
  547. {
  548. c.m_appenderLock.ReleaseReaderLock();
  549. }
  550. }
  551. if (!c.m_additive)
  552. {
  553. break;
  554. }
  555. }
  556. // No appenders in hierarchy, warn user only once.
  557. //
  558. // Note that by including the AppDomain values for the currently running
  559. // thread, it becomes much easier to see which application the warning
  560. // is from, which is especially helpful in a multi-AppDomain environment
  561. // (like IIS with multiple VDIRS). Without this, it can be difficult
  562. // or impossible to determine which .config file is missing appender
  563. // definitions.
  564. //
  565. if (!m_hierarchy.EmittedNoAppenderWarning && writes == 0)
  566. {
  567. m_hierarchy.EmittedNoAppenderWarning = true;
  568. LogLog.Debug(declaringType, "No appenders could be found for logger [" + Name + "] repository [" + Repository.Name + "]");
  569. LogLog.Debug(declaringType, "Please initialize the log4net system properly.");
  570. try
  571. {
  572. LogLog.Debug(declaringType, " Current AppDomain context information: ");
  573. LogLog.Debug(declaringType, " BaseDirectory : " + SystemInfo.ApplicationBaseDirectory);
  574. #if !(NETCF || NETSTANDARD1_3)
  575. LogLog.Debug(declaringType, " FriendlyName : " + AppDomain.CurrentDomain.FriendlyName);
  576. LogLog.Debug(declaringType, " DynamicDirectory: " + AppDomain.CurrentDomain.DynamicDirectory);
  577. #endif
  578. }
  579. catch(System.Security.SecurityException)
  580. {
  581. // Insufficient permissions to display info from the AppDomain
  582. }
  583. }
  584. }
  585. /// <summary>
  586. /// Closes all attached appenders implementing the <see cref="IAppenderAttachable"/> interface.
  587. /// </summary>
  588. /// <remarks>
  589. /// <para>
  590. /// Used to ensure that the appenders are correctly shutdown.
  591. /// </para>
  592. /// </remarks>
  593. virtual public void CloseNestedAppenders()
  594. {
  595. m_appenderLock.AcquireWriterLock();
  596. try
  597. {
  598. if (m_appenderAttachedImpl != null)
  599. {
  600. AppenderCollection appenders = m_appenderAttachedImpl.Appenders;
  601. foreach(IAppender appender in appenders)
  602. {
  603. if (appender is IAppenderAttachable)
  604. {
  605. appender.Close();
  606. }
  607. }
  608. }
  609. }
  610. finally
  611. {
  612. m_appenderLock.ReleaseWriterLock();
  613. }
  614. }
  615. /// <summary>
  616. /// This is the most generic printing method. This generic form is intended to be used by wrappers
  617. /// </summary>
  618. /// <param name="level">The level of the message to be logged.</param>
  619. /// <param name="message">The message object to log.</param>
  620. /// <param name="exception">The exception to log, including its stack trace.</param>
  621. /// <remarks>
  622. /// <para>
  623. /// Generate a logging event for the specified <paramref name="level"/> using
  624. /// the <paramref name="message"/>.
  625. /// </para>
  626. /// </remarks>
  627. virtual public void Log(Level level, object message, Exception exception)
  628. {
  629. if (IsEnabledFor(level))
  630. {
  631. ForcedLog(declaringType, level, message, exception);
  632. }
  633. }
  634. /// <summary>
  635. /// Creates a new logging event and logs the event without further checks.
  636. /// </summary>
  637. /// <param name="callerStackBoundaryDeclaringType">The declaring type of the method that is
  638. /// the stack boundary into the logging system for this call.</param>
  639. /// <param name="level">The level of the message to be logged.</param>
  640. /// <param name="message">The message object to log.</param>
  641. /// <param name="exception">The exception to log, including its stack trace.</param>
  642. /// <remarks>
  643. /// <para>
  644. /// Generates a logging event and delivers it to the attached
  645. /// appenders.
  646. /// </para>
  647. /// </remarks>
  648. virtual protected void ForcedLog(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception)
  649. {
  650. CallAppenders(new LoggingEvent(callerStackBoundaryDeclaringType, this.Hierarchy, this.Name, level, message, exception));
  651. }
  652. /// <summary>
  653. /// Creates a new logging event and logs the event without further checks.
  654. /// </summary>
  655. /// <param name="logEvent">The event being logged.</param>
  656. /// <remarks>
  657. /// <para>
  658. /// Delivers the logging event to the attached appenders.
  659. /// </para>
  660. /// </remarks>
  661. virtual protected void ForcedLog(LoggingEvent logEvent)
  662. {
  663. // The logging event may not have been created by this logger
  664. // the Repository may not be correctly set on the event. This
  665. // is required for the appenders to correctly lookup renderers etc...
  666. logEvent.EnsureRepository(this.Hierarchy);
  667. CallAppenders(logEvent);
  668. }
  669. #region Private Static Fields
  670. /// <summary>
  671. /// The fully qualified type of the Logger class.
  672. /// </summary>
  673. private readonly static Type declaringType = typeof(Logger);
  674. #endregion Private Static Fields
  675. #region Private Instance Fields
  676. /// <summary>
  677. /// The name of this logger.
  678. /// </summary>
  679. private readonly string m_name;
  680. /// <summary>
  681. /// The assigned level of this logger.
  682. /// </summary>
  683. /// <remarks>
  684. /// <para>
  685. /// The <c>level</c> variable need not be
  686. /// assigned a value in which case it is inherited
  687. /// form the hierarchy.
  688. /// </para>
  689. /// </remarks>
  690. private Level m_level;
  691. /// <summary>
  692. /// The parent of this logger.
  693. /// </summary>
  694. /// <remarks>
  695. /// <para>
  696. /// The parent of this logger.
  697. /// All loggers have at least one ancestor which is the root logger.
  698. /// </para>
  699. /// </remarks>
  700. private Logger m_parent;
  701. /// <summary>
  702. /// Loggers need to know what Hierarchy they are in.
  703. /// </summary>
  704. /// <remarks>
  705. /// <para>
  706. /// Loggers need to know what Hierarchy they are in.
  707. /// The hierarchy that this logger is a member of is stored
  708. /// here.
  709. /// </para>
  710. /// </remarks>
  711. private Hierarchy m_hierarchy;
  712. /// <summary>
  713. /// Helper implementation of the <see cref="IAppenderAttachable"/> interface
  714. /// </summary>
  715. private log4net.Util.AppenderAttachedImpl m_appenderAttachedImpl;
  716. /// <summary>
  717. /// Flag indicating if child loggers inherit their parents appenders
  718. /// </summary>
  719. /// <remarks>
  720. /// <para>
  721. /// Additivity is set to true by default, that is children inherit
  722. /// the appenders of their ancestors by default. If this variable is
  723. /// set to <c>false</c> then the appenders found in the
  724. /// ancestors of this logger are not used. However, the children
  725. /// of this logger will inherit its appenders, unless the children
  726. /// have their additivity flag set to <c>false</c> too. See
  727. /// the user manual for more details.
  728. /// </para>
  729. /// </remarks>
  730. private bool m_additive = true;
  731. /// <summary>
  732. /// Lock to protect AppenderAttachedImpl variable m_appenderAttachedImpl
  733. /// </summary>
  734. private readonly ReaderWriterLock m_appenderLock = new ReaderWriterLock();
  735. #endregion
  736. }
  737. }