Fixing an issue with output parameters that are of type IntPtr
[castle.git] / Core / Castle.Core / Logging / Loggers / TraceLogger.cs
blob517abbcc4abe99eb07e05ca5f823d6ee276bcfa9
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Core.Logging
17 #if !SILVERLIGHT
19 using System;
20 using System.Diagnostics;
21 using System.Collections.Generic;
23 /// <summary>
24 /// The TraceLogger sends all logging to the System.Diagnostics.TraceSource
25 /// built into the .net framework.
26 /// </summary>
27 /// <remarks>
28 /// Logging can be configured in the system.diagnostics configuration
29 /// section.
30 ///
31 /// If logger doesn't find a source name with a full match it will
32 /// use source names which match the namespace partially. For example you can
33 /// configure from all castle components by adding a source name with the
34 /// name "Castle".
35 ///
36 /// If no portion of the namespace matches the source named "Default" will
37 /// be used.
38 /// </remarks>
39 public class TraceLogger : LevelFilteredLogger
41 private static readonly Dictionary<string, TraceSource> cache = new Dictionary<string, TraceSource>();
43 TraceSource traceSource;
45 /// <summary>
46 /// Build a new trace logger based on the named TraceSource
47 /// </summary>
48 /// <param name="name">The name used to locate the best TraceSource. In most cases comes from the using type's fullname.</param>
49 public TraceLogger(string name)
50 : base(name)
52 Initialize();
53 Level = MapLoggerLevel(traceSource.Switch.Level);
56 /// <summary>
57 /// Build a new trace logger based on the named TraceSource
58 /// </summary>
59 /// <param name="name">The name used to locate the best TraceSource. In most cases comes from the using type's fullname.</param>
60 /// <param name="level">The default logging level at which this source should write messages. In almost all cases this
61 /// default value will be overridden in the config file. </param>
62 public TraceLogger(string name, LoggerLevel level)
63 : base(name, level)
65 Initialize();
66 Level = MapLoggerLevel(traceSource.Switch.Level);
69 /// <summary>
70 /// Create a new child logger.
71 /// The name of the child logger is [current-loggers-name].[passed-in-name]
72 /// </summary>
73 /// <param name="name">The Subname of this logger.</param>
74 /// <returns>The New ILogger instance.</returns>
75 public override ILogger CreateChildLogger(string name)
77 return new TraceLogger(string.Concat(Name, ".", name), Level);
80 protected override void Log(LoggerLevel level, string name, string message, Exception exception)
82 if (exception == null)
84 traceSource.TraceEvent(MapTraceEventType(level), 0, message);
86 else
88 traceSource.TraceData(MapTraceEventType(level), 0, message, exception);
92 void Initialize()
94 lock (cache)
96 // because TraceSource is meant to be used as a static member, and because
97 // building up the configuraion inheritance is non-trivial, the instances
98 // themselves are cached for so multiple TraceLogger instances will reuse
99 // the named TraceSources which have been created
101 if (cache.TryGetValue(Name, out traceSource))
102 return;
105 SourceLevels defaultLevel = MapSourceLevels(Level);
106 traceSource = new TraceSource(Name, defaultLevel);
108 // no further action necessary when the named source is configured
109 if (IsSourceConfigured(traceSource))
111 cache.Add(Name, traceSource);
112 return;
115 // otherwise hunt for a shorter source that been configured
116 TraceSource foundSource = new TraceSource("Default", defaultLevel);
118 string searchName = ShortenName(Name);
119 while (!string.IsNullOrEmpty(searchName))
121 TraceSource searchSource = new TraceSource(searchName, defaultLevel);
122 if (IsSourceConfigured(searchSource))
124 foundSource = searchSource;
125 break;
128 searchName = ShortenName(searchName);
131 // reconfigure the created source to act like the found source
132 traceSource.Switch = foundSource.Switch;
133 traceSource.Listeners.Clear();
134 foreach (TraceListener listener in foundSource.Listeners)
135 traceSource.Listeners.Add(listener);
137 cache.Add(Name, traceSource);
141 static string ShortenName(string name)
143 int lastDot = name.LastIndexOf('.');
144 if (lastDot != -1)
146 return name.Substring(0, lastDot);
148 return null;
152 static bool IsSourceConfigured(TraceSource source)
154 if (source.Listeners.Count == 1 &&
155 source.Listeners[0] is DefaultTraceListener &&
156 source.Listeners[0].Name == "Default")
158 return false;
160 return true;
164 static LoggerLevel MapLoggerLevel(SourceLevels level)
166 switch (level)
168 case SourceLevels.All:
169 return LoggerLevel.Debug;
170 case SourceLevels.Verbose:
171 return LoggerLevel.Debug;
172 case SourceLevels.Information:
173 return LoggerLevel.Info;
174 case SourceLevels.Warning:
175 return LoggerLevel.Warn;
176 case SourceLevels.Error:
177 return LoggerLevel.Error;
178 case SourceLevels.Critical:
179 return LoggerLevel.Fatal;
181 return LoggerLevel.Off;
184 static SourceLevels MapSourceLevels(LoggerLevel level)
186 switch (level)
188 case LoggerLevel.Debug:
189 return SourceLevels.Verbose;
190 case LoggerLevel.Info:
191 return SourceLevels.Information;
192 case LoggerLevel.Warn:
193 return SourceLevels.Warning;
194 case LoggerLevel.Error:
195 return SourceLevels.Error;
196 case LoggerLevel.Fatal:
197 return SourceLevels.Critical;
199 return SourceLevels.Off;
202 static TraceEventType MapTraceEventType(LoggerLevel level)
204 switch (level)
206 case LoggerLevel.Debug:
207 return TraceEventType.Verbose;
208 case LoggerLevel.Info:
209 return TraceEventType.Information;
210 case LoggerLevel.Warn:
211 return TraceEventType.Warning;
212 case LoggerLevel.Error:
213 return TraceEventType.Error;
214 case LoggerLevel.Fatal:
215 return TraceEventType.Critical;
217 return TraceEventType.Verbose;
221 #endif