public override Task EventProcessingAsync(EventContext context) { if (!context.Event.IsError()) return Task.CompletedTask; Error error = context.Event.GetError(); if (error == null) return Task.CompletedTask; 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 Task.CompletedTask; var targetInfo = new SettingsDictionary(signature.SignatureInfo); var stackingTarget = error.GetStackingTarget(); if (stackingTarget?.Error?.StackTrace != null && stackingTarget.Error.StackTrace.Count > 0 && !targetInfo.ContainsKey("Message")) targetInfo["Message"] = stackingTarget.Error.Message; error.Data[Error.KnownDataKeys.TargetInfo] = targetInfo; foreach (var key in signature.SignatureInfo.Keys) context.StackSignatureData.Add(key, signature.SignatureInfo[key]); return Task.CompletedTask; }
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 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 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(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; }