LoggerManager.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  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. #if NETSTANDARD1_3
  21. using System.Runtime.InteropServices;
  22. #else
  23. using System.Configuration;
  24. #endif
  25. using System.Reflection;
  26. using log4net.Util;
  27. using log4net.Repository;
  28. namespace log4net.Core
  29. {
  30. /// <summary>
  31. /// Static manager that controls the creation of repositories
  32. /// </summary>
  33. /// <remarks>
  34. /// <para>
  35. /// Static manager that controls the creation of repositories
  36. /// </para>
  37. /// <para>
  38. /// This class is used by the wrapper managers (e.g. <see cref="log4net.LogManager"/>)
  39. /// to provide access to the <see cref="ILogger"/> objects.
  40. /// </para>
  41. /// <para>
  42. /// This manager also holds the <see cref="IRepositorySelector"/> that is used to
  43. /// lookup and create repositories. The selector can be set either programmatically using
  44. /// the <see cref="RepositorySelector"/> property, or by setting the <c>log4net.RepositorySelector</c>
  45. /// AppSetting in the applications config file to the fully qualified type name of the
  46. /// selector to use.
  47. /// </para>
  48. /// </remarks>
  49. /// <author>Nicko Cadell</author>
  50. /// <author>Gert Driesen</author>
  51. public sealed class LoggerManager
  52. {
  53. #region Private Instance Constructors
  54. /// <summary>
  55. /// Private constructor to prevent instances. Only static methods should be used.
  56. /// </summary>
  57. /// <remarks>
  58. /// <para>
  59. /// Private constructor to prevent instances. Only static methods should be used.
  60. /// </para>
  61. /// </remarks>
  62. private LoggerManager()
  63. {
  64. }
  65. #endregion Private Instance Constructors
  66. #region Static Constructor
  67. /// <summary>
  68. /// Hook the shutdown event
  69. /// </summary>
  70. /// <remarks>
  71. /// <para>
  72. /// On the full .NET runtime, the static constructor hooks up the
  73. /// <c>AppDomain.ProcessExit</c> and <c>AppDomain.DomainUnload</c>> events.
  74. /// These are used to shutdown the log4net system as the application exits.
  75. /// </para>
  76. /// </remarks>
  77. static LoggerManager()
  78. {
  79. try
  80. {
  81. // Register the AppDomain events, note we have to do this with a
  82. // method call rather than directly here because the AppDomain
  83. // makes a LinkDemand which throws the exception during the JIT phase.
  84. RegisterAppDomainEvents();
  85. }
  86. catch(System.Security.SecurityException)
  87. {
  88. LogLog.Debug(declaringType, "Security Exception (ControlAppDomain LinkDemand) while trying "+
  89. "to register Shutdown handler with the AppDomain. LoggerManager.Shutdown() "+
  90. "will not be called automatically when the AppDomain exits. It must be called "+
  91. "programmatically.");
  92. }
  93. // Dump out our assembly version into the log if debug is enabled
  94. LogLog.Debug(declaringType, GetVersionInfo());
  95. // Set the default repository selector
  96. #if NETCF
  97. s_repositorySelector = new CompactRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy));
  98. return;
  99. #elif !NETSTANDARD1_3
  100. // Look for the RepositorySelector type specified in the AppSettings 'log4net.RepositorySelector'
  101. string appRepositorySelectorTypeName = SystemInfo.GetAppSetting("log4net.RepositorySelector");
  102. if (appRepositorySelectorTypeName != null && appRepositorySelectorTypeName.Length > 0)
  103. {
  104. // Resolve the config string into a Type
  105. Type appRepositorySelectorType = null;
  106. try
  107. {
  108. appRepositorySelectorType = SystemInfo.GetTypeFromString(appRepositorySelectorTypeName, false, true);
  109. }
  110. catch(Exception ex)
  111. {
  112. LogLog.Error(declaringType, "Exception while resolving RepositorySelector Type ["+appRepositorySelectorTypeName+"]", ex);
  113. }
  114. if (appRepositorySelectorType != null)
  115. {
  116. // Create an instance of the RepositorySelectorType
  117. object appRepositorySelectorObj = null;
  118. try
  119. {
  120. appRepositorySelectorObj = Activator.CreateInstance(appRepositorySelectorType);
  121. }
  122. catch(Exception ex)
  123. {
  124. LogLog.Error(declaringType, "Exception while creating RepositorySelector ["+appRepositorySelectorType.FullName+"]", ex);
  125. }
  126. if (appRepositorySelectorObj != null && appRepositorySelectorObj is IRepositorySelector)
  127. {
  128. s_repositorySelector = (IRepositorySelector)appRepositorySelectorObj;
  129. }
  130. else
  131. {
  132. LogLog.Error(declaringType, "RepositorySelector Type ["+appRepositorySelectorType.FullName+"] is not an IRepositorySelector");
  133. }
  134. }
  135. }
  136. #endif
  137. // Create the DefaultRepositorySelector if not configured above
  138. if (s_repositorySelector == null)
  139. {
  140. s_repositorySelector = new DefaultRepositorySelector(typeof(log4net.Repository.Hierarchy.Hierarchy));
  141. }
  142. }
  143. /// <summary>
  144. /// Register for ProcessExit and DomainUnload events on the AppDomain
  145. /// </summary>
  146. /// <remarks>
  147. /// <para>
  148. /// This needs to be in a separate method because the events make
  149. /// a LinkDemand for the ControlAppDomain SecurityPermission. Because
  150. /// this is a LinkDemand it is demanded at JIT time. Therefore we cannot
  151. /// catch the exception in the method itself, we have to catch it in the
  152. /// caller.
  153. /// </para>
  154. /// </remarks>
  155. private static void RegisterAppDomainEvents()
  156. {
  157. #if !(NETCF || NETSTANDARD1_3)
  158. // ProcessExit seems to be fired if we are part of the default domain
  159. AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
  160. // Otherwise DomainUnload is fired
  161. AppDomain.CurrentDomain.DomainUnload += new EventHandler(OnDomainUnload);
  162. #endif
  163. }
  164. #endregion Static Constructor
  165. #region Public Static Methods
  166. /// <summary>
  167. /// Return the default <see cref="ILoggerRepository"/> instance.
  168. /// </summary>
  169. /// <param name="repository">the repository to lookup in</param>
  170. /// <returns>Return the default <see cref="ILoggerRepository"/> instance</returns>
  171. /// <remarks>
  172. /// <para>
  173. /// Gets the <see cref="ILoggerRepository"/> for the repository specified
  174. /// by the <paramref name="repository"/> argument.
  175. /// </para>
  176. /// </remarks>
  177. [Obsolete("Use GetRepository instead of GetLoggerRepository")]
  178. public static ILoggerRepository GetLoggerRepository(string repository)
  179. {
  180. return GetRepository(repository);
  181. }
  182. /// <summary>
  183. /// Returns the default <see cref="ILoggerRepository"/> instance.
  184. /// </summary>
  185. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  186. /// <returns>The default <see cref="ILoggerRepository"/> instance.</returns>
  187. [Obsolete("Use GetRepository instead of GetLoggerRepository")]
  188. public static ILoggerRepository GetLoggerRepository(Assembly repositoryAssembly)
  189. {
  190. return GetRepository(repositoryAssembly);
  191. }
  192. /// <summary>
  193. /// Return the default <see cref="ILoggerRepository"/> instance.
  194. /// </summary>
  195. /// <param name="repository">the repository to lookup in</param>
  196. /// <returns>Return the default <see cref="ILoggerRepository"/> instance</returns>
  197. /// <remarks>
  198. /// <para>
  199. /// Gets the <see cref="ILoggerRepository"/> for the repository specified
  200. /// by the <paramref name="repository"/> argument.
  201. /// </para>
  202. /// </remarks>
  203. public static ILoggerRepository GetRepository(string repository)
  204. {
  205. if (repository == null)
  206. {
  207. throw new ArgumentNullException("repository");
  208. }
  209. return RepositorySelector.GetRepository(repository);
  210. }
  211. /// <summary>
  212. /// Returns the default <see cref="ILoggerRepository"/> instance.
  213. /// </summary>
  214. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  215. /// <returns>The default <see cref="ILoggerRepository"/> instance.</returns>
  216. /// <remarks>
  217. /// <para>
  218. /// Returns the default <see cref="ILoggerRepository"/> instance.
  219. /// </para>
  220. /// </remarks>
  221. public static ILoggerRepository GetRepository(Assembly repositoryAssembly)
  222. {
  223. if (repositoryAssembly == null)
  224. {
  225. throw new ArgumentNullException("repositoryAssembly");
  226. }
  227. return RepositorySelector.GetRepository(repositoryAssembly);
  228. }
  229. /// <summary>
  230. /// Returns the named logger if it exists.
  231. /// </summary>
  232. /// <param name="repository">The repository to lookup in.</param>
  233. /// <param name="name">The fully qualified logger name to look for.</param>
  234. /// <returns>
  235. /// The logger found, or <c>null</c> if the named logger does not exist in the
  236. /// specified repository.
  237. /// </returns>
  238. /// <remarks>
  239. /// <para>
  240. /// If the named logger exists (in the specified repository) then it
  241. /// returns a reference to the logger, otherwise it returns
  242. /// <c>null</c>.
  243. /// </para>
  244. /// </remarks>
  245. public static ILogger Exists(string repository, string name)
  246. {
  247. if (repository == null)
  248. {
  249. throw new ArgumentNullException("repository");
  250. }
  251. if (name == null)
  252. {
  253. throw new ArgumentNullException("name");
  254. }
  255. return RepositorySelector.GetRepository(repository).Exists(name);
  256. }
  257. /// <summary>
  258. /// Returns the named logger if it exists.
  259. /// </summary>
  260. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  261. /// <param name="name">The fully qualified logger name to look for.</param>
  262. /// <returns>
  263. /// The logger found, or <c>null</c> if the named logger does not exist in the
  264. /// specified assembly's repository.
  265. /// </returns>
  266. /// <remarks>
  267. /// <para>
  268. /// If the named logger exists (in the specified assembly's repository) then it
  269. /// returns a reference to the logger, otherwise it returns
  270. /// <c>null</c>.
  271. /// </para>
  272. /// </remarks>
  273. public static ILogger Exists(Assembly repositoryAssembly, string name)
  274. {
  275. if (repositoryAssembly == null)
  276. {
  277. throw new ArgumentNullException("repositoryAssembly");
  278. }
  279. if (name == null)
  280. {
  281. throw new ArgumentNullException("name");
  282. }
  283. return RepositorySelector.GetRepository(repositoryAssembly).Exists(name);
  284. }
  285. /// <summary>
  286. /// Returns all the currently defined loggers in the specified repository.
  287. /// </summary>
  288. /// <param name="repository">The repository to lookup in.</param>
  289. /// <returns>All the defined loggers.</returns>
  290. /// <remarks>
  291. /// <para>
  292. /// The root logger is <b>not</b> included in the returned array.
  293. /// </para>
  294. /// </remarks>
  295. public static ILogger[] GetCurrentLoggers(string repository)
  296. {
  297. if (repository == null)
  298. {
  299. throw new ArgumentNullException("repository");
  300. }
  301. return RepositorySelector.GetRepository(repository).GetCurrentLoggers();
  302. }
  303. /// <summary>
  304. /// Returns all the currently defined loggers in the specified assembly's repository.
  305. /// </summary>
  306. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  307. /// <returns>All the defined loggers.</returns>
  308. /// <remarks>
  309. /// <para>
  310. /// The root logger is <b>not</b> included in the returned array.
  311. /// </para>
  312. /// </remarks>
  313. public static ILogger[] GetCurrentLoggers(Assembly repositoryAssembly)
  314. {
  315. if (repositoryAssembly == null)
  316. {
  317. throw new ArgumentNullException("repositoryAssembly");
  318. }
  319. return RepositorySelector.GetRepository(repositoryAssembly).GetCurrentLoggers();
  320. }
  321. /// <summary>
  322. /// Retrieves or creates a named logger.
  323. /// </summary>
  324. /// <param name="repository">The repository to lookup in.</param>
  325. /// <param name="name">The name of the logger to retrieve.</param>
  326. /// <returns>The logger with the name specified.</returns>
  327. /// <remarks>
  328. /// <para>
  329. /// Retrieves a logger named as the <paramref name="name"/>
  330. /// parameter. If the named logger already exists, then the
  331. /// existing instance will be returned. Otherwise, a new instance is
  332. /// created.
  333. /// </para>
  334. /// <para>
  335. /// By default, loggers do not have a set level but inherit
  336. /// it from the hierarchy. This is one of the central features of
  337. /// log4net.
  338. /// </para>
  339. /// </remarks>
  340. public static ILogger GetLogger(string repository, string name)
  341. {
  342. if (repository == null)
  343. {
  344. throw new ArgumentNullException("repository");
  345. }
  346. if (name == null)
  347. {
  348. throw new ArgumentNullException("name");
  349. }
  350. return RepositorySelector.GetRepository(repository).GetLogger(name);
  351. }
  352. /// <summary>
  353. /// Retrieves or creates a named logger.
  354. /// </summary>
  355. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  356. /// <param name="name">The name of the logger to retrieve.</param>
  357. /// <returns>The logger with the name specified.</returns>
  358. /// <remarks>
  359. /// <para>
  360. /// Retrieves a logger named as the <paramref name="name"/>
  361. /// parameter. If the named logger already exists, then the
  362. /// existing instance will be returned. Otherwise, a new instance is
  363. /// created.
  364. /// </para>
  365. /// <para>
  366. /// By default, loggers do not have a set level but inherit
  367. /// it from the hierarchy. This is one of the central features of
  368. /// log4net.
  369. /// </para>
  370. /// </remarks>
  371. public static ILogger GetLogger(Assembly repositoryAssembly, string name)
  372. {
  373. if (repositoryAssembly == null)
  374. {
  375. throw new ArgumentNullException("repositoryAssembly");
  376. }
  377. if (name == null)
  378. {
  379. throw new ArgumentNullException("name");
  380. }
  381. return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(name);
  382. }
  383. /// <summary>
  384. /// Shorthand for <see cref="M:LogManager.GetLogger(string)"/>.
  385. /// </summary>
  386. /// <param name="repository">The repository to lookup in.</param>
  387. /// <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
  388. /// <returns>The logger with the name specified.</returns>
  389. /// <remarks>
  390. /// <para>
  391. /// Gets the logger for the fully qualified name of the type specified.
  392. /// </para>
  393. /// </remarks>
  394. public static ILogger GetLogger(string repository, Type type)
  395. {
  396. if (repository == null)
  397. {
  398. throw new ArgumentNullException("repository");
  399. }
  400. if (type == null)
  401. {
  402. throw new ArgumentNullException("type");
  403. }
  404. return RepositorySelector.GetRepository(repository).GetLogger(type.FullName);
  405. }
  406. /// <summary>
  407. /// Shorthand for <see cref="M:LogManager.GetLogger(string)"/>.
  408. /// </summary>
  409. /// <param name="repositoryAssembly">the assembly to use to lookup the repository</param>
  410. /// <param name="type">The <paramref name="type"/> of which the fullname will be used as the name of the logger to retrieve.</param>
  411. /// <returns>The logger with the name specified.</returns>
  412. /// <remarks>
  413. /// <para>
  414. /// Gets the logger for the fully qualified name of the type specified.
  415. /// </para>
  416. /// </remarks>
  417. public static ILogger GetLogger(Assembly repositoryAssembly, Type type)
  418. {
  419. if (repositoryAssembly == null)
  420. {
  421. throw new ArgumentNullException("repositoryAssembly");
  422. }
  423. if (type == null)
  424. {
  425. throw new ArgumentNullException("type");
  426. }
  427. return RepositorySelector.GetRepository(repositoryAssembly).GetLogger(type.FullName);
  428. }
  429. /// <summary>
  430. /// Shuts down the log4net system.
  431. /// </summary>
  432. /// <remarks>
  433. /// <para>
  434. /// Calling this method will <b>safely</b> close and remove all
  435. /// appenders in all the loggers including root contained in all the
  436. /// default repositories.
  437. /// </para>
  438. /// <para>
  439. /// Some appenders need to be closed before the application exists.
  440. /// Otherwise, pending logging events might be lost.
  441. /// </para>
  442. /// <para>
  443. /// The <c>shutdown</c> method is careful to close nested
  444. /// appenders before closing regular appenders. This is allows
  445. /// configurations where a regular appender is attached to a logger
  446. /// and again to a nested appender.
  447. /// </para>
  448. /// </remarks>
  449. public static void Shutdown()
  450. {
  451. foreach(ILoggerRepository repository in GetAllRepositories())
  452. {
  453. repository.Shutdown();
  454. }
  455. }
  456. /// <summary>
  457. /// Shuts down the repository for the repository specified.
  458. /// </summary>
  459. /// <param name="repository">The repository to shutdown.</param>
  460. /// <remarks>
  461. /// <para>
  462. /// Calling this method will <b>safely</b> close and remove all
  463. /// appenders in all the loggers including root contained in the
  464. /// repository for the <paramref name="repository"/> specified.
  465. /// </para>
  466. /// <para>
  467. /// Some appenders need to be closed before the application exists.
  468. /// Otherwise, pending logging events might be lost.
  469. /// </para>
  470. /// <para>
  471. /// The <c>shutdown</c> method is careful to close nested
  472. /// appenders before closing regular appenders. This is allows
  473. /// configurations where a regular appender is attached to a logger
  474. /// and again to a nested appender.
  475. /// </para>
  476. /// </remarks>
  477. public static void ShutdownRepository(string repository)
  478. {
  479. if (repository == null)
  480. {
  481. throw new ArgumentNullException("repository");
  482. }
  483. RepositorySelector.GetRepository(repository).Shutdown();
  484. }
  485. /// <summary>
  486. /// Shuts down the repository for the repository specified.
  487. /// </summary>
  488. /// <param name="repositoryAssembly">The assembly to use to lookup the repository.</param>
  489. /// <remarks>
  490. /// <para>
  491. /// Calling this method will <b>safely</b> close and remove all
  492. /// appenders in all the loggers including root contained in the
  493. /// repository for the repository. The repository is looked up using
  494. /// the <paramref name="repositoryAssembly"/> specified.
  495. /// </para>
  496. /// <para>
  497. /// Some appenders need to be closed before the application exists.
  498. /// Otherwise, pending logging events might be lost.
  499. /// </para>
  500. /// <para>
  501. /// The <c>shutdown</c> method is careful to close nested
  502. /// appenders before closing regular appenders. This is allows
  503. /// configurations where a regular appender is attached to a logger
  504. /// and again to a nested appender.
  505. /// </para>
  506. /// </remarks>
  507. public static void ShutdownRepository(Assembly repositoryAssembly)
  508. {
  509. if (repositoryAssembly == null)
  510. {
  511. throw new ArgumentNullException("repositoryAssembly");
  512. }
  513. RepositorySelector.GetRepository(repositoryAssembly).Shutdown();
  514. }
  515. /// <summary>
  516. /// Resets all values contained in this repository instance to their defaults.
  517. /// </summary>
  518. /// <param name="repository">The repository to reset.</param>
  519. /// <remarks>
  520. /// <para>
  521. /// Resets all values contained in the repository instance to their
  522. /// defaults. This removes all appenders from all loggers, sets
  523. /// the level of all non-root loggers to <c>null</c>,
  524. /// sets their additivity flag to <c>true</c> and sets the level
  525. /// of the root logger to <see cref="Level.Debug"/>. Moreover,
  526. /// message disabling is set its default "off" value.
  527. /// </para>
  528. /// </remarks>
  529. public static void ResetConfiguration(string repository)
  530. {
  531. if (repository == null)
  532. {
  533. throw new ArgumentNullException("repository");
  534. }
  535. RepositorySelector.GetRepository(repository).ResetConfiguration();
  536. }
  537. /// <summary>
  538. /// Resets all values contained in this repository instance to their defaults.
  539. /// </summary>
  540. /// <param name="repositoryAssembly">The assembly to use to lookup the repository to reset.</param>
  541. /// <remarks>
  542. /// <para>
  543. /// Resets all values contained in the repository instance to their
  544. /// defaults. This removes all appenders from all loggers, sets
  545. /// the level of all non-root loggers to <c>null</c>,
  546. /// sets their additivity flag to <c>true</c> and sets the level
  547. /// of the root logger to <see cref="Level.Debug"/>. Moreover,
  548. /// message disabling is set its default "off" value.
  549. /// </para>
  550. /// </remarks>
  551. public static void ResetConfiguration(Assembly repositoryAssembly)
  552. {
  553. if (repositoryAssembly == null)
  554. {
  555. throw new ArgumentNullException("repositoryAssembly");
  556. }
  557. RepositorySelector.GetRepository(repositoryAssembly).ResetConfiguration();
  558. }
  559. /// <summary>
  560. /// Creates a repository with the specified name.
  561. /// </summary>
  562. /// <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
  563. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  564. /// <remarks>
  565. /// <para>
  566. /// <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
  567. /// </para>
  568. /// <para>
  569. /// Creates the default type of <see cref="ILoggerRepository"/> which is a
  570. /// <see cref="log4net.Repository.Hierarchy.Hierarchy"/> object.
  571. /// </para>
  572. /// <para>
  573. /// The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
  574. /// An <see cref="Exception"/> will be thrown if the repository already exists.
  575. /// </para>
  576. /// </remarks>
  577. /// <exception cref="LogException">The specified repository already exists.</exception>
  578. [Obsolete("Use CreateRepository instead of CreateDomain")]
  579. public static ILoggerRepository CreateDomain(string repository)
  580. {
  581. return CreateRepository(repository);
  582. }
  583. /// <summary>
  584. /// Creates a repository with the specified name.
  585. /// </summary>
  586. /// <param name="repository">The name of the repository, this must be unique amongst repositories.</param>
  587. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  588. /// <remarks>
  589. /// <para>
  590. /// Creates the default type of <see cref="ILoggerRepository"/> which is a
  591. /// <see cref="log4net.Repository.Hierarchy.Hierarchy"/> object.
  592. /// </para>
  593. /// <para>
  594. /// The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
  595. /// An <see cref="Exception"/> will be thrown if the repository already exists.
  596. /// </para>
  597. /// </remarks>
  598. /// <exception cref="LogException">The specified repository already exists.</exception>
  599. public static ILoggerRepository CreateRepository(string repository)
  600. {
  601. if (repository == null)
  602. {
  603. throw new ArgumentNullException("repository");
  604. }
  605. return RepositorySelector.CreateRepository(repository, null);
  606. }
  607. /// <summary>
  608. /// Creates a repository with the specified name and repository type.
  609. /// </summary>
  610. /// <param name="repository">The name of the repository, this must be unique to the repository.</param>
  611. /// <param name="repositoryType">A <see cref="Type"/> that implements <see cref="ILoggerRepository"/>
  612. /// and has a no arg constructor. An instance of this type will be created to act
  613. /// as the <see cref="ILoggerRepository"/> for the repository specified.</param>
  614. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  615. /// <remarks>
  616. /// <para>
  617. /// <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
  618. /// </para>
  619. /// <para>
  620. /// The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
  621. /// An Exception will be thrown if the repository already exists.
  622. /// </para>
  623. /// </remarks>
  624. /// <exception cref="LogException">The specified repository already exists.</exception>
  625. [Obsolete("Use CreateRepository instead of CreateDomain")]
  626. public static ILoggerRepository CreateDomain(string repository, Type repositoryType)
  627. {
  628. return CreateRepository(repository, repositoryType);
  629. }
  630. /// <summary>
  631. /// Creates a repository with the specified name and repository type.
  632. /// </summary>
  633. /// <param name="repository">The name of the repository, this must be unique to the repository.</param>
  634. /// <param name="repositoryType">A <see cref="Type"/> that implements <see cref="ILoggerRepository"/>
  635. /// and has a no arg constructor. An instance of this type will be created to act
  636. /// as the <see cref="ILoggerRepository"/> for the repository specified.</param>
  637. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  638. /// <remarks>
  639. /// <para>
  640. /// The <paramref name="repository"/> name must be unique. Repositories cannot be redefined.
  641. /// An Exception will be thrown if the repository already exists.
  642. /// </para>
  643. /// </remarks>
  644. /// <exception cref="LogException">The specified repository already exists.</exception>
  645. public static ILoggerRepository CreateRepository(string repository, Type repositoryType)
  646. {
  647. if (repository == null)
  648. {
  649. throw new ArgumentNullException("repository");
  650. }
  651. if (repositoryType == null)
  652. {
  653. throw new ArgumentNullException("repositoryType");
  654. }
  655. return RepositorySelector.CreateRepository(repository, repositoryType);
  656. }
  657. /// <summary>
  658. /// Creates a repository for the specified assembly and repository type.
  659. /// </summary>
  660. /// <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
  661. /// <param name="repositoryType">A <see cref="Type"/> that implements <see cref="ILoggerRepository"/>
  662. /// and has a no arg constructor. An instance of this type will be created to act
  663. /// as the <see cref="ILoggerRepository"/> for the repository specified.</param>
  664. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  665. /// <remarks>
  666. /// <para>
  667. /// <b>CreateDomain is obsolete. Use CreateRepository instead of CreateDomain.</b>
  668. /// </para>
  669. /// <para>
  670. /// The <see cref="ILoggerRepository"/> created will be associated with the repository
  671. /// specified such that a call to <see cref="M:GetRepository(Assembly)"/> with the
  672. /// same assembly specified will return the same repository instance.
  673. /// </para>
  674. /// </remarks>
  675. [Obsolete("Use CreateRepository instead of CreateDomain")]
  676. public static ILoggerRepository CreateDomain(Assembly repositoryAssembly, Type repositoryType)
  677. {
  678. return CreateRepository(repositoryAssembly, repositoryType);
  679. }
  680. /// <summary>
  681. /// Creates a repository for the specified assembly and repository type.
  682. /// </summary>
  683. /// <param name="repositoryAssembly">The assembly to use to get the name of the repository.</param>
  684. /// <param name="repositoryType">A <see cref="Type"/> that implements <see cref="ILoggerRepository"/>
  685. /// and has a no arg constructor. An instance of this type will be created to act
  686. /// as the <see cref="ILoggerRepository"/> for the repository specified.</param>
  687. /// <returns>The <see cref="ILoggerRepository"/> created for the repository.</returns>
  688. /// <remarks>
  689. /// <para>
  690. /// The <see cref="ILoggerRepository"/> created will be associated with the repository
  691. /// specified such that a call to <see cref="M:GetRepository(Assembly)"/> with the
  692. /// same assembly specified will return the same repository instance.
  693. /// </para>
  694. /// </remarks>
  695. public static ILoggerRepository CreateRepository(Assembly repositoryAssembly, Type repositoryType)
  696. {
  697. if (repositoryAssembly == null)
  698. {
  699. throw new ArgumentNullException("repositoryAssembly");
  700. }
  701. if (repositoryType == null)
  702. {
  703. throw new ArgumentNullException("repositoryType");
  704. }
  705. return RepositorySelector.CreateRepository(repositoryAssembly, repositoryType);
  706. }
  707. /// <summary>
  708. /// Gets an array of all currently defined repositories.
  709. /// </summary>
  710. /// <returns>An array of all the known <see cref="ILoggerRepository"/> objects.</returns>
  711. /// <remarks>
  712. /// <para>
  713. /// Gets an array of all currently defined repositories.
  714. /// </para>
  715. /// </remarks>
  716. public static ILoggerRepository[] GetAllRepositories()
  717. {
  718. return RepositorySelector.GetAllRepositories();
  719. }
  720. /// <summary>
  721. /// Gets or sets the repository selector used by the <see cref="LogManager" />.
  722. /// </summary>
  723. /// <value>
  724. /// The repository selector used by the <see cref="LogManager" />.
  725. /// </value>
  726. /// <remarks>
  727. /// <para>
  728. /// The repository selector (<see cref="IRepositorySelector"/>) is used by
  729. /// the <see cref="LogManager"/> to create and select repositories
  730. /// (<see cref="ILoggerRepository"/>).
  731. /// </para>
  732. /// <para>
  733. /// The caller to <see cref="LogManager"/> supplies either a string name
  734. /// or an assembly (if not supplied the assembly is inferred using
  735. /// <see cref="M:Assembly.GetCallingAssembly()"/>).
  736. /// </para>
  737. /// <para>
  738. /// This context is used by the selector to lookup a specific repository.
  739. /// </para>
  740. /// <para>
  741. /// For the full .NET Framework, the default repository is <c>DefaultRepositorySelector</c>;
  742. /// for the .NET Compact Framework <c>CompactRepositorySelector</c> is the default
  743. /// repository.
  744. /// </para>
  745. /// </remarks>
  746. public static IRepositorySelector RepositorySelector
  747. {
  748. get { return s_repositorySelector; }
  749. set { s_repositorySelector = value; }
  750. }
  751. #endregion Public Static Methods
  752. #region Private Static Methods
  753. /// <summary>
  754. /// Internal method to get pertinent version info.
  755. /// </summary>
  756. /// <returns>A string of version info.</returns>
  757. private static string GetVersionInfo()
  758. {
  759. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  760. #if NETSTANDARD1_3
  761. Assembly myAssembly = typeof(LoggerManager).GetTypeInfo().Assembly;
  762. sb.Append($"log4net assembly [{myAssembly.FullName}]. ");
  763. //sb.Append($"Loaded from [{myAssembly.Location}]. "); // TODO Assembly.Location available in netstandard1.5
  764. sb.Append($"(.NET Framework [{RuntimeInformation.FrameworkDescription}] on {RuntimeInformation.OSDescription}");
  765. #else
  766. Assembly myAssembly = Assembly.GetExecutingAssembly();
  767. sb.Append("log4net assembly [").Append(myAssembly.FullName).Append("]. ");
  768. sb.Append("Loaded from [").Append(SystemInfo.AssemblyLocationInfo(myAssembly)).Append("]. ");
  769. sb.Append("(.NET Runtime [").Append(Environment.Version.ToString()).Append("]");
  770. #if (!SSCLI)
  771. sb.Append(" on ").Append(Environment.OSVersion.ToString());
  772. #endif
  773. #endif // NETSTANDARD1_3
  774. sb.Append(")");
  775. return sb.ToString();
  776. }
  777. #if (!NETCF)
  778. /// <summary>
  779. /// Called when the <see cref="AppDomain.DomainUnload"/> event fires
  780. /// </summary>
  781. /// <param name="sender">the <see cref="AppDomain"/> that is exiting</param>
  782. /// <param name="e">null</param>
  783. /// <remarks>
  784. /// <para>
  785. /// Called when the <see cref="AppDomain.DomainUnload"/> event fires.
  786. /// </para>
  787. /// <para>
  788. /// When the event is triggered the log4net system is <see cref="M:Shutdown()"/>.
  789. /// </para>
  790. /// </remarks>
  791. private static void OnDomainUnload(object sender, EventArgs e)
  792. {
  793. Shutdown();
  794. }
  795. /// <summary>
  796. /// Called when the <see cref="AppDomain.ProcessExit"/> event fires
  797. /// </summary>
  798. /// <param name="sender">the <see cref="AppDomain"/> that is exiting</param>
  799. /// <param name="e">null</param>
  800. /// <remarks>
  801. /// <para>
  802. /// Called when the <see cref="AppDomain.ProcessExit"/> event fires.
  803. /// </para>
  804. /// <para>
  805. /// When the event is triggered the log4net system is <see cref="M:Shutdown()"/>.
  806. /// </para>
  807. /// </remarks>
  808. private static void OnProcessExit(object sender, EventArgs e)
  809. {
  810. Shutdown();
  811. }
  812. #endif
  813. #endregion Private Static Methods
  814. #region Private Static Fields
  815. /// <summary>
  816. /// The fully qualified type of the LoggerManager class.
  817. /// </summary>
  818. /// <remarks>
  819. /// Used by the internal logger to record the Type of the
  820. /// log message.
  821. /// </remarks>
  822. private readonly static Type declaringType = typeof(LoggerManager);
  823. /// <summary>
  824. /// Initialize the default repository selector
  825. /// </summary>
  826. private static IRepositorySelector s_repositorySelector;
  827. #endregion Private Static Fields
  828. }
  829. }