No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LogProvider.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // <auto-generated/>
  2. // ReSharper disable CheckNamespace
  3. //===============================================================================
  4. // LibLog
  5. //
  6. // https://github.com/damianh/LibLog
  7. //===============================================================================
  8. // Copyright © 2011-2017 Damian Hickey. All rights reserved.
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining a copy
  11. // of this software and associated documentation files (the "Software"), to deal
  12. // in the Software without restriction, including without limitation the rights
  13. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. // copies of the Software, and to permit persons to whom the Software is
  15. // furnished to do so, subject to the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be included in
  18. // all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  26. // SOFTWARE.
  27. //===============================================================================
  28. // @formatter:off — disable resharper formatter after this line
  29. // ReSharper disable PossibleNullReferenceException
  30. // Define LIBLOG_PUBLIC to enable ability to GET a logger (LogProvider.For<>() etc) from outside this library. NOTE:
  31. // this can have unintended consequences of consumers of your library using your library to resolve a logger. If the
  32. // reason is because you want to open this functionality to other projects within your solution,
  33. // consider [InternalsVisibleTo] instead.
  34. //
  35. // Define LIBLOG_PROVIDERS_ONLY if your library provides its own logging API and you just want to use the
  36. // LibLog providers internally to provide built in support for popular logging frameworks.
  37. #pragma warning disable 1591
  38. using global::System.Diagnostics.CodeAnalysis;
  39. [assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "RSTP_DSLink.Logging")]
  40. [assembly: SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed", Scope = "member", Target = "RSTP_DSLink.Logging.Logger.#Invoke(RSTP_DSLink.Logging.LogLevel,System.Func`1<System.String>,System.Exception,System.Object[])")]
  41. // If you copied this file manually, you need to change all "YourRootNameSpace" so not to clash with other libraries
  42. // that use LibLog
  43. namespace RSTP_DSLink.Logging
  44. {
  45. using global::System.Collections.Generic;
  46. using global::System.Diagnostics.CodeAnalysis;
  47. using global::RSTP_DSLink.Logging.LogProviders;
  48. using global::System;
  49. #if !LIBLOG_PROVIDERS_ONLY
  50. using global::System.Diagnostics;
  51. using global::System.Runtime.CompilerServices;
  52. #endif
  53. #if LIBLOG_EXCLUDE_CODE_COVERAGE
  54. [ExcludeFromCodeCoverage]
  55. #endif
  56. #if LIBLOG_PROVIDERS_ONLY
  57. /// <summary>
  58. /// Provides a mechanism to set the <see cref="ILogProvider" />
  59. /// and create instances of <see cref="ILog" /> objects.
  60. /// </summary>
  61. internal
  62. #else
  63. /// <summary>
  64. /// Provides a mechanism to set the <see cref="ILogProvider" />.
  65. /// </summary>
  66. public
  67. #endif
  68. static class LogProvider
  69. {
  70. private static readonly Lazy<ILogProvider> ResolvedLogProvider = new Lazy<ILogProvider>(ForceResolveLogProvider);
  71. #if !LIBLOG_PROVIDERS_ONLY
  72. private static ILogProvider s_currentLogProvider;
  73. private static Action<ILogProvider> s_onCurrentLogProviderSet;
  74. [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
  75. static LogProvider()
  76. {
  77. IsDisabled = false;
  78. }
  79. /// <summary>
  80. /// Sets the current log provider.
  81. /// </summary>
  82. /// <param name="logProvider">The log provider.</param>
  83. public static void SetCurrentLogProvider(ILogProvider logProvider)
  84. {
  85. s_currentLogProvider = logProvider;
  86. RaiseOnCurrentLogProviderSet();
  87. }
  88. /// <summary>
  89. /// Gets or sets a value indicating whether this is logging is disabled.
  90. /// </summary>
  91. /// <value>
  92. /// <c>true</c> if logging is disabled; otherwise, <c>false</c>.
  93. /// </value>
  94. public static bool IsDisabled { get; set; }
  95. /// <summary>
  96. /// Sets an action that is invoked when a consumer of your library has called SetCurrentLogProvider. It is
  97. /// important that hook into this if you are using child libraries (especially ilmerged ones) that are using
  98. /// LibLog (or other logging abstraction) so you adapt and delegate to them.
  99. /// <see cref="SetCurrentLogProvider"/>
  100. /// </summary>
  101. internal static Action<ILogProvider> OnCurrentLogProviderSet
  102. {
  103. set
  104. {
  105. s_onCurrentLogProviderSet = value;
  106. RaiseOnCurrentLogProviderSet();
  107. }
  108. }
  109. internal static ILogProvider CurrentLogProvider
  110. {
  111. get { return s_currentLogProvider; }
  112. }
  113. /// <summary>
  114. /// Gets a logger for the specified type.
  115. /// </summary>
  116. /// <typeparam name="T">The type whose name will be used for the logger.</typeparam>
  117. /// <returns>An instance of <see cref="ILog"/></returns>
  118. #if LIBLOG_PUBLIC
  119. public
  120. #else
  121. internal
  122. #endif
  123. static ILog For<T>()
  124. {
  125. return GetLogger(typeof(T));
  126. }
  127. /// <summary>
  128. /// Gets a logger for the current class.
  129. /// </summary>
  130. /// <returns>An instance of <see cref="ILog"/></returns>
  131. [MethodImpl(MethodImplOptions.NoInlining)]
  132. #if LIBLOG_PUBLIC
  133. public
  134. #else
  135. internal
  136. #endif
  137. static ILog GetCurrentClassLogger()
  138. {
  139. var stackFrame = new StackFrame(1, false);
  140. return GetLogger(stackFrame.GetMethod().DeclaringType);
  141. }
  142. /// <summary>
  143. /// Gets a logger for the specified type.
  144. /// </summary>
  145. /// <param name="type">The type whose name will be used for the logger.</param>
  146. /// <param name="fallbackTypeName">If the type is null then this name will be used as the log name instead</param>
  147. /// <returns>An instance of <see cref="ILog"/></returns>
  148. #if LIBLOG_PUBLIC
  149. public
  150. #else
  151. internal
  152. #endif
  153. static ILog GetLogger(Type type, string fallbackTypeName = "System.Object")
  154. {
  155. // If the type passed in is null then fallback to the type name specified
  156. return GetLogger(type != null ? type.ToString() : fallbackTypeName);
  157. }
  158. /// <summary>
  159. /// Gets a logger with the specified name.
  160. /// </summary>
  161. /// <param name="name">The name.</param>
  162. /// <returns>An instance of <see cref="ILog"/></returns>
  163. #if LIBLOG_PUBLIC
  164. public
  165. #else
  166. internal
  167. #endif
  168. static ILog GetLogger(string name)
  169. {
  170. var logProvider = CurrentLogProvider ?? ResolveLogProvider();
  171. return logProvider == null
  172. ? NoOpLogger.Instance
  173. : (ILog)new LoggerExecutionWrapper(logProvider.GetLogger(name), () => IsDisabled);
  174. }
  175. /// <summary>
  176. /// Opens a nested diagnostics context.
  177. /// </summary>
  178. /// <param name="message">A message.</param>
  179. /// <returns>An <see cref="IDisposable"/> that closes context when disposed.</returns>
  180. [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "SetCurrentLogProvider")]
  181. #if LIBLOG_PUBLIC
  182. public
  183. #else
  184. internal
  185. #endif
  186. static IDisposable OpenNestedContext(string message)
  187. {
  188. var logProvider = CurrentLogProvider ?? ResolveLogProvider();
  189. return logProvider == null
  190. ? new DisposableAction(() => { })
  191. : logProvider.OpenNestedContext(message);
  192. }
  193. /// <summary>
  194. /// Opens a mapped diagnostics context.
  195. /// </summary>
  196. /// <param name="key">A key.</param>
  197. /// <param name="value">A value.</param>
  198. /// <param name="destructure">A optional paramater to indicate message should be destructured.</param>
  199. /// <returns>An <see cref="IDisposable"/> that closes context when disposed.</returns>
  200. [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "SetCurrentLogProvider")]
  201. #if LIBLOG_PUBLIC
  202. public
  203. #else
  204. internal
  205. #endif
  206. static IDisposable OpenMappedContext(string key, object value, bool destructure = false)
  207. {
  208. var logProvider = CurrentLogProvider ?? ResolveLogProvider();
  209. return logProvider == null
  210. ? new DisposableAction(() => { })
  211. : logProvider.OpenMappedContext(key, value, destructure);
  212. }
  213. #endif
  214. #if LIBLOG_PROVIDERS_ONLY
  215. private
  216. #else
  217. internal
  218. #endif
  219. delegate bool IsLoggerAvailable();
  220. #if LIBLOG_PROVIDERS_ONLY
  221. private
  222. #else
  223. internal
  224. #endif
  225. delegate ILogProvider CreateLogProvider();
  226. #if LIBLOG_PROVIDERS_ONLY
  227. private
  228. #else
  229. internal
  230. #endif
  231. static readonly List<Tuple<IsLoggerAvailable, CreateLogProvider>> LogProviderResolvers =
  232. new List<Tuple<IsLoggerAvailable, CreateLogProvider>>
  233. {
  234. new Tuple<IsLoggerAvailable, CreateLogProvider>(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()),
  235. new Tuple<IsLoggerAvailable, CreateLogProvider>(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()),
  236. new Tuple<IsLoggerAvailable, CreateLogProvider>(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()),
  237. new Tuple<IsLoggerAvailable, CreateLogProvider>(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()),
  238. };
  239. #if !LIBLOG_PROVIDERS_ONLY
  240. private static void RaiseOnCurrentLogProviderSet()
  241. {
  242. if (s_onCurrentLogProviderSet != null)
  243. {
  244. s_onCurrentLogProviderSet(s_currentLogProvider);
  245. }
  246. }
  247. #endif
  248. internal static ILogProvider ResolveLogProvider()
  249. {
  250. return ResolvedLogProvider.Value;
  251. }
  252. [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Console.WriteLine(System.String,System.Object,System.Object)")]
  253. [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
  254. internal static ILogProvider ForceResolveLogProvider()
  255. {
  256. try
  257. {
  258. foreach (var providerResolver in LogProviderResolvers)
  259. {
  260. if (providerResolver.Item1())
  261. {
  262. return providerResolver.Item2();
  263. }
  264. }
  265. }
  266. catch (Exception ex)
  267. {
  268. Console.WriteLine(
  269. "Exception occurred resolving a log provider. Logging for this assembly {0} is disabled. {1}",
  270. typeof(LogProvider).Assembly.FullName,
  271. ex);
  272. }
  273. return null;
  274. }
  275. #if !LIBLOG_PROVIDERS_ONLY
  276. #if LIBLOG_EXCLUDE_CODE_COVERAGE
  277. [ExcludeFromCodeCoverage]
  278. #endif
  279. internal class NoOpLogger : ILog
  280. {
  281. internal static readonly NoOpLogger Instance = new NoOpLogger();
  282. public bool Log(LogLevel logLevel, Func<string> messageFunc, Exception exception, params object[] formatParameters)
  283. {
  284. return false;
  285. }
  286. }
  287. #endif
  288. }
  289. }