public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) { var frames = new StackTrace().GetFrames(); Func<StackFrame, bool> serilogFrames = stack => stack.GetMethod() .DeclaringType .Namespace .StartsWith("serilog.core", StringComparison.InvariantCultureIgnoreCase); var serilogFrameCount = frames.Count(serilogFrames); var callerFrame = frames.Skip(serilogFrameCount + 1).First(); var method = callerFrame.GetMethod().Name; var caller = callerFrame.GetMethod().DeclaringType.FullName; var property = propertyFactory.CreateProperty("LogCaller", new LogCaller {ClassName = caller, Method = method}); logEvent.AddOrUpdateProperty(property); }
/// <summary> /// unrolls and converts an exception to a string with an optional message /// </summary> public static string ToStringUnrolled(this Exception ex) { //if ex is null, throw if (ex == null) { throw new ArgumentNullException(nameof(ex)); } //setup newline string string nl = "\r\n"; //start with unrolled inner exceptions string msg = UnrollInnnerExceptions(ex, "", nl) + nl + "########## EXCEPTION LOGGED HERE ##############" + nl; //add current stack string prefix = ""; StackFrame[] frames = new StackTrace().GetFrames(); if ( frames != null ) { foreach ( var frame in frames.Skip(1) ) { MethodBase m = frame.GetMethod(); //ignore methods we can't load if ( m == null || m.DeclaringType == null || m.DeclaringType.FullName == null ) { msg = msg + "Unknown method" + nl; continue; } msg = msg + " " + m.DeclaringType.FullName + "." + m.Name + "(" + string.Join(",", m.GetParameters().Select(p => p.ParameterType.Name + " " + p.Name).ToArray()) + ")" + nl; } } //create full message msg = prefix + msg; return msg; }
/// <summary> /// Logs an exception to the configured error store, or the in-memory default store if none is configured /// </summary> /// <param name="ex">The exception to log</param> /// <param name="context">The HTTPContext to record variables from. If this isn't a web request, pass <see langword="null" /> in here</param> /// <param name="appendFullStackTrace">Wehther to append a full stack trace to the exception's detail</param> /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine</param> /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use</param> /// <param name="applicationName">If specified, the application name to log with, if not specified the name in the config is used</param> /// <returns>The Error created, if one was created and logged, null if nothing was logged</returns> /// <remarks> /// When dealing with a non web requests, pass <see langword="null" /> in for context. /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter. /// </remarks> public static Error LogException(Exception ex, HttpContext context, bool appendFullStackTrace = false, bool rollupPerServer = false, Dictionary<string, string> customData = null, string applicationName = null) { if (!_enableLogging) return null; try { if (IgnoreRegexes.Any(re => re.IsMatch(ex.ToString()))) return null; if (IgnoreExceptions.Any(type => IsDescendentOf(ex.GetType(), type.ToString()))) return null; if (customData == null && GetCustomData != null) { customData = new Dictionary<string, string>(); try { GetCustomData(ex, context, customData); } catch (Exception cde) { // if there was an error getting custom errors, log it so we can display such in the view...and not fail to log the original error customData.Add(CustomDataErrorKey, cde.ToString()); } } var error = new Error(ex, context, applicationName) { RollupPerServer = rollupPerServer, CustomData = customData }; var exCursor = ex; while (exCursor != null) { AddErrorData(error, exCursor); exCursor = exCursor.InnerException; } if (appendFullStackTrace) { var frames = new StackTrace(fNeedFileInfo: true).GetFrames(); if (frames != null) error.Detail += "\n\nFull Trace:\n\n" + string.Join("", frames.Skip(2)); error.ErrorHash = error.GetHash(); } if (OnBeforeLog != null) { try { var args = new ErrorBeforeLogEventArgs(error); OnBeforeLog(Default, args); if (args.Abort) return null; // if we've been told to abort, then abort dammit! } catch (Exception e) { Trace.WriteLine(e); } } Trace.WriteLine(ex); // always echo the error to trace for local debugging Default.Log(error); if (OnAfterLog != null) { try { OnAfterLog(Default, new ErrorAfterLogEventArgs(error)); } catch (Exception e) { Trace.WriteLine(e); } } return error; } catch (Exception e) { Trace.WriteLine(e); return null; } }
public static StackAnalyser ForCurrentStack() { IEnumerable<StackFrame> curentStack = new StackTrace(true).GetFrames() ?? Enumerable.Empty<StackFrame>(); return new StackAnalyser(curentStack.Skip(1)); // Skip top frame so index arguments are relative to caller, not this method }
/// <summary> /// Logs an exception to the configured error store, or the in-memory default store if none is configured /// </summary> /// <param name="ex">The exception to log</param> /// <param name="context">The HTTPContext to record variables from. If this isn't a web request, pass <see langword="null" /> in here</param> /// <param name="appendFullStackTrace">Wehther to append a full stack trace to the exception's detail</param> /// <param name="rollupPerServer">Whether to log up per-server, e.g. errors are only duplicates if they have same stack on the same machine</param> /// <param name="customData">Any custom data to store with the exception like UserId, etc...this will be rendered as JSON in the error view for script use</param> /// <remarks> /// When dealing with a non web requests, pass <see langword="null" /> in for context. /// It shouldn't be forgotten for most web application usages, so it's not an optional parameter. /// </remarks> public static void LogException(Exception ex, HttpContext context, bool appendFullStackTrace = false, bool rollupPerServer = false, Dictionary<string, string> customData = null) { if (!_enableLogging) return; try { if (IgnoreRegexes.Any(re => re.IsMatch(ex.ToString()))) return; if (IgnoreExceptions.Any(type => IsDescendentOf(ex.GetType(), type.ToString()))) return; if (customData == null && GetCustomData != null) { customData = new Dictionary<string, string>(); try { GetCustomData(ex, context, customData); } catch (Exception cde) { // if there was an error getting custom errors, log it so we can display such in the view...and not fail to log the original error customData.Add(CustomDataErrorKey, cde.ToString()); } } var error = new Error(ex, context) { RollupPerServer = rollupPerServer, CustomData = customData }; var exCursor = ex; while (exCursor != null) { if (exCursor.Data.Contains("SQL")) error.SQL = exCursor.Data["SQL"] as string; exCursor = exCursor.InnerException; } if (appendFullStackTrace) { var frames = new StackTrace(fNeedFileInfo: true).GetFrames(); if (frames != null) error.Detail += "\n\nFull Trace:\n\n" + string.Join("", frames.Skip(2)); } Trace.WriteLine(ex); // always echo the error to trace for local debugging Default.Log(error); } catch (Exception e) { Trace.WriteLine(e); } }
private static void Initialize() { try { Assembly currentAssembly = typeof(Log).Assembly; List<Assembly> asmList = new StackTrace().GetFrames() .Where(frame => { MethodBase method = frame.GetMethod(); return method != null && method.DeclaringType != null && method.DeclaringType.Assembly != null; }) .Select(frame => frame.GetMethod().DeclaringType.Assembly) .ToList(); int currentAssemblyIndex = asmList.FindLastIndex(asm => asm.FullName.Equals(currentAssembly.FullName, StringComparison.OrdinalIgnoreCase)) + 1; Assembly entryAssembly = null; if (currentAssemblyIndex < asmList.Count) { entryAssembly = asmList .Skip(currentAssemblyIndex) .LastOrDefault(asm => asm.FullName.IndexOf(MasterNamespace, StringComparison.OrdinalIgnoreCase) != -1); } else { entryAssembly = asmList.LastOrDefault(asm => asm.FullName.IndexOf(MasterNamespace, StringComparison.OrdinalIgnoreCase) != -1); } if (entryAssembly == null) { if (currentAssemblyIndex < asmList.Count) { entryAssembly = asmList .Skip(currentAssemblyIndex) .LastOrDefault(asm => !asm.GlobalAssemblyCache); } else { entryAssembly = asmList.LastOrDefault(asm => !asm.GlobalAssemblyCache); } } if (entryAssembly == null) { MethodBase method = new StackTrace().GetFrames().Last().GetMethod(); if (method != null && method.DeclaringType != null && method.DeclaringType.Assembly != null) entryAssembly = method.DeclaringType.Assembly; } Version asmVer = entryAssembly.GetName().Version; log4net.GlobalContext.Properties["Assembly.Version"] = asmVer.ToString(); log4net.GlobalContext.Properties["Assembly.Version.Short"] = string.Format("{0}_{1}", asmVer.Major, asmVer.Minor); log4net.GlobalContext.Properties["Assembly.FullName"] = entryAssembly.FullName; log4net.GlobalContext.Properties["Runtime.Version"] = entryAssembly.ImageRuntimeVersion; } catch { // unable to set up log4net properties } // Configure log4net within application configuration file // For web apps, this will work if the config info is in web.config: Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile); }