LogLog.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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. #if !NETSTANDARD1_3
  22. using System.Configuration;
  23. #endif
  24. using System.Diagnostics;
  25. namespace log4net.Util
  26. {
  27. /// <summary>
  28. ///
  29. /// </summary>
  30. /// <param name="source"></param>
  31. /// <param name="e"></param>
  32. public delegate void LogReceivedEventHandler(object source, LogReceivedEventArgs e);
  33. /// <summary>
  34. /// Outputs log statements from within the log4net assembly.
  35. /// </summary>
  36. /// <remarks>
  37. /// <para>
  38. /// Log4net components cannot make log4net logging calls. However, it is
  39. /// sometimes useful for the user to learn about what log4net is
  40. /// doing.
  41. /// </para>
  42. /// <para>
  43. /// All log4net internal debug calls go to the standard output stream
  44. /// whereas internal error messages are sent to the standard error output
  45. /// stream.
  46. /// </para>
  47. /// </remarks>
  48. /// <author>Nicko Cadell</author>
  49. /// <author>Gert Driesen</author>
  50. public sealed class LogLog
  51. {
  52. /// <summary>
  53. /// The event raised when an internal message has been received.
  54. /// </summary>
  55. public static event LogReceivedEventHandler LogReceived;
  56. private readonly Type source;
  57. private readonly DateTime timeStampUtc;
  58. private readonly string prefix;
  59. private readonly string message;
  60. private readonly Exception exception;
  61. /// <summary>
  62. /// The Type that generated the internal message.
  63. /// </summary>
  64. public Type Source
  65. {
  66. get { return source; }
  67. }
  68. /// <summary>
  69. /// The DateTime stamp of when the internal message was received.
  70. /// </summary>
  71. public DateTime TimeStamp
  72. {
  73. get { return timeStampUtc.ToLocalTime(); }
  74. }
  75. /// <summary>
  76. /// The UTC DateTime stamp of when the internal message was received.
  77. /// </summary>
  78. public DateTime TimeStampUtc
  79. {
  80. get { return timeStampUtc; }
  81. }
  82. /// <summary>
  83. /// A string indicating the severity of the internal message.
  84. /// </summary>
  85. /// <remarks>
  86. /// "log4net: ",
  87. /// "log4net:ERROR ",
  88. /// "log4net:WARN "
  89. /// </remarks>
  90. public string Prefix
  91. {
  92. get { return prefix; }
  93. }
  94. /// <summary>
  95. /// The internal log message.
  96. /// </summary>
  97. public string Message
  98. {
  99. get { return message; }
  100. }
  101. /// <summary>
  102. /// The Exception related to the message.
  103. /// </summary>
  104. /// <remarks>
  105. /// Optional. Will be null if no Exception was passed.
  106. /// </remarks>
  107. public Exception Exception
  108. {
  109. get { return exception; }
  110. }
  111. /// <summary>
  112. /// Formats Prefix, Source, and Message in the same format as the value
  113. /// sent to Console.Out and Trace.Write.
  114. /// </summary>
  115. /// <returns></returns>
  116. public override string ToString()
  117. {
  118. return Prefix + Source.Name + ": " + Message;
  119. }
  120. #region Private Instance Constructors
  121. /// <summary>
  122. /// Initializes a new instance of the <see cref="LogLog" /> class.
  123. /// </summary>
  124. /// <param name="source"></param>
  125. /// <param name="prefix"></param>
  126. /// <param name="message"></param>
  127. /// <param name="exception"></param>
  128. public LogLog(Type source, string prefix, string message, Exception exception)
  129. {
  130. timeStampUtc = DateTime.UtcNow;
  131. this.source = source;
  132. this.prefix = prefix;
  133. this.message = message;
  134. this.exception = exception;
  135. }
  136. #endregion Private Instance Constructors
  137. #region Static Constructor
  138. /// <summary>
  139. /// Static constructor that initializes logging by reading
  140. /// settings from the application configuration file.
  141. /// </summary>
  142. /// <remarks>
  143. /// <para>
  144. /// The <c>log4net.Internal.Debug</c> application setting
  145. /// controls internal debugging. This setting should be set
  146. /// to <c>true</c> to enable debugging.
  147. /// </para>
  148. /// <para>
  149. /// The <c>log4net.Internal.Quiet</c> application setting
  150. /// suppresses all internal logging including error messages.
  151. /// This setting should be set to <c>true</c> to enable message
  152. /// suppression.
  153. /// </para>
  154. /// </remarks>
  155. static LogLog()
  156. {
  157. #if !NETCF
  158. try
  159. {
  160. InternalDebugging = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Debug"), false);
  161. QuietMode = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Quiet"), false);
  162. EmitInternalMessages = OptionConverter.ToBoolean(SystemInfo.GetAppSetting("log4net.Internal.Emit"), true);
  163. }
  164. catch(Exception ex)
  165. {
  166. // If an exception is thrown here then it looks like the config file does not
  167. // parse correctly.
  168. //
  169. // We will leave debug OFF and print an Error message
  170. Error(typeof(LogLog), "Exception while reading ConfigurationSettings. Check your .config file is well formed XML.", ex);
  171. }
  172. #endif
  173. }
  174. #endregion Static Constructor
  175. #region Public Static Properties
  176. /// <summary>
  177. /// Gets or sets a value indicating whether log4net internal logging
  178. /// is enabled or disabled.
  179. /// </summary>
  180. /// <value>
  181. /// <c>true</c> if log4net internal logging is enabled, otherwise
  182. /// <c>false</c>.
  183. /// </value>
  184. /// <remarks>
  185. /// <para>
  186. /// When set to <c>true</c>, internal debug level logging will be
  187. /// displayed.
  188. /// </para>
  189. /// <para>
  190. /// This value can be set by setting the application setting
  191. /// <c>log4net.Internal.Debug</c> in the application configuration
  192. /// file.
  193. /// </para>
  194. /// <para>
  195. /// The default value is <c>false</c>, i.e. debugging is
  196. /// disabled.
  197. /// </para>
  198. /// </remarks>
  199. /// <example>
  200. /// <para>
  201. /// The following example enables internal debugging using the
  202. /// application configuration file :
  203. /// </para>
  204. /// <code lang="XML" escaped="true">
  205. /// <configuration>
  206. /// <appSettings>
  207. /// <add key="log4net.Internal.Debug" value="true" />
  208. /// </appSettings>
  209. /// </configuration>
  210. /// </code>
  211. /// </example>
  212. public static bool InternalDebugging
  213. {
  214. get { return s_debugEnabled; }
  215. set { s_debugEnabled = value; }
  216. }
  217. /// <summary>
  218. /// Gets or sets a value indicating whether log4net should generate no output
  219. /// from internal logging, not even for errors.
  220. /// </summary>
  221. /// <value>
  222. /// <c>true</c> if log4net should generate no output at all from internal
  223. /// logging, otherwise <c>false</c>.
  224. /// </value>
  225. /// <remarks>
  226. /// <para>
  227. /// When set to <c>true</c> will cause internal logging at all levels to be
  228. /// suppressed. This means that no warning or error reports will be logged.
  229. /// This option overrides the <see cref="InternalDebugging"/> setting and
  230. /// disables all debug also.
  231. /// </para>
  232. /// <para>This value can be set by setting the application setting
  233. /// <c>log4net.Internal.Quiet</c> in the application configuration file.
  234. /// </para>
  235. /// <para>
  236. /// The default value is <c>false</c>, i.e. internal logging is not
  237. /// disabled.
  238. /// </para>
  239. /// </remarks>
  240. /// <example>
  241. /// The following example disables internal logging using the
  242. /// application configuration file :
  243. /// <code lang="XML" escaped="true">
  244. /// <configuration>
  245. /// <appSettings>
  246. /// <add key="log4net.Internal.Quiet" value="true" />
  247. /// </appSettings>
  248. /// </configuration>
  249. /// </code>
  250. /// </example>
  251. public static bool QuietMode
  252. {
  253. get { return s_quietMode; }
  254. set { s_quietMode = value; }
  255. }
  256. /// <summary>
  257. ///
  258. /// </summary>
  259. public static bool EmitInternalMessages
  260. {
  261. get { return s_emitInternalMessages; }
  262. set { s_emitInternalMessages = value; }
  263. }
  264. #endregion Public Static Properties
  265. #region Public Static Methods
  266. /// <summary>
  267. /// Raises the LogReceived event when an internal messages is received.
  268. /// </summary>
  269. /// <param name="source"></param>
  270. /// <param name="prefix"></param>
  271. /// <param name="message"></param>
  272. /// <param name="exception"></param>
  273. public static void OnLogReceived(Type source, string prefix, string message, Exception exception)
  274. {
  275. if (LogReceived != null)
  276. {
  277. LogReceived(null, new LogReceivedEventArgs(new LogLog(source, prefix, message, exception)));
  278. }
  279. }
  280. /// <summary>
  281. /// Test if LogLog.Debug is enabled for output.
  282. /// </summary>
  283. /// <value>
  284. /// <c>true</c> if Debug is enabled
  285. /// </value>
  286. /// <remarks>
  287. /// <para>
  288. /// Test if LogLog.Debug is enabled for output.
  289. /// </para>
  290. /// </remarks>
  291. public static bool IsDebugEnabled
  292. {
  293. get { return s_debugEnabled && !s_quietMode; }
  294. }
  295. /// <summary>
  296. /// Writes log4net internal debug messages to the
  297. /// standard output stream.
  298. /// </summary>
  299. /// <param name="source"></param>
  300. /// <param name="message">The message to log.</param>
  301. /// <remarks>
  302. /// <para>
  303. /// All internal debug messages are prepended with
  304. /// the string "log4net: ".
  305. /// </para>
  306. /// </remarks>
  307. public static void Debug(Type source, string message)
  308. {
  309. if (IsDebugEnabled)
  310. {
  311. if (EmitInternalMessages)
  312. {
  313. EmitOutLine(PREFIX + message);
  314. }
  315. OnLogReceived(source, PREFIX, message, null);
  316. }
  317. }
  318. /// <summary>
  319. /// Writes log4net internal debug messages to the
  320. /// standard output stream.
  321. /// </summary>
  322. /// <param name="source">The Type that generated this message.</param>
  323. /// <param name="message">The message to log.</param>
  324. /// <param name="exception">An exception to log.</param>
  325. /// <remarks>
  326. /// <para>
  327. /// All internal debug messages are prepended with
  328. /// the string "log4net: ".
  329. /// </para>
  330. /// </remarks>
  331. public static void Debug(Type source, string message, Exception exception)
  332. {
  333. if (IsDebugEnabled)
  334. {
  335. if (EmitInternalMessages)
  336. {
  337. EmitOutLine(PREFIX + message);
  338. if (exception != null)
  339. {
  340. EmitOutLine(exception.ToString());
  341. }
  342. }
  343. OnLogReceived(source, PREFIX, message, exception);
  344. }
  345. }
  346. /// <summary>
  347. /// Test if LogLog.Warn is enabled for output.
  348. /// </summary>
  349. /// <value>
  350. /// <c>true</c> if Warn is enabled
  351. /// </value>
  352. /// <remarks>
  353. /// <para>
  354. /// Test if LogLog.Warn is enabled for output.
  355. /// </para>
  356. /// </remarks>
  357. public static bool IsWarnEnabled
  358. {
  359. get { return !s_quietMode; }
  360. }
  361. /// <summary>
  362. /// Writes log4net internal warning messages to the
  363. /// standard error stream.
  364. /// </summary>
  365. /// <param name="source">The Type that generated this message.</param>
  366. /// <param name="message">The message to log.</param>
  367. /// <remarks>
  368. /// <para>
  369. /// All internal warning messages are prepended with
  370. /// the string "log4net:WARN ".
  371. /// </para>
  372. /// </remarks>
  373. public static void Warn(Type source, string message)
  374. {
  375. if (IsWarnEnabled)
  376. {
  377. if (EmitInternalMessages)
  378. {
  379. EmitErrorLine(WARN_PREFIX + message);
  380. }
  381. OnLogReceived(source, WARN_PREFIX, message, null);
  382. }
  383. }
  384. /// <summary>
  385. /// Writes log4net internal warning messages to the
  386. /// standard error stream.
  387. /// </summary>
  388. /// <param name="source">The Type that generated this message.</param>
  389. /// <param name="message">The message to log.</param>
  390. /// <param name="exception">An exception to log.</param>
  391. /// <remarks>
  392. /// <para>
  393. /// All internal warning messages are prepended with
  394. /// the string "log4net:WARN ".
  395. /// </para>
  396. /// </remarks>
  397. public static void Warn(Type source, string message, Exception exception)
  398. {
  399. if (IsWarnEnabled)
  400. {
  401. if (EmitInternalMessages)
  402. {
  403. EmitErrorLine(WARN_PREFIX + message);
  404. if (exception != null)
  405. {
  406. EmitErrorLine(exception.ToString());
  407. }
  408. }
  409. OnLogReceived(source, WARN_PREFIX, message, exception);
  410. }
  411. }
  412. /// <summary>
  413. /// Test if LogLog.Error is enabled for output.
  414. /// </summary>
  415. /// <value>
  416. /// <c>true</c> if Error is enabled
  417. /// </value>
  418. /// <remarks>
  419. /// <para>
  420. /// Test if LogLog.Error is enabled for output.
  421. /// </para>
  422. /// </remarks>
  423. public static bool IsErrorEnabled
  424. {
  425. get { return !s_quietMode; }
  426. }
  427. /// <summary>
  428. /// Writes log4net internal error messages to the
  429. /// standard error stream.
  430. /// </summary>
  431. /// <param name="source">The Type that generated this message.</param>
  432. /// <param name="message">The message to log.</param>
  433. /// <remarks>
  434. /// <para>
  435. /// All internal error messages are prepended with
  436. /// the string "log4net:ERROR ".
  437. /// </para>
  438. /// </remarks>
  439. public static void Error(Type source, string message)
  440. {
  441. if (IsErrorEnabled)
  442. {
  443. if (EmitInternalMessages)
  444. {
  445. EmitErrorLine(ERR_PREFIX + message);
  446. }
  447. OnLogReceived(source, ERR_PREFIX, message, null);
  448. }
  449. }
  450. /// <summary>
  451. /// Writes log4net internal error messages to the
  452. /// standard error stream.
  453. /// </summary>
  454. /// <param name="source">The Type that generated this message.</param>
  455. /// <param name="message">The message to log.</param>
  456. /// <param name="exception">An exception to log.</param>
  457. /// <remarks>
  458. /// <para>
  459. /// All internal debug messages are prepended with
  460. /// the string "log4net:ERROR ".
  461. /// </para>
  462. /// </remarks>
  463. public static void Error(Type source, string message, Exception exception)
  464. {
  465. if (IsErrorEnabled)
  466. {
  467. if (EmitInternalMessages)
  468. {
  469. EmitErrorLine(ERR_PREFIX + message);
  470. if (exception != null)
  471. {
  472. EmitErrorLine(exception.ToString());
  473. }
  474. }
  475. OnLogReceived(source, ERR_PREFIX, message, exception);
  476. }
  477. }
  478. #endregion Public Static Methods
  479. /// <summary>
  480. /// Writes output to the standard output stream.
  481. /// </summary>
  482. /// <param name="message">The message to log.</param>
  483. /// <remarks>
  484. /// <para>
  485. /// Writes to both Console.Out and System.Diagnostics.Trace.
  486. /// Note that the System.Diagnostics.Trace is not supported
  487. /// on the Compact Framework.
  488. /// </para>
  489. /// <para>
  490. /// If the AppDomain is not configured with a config file then
  491. /// the call to System.Diagnostics.Trace may fail. This is only
  492. /// an issue if you are programmatically creating your own AppDomains.
  493. /// </para>
  494. /// </remarks>
  495. private static void EmitOutLine(string message)
  496. {
  497. try
  498. {
  499. #if NETCF
  500. Console.WriteLine(message);
  501. //System.Diagnostics.Debug.WriteLine(message);
  502. #else
  503. Console.Out.WriteLine(message);
  504. Trace.WriteLine(message);
  505. #endif
  506. }
  507. catch
  508. {
  509. // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller
  510. }
  511. }
  512. /// <summary>
  513. /// Writes output to the standard error stream.
  514. /// </summary>
  515. /// <param name="message">The message to log.</param>
  516. /// <remarks>
  517. /// <para>
  518. /// Writes to both Console.Error and System.Diagnostics.Trace.
  519. /// Note that the System.Diagnostics.Trace is not supported
  520. /// on the Compact Framework.
  521. /// </para>
  522. /// <para>
  523. /// If the AppDomain is not configured with a config file then
  524. /// the call to System.Diagnostics.Trace may fail. This is only
  525. /// an issue if you are programmatically creating your own AppDomains.
  526. /// </para>
  527. /// </remarks>
  528. private static void EmitErrorLine(string message)
  529. {
  530. try
  531. {
  532. #if NETCF
  533. Console.WriteLine(message);
  534. //System.Diagnostics.Debug.WriteLine(message);
  535. #else
  536. Console.Error.WriteLine(message);
  537. Trace.WriteLine(message);
  538. #endif
  539. }
  540. catch
  541. {
  542. // Ignore exception, what else can we do? Not really a good idea to propagate back to the caller
  543. }
  544. }
  545. #region Private Static Fields
  546. /// <summary>
  547. /// Default debug level
  548. /// </summary>
  549. private static bool s_debugEnabled = false;
  550. /// <summary>
  551. /// In quietMode not even errors generate any output.
  552. /// </summary>
  553. private static bool s_quietMode = false;
  554. private static bool s_emitInternalMessages = true;
  555. private const string PREFIX = "log4net: ";
  556. private const string ERR_PREFIX = "log4net:ERROR ";
  557. private const string WARN_PREFIX = "log4net:WARN ";
  558. #endregion Private Static Fields
  559. /// <summary>
  560. /// Subscribes to the LogLog.LogReceived event and stores messages
  561. /// to the supplied IList instance.
  562. /// </summary>
  563. public class LogReceivedAdapter : IDisposable
  564. {
  565. private readonly IList items;
  566. private readonly LogReceivedEventHandler handler;
  567. /// <summary>
  568. ///
  569. /// </summary>
  570. /// <param name="items"></param>
  571. public LogReceivedAdapter(IList items)
  572. {
  573. this.items = items;
  574. handler = new LogReceivedEventHandler(LogLog_LogReceived);
  575. LogReceived += handler;
  576. }
  577. void LogLog_LogReceived(object source, LogReceivedEventArgs e)
  578. {
  579. items.Add(e.LogLog);
  580. }
  581. /// <summary>
  582. ///
  583. /// </summary>
  584. public IList Items
  585. {
  586. get { return items; }
  587. }
  588. /// <summary>
  589. ///
  590. /// </summary>
  591. public void Dispose()
  592. {
  593. LogReceived -= handler;
  594. }
  595. }
  596. }
  597. /// <summary>
  598. ///
  599. /// </summary>
  600. public class LogReceivedEventArgs : EventArgs
  601. {
  602. private readonly LogLog loglog;
  603. /// <summary>
  604. ///
  605. /// </summary>
  606. /// <param name="loglog"></param>
  607. public LogReceivedEventArgs(LogLog loglog)
  608. {
  609. this.loglog = loglog;
  610. }
  611. /// <summary>
  612. ///
  613. /// </summary>
  614. public LogLog LogLog
  615. {
  616. get { return loglog; }
  617. }
  618. }
  619. }