public StackingInfo(Error error, ErrorSignatureFactory errorSignatureFactory) { if (error == null) { throw new ArgumentNullException("error"); } ErrorInfo innerMostError = error.GetInnermostError(); Method defaultMethod = innerMostError.StackTrace != null?innerMostError.StackTrace.FirstOrDefault() : null; if (defaultMethod == null && error.StackTrace != null) { defaultMethod = error.StackTrace.FirstOrDefault(); } Tuple <ErrorInfo, Method> st = error.GetStackingTarget(); // if we can't find the info, try doing a new signature to mark the target. if (st == null) { ErrorSignature sig = errorSignatureFactory.GetSignature(error); st = error.GetStackingTarget(); } Error = st != null ? st.Item1 ?? error : error.GetInnermostError(); Method = st != null ? st.Item2 : defaultMethod; if (error.Code == "404" && error.RequestInfo != null && !String.IsNullOrEmpty(error.RequestInfo.Path)) { Is404 = true; Path = error.RequestInfo.Path; } }
public override Task EventProcessingAsync(EventContext context) { if (!context.Event.IsError()) { return(Task.CompletedTask); } var error = context.Event.GetError(); if (error == null) { return(Task.CompletedTask); } if (String.IsNullOrWhiteSpace(context.Event.Message)) { context.Event.Message = error.Message; } if (context.StackSignatureData.Count > 0) { return(Task.CompletedTask); } string[] commonUserMethods = { "DataContext.SubmitChanges", "Entities.SaveChanges" }; if (context.HasProperty("CommonMethods")) { commonUserMethods = context.GetProperty <string>("CommonMethods").SplitAndTrim(new [] { ',' }); } string[] userNamespaces = null; if (context.HasProperty("UserNamespaces")) { userNamespaces = context.GetProperty <string>("UserNamespaces").SplitAndTrim(new [] { ',' }); } var signature = new ErrorSignature(error, userCommonMethods: commonUserMethods, userNamespaces: userNamespaces); if (signature.SignatureInfo.Count <= 0) { return(Task.CompletedTask); } var targetInfo = new SettingsDictionary(signature.SignatureInfo); var stackingTarget = error.GetStackingTarget(); if (stackingTarget?.Error?.StackTrace?.Count > 0 && !targetInfo.ContainsKey("Message")) { targetInfo["Message"] = stackingTarget.Error.Message; } error.Data[Error.KnownDataKeys.TargetInfo] = targetInfo; foreach (string key in signature.SignatureInfo.Keys) { context.StackSignatureData.Add(key, signature.SignatureInfo[key]); } return(Task.CompletedTask); }
public override void UpdateDocument(MongoCollection <BsonDocument> collection, BsonDocument document) { var errorRepository = new ErrorRepository(collection.Database, null, null, null); BsonValue id = document.GetDocumentId(); if (id == null || !id.IsObjectId) { return; } Error error = errorRepository.GetById(id.ToString()); if (error == null) { return; } if (document.Contains("sig")) { document.Remove("sig"); } var signatureFactory = new ErrorSignatureFactory(); // updates the document to set the IsSignatureTarget ErrorSignature signature = signatureFactory.GetSignature(error); errorRepository.Update(error); }
public override void EventProcessing(EventContext context) { if (!context.Event.IsError()) { return; } Error error = context.Event.GetError(); if (error == null) { return; } if (String.IsNullOrWhiteSpace(context.Event.Message)) { context.Event.Message = error.Message; } string[] commonUserMethods = { "DataContext.SubmitChanges", "Entities.SaveChanges" }; if (context.HasProperty("CommonMethods")) { commonUserMethods = context.GetProperty <string>("CommonMethods").SplitAndTrim(','); } string[] userNamespaces = null; if (context.HasProperty("UserNamespaces")) { userNamespaces = context.GetProperty <string>("UserNamespaces").SplitAndTrim(','); } var signature = new ErrorSignature(error, userCommonMethods: commonUserMethods, userNamespaces: userNamespaces); if (signature.SignatureInfo.Count <= 0) { return; } var targetInfo = new SettingsDictionary(signature.SignatureInfo); var stackingTarget = error.GetStackingTarget(); if (stackingTarget != null && stackingTarget.Error != null) { targetInfo.Add("Message", error.GetStackingTarget().Error.Message); } error.Data[Error.KnownDataKeys.TargetInfo] = targetInfo; foreach (var key in signature.SignatureInfo.Keys) { context.StackSignatureData.Add(key, signature.SignatureInfo[key]); } }
public void CommonMethodTest() { try { CommonMethodA(5); } catch (Exception e) { Error ed = e.ToErrorModel(); var sig = new ErrorSignature(ed, _userNamespaces, _commonMethods); Assert.Equal("System.Exception", sig.SignatureInfo["ExceptionType"]); Assert.Equal("Exceptionless.Tests.Stacking.ErrorSignatureTests.CommonMethodTest()", sig.SignatureInfo["Method"]); } }
public void ExceptionWithExtras() { try { throw new WithExtrasException { ErrorCode = 234423, Number = 55, SomeBool = true, SomeEnum = SomeEnum.Value2 }; } catch (Exception ex) { Error ed = ex.ToErrorModel(); var sig = new ErrorSignature(ed, _userNamespaces, _commonMethods); Assert.Equal("Exceptionless.Tests.Stacking.WithExtrasException", sig.SignatureInfo["ExceptionType"]); Assert.Equal("Exceptionless.Tests.Stacking.ErrorSignatureTests.ExceptionWithExtras()", sig.SignatureInfo["Method"]); Assert.Equal("55", sig.SignatureInfo["Number"]); } }
public override void EventProcessing(EventContext context) { if (!context.Event.IsError()) { return; } Error error = context.Event.GetError(); if (error == null) { return; } if (String.IsNullOrWhiteSpace(context.Event.Message)) { context.Event.Message = error.Message; } string[] commonUserMethods = { "DataContext.SubmitChanges", "Entities.SaveChanges" }; if (context.HasProperty("CommonMethods")) { commonUserMethods = context.GetProperty <string>("CommonMethods").SplitAndTrim(','); } string[] userNamespaces = null; if (context.HasProperty("UserNamespaces")) { userNamespaces = context.GetProperty <string>("UserNamespaces").SplitAndTrim(','); } var signature = new ErrorSignature(error, userCommonMethods: commonUserMethods, userNamespaces: userNamespaces); if (signature.SignatureInfo.Count <= 0) { return; } foreach (var key in signature.SignatureInfo.Keys) { context.StackSignatureData.Add(key, signature.SignatureInfo[key]); } }
public void NestedExceptionSignature() { ApplicationException appEx; try { throw new Exception("iBland"); } catch (Exception ex) { try { throw new ArgumentException("iThrow", ex); } catch (Exception argEx) { appEx = new ApplicationException("iWrap", argEx); } } Error ed = appEx.ToErrorModel(); var sig = new ErrorSignature(ed, _userNamespaces); Assert.Equal("System.Exception", sig.SignatureInfo["ExceptionType"]); Assert.Equal("Exceptionless.Tests.Stacking.ErrorSignatureTests.NestedExceptionSignature()", sig.SignatureInfo["Method"]); }
public void FromDeepCallstackException() { ApplicationException appEx = null; try { SampleErrors.ThrowExceptionFromSubSubMethod(); } catch (Exception ex) { try { throw new ArgumentException("iThrow", ex); } catch (Exception argEx) { appEx = new ApplicationException("iWrap", argEx); } } Assert.NotNull(appEx); Error ed = appEx.ToErrorModel(); var sig = new ErrorSignature(ed); Assert.Equal("System.ApplicationException", sig.SignatureInfo["ExceptionType"]); Assert.Equal("Samples.SampleErrors.SubMethod()", sig.SignatureInfo["Method"]); }
public void FromLamda() { ApplicationException appEx = null; try { SampleErrors.ThrowExceptionFromLambda(); } catch (Exception ex) { try { throw new ArgumentException("iThrow", ex); } catch (Exception argEx) { appEx = new ApplicationException("iWrap", argEx); } } Assert.NotNull(appEx); Error ed = appEx.ToErrorModel(); var sig = new ErrorSignature(ed); Assert.Equal("System.ApplicationException", sig.SignatureInfo["ExceptionType"]); Assert.Equal("Samples.SampleErrors.<ThrowExceptionFromLambda>b__0(String s, Int32 b)", sig.SignatureInfo["Method"]); }
protected override async Task <JobResult> RunInternalAsync(CancellationToken token) { OutputPublicIp(); QueueEntry <EventMigrationBatch> queueEntry = null; try { queueEntry = _queue.Dequeue(); } catch (Exception ex) { if (!(ex is TimeoutException)) { Log.Error().Exception(ex).Message("Error trying to dequeue message: {0}", ex.Message).Write(); return(JobResult.FromException(ex)); } } if (queueEntry == null) { return(JobResult.Success); } Log.Info().Message("Processing event migration jobs for date range: {0}-{1}", new DateTimeOffset(queueEntry.Value.StartTicks, TimeSpan.Zero).ToString("O"), new DateTimeOffset(queueEntry.Value.EndTicks, TimeSpan.Zero).ToString("O")).Write(); int total = 0; var stopwatch = new Stopwatch(); stopwatch.Start(); var errorCollection = GetErrorCollection(); var knownStackIds = new List <string>(); var serializerSettings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore }; serializerSettings.AddModelConverters(); var query = Query.And(Query.GTE(ErrorFieldNames.OccurrenceDate_UTC, queueEntry.Value.StartTicks), Query.LT(ErrorFieldNames.OccurrenceDate_UTC, queueEntry.Value.EndTicks)); var errors = errorCollection.Find(query).SetSortOrder(SortBy.Ascending(ErrorFieldNames.OccurrenceDate_UTC)).SetLimit(_batchSize).ToList(); while (errors.Count > 0) { Log.Info().Message("Migrating events {0}-{1} {2:N0} total {3:N0}/s...", errors.First().Id, errors.Last().Id, total, total > 0 ? total / stopwatch.Elapsed.TotalSeconds : 0).Write(); var upgradedErrors = JArray.FromObject(errors); var ctx = new EventUpgraderContext(upgradedErrors, new Version(1, 5), true); _eventUpgraderPluginManager.Upgrade(ctx); var upgradedEvents = upgradedErrors.FromJson <PersistentEvent>(serializerSettings); var stackIdsToCheck = upgradedEvents.Where(e => !knownStackIds.Contains(e.StackId)).Select(e => e.StackId).Distinct().ToArray(); if (stackIdsToCheck.Length > 0) { knownStackIds.AddRange(_eventRepository.ExistsByStackIds(stackIdsToCheck)); } upgradedEvents.ForEach(e => { if (e.Date.UtcDateTime > DateTimeOffset.UtcNow.AddHours(1)) { e.Date = DateTimeOffset.Now; } e.CreatedUtc = e.Date.ToUniversalTime().DateTime; if (!knownStackIds.Contains(e.StackId)) { // We haven't processed this stack id yet in this run. Check to see if this stack has already been imported.. e.IsFirstOccurrence = true; knownStackIds.Add(e.StackId); } var request = e.GetRequestInfo(); if (request != null) { e.AddRequestInfo(request.ApplyDataExclusions(RequestInfoPlugin.DefaultExclusions, RequestInfoPlugin.MAX_VALUE_LENGTH)); } foreach (var ip in GetIpAddresses(e, request)) { var location = _geoIpResolver.ResolveIp(ip); if (location == null || !location.IsValid()) { continue; } e.Geo = location.ToString(); break; } if (e.Type == Event.KnownTypes.NotFound && request != null) { if (String.IsNullOrWhiteSpace(e.Source)) { e.Message = null; e.Source = request.GetFullPath(includeHttpMethod: true, includeHost: false, includeQueryString: false); } return; } var error = e.GetError(); if (error == null) { Debugger.Break(); Log.Error().Project(e.ProjectId).Message("Unable to get parse error model: {0}", e.Id).Write(); return; } var stackingTarget = error.GetStackingTarget(); if (stackingTarget != null && stackingTarget.Method != null && !String.IsNullOrEmpty(stackingTarget.Method.GetDeclaringTypeFullName())) { e.Source = stackingTarget.Method.GetDeclaringTypeFullName().Truncate(2000); } var signature = new ErrorSignature(error); if (signature.SignatureInfo.Count <= 0) { return; } var targetInfo = new SettingsDictionary(signature.SignatureInfo); if (stackingTarget != null && stackingTarget.Error != null && !targetInfo.ContainsKey("Message")) { targetInfo["Message"] = error.GetStackingTarget().Error.Message; } error.Data[Error.KnownDataKeys.TargetInfo] = targetInfo; }); try { _eventRepository.Add(upgradedEvents, sendNotification: false); } catch (Exception) { foreach (var persistentEvent in upgradedEvents) { try { _eventRepository.Add(persistentEvent, sendNotification: false); } catch (Exception ex) { //Debugger.Break(); Log.Error().Exception(ex).Message("An error occurred while migrating event '{0}': {1}", persistentEvent.Id, ex.Message).Write(); } } } total += upgradedEvents.Count; var lastId = upgradedEvents.Last().Id; _cache.Set("migration-errorid", lastId); errors = errorCollection.Find(Query.And(Query.GT(ErrorFieldNames.Id, ObjectId.Parse(lastId)), Query.LT(ErrorFieldNames.OccurrenceDate_UTC, queueEntry.Value.EndTicks))) .SetSortOrder(SortBy.Ascending(ErrorFieldNames.OccurrenceDate_UTC)) .SetLimit(_batchSize).ToList(); } _cache.Set("migration-completedday", queueEntry.Value.EndTicks); queueEntry.Complete(); return(JobResult.Success); }
protected override async Task <JobResult> RunInternalAsync(CancellationToken token) { OutputPublicIp(); QueueEntry <EventMigrationBatch> queueEntry = null; try { queueEntry = _queue.Dequeue(TimeSpan.FromSeconds(1)); } catch (Exception ex) { if (!(ex is TimeoutException)) { Log.Error().Exception(ex).Message("Error trying to dequeue message: {0}", ex.Message).Write(); return(JobResult.FromException(ex)); } } if (queueEntry == null) { return(JobResult.Success); } Log.Info().Message("Processing event migration jobs for date range: {0}-{1}", new DateTimeOffset(queueEntry.Value.StartTicks, TimeSpan.Zero).ToString("O"), new DateTimeOffset(queueEntry.Value.EndTicks, TimeSpan.Zero).ToString("O")).Write(); int total = 0; var stopwatch = new Stopwatch(); stopwatch.Start(); var errorCollection = GetErrorCollection(); var knownStackIds = new List <string>(); var userAgentParser = Parser.GetDefault(); var query = Query.And(Query.GTE(ErrorFieldNames.OccurrenceDate_UTC, queueEntry.Value.StartTicks), Query.LT(ErrorFieldNames.OccurrenceDate_UTC, queueEntry.Value.EndTicks)); var errors = errorCollection.Find(query).SetSortOrder(SortBy.Ascending(ErrorFieldNames.OccurrenceDate_UTC)).SetLimit(_batchSize).ToList(); int batch = 0; while (errors.Count > 0) { Log.Info().Message("Migrating events {0}-{1} {2:N0} total {3:N0}/s...", errors.First().Id, errors.Last().Id, total, total > 0 ? total / stopwatch.Elapsed.TotalSeconds : 0).Write(); var upgradedErrors = JArray.FromObject(errors); var ctx = new EventUpgraderContext(upgradedErrors, new Version(1, 5), true); _eventUpgraderPluginManager.Upgrade(ctx); var upgradedEvents = upgradedErrors.FromJson <PersistentEvent>(_settings); var stackIdsToCheck = upgradedEvents.Where(e => !knownStackIds.Contains(e.StackId)).Select(e => e.StackId).Distinct().ToArray(); if (stackIdsToCheck.Length > 0) { knownStackIds.AddRange(_eventRepository.ExistsByStackIds(stackIdsToCheck)); } upgradedEvents.ForEach(async e => { if (e.Date.UtcDateTime > DateTimeOffset.UtcNow.AddHours(1)) { e.Date = DateTimeOffset.Now; } e.CreatedUtc = e.Date.ToUniversalTime().DateTime; // Truncate really large fields if (e.Message != null && e.Message.Length > 2000) { Log.Error().Project(e.ProjectId).Message("Event: {0} Message is Too Big: {1}", e.Id, e.Message.Length).Write(); e.Message = e.Message.Truncate(2000); } if (e.Source != null && e.Source.Length > 2000) { Log.Error().Project(e.ProjectId).Message("Event: {0} Source is Too Big: {1}", e.Id, e.Source.Length).Write(); e.Source = e.Source.Truncate(2000); } if (!knownStackIds.Contains(e.StackId)) { // We haven't processed this stack id yet in this run. Check to see if this stack has already been imported.. e.IsFirstOccurrence = true; knownStackIds.Add(e.StackId); } var request = e.GetRequestInfo(); if (request != null) { request = request.ApplyDataExclusions(RequestInfoPlugin.DefaultExclusions, RequestInfoPlugin.MAX_VALUE_LENGTH); if (!String.IsNullOrEmpty(request.UserAgent)) { try { var info = userAgentParser.Parse(request.UserAgent); if (!String.Equals(info.UserAgent.Family, "Other")) { request.Data[RequestInfo.KnownDataKeys.Browser] = info.UserAgent.Family; if (!String.IsNullOrEmpty(info.UserAgent.Major)) { request.Data[RequestInfo.KnownDataKeys.BrowserVersion] = String.Join(".", new[] { info.UserAgent.Major, info.UserAgent.Minor, info.UserAgent.Patch }.Where(v => !String.IsNullOrEmpty(v))); request.Data[RequestInfo.KnownDataKeys.BrowserMajorVersion] = info.UserAgent.Major; } } if (!String.Equals(info.Device.Family, "Other")) { request.Data[RequestInfo.KnownDataKeys.Device] = info.Device.Family; } if (!String.Equals(info.OS.Family, "Other")) { request.Data[RequestInfo.KnownDataKeys.OS] = info.OS.Family; if (!String.IsNullOrEmpty(info.OS.Major)) { request.Data[RequestInfo.KnownDataKeys.OSVersion] = String.Join(".", new[] { info.OS.Major, info.OS.Minor, info.OS.Patch }.Where(v => !String.IsNullOrEmpty(v))); request.Data[RequestInfo.KnownDataKeys.OSMajorVersion] = info.OS.Major; } } request.Data[RequestInfo.KnownDataKeys.IsBot] = info.Device.IsSpider; } catch (Exception ex) { Log.Warn().Project(e.ProjectId).Message("Unable to parse user agent {0}. Exception: {1}", request.UserAgent, ex.Message).Write(); } } e.AddRequestInfo(request); } foreach (var ip in GetIpAddresses(e, request)) { var location = await _geoIpResolver.ResolveIpAsync(ip, token); if (location == null || !location.IsValid()) { continue; } e.Geo = location.ToString(); break; } if (e.Type == Event.KnownTypes.NotFound && request != null) { if (String.IsNullOrWhiteSpace(e.Source)) { e.Message = null; e.Source = request.GetFullPath(includeHttpMethod: true, includeHost: false, includeQueryString: false); } return; } var error = e.GetError(); if (error == null) { Debugger.Break(); Log.Error().Project(e.ProjectId).Message("Unable to get parse error model: {0}", e.Id).Write(); return; } var stackingTarget = error.GetStackingTarget(); if (stackingTarget != null && stackingTarget.Method != null && !String.IsNullOrEmpty(stackingTarget.Method.GetDeclaringTypeFullName())) { e.Source = stackingTarget.Method.GetDeclaringTypeFullName().Truncate(2000); } var signature = new ErrorSignature(error); if (signature.SignatureInfo.Count <= 0) { return; } var targetInfo = new SettingsDictionary(signature.SignatureInfo); if (stackingTarget != null && stackingTarget.Error != null && !targetInfo.ContainsKey("Message")) { targetInfo["Message"] = stackingTarget.Error.Message; } error.Data[Error.KnownDataKeys.TargetInfo] = targetInfo; }); Log.Info().Message("Saving events {0}-{1} {2:N0} total", errors.First().Id, errors.Last().Id, upgradedEvents.Count).Write(); try { _eventRepository.Add(upgradedEvents, sendNotification: false); } catch (Exception) { foreach (var persistentEvent in upgradedEvents) { try { _eventRepository.Add(persistentEvent, sendNotification: false); } catch (Exception ex) { //Debugger.Break(); Log.Error().Exception(ex).Project(persistentEvent.ProjectId).Message("An error occurred while migrating event '{0}': {1}", persistentEvent.Id, ex.Message).Write(); } } } batch++; total += upgradedEvents.Count; Log.Info().Message("Getting next batch of events").Write(); var sw = new Stopwatch(); sw.Start(); errors = errorCollection.Find(query).SetSortOrder(SortBy.Ascending(ErrorFieldNames.OccurrenceDate_UTC)).SetLimit(_batchSize).SetSkip(_batchSize * batch).ToList(); sw.Stop(); Log.Info().Message("Finished getting next batch of events in {0}ms", sw.ElapsedMilliseconds).Write(); } Log.Info().Message("Finished processing event migration jobs for date range: {0}-{1}", new DateTimeOffset(queueEntry.Value.StartTicks, TimeSpan.Zero).ToString("O"), new DateTimeOffset(queueEntry.Value.EndTicks, TimeSpan.Zero).ToString("O")).Write(); _cache.Set("migration-completedperiod", queueEntry.Value.EndTicks); queueEntry.Complete(); return(JobResult.Success); }