PatternLayout.cs 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  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 System.IO;
  22. #if NETSTANDARD1_3
  23. using System.Reflection;
  24. #endif
  25. using log4net.Core;
  26. using log4net.Layout.Pattern;
  27. using log4net.Util;
  28. using log4net.Util.PatternStringConverters;
  29. using AppDomainPatternConverter=log4net.Layout.Pattern.AppDomainPatternConverter;
  30. using DatePatternConverter=log4net.Layout.Pattern.DatePatternConverter;
  31. using IdentityPatternConverter=log4net.Layout.Pattern.IdentityPatternConverter;
  32. using PropertyPatternConverter=log4net.Layout.Pattern.PropertyPatternConverter;
  33. using UserNamePatternConverter=log4net.Layout.Pattern.UserNamePatternConverter;
  34. using UtcDatePatternConverter=log4net.Layout.Pattern.UtcDatePatternConverter;
  35. namespace log4net.Layout
  36. {
  37. /// <summary>
  38. /// A flexible layout configurable with pattern string.
  39. /// </summary>
  40. /// <remarks>
  41. /// <para>
  42. /// The goal of this class is to <see cref="M:PatternLayout.Format(TextWriter,LoggingEvent)"/> a
  43. /// <see cref="LoggingEvent"/> as a string. The results
  44. /// depend on the <i>conversion pattern</i>.
  45. /// </para>
  46. /// <para>
  47. /// The conversion pattern is closely related to the conversion
  48. /// pattern of the printf function in C. A conversion pattern is
  49. /// composed of literal text and format control expressions called
  50. /// <i>conversion specifiers</i>.
  51. /// </para>
  52. /// <para>
  53. /// <i>You are free to insert any literal text within the conversion
  54. /// pattern.</i>
  55. /// </para>
  56. /// <para>
  57. /// Each conversion specifier starts with a percent sign (%) and is
  58. /// followed by optional <i>format modifiers</i> and a <i>conversion
  59. /// pattern name</i>. The conversion pattern name specifies the type of
  60. /// data, e.g. logger, level, date, thread name. The format
  61. /// modifiers control such things as field width, padding, left and
  62. /// right justification. The following is a simple example.
  63. /// </para>
  64. /// <para>
  65. /// Let the conversion pattern be <b>"%-5level [%thread]: %message%newline"</b> and assume
  66. /// that the log4net environment was set to use a PatternLayout. Then the
  67. /// statements
  68. /// </para>
  69. /// <code lang="C#">
  70. /// ILog log = LogManager.GetLogger(typeof(TestApp));
  71. /// log.Debug("Message 1");
  72. /// log.Warn("Message 2");
  73. /// </code>
  74. /// <para>would yield the output</para>
  75. /// <code>
  76. /// DEBUG [main]: Message 1
  77. /// WARN [main]: Message 2
  78. /// </code>
  79. /// <para>
  80. /// Note that there is no explicit separator between text and
  81. /// conversion specifiers. The pattern parser knows when it has reached
  82. /// the end of a conversion specifier when it reads a conversion
  83. /// character. In the example above the conversion specifier
  84. /// <b>%-5level</b> means the level of the logging event should be left
  85. /// justified to a width of five characters.
  86. /// </para>
  87. /// <para>
  88. /// The recognized conversion pattern names are:
  89. /// </para>
  90. /// <list type="table">
  91. /// <listheader>
  92. /// <term>Conversion Pattern Name</term>
  93. /// <description>Effect</description>
  94. /// </listheader>
  95. /// <item>
  96. /// <term>a</term>
  97. /// <description>Equivalent to <b>appdomain</b></description>
  98. /// </item>
  99. /// <item>
  100. /// <term>appdomain</term>
  101. /// <description>
  102. /// Used to output the friendly name of the AppDomain where the
  103. /// logging event was generated.
  104. /// </description>
  105. /// </item>
  106. /// <item>
  107. /// <term>aspnet-cache</term>
  108. /// <description>
  109. /// <para>
  110. /// Used to output all cache items in the case of <b>%aspnet-cache</b> or just one named item if used as <b>%aspnet-cache{key}</b>
  111. /// </para>
  112. /// <para>
  113. /// This pattern is not available for Compact Framework or Client Profile assemblies.
  114. /// </para>
  115. /// </description>
  116. /// </item>
  117. /// <item>
  118. /// <term>aspnet-context</term>
  119. /// <description>
  120. /// <para>
  121. /// Used to output all context items in the case of <b>%aspnet-context</b> or just one named item if used as <b>%aspnet-context{key}</b>
  122. /// </para>
  123. /// <para>
  124. /// This pattern is not available for Compact Framework or Client Profile assemblies.
  125. /// </para>
  126. /// </description>
  127. /// </item>
  128. /// <item>
  129. /// <term>aspnet-request</term>
  130. /// <description>
  131. /// <para>
  132. /// Used to output all request parameters in the case of <b>%aspnet-request</b> or just one named param if used as <b>%aspnet-request{key}</b>
  133. /// </para>
  134. /// <para>
  135. /// This pattern is not available for Compact Framework or Client Profile assemblies.
  136. /// </para>
  137. /// </description>
  138. /// </item>
  139. /// <item>
  140. /// <term>aspnet-session</term>
  141. /// <description>
  142. /// <para>
  143. /// Used to output all session items in the case of <b>%aspnet-session</b> or just one named item if used as <b>%aspnet-session{key}</b>
  144. /// </para>
  145. /// <para>
  146. /// This pattern is not available for Compact Framework or Client Profile assemblies.
  147. /// </para>
  148. /// </description>
  149. /// </item>
  150. /// <item>
  151. /// <term>c</term>
  152. /// <description>Equivalent to <b>logger</b></description>
  153. /// </item>
  154. /// <item>
  155. /// <term>C</term>
  156. /// <description>Equivalent to <b>type</b></description>
  157. /// </item>
  158. /// <item>
  159. /// <term>class</term>
  160. /// <description>Equivalent to <b>type</b></description>
  161. /// </item>
  162. /// <item>
  163. /// <term>d</term>
  164. /// <description>Equivalent to <b>date</b></description>
  165. /// </item>
  166. /// <item>
  167. /// <term>date</term>
  168. /// <description>
  169. /// <para>
  170. /// Used to output the date of the logging event in the local time zone.
  171. /// To output the date in universal time use the <c>%utcdate</c> pattern.
  172. /// The date conversion
  173. /// specifier may be followed by a <i>date format specifier</i> enclosed
  174. /// between braces. For example, <b>%date{HH:mm:ss,fff}</b> or
  175. /// <b>%date{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
  176. /// given then ISO8601 format is
  177. /// assumed (<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>).
  178. /// </para>
  179. /// <para>
  180. /// The date format specifier admits the same syntax as the
  181. /// time pattern string of the <see cref="M:DateTime.ToString(string)"/>.
  182. /// </para>
  183. /// <para>
  184. /// For better results it is recommended to use the log4net date
  185. /// formatters. These can be specified using one of the strings
  186. /// "ABSOLUTE", "DATE" and "ISO8601" for specifying
  187. /// <see cref="log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
  188. /// <see cref="log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
  189. /// <see cref="log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
  190. /// <b>%date{ISO8601}</b> or <b>%date{ABSOLUTE}</b>.
  191. /// </para>
  192. /// <para>
  193. /// These dedicated date formatters perform significantly
  194. /// better than <see cref="M:DateTime.ToString(string)"/>.
  195. /// </para>
  196. /// </description>
  197. /// </item>
  198. /// <item>
  199. /// <term>exception</term>
  200. /// <description>
  201. /// <para>
  202. /// Used to output the exception passed in with the log message.
  203. /// </para>
  204. /// <para>
  205. /// If an exception object is stored in the logging event
  206. /// it will be rendered into the pattern output with a
  207. /// trailing newline.
  208. /// If there is no exception then nothing will be output
  209. /// and no trailing newline will be appended.
  210. /// It is typical to put a newline before the exception
  211. /// and to have the exception as the last data in the pattern.
  212. /// </para>
  213. /// </description>
  214. /// </item>
  215. /// <item>
  216. /// <term>F</term>
  217. /// <description>Equivalent to <b>file</b></description>
  218. /// </item>
  219. /// <item>
  220. /// <term>file</term>
  221. /// <description>
  222. /// <para>
  223. /// Used to output the file name where the logging request was
  224. /// issued.
  225. /// </para>
  226. /// <para>
  227. /// <b>WARNING</b> Generating caller location information is
  228. /// extremely slow. Its use should be avoided unless execution speed
  229. /// is not an issue.
  230. /// </para>
  231. /// <para>
  232. /// See the note below on the availability of caller location information.
  233. /// </para>
  234. /// </description>
  235. /// </item>
  236. /// <item>
  237. /// <term>identity</term>
  238. /// <description>
  239. /// <para>
  240. /// Used to output the user name for the currently active user
  241. /// (Principal.Identity.Name).
  242. /// </para>
  243. /// <para>
  244. /// <b>WARNING</b> Generating caller information is
  245. /// extremely slow. Its use should be avoided unless execution speed
  246. /// is not an issue.
  247. /// </para>
  248. /// </description>
  249. /// </item>
  250. /// <item>
  251. /// <term>l</term>
  252. /// <description>Equivalent to <b>location</b></description>
  253. /// </item>
  254. /// <item>
  255. /// <term>L</term>
  256. /// <description>Equivalent to <b>line</b></description>
  257. /// </item>
  258. /// <item>
  259. /// <term>location</term>
  260. /// <description>
  261. /// <para>
  262. /// Used to output location information of the caller which generated
  263. /// the logging event.
  264. /// </para>
  265. /// <para>
  266. /// The location information depends on the CLI implementation but
  267. /// usually consists of the fully qualified name of the calling
  268. /// method followed by the callers source the file name and line
  269. /// number between parentheses.
  270. /// </para>
  271. /// <para>
  272. /// The location information can be very useful. However, its
  273. /// generation is <b>extremely</b> slow. Its use should be avoided
  274. /// unless execution speed is not an issue.
  275. /// </para>
  276. /// <para>
  277. /// See the note below on the availability of caller location information.
  278. /// </para>
  279. /// </description>
  280. /// </item>
  281. /// <item>
  282. /// <term>level</term>
  283. /// <description>
  284. /// <para>
  285. /// Used to output the level of the logging event.
  286. /// </para>
  287. /// </description>
  288. /// </item>
  289. /// <item>
  290. /// <term>line</term>
  291. /// <description>
  292. /// <para>
  293. /// Used to output the line number from where the logging request
  294. /// was issued.
  295. /// </para>
  296. /// <para>
  297. /// <b>WARNING</b> Generating caller location information is
  298. /// extremely slow. Its use should be avoided unless execution speed
  299. /// is not an issue.
  300. /// </para>
  301. /// <para>
  302. /// See the note below on the availability of caller location information.
  303. /// </para>
  304. /// </description>
  305. /// </item>
  306. /// <item>
  307. /// <term>logger</term>
  308. /// <description>
  309. /// <para>
  310. /// Used to output the logger of the logging event. The
  311. /// logger conversion specifier can be optionally followed by
  312. /// <i>precision specifier</i>, that is a decimal constant in
  313. /// brackets.
  314. /// </para>
  315. /// <para>
  316. /// If a precision specifier is given, then only the corresponding
  317. /// number of right most components of the logger name will be
  318. /// printed. By default the logger name is printed in full.
  319. /// </para>
  320. /// <para>
  321. /// For example, for the logger name "a.b.c" the pattern
  322. /// <b>%logger{2}</b> will output "b.c".
  323. /// </para>
  324. /// </description>
  325. /// </item>
  326. /// <item>
  327. /// <term>m</term>
  328. /// <description>Equivalent to <b>message</b></description>
  329. /// </item>
  330. /// <item>
  331. /// <term>M</term>
  332. /// <description>Equivalent to <b>method</b></description>
  333. /// </item>
  334. /// <item>
  335. /// <term>message</term>
  336. /// <description>
  337. /// <para>
  338. /// Used to output the application supplied message associated with
  339. /// the logging event.
  340. /// </para>
  341. /// </description>
  342. /// </item>
  343. /// <item>
  344. /// <term>mdc</term>
  345. /// <description>
  346. /// <para>
  347. /// The MDC (old name for the ThreadContext.Properties) is now part of the
  348. /// combined event properties. This pattern is supported for compatibility
  349. /// but is equivalent to <b>property</b>.
  350. /// </para>
  351. /// </description>
  352. /// </item>
  353. /// <item>
  354. /// <term>method</term>
  355. /// <description>
  356. /// <para>
  357. /// Used to output the method name where the logging request was
  358. /// issued.
  359. /// </para>
  360. /// <para>
  361. /// <b>WARNING</b> Generating caller location information is
  362. /// extremely slow. Its use should be avoided unless execution speed
  363. /// is not an issue.
  364. /// </para>
  365. /// <para>
  366. /// See the note below on the availability of caller location information.
  367. /// </para>
  368. /// </description>
  369. /// </item>
  370. /// <item>
  371. /// <term>n</term>
  372. /// <description>Equivalent to <b>newline</b></description>
  373. /// </item>
  374. /// <item>
  375. /// <term>newline</term>
  376. /// <description>
  377. /// <para>
  378. /// Outputs the platform dependent line separator character or
  379. /// characters.
  380. /// </para>
  381. /// <para>
  382. /// This conversion pattern offers the same performance as using
  383. /// non-portable line separator strings such as "\n", or "\r\n".
  384. /// Thus, it is the preferred way of specifying a line separator.
  385. /// </para>
  386. /// </description>
  387. /// </item>
  388. /// <item>
  389. /// <term>ndc</term>
  390. /// <description>
  391. /// <para>
  392. /// Used to output the NDC (nested diagnostic context) associated
  393. /// with the thread that generated the logging event.
  394. /// </para>
  395. /// </description>
  396. /// </item>
  397. /// <item>
  398. /// <term>p</term>
  399. /// <description>Equivalent to <b>level</b></description>
  400. /// </item>
  401. /// <item>
  402. /// <term>P</term>
  403. /// <description>Equivalent to <b>property</b></description>
  404. /// </item>
  405. /// <item>
  406. /// <term>properties</term>
  407. /// <description>Equivalent to <b>property</b></description>
  408. /// </item>
  409. /// <item>
  410. /// <term>property</term>
  411. /// <description>
  412. /// <para>
  413. /// Used to output the an event specific property. The key to
  414. /// lookup must be specified within braces and directly following the
  415. /// pattern specifier, e.g. <b>%property{user}</b> would include the value
  416. /// from the property that is keyed by the string 'user'. Each property value
  417. /// that is to be included in the log must be specified separately.
  418. /// Properties are added to events by loggers or appenders. By default
  419. /// the <c>log4net:HostName</c> property is set to the name of machine on
  420. /// which the event was originally logged.
  421. /// </para>
  422. /// <para>
  423. /// If no key is specified, e.g. <b>%property</b> then all the keys and their
  424. /// values are printed in a comma separated list.
  425. /// </para>
  426. /// <para>
  427. /// The properties of an event are combined from a number of different
  428. /// contexts. These are listed below in the order in which they are searched.
  429. /// </para>
  430. /// <list type="definition">
  431. /// <item>
  432. /// <term>the event properties</term>
  433. /// <description>
  434. /// The event has <see cref="LoggingEvent.Properties"/> that can be set. These
  435. /// properties are specific to this event only.
  436. /// </description>
  437. /// </item>
  438. /// <item>
  439. /// <term>the thread properties</term>
  440. /// <description>
  441. /// The <see cref="ThreadContext.Properties"/> that are set on the current
  442. /// thread. These properties are shared by all events logged on this thread.
  443. /// </description>
  444. /// </item>
  445. /// <item>
  446. /// <term>the global properties</term>
  447. /// <description>
  448. /// The <see cref="GlobalContext.Properties"/> that are set globally. These
  449. /// properties are shared by all the threads in the AppDomain.
  450. /// </description>
  451. /// </item>
  452. /// </list>
  453. ///
  454. /// </description>
  455. /// </item>
  456. /// <item>
  457. /// <term>r</term>
  458. /// <description>Equivalent to <b>timestamp</b></description>
  459. /// </item>
  460. /// <item>
  461. /// <term>stacktrace</term>
  462. /// <description>
  463. /// <para>
  464. /// Used to output the stack trace of the logging event
  465. /// The stack trace level specifier may be enclosed
  466. /// between braces. For example, <b>%stacktrace{level}</b>.
  467. /// If no stack trace level specifier is given then 1 is assumed
  468. /// </para>
  469. /// <para>
  470. /// Output uses the format:
  471. /// type3.MethodCall3 > type2.MethodCall2 > type1.MethodCall1
  472. /// </para>
  473. /// <para>
  474. /// This pattern is not available for Compact Framework assemblies.
  475. /// </para>
  476. /// </description>
  477. /// </item>
  478. /// <item>
  479. /// <term>stacktracedetail</term>
  480. /// <description>
  481. /// <para>
  482. /// Used to output the stack trace of the logging event
  483. /// The stack trace level specifier may be enclosed
  484. /// between braces. For example, <b>%stacktracedetail{level}</b>.
  485. /// If no stack trace level specifier is given then 1 is assumed
  486. /// </para>
  487. /// <para>
  488. /// Output uses the format:
  489. /// type3.MethodCall3(type param,...) > type2.MethodCall2(type param,...) > type1.MethodCall1(type param,...)
  490. /// </para>
  491. /// <para>
  492. /// This pattern is not available for Compact Framework assemblies.
  493. /// </para>
  494. /// </description>
  495. /// </item>
  496. /// <item>
  497. /// <term>t</term>
  498. /// <description>Equivalent to <b>thread</b></description>
  499. /// </item>
  500. /// <item>
  501. /// <term>timestamp</term>
  502. /// <description>
  503. /// <para>
  504. /// Used to output the number of milliseconds elapsed since the start
  505. /// of the application until the creation of the logging event.
  506. /// </para>
  507. /// </description>
  508. /// </item>
  509. /// <item>
  510. /// <term>thread</term>
  511. /// <description>
  512. /// <para>
  513. /// Used to output the name of the thread that generated the
  514. /// logging event. Uses the thread number if no name is available.
  515. /// </para>
  516. /// </description>
  517. /// </item>
  518. /// <item>
  519. /// <term>type</term>
  520. /// <description>
  521. /// <para>
  522. /// Used to output the fully qualified type name of the caller
  523. /// issuing the logging request. This conversion specifier
  524. /// can be optionally followed by <i>precision specifier</i>, that
  525. /// is a decimal constant in brackets.
  526. /// </para>
  527. /// <para>
  528. /// If a precision specifier is given, then only the corresponding
  529. /// number of right most components of the class name will be
  530. /// printed. By default the class name is output in fully qualified form.
  531. /// </para>
  532. /// <para>
  533. /// For example, for the class name "log4net.Layout.PatternLayout", the
  534. /// pattern <b>%type{1}</b> will output "PatternLayout".
  535. /// </para>
  536. /// <para>
  537. /// <b>WARNING</b> Generating the caller class information is
  538. /// slow. Thus, its use should be avoided unless execution speed is
  539. /// not an issue.
  540. /// </para>
  541. /// <para>
  542. /// See the note below on the availability of caller location information.
  543. /// </para>
  544. /// </description>
  545. /// </item>
  546. /// <item>
  547. /// <term>u</term>
  548. /// <description>Equivalent to <b>identity</b></description>
  549. /// </item>
  550. /// <item>
  551. /// <term>username</term>
  552. /// <description>
  553. /// <para>
  554. /// Used to output the WindowsIdentity for the currently
  555. /// active user.
  556. /// </para>
  557. /// <para>
  558. /// <b>WARNING</b> Generating caller WindowsIdentity information is
  559. /// extremely slow. Its use should be avoided unless execution speed
  560. /// is not an issue.
  561. /// </para>
  562. /// </description>
  563. /// </item>
  564. /// <item>
  565. /// <term>utcdate</term>
  566. /// <description>
  567. /// <para>
  568. /// Used to output the date of the logging event in universal time.
  569. /// The date conversion
  570. /// specifier may be followed by a <i>date format specifier</i> enclosed
  571. /// between braces. For example, <b>%utcdate{HH:mm:ss,fff}</b> or
  572. /// <b>%utcdate{dd MMM yyyy HH:mm:ss,fff}</b>. If no date format specifier is
  573. /// given then ISO8601 format is
  574. /// assumed (<see cref="log4net.DateFormatter.Iso8601DateFormatter"/>).
  575. /// </para>
  576. /// <para>
  577. /// The date format specifier admits the same syntax as the
  578. /// time pattern string of the <see cref="M:DateTime.ToString(string)"/>.
  579. /// </para>
  580. /// <para>
  581. /// For better results it is recommended to use the log4net date
  582. /// formatters. These can be specified using one of the strings
  583. /// "ABSOLUTE", "DATE" and "ISO8601" for specifying
  584. /// <see cref="log4net.DateFormatter.AbsoluteTimeDateFormatter"/>,
  585. /// <see cref="log4net.DateFormatter.DateTimeDateFormatter"/> and respectively
  586. /// <see cref="log4net.DateFormatter.Iso8601DateFormatter"/>. For example,
  587. /// <b>%utcdate{ISO8601}</b> or <b>%utcdate{ABSOLUTE}</b>.
  588. /// </para>
  589. /// <para>
  590. /// These dedicated date formatters perform significantly
  591. /// better than <see cref="M:DateTime.ToString(string)"/>.
  592. /// </para>
  593. /// </description>
  594. /// </item>
  595. /// <item>
  596. /// <term>w</term>
  597. /// <description>Equivalent to <b>username</b></description>
  598. /// </item>
  599. /// <item>
  600. /// <term>x</term>
  601. /// <description>Equivalent to <b>ndc</b></description>
  602. /// </item>
  603. /// <item>
  604. /// <term>X</term>
  605. /// <description>Equivalent to <b>mdc</b></description>
  606. /// </item>
  607. /// <item>
  608. /// <term>%</term>
  609. /// <description>
  610. /// <para>
  611. /// The sequence %% outputs a single percent sign.
  612. /// </para>
  613. /// </description>
  614. /// </item>
  615. /// </list>
  616. /// <para>
  617. /// The single letter patterns are deprecated in favor of the
  618. /// longer more descriptive pattern names.
  619. /// </para>
  620. /// <para>
  621. /// By default the relevant information is output as is. However,
  622. /// with the aid of format modifiers it is possible to change the
  623. /// minimum field width, the maximum field width and justification.
  624. /// </para>
  625. /// <para>
  626. /// The optional format modifier is placed between the percent sign
  627. /// and the conversion pattern name.
  628. /// </para>
  629. /// <para>
  630. /// The first optional format modifier is the <i>left justification
  631. /// flag</i> which is just the minus (-) character. Then comes the
  632. /// optional <i>minimum field width</i> modifier. This is a decimal
  633. /// constant that represents the minimum number of characters to
  634. /// output. If the data item requires fewer characters, it is padded on
  635. /// either the left or the right until the minimum width is
  636. /// reached. The default is to pad on the left (right justify) but you
  637. /// can specify right padding with the left justification flag. The
  638. /// padding character is space. If the data item is larger than the
  639. /// minimum field width, the field is expanded to accommodate the
  640. /// data. The value is never truncated.
  641. /// </para>
  642. /// <para>
  643. /// This behavior can be changed using the <i>maximum field
  644. /// width</i> modifier which is designated by a period followed by a
  645. /// decimal constant. If the data item is longer than the maximum
  646. /// field, then the extra characters are removed from the
  647. /// <i>beginning</i> of the data item and not from the end. For
  648. /// example, it the maximum field width is eight and the data item is
  649. /// ten characters long, then the first two characters of the data item
  650. /// are dropped. This behavior deviates from the printf function in C
  651. /// where truncation is done from the end.
  652. /// </para>
  653. /// <para>
  654. /// Below are various format modifier examples for the logger
  655. /// conversion specifier.
  656. /// </para>
  657. /// <div class="tablediv">
  658. /// <table class="dtTABLE" cellspacing="0">
  659. /// <tr>
  660. /// <th>Format modifier</th>
  661. /// <th>left justify</th>
  662. /// <th>minimum width</th>
  663. /// <th>maximum width</th>
  664. /// <th>comment</th>
  665. /// </tr>
  666. /// <tr>
  667. /// <td align="center">%20logger</td>
  668. /// <td align="center">false</td>
  669. /// <td align="center">20</td>
  670. /// <td align="center">none</td>
  671. /// <td>
  672. /// <para>
  673. /// Left pad with spaces if the logger name is less than 20
  674. /// characters long.
  675. /// </para>
  676. /// </td>
  677. /// </tr>
  678. /// <tr>
  679. /// <td align="center">%-20logger</td>
  680. /// <td align="center">true</td>
  681. /// <td align="center">20</td>
  682. /// <td align="center">none</td>
  683. /// <td>
  684. /// <para>
  685. /// Right pad with spaces if the logger
  686. /// name is less than 20 characters long.
  687. /// </para>
  688. /// </td>
  689. /// </tr>
  690. /// <tr>
  691. /// <td align="center">%.30logger</td>
  692. /// <td align="center">NA</td>
  693. /// <td align="center">none</td>
  694. /// <td align="center">30</td>
  695. /// <td>
  696. /// <para>
  697. /// Truncate from the beginning if the logger
  698. /// name is longer than 30 characters.
  699. /// </para>
  700. /// </td>
  701. /// </tr>
  702. /// <tr>
  703. /// <td align="center"><nobr>%20.30logger</nobr></td>
  704. /// <td align="center">false</td>
  705. /// <td align="center">20</td>
  706. /// <td align="center">30</td>
  707. /// <td>
  708. /// <para>
  709. /// Left pad with spaces if the logger name is shorter than 20
  710. /// characters. However, if logger name is longer than 30 characters,
  711. /// then truncate from the beginning.
  712. /// </para>
  713. /// </td>
  714. /// </tr>
  715. /// <tr>
  716. /// <td align="center">%-20.30logger</td>
  717. /// <td align="center">true</td>
  718. /// <td align="center">20</td>
  719. /// <td align="center">30</td>
  720. /// <td>
  721. /// <para>
  722. /// Right pad with spaces if the logger name is shorter than 20
  723. /// characters. However, if logger name is longer than 30 characters,
  724. /// then truncate from the beginning.
  725. /// </para>
  726. /// </td>
  727. /// </tr>
  728. /// </table>
  729. /// </div>
  730. /// <para>
  731. /// <b>Note about caller location information.</b><br />
  732. /// The following patterns <c>%type %file %line %method %location %class %C %F %L %l %M</c>
  733. /// all generate caller location information.
  734. /// Location information uses the <c>System.Diagnostics.StackTrace</c> class to generate
  735. /// a call stack. The caller's information is then extracted from this stack.
  736. /// </para>
  737. /// <note type="caution">
  738. /// <para>
  739. /// The <c>System.Diagnostics.StackTrace</c> class is not supported on the
  740. /// .NET Compact Framework 1.0 therefore caller location information is not
  741. /// available on that framework.
  742. /// </para>
  743. /// </note>
  744. /// <note type="caution">
  745. /// <para>
  746. /// The <c>System.Diagnostics.StackTrace</c> class has this to say about Release builds:
  747. /// </para>
  748. /// <para>
  749. /// "StackTrace information will be most informative with Debug build configurations.
  750. /// By default, Debug builds include debug symbols, while Release builds do not. The
  751. /// debug symbols contain most of the file, method name, line number, and column
  752. /// information used in constructing StackFrame and StackTrace objects. StackTrace
  753. /// might not report as many method calls as expected, due to code transformations
  754. /// that occur during optimization."
  755. /// </para>
  756. /// <para>
  757. /// This means that in a Release build the caller information may be incomplete or may
  758. /// not exist at all! Therefore caller location information cannot be relied upon in a Release build.
  759. /// </para>
  760. /// </note>
  761. /// <para>
  762. /// Additional pattern converters may be registered with a specific <see cref="PatternLayout"/>
  763. /// instance using the <see cref="M:AddConverter(string, Type)"/> method.
  764. /// </para>
  765. /// </remarks>
  766. /// <example>
  767. /// This is a more detailed pattern.
  768. /// <code><b>%timestamp [%thread] %level %logger %ndc - %message%newline</b></code>
  769. /// </example>
  770. /// <example>
  771. /// A similar pattern except that the relative time is
  772. /// right padded if less than 6 digits, thread name is right padded if
  773. /// less than 15 characters and truncated if longer and the logger
  774. /// name is left padded if shorter than 30 characters and truncated if
  775. /// longer.
  776. /// <code><b>%-6timestamp [%15.15thread] %-5level %30.30logger %ndc - %message%newline</b></code>
  777. /// </example>
  778. /// <author>Nicko Cadell</author>
  779. /// <author>Gert Driesen</author>
  780. /// <author>Douglas de la Torre</author>
  781. /// <author>Daniel Cazzulino</author>
  782. public class PatternLayout : LayoutSkeleton
  783. {
  784. #region Constants
  785. /// <summary>
  786. /// Default pattern string for log output.
  787. /// </summary>
  788. /// <remarks>
  789. /// <para>
  790. /// Default pattern string for log output.
  791. /// Currently set to the string <b>"%message%newline"</b>
  792. /// which just prints the application supplied message.
  793. /// </para>
  794. /// </remarks>
  795. public const string DefaultConversionPattern ="%message%newline";
  796. /// <summary>
  797. /// A detailed conversion pattern
  798. /// </summary>
  799. /// <remarks>
  800. /// <para>
  801. /// A conversion pattern which includes Time, Thread, Logger, and Nested Context.
  802. /// Current value is <b>%timestamp [%thread] %level %logger %ndc - %message%newline</b>.
  803. /// </para>
  804. /// </remarks>
  805. public const string DetailConversionPattern = "%timestamp [%thread] %level %logger %ndc - %message%newline";
  806. #endregion
  807. #region Static Fields
  808. /// <summary>
  809. /// Internal map of converter identifiers to converter types.
  810. /// </summary>
  811. /// <remarks>
  812. /// <para>
  813. /// This static map is overridden by the m_converterRegistry instance map
  814. /// </para>
  815. /// </remarks>
  816. private static Hashtable s_globalRulesRegistry;
  817. #endregion Static Fields
  818. #region Member Variables
  819. /// <summary>
  820. /// the pattern
  821. /// </summary>
  822. private string m_pattern;
  823. /// <summary>
  824. /// the head of the pattern converter chain
  825. /// </summary>
  826. private PatternConverter m_head;
  827. /// <summary>
  828. /// patterns defined on this PatternLayout only
  829. /// </summary>
  830. private Hashtable m_instanceRulesRegistry = new Hashtable();
  831. #endregion
  832. #region Static Constructor
  833. /// <summary>
  834. /// Initialize the global registry
  835. /// </summary>
  836. /// <remarks>
  837. /// <para>
  838. /// Defines the builtin global rules.
  839. /// </para>
  840. /// </remarks>
  841. static PatternLayout()
  842. {
  843. s_globalRulesRegistry = new Hashtable(45);
  844. s_globalRulesRegistry.Add("literal", typeof(LiteralPatternConverter));
  845. s_globalRulesRegistry.Add("newline", typeof(NewLinePatternConverter));
  846. s_globalRulesRegistry.Add("n", typeof(NewLinePatternConverter));
  847. // .NET Compact Framework 1.0 has no support for ASP.NET
  848. // SSCLI 1.0 has no support for ASP.NET
  849. #if !NETCF && !SSCLI && !CLIENT_PROFILE && !NETSTANDARD1_3
  850. s_globalRulesRegistry.Add("aspnet-cache", typeof(AspNetCachePatternConverter));
  851. s_globalRulesRegistry.Add("aspnet-context", typeof(AspNetContextPatternConverter));
  852. s_globalRulesRegistry.Add("aspnet-request", typeof(AspNetRequestPatternConverter));
  853. s_globalRulesRegistry.Add("aspnet-session", typeof(AspNetSessionPatternConverter));
  854. #endif
  855. s_globalRulesRegistry.Add("c", typeof(LoggerPatternConverter));
  856. s_globalRulesRegistry.Add("logger", typeof(LoggerPatternConverter));
  857. s_globalRulesRegistry.Add("C", typeof(TypeNamePatternConverter));
  858. s_globalRulesRegistry.Add("class", typeof(TypeNamePatternConverter));
  859. s_globalRulesRegistry.Add("type", typeof(TypeNamePatternConverter));
  860. s_globalRulesRegistry.Add("d", typeof(DatePatternConverter));
  861. s_globalRulesRegistry.Add("date", typeof(DatePatternConverter));
  862. s_globalRulesRegistry.Add("exception", typeof(ExceptionPatternConverter));
  863. s_globalRulesRegistry.Add("F", typeof(FileLocationPatternConverter));
  864. s_globalRulesRegistry.Add("file", typeof(FileLocationPatternConverter));
  865. s_globalRulesRegistry.Add("l", typeof(FullLocationPatternConverter));
  866. s_globalRulesRegistry.Add("location", typeof(FullLocationPatternConverter));
  867. s_globalRulesRegistry.Add("L", typeof(LineLocationPatternConverter));
  868. s_globalRulesRegistry.Add("line", typeof(LineLocationPatternConverter));
  869. s_globalRulesRegistry.Add("m", typeof(MessagePatternConverter));
  870. s_globalRulesRegistry.Add("message", typeof(MessagePatternConverter));
  871. s_globalRulesRegistry.Add("M", typeof(MethodLocationPatternConverter));
  872. s_globalRulesRegistry.Add("method", typeof(MethodLocationPatternConverter));
  873. s_globalRulesRegistry.Add("p", typeof(LevelPatternConverter));
  874. s_globalRulesRegistry.Add("level", typeof(LevelPatternConverter));
  875. s_globalRulesRegistry.Add("P", typeof(PropertyPatternConverter));
  876. s_globalRulesRegistry.Add("property", typeof(PropertyPatternConverter));
  877. s_globalRulesRegistry.Add("properties", typeof(PropertyPatternConverter));
  878. s_globalRulesRegistry.Add("r", typeof(RelativeTimePatternConverter));
  879. s_globalRulesRegistry.Add("timestamp", typeof(RelativeTimePatternConverter));
  880. #if !(NETCF || NETSTANDARD1_3)
  881. s_globalRulesRegistry.Add("stacktrace", typeof(StackTracePatternConverter));
  882. s_globalRulesRegistry.Add("stacktracedetail", typeof(StackTraceDetailPatternConverter));
  883. #endif
  884. s_globalRulesRegistry.Add("t", typeof(ThreadPatternConverter));
  885. s_globalRulesRegistry.Add("thread", typeof(ThreadPatternConverter));
  886. // For backwards compatibility the NDC patterns
  887. s_globalRulesRegistry.Add("x", typeof(NdcPatternConverter));
  888. s_globalRulesRegistry.Add("ndc", typeof(NdcPatternConverter));
  889. // For backwards compatibility the MDC patterns just do a property lookup
  890. s_globalRulesRegistry.Add("X", typeof(PropertyPatternConverter));
  891. s_globalRulesRegistry.Add("mdc", typeof(PropertyPatternConverter));
  892. s_globalRulesRegistry.Add("a", typeof(AppDomainPatternConverter));
  893. s_globalRulesRegistry.Add("appdomain", typeof(AppDomainPatternConverter));
  894. s_globalRulesRegistry.Add("u", typeof(IdentityPatternConverter));
  895. s_globalRulesRegistry.Add("identity", typeof(IdentityPatternConverter));
  896. s_globalRulesRegistry.Add("utcdate", typeof(UtcDatePatternConverter));
  897. s_globalRulesRegistry.Add("utcDate", typeof(UtcDatePatternConverter));
  898. s_globalRulesRegistry.Add("UtcDate", typeof(UtcDatePatternConverter));
  899. s_globalRulesRegistry.Add("w", typeof(UserNamePatternConverter));
  900. s_globalRulesRegistry.Add("username", typeof(UserNamePatternConverter));
  901. }
  902. #endregion Static Constructor
  903. #region Constructors
  904. /// <summary>
  905. /// Constructs a PatternLayout using the DefaultConversionPattern
  906. /// </summary>
  907. /// <remarks>
  908. /// <para>
  909. /// The default pattern just produces the application supplied message.
  910. /// </para>
  911. /// <para>
  912. /// Note to Inheritors: This constructor calls the virtual method
  913. /// <see cref="CreatePatternParser"/>. If you override this method be
  914. /// aware that it will be called before your is called constructor.
  915. /// </para>
  916. /// <para>
  917. /// As per the <see cref="IOptionHandler"/> contract the <see cref="ActivateOptions"/>
  918. /// method must be called after the properties on this object have been
  919. /// configured.
  920. /// </para>
  921. /// </remarks>
  922. public PatternLayout() : this(DefaultConversionPattern)
  923. {
  924. }
  925. /// <summary>
  926. /// Constructs a PatternLayout using the supplied conversion pattern
  927. /// </summary>
  928. /// <param name="pattern">the pattern to use</param>
  929. /// <remarks>
  930. /// <para>
  931. /// Note to Inheritors: This constructor calls the virtual method
  932. /// <see cref="CreatePatternParser"/>. If you override this method be
  933. /// aware that it will be called before your is called constructor.
  934. /// </para>
  935. /// <para>
  936. /// When using this constructor the <see cref="ActivateOptions"/> method
  937. /// need not be called. This may not be the case when using a subclass.
  938. /// </para>
  939. /// </remarks>
  940. public PatternLayout(string pattern)
  941. {
  942. // By default we do not process the exception
  943. IgnoresException = true;
  944. m_pattern = pattern;
  945. if (m_pattern == null)
  946. {
  947. m_pattern = DefaultConversionPattern;
  948. }
  949. ActivateOptions();
  950. }
  951. #endregion
  952. /// <summary>
  953. /// The pattern formatting string
  954. /// </summary>
  955. /// <remarks>
  956. /// <para>
  957. /// The <b>ConversionPattern</b> option. This is the string which
  958. /// controls formatting and consists of a mix of literal content and
  959. /// conversion specifiers.
  960. /// </para>
  961. /// </remarks>
  962. public string ConversionPattern
  963. {
  964. get { return m_pattern; }
  965. set { m_pattern = value; }
  966. }
  967. /// <summary>
  968. /// Create the pattern parser instance
  969. /// </summary>
  970. /// <param name="pattern">the pattern to parse</param>
  971. /// <returns>The <see cref="PatternParser"/> that will format the event</returns>
  972. /// <remarks>
  973. /// <para>
  974. /// Creates the <see cref="PatternParser"/> used to parse the conversion string. Sets the
  975. /// global and instance rules on the <see cref="PatternParser"/>.
  976. /// </para>
  977. /// </remarks>
  978. virtual protected PatternParser CreatePatternParser(string pattern)
  979. {
  980. PatternParser patternParser = new PatternParser(pattern);
  981. // Add all the builtin patterns
  982. foreach(DictionaryEntry entry in s_globalRulesRegistry)
  983. {
  984. ConverterInfo converterInfo = new ConverterInfo();
  985. converterInfo.Name = (string)entry.Key;
  986. converterInfo.Type = (Type)entry.Value;
  987. patternParser.PatternConverters[entry.Key] = converterInfo;
  988. }
  989. // Add the instance patterns
  990. foreach(DictionaryEntry entry in m_instanceRulesRegistry)
  991. {
  992. patternParser.PatternConverters[entry.Key] = entry.Value;
  993. }
  994. return patternParser;
  995. }
  996. #region Implementation of IOptionHandler
  997. /// <summary>
  998. /// Initialize layout options
  999. /// </summary>
  1000. /// <remarks>
  1001. /// <para>
  1002. /// This is part of the <see cref="IOptionHandler"/> delayed object
  1003. /// activation scheme. The <see cref="ActivateOptions"/> method must
  1004. /// be called on this object after the configuration properties have
  1005. /// been set. Until <see cref="ActivateOptions"/> is called this
  1006. /// object is in an undefined state and must not be used.
  1007. /// </para>
  1008. /// <para>
  1009. /// If any of the configuration properties are modified then
  1010. /// <see cref="ActivateOptions"/> must be called again.
  1011. /// </para>
  1012. /// </remarks>
  1013. override public void ActivateOptions()
  1014. {
  1015. m_head = CreatePatternParser(m_pattern).Parse();
  1016. PatternConverter curConverter = m_head;
  1017. while(curConverter != null)
  1018. {
  1019. PatternLayoutConverter layoutConverter = curConverter as PatternLayoutConverter;
  1020. if (layoutConverter != null)
  1021. {
  1022. if (!layoutConverter.IgnoresException)
  1023. {
  1024. // Found converter that handles the exception
  1025. this.IgnoresException = false;
  1026. break;
  1027. }
  1028. }
  1029. curConverter = curConverter.Next;
  1030. }
  1031. }
  1032. #endregion
  1033. #region Override implementation of LayoutSkeleton
  1034. /// <summary>
  1035. /// Produces a formatted string as specified by the conversion pattern.
  1036. /// </summary>
  1037. /// <param name="loggingEvent">the event being logged</param>
  1038. /// <param name="writer">The TextWriter to write the formatted event to</param>
  1039. /// <remarks>
  1040. /// <para>
  1041. /// Parse the <see cref="LoggingEvent"/> using the patter format
  1042. /// specified in the <see cref="ConversionPattern"/> property.
  1043. /// </para>
  1044. /// </remarks>
  1045. override public void Format(TextWriter writer, LoggingEvent loggingEvent)
  1046. {
  1047. if (writer == null)
  1048. {
  1049. throw new ArgumentNullException("writer");
  1050. }
  1051. if (loggingEvent == null)
  1052. {
  1053. throw new ArgumentNullException("loggingEvent");
  1054. }
  1055. PatternConverter c = m_head;
  1056. // loop through the chain of pattern converters
  1057. while(c != null)
  1058. {
  1059. c.Format(writer, loggingEvent);
  1060. c = c.Next;
  1061. }
  1062. }
  1063. #endregion
  1064. /// <summary>
  1065. /// Add a converter to this PatternLayout
  1066. /// </summary>
  1067. /// <param name="converterInfo">the converter info</param>
  1068. /// <remarks>
  1069. /// <para>
  1070. /// This version of the method is used by the configurator.
  1071. /// Programmatic users should use the alternative <see cref="M:AddConverter(string,Type)"/> method.
  1072. /// </para>
  1073. /// </remarks>
  1074. public void AddConverter(ConverterInfo converterInfo)
  1075. {
  1076. if (converterInfo == null) throw new ArgumentNullException("converterInfo");
  1077. if (!typeof(PatternConverter).IsAssignableFrom(converterInfo.Type))
  1078. {
  1079. throw new ArgumentException("The converter type specified [" + converterInfo.Type + "] must be a subclass of log4net.Util.PatternConverter", "converterInfo");
  1080. }
  1081. m_instanceRulesRegistry[converterInfo.Name] = converterInfo;
  1082. }
  1083. /// <summary>
  1084. /// Add a converter to this PatternLayout
  1085. /// </summary>
  1086. /// <param name="name">the name of the conversion pattern for this converter</param>
  1087. /// <param name="type">the type of the converter</param>
  1088. /// <remarks>
  1089. /// <para>
  1090. /// Add a named pattern converter to this instance. This
  1091. /// converter will be used in the formatting of the event.
  1092. /// This method must be called before <see cref="ActivateOptions"/>.
  1093. /// </para>
  1094. /// <para>
  1095. /// The <paramref name="type"/> specified must extend the
  1096. /// <see cref="PatternConverter"/> type.
  1097. /// </para>
  1098. /// </remarks>
  1099. public void AddConverter(string name, Type type)
  1100. {
  1101. if (name == null) throw new ArgumentNullException("name");
  1102. if (type == null) throw new ArgumentNullException("type");
  1103. ConverterInfo converterInfo = new ConverterInfo();
  1104. converterInfo.Name = name;
  1105. converterInfo.Type = type;
  1106. AddConverter(converterInfo);
  1107. }
  1108. }
  1109. }