public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 500)) { return; } foreach (var doc in ctx.Documents) { if (!(doc["ExceptionlessClientInfo"] is JObject clientInfo) || !clientInfo.HasValues || clientInfo["InstallDate"] == null) { return; } // This shouldn't hurt using DateTimeOffset to try and parse a date. It insures you won't lose any info. if (DateTimeOffset.TryParse(clientInfo["InstallDate"].ToString(), out var date)) { clientInfo.Remove("InstallDate"); clientInfo.Add("InstallDate", new JValue(date)); } else { clientInfo.Remove("InstallDate"); } } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 850)) { return; } foreach (var doc in ctx.Documents.OfType <JObject>()) { JObject current = doc; while (current != null) { var extendedData = doc["ExtendedData"] as JObject; if (extendedData != null) { if (extendedData["ExtraExceptionProperties"] != null) { extendedData.Rename("ExtraExceptionProperties", "__ExceptionInfo"); } if (extendedData["ExceptionInfo"] != null) { extendedData.Rename("ExceptionInfo", "__ExceptionInfo"); } if (extendedData["TraceInfo"] != null) { extendedData.Rename("TraceInfo", "TraceLog"); } } current = current["Inner"] as JObject; } } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 844)) return; foreach (var doc in ctx.Documents) { var requestInfo = doc["RequestInfo"] as JObject; if (requestInfo == null || !requestInfo.HasValues) return; if (requestInfo["Cookies"] != null && requestInfo["Cookies"].HasValues) { var cookies = requestInfo["Cookies"] as JObject; if (cookies != null) cookies.Remove(""); } if (requestInfo["Form"] != null && requestInfo["Form"].HasValues) { var form = requestInfo["Form"] as JObject; if (form != null) form.Remove(""); } if (requestInfo["QueryString"] != null && requestInfo["QueryString"].HasValues) { var queryString = requestInfo["QueryString"] as JObject; if (queryString != null) queryString.Remove(""); } } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version != null) return; if (ctx.Documents.Count == 0 || !ctx.Documents.First().HasValues) { ctx.Version = new Version(); return; } var doc = ctx.Documents.First(); var clientInfo = doc["ExceptionlessClientInfo"] as JObject; if (clientInfo == null || !clientInfo.HasValues || clientInfo["Version"] == null) { ctx.Version = new Version(); return; } if (clientInfo["Version"].ToString().Contains(" ")) { string version = clientInfo["Version"].ToString().Split(' ').First(); ctx.Version = new Version(version); return; } if (clientInfo["Version"].ToString().Contains("-")) { string version = clientInfo["Version"].ToString().Split('-').First(); ctx.Version = new Version(version); return; } // old version format ctx.Version = new Version(clientInfo["Version"].ToString()); }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(2, 0)) return; bool isNotFound = ctx.Document.GetPropertyStringValue("Code") == "404"; if (isNotFound) ctx.Document.Remove("Id"); else ctx.Document.RenameOrRemoveIfNullOrEmpty("Id", "ReferenceId"); ctx.Document.RenameOrRemoveIfNullOrEmpty("OccurrenceDate", "Date"); ctx.Document.Remove("OrganizationId"); ctx.Document.Remove("ProjectId"); ctx.Document.Remove("ErrorStackId"); ctx.Document.Remove("ExceptionlessClientInfo"); ctx.Document.Remove("IsFixed"); ctx.Document.Remove("IsHidden"); ctx.Document.RemoveIfNullOrEmpty("Tags"); ctx.Document.RenameOrRemoveIfNullOrEmpty("RequestInfo", "req"); ctx.Document.RenameOrRemoveIfNullOrEmpty("EnvironmentInfo", "env"); ctx.Document.RenameAll("ExtendedData", "Data"); var extendedData = ctx.Document.Property("Data") != null ? ctx.Document.Property("Data").Value as JObject : null; if (extendedData != null) extendedData.RenameOrRemoveIfNullOrEmpty("TraceLog", "trace"); var error = new JObject(); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "Code"); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "Type"); error.CopyOrRemoveIfNullOrEmpty(ctx.Document, "Message"); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "Inner"); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "StackTrace"); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "TargetMethod"); error.MoveOrRemoveIfNullOrEmpty(ctx.Document, "Modules"); MoveExtraExceptionProperties(error, extendedData); var inner = error["inner"] as JObject; while (inner != null) { MoveExtraExceptionProperties(inner); inner = inner["inner"] as JObject; } ctx.Document.Add("Type", new JValue(isNotFound ? "404" : "error")); ctx.Document.Add("err", error); string emailAddress = ctx.Document.GetPropertyStringValueAndRemove("UserEmail"); string userDescription = ctx.Document.GetPropertyStringValueAndRemove("UserDescription"); if (!String.IsNullOrWhiteSpace(emailAddress) && !String.IsNullOrWhiteSpace(userDescription)) ctx.Document.Add("desc", JObject.FromObject(new UserDescription(emailAddress, userDescription))); string identity = ctx.Document.GetPropertyStringValueAndRemove("UserName"); if (!String.IsNullOrWhiteSpace(identity)) ctx.Document.Add("user", JObject.FromObject(new UserInfo(identity))); ctx.Document.RemoveAllIfNullOrEmpty("Data"); ctx.Document.RemoveAllIfNullOrEmpty("GenericArguments"); ctx.Document.RemoveAllIfNullOrEmpty("Parameters"); }
public void ParseEvents(string errorFilePath) { var json = File.ReadAllText(errorFilePath); var ctx = new EventUpgraderContext(json); _eventUpgraderPluginManager.Upgrade(ctx); ApprovalsUtility.VerifyFile(Path.ChangeExtension(errorFilePath, ".expected.json"), ctx.Document.ToString()); var events = _eventParserPluginManager.ParseEvents(ctx.Document.ToString(), 2, "exceptionless/2.0.0.0"); Assert.Equal(1, events.Count); }
/// <summary> /// Runs all of the event upgrade plugins upgrade method. /// </summary> public void Upgrade(EventUpgraderContext context) { foreach (var plugin in Plugins.Values.ToList()) { try { plugin.Upgrade(context); } catch (Exception ex) { Logger.Error().Exception(ex).Message("Error calling upgrade in plugin \"{0}\": {1}", plugin.GetType().FullName, ex.Message).Property("Context", context).Write(); throw; } } }
public List<PersistentEvent> ParseEvents(string input, int apiVersion, string userAgent) { if (apiVersion != 1) return null; try { var ctx = new EventUpgraderContext(input); _manager.Upgrade(ctx); return ctx.Documents.FromJson<PersistentEvent>(_settings); } catch (Exception ex) { Logger.Error().Message("Error parsing event: {0}", ex.Message).Exception(ex).Write(); return null; } }
/// <summary> /// Runs all of the event upgrade plugins upgrade method. /// </summary> public async Task UpgradeAsync(EventUpgraderContext context) { string metricPrefix = String.Concat(_metricPrefix, nameof(UpgradeAsync).ToLower(), "."); foreach (var plugin in Plugins.Values.ToList()) { string metricName = String.Concat(metricPrefix, plugin.Name.ToLower()); try { await _metricsClient.TimeAsync(() => plugin.Upgrade(context), metricName).AnyContext(); } catch (Exception ex) { _logger.Error().Exception(ex).Message("Error calling upgrade in plugin \"{0}\": {1}", plugin.Name, ex.Message).Property("Context", context).Write(); throw; } } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 500)) return; var clientInfo = ctx.Document["ExceptionlessClientInfo"] as JObject; if (clientInfo == null || !clientInfo.HasValues || clientInfo["InstallDate"] == null) return; DateTimeOffset date; // This shouldn't hurt using DateTimeOffset to try and parse a date. It insures you won't lose any info. if (DateTimeOffset.TryParse(clientInfo["InstallDate"].ToString(), out date)) { clientInfo.Remove("InstallDate"); clientInfo.Add("InstallDate", new JValue(date)); } else clientInfo.Remove("InstallDate"); }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 844)) { return; } foreach (var doc in ctx.Documents) { var requestInfo = doc["RequestInfo"] as JObject; if (requestInfo == null || !requestInfo.HasValues) { return; } if (requestInfo["Cookies"] != null && requestInfo["Cookies"].HasValues) { var cookies = requestInfo["Cookies"] as JObject; if (cookies != null) { cookies.Remove(""); } } if (requestInfo["Form"] != null && requestInfo["Form"].HasValues) { var form = requestInfo["Form"] as JObject; if (form != null) { form.Remove(""); } } if (requestInfo["QueryString"] != null && requestInfo["QueryString"].HasValues) { var queryString = requestInfo["QueryString"] as JObject; if (queryString != null) { queryString.Remove(""); } } } }
/// <summary> /// Runs all of the event upgrade plugins upgrade method. /// </summary> public void Upgrade(EventUpgraderContext context) { string metricPrefix = String.Concat(_metricPrefix, nameof(Upgrade).ToLower(), "."); foreach (var plugin in Plugins.Values.ToList()) { string metricName = String.Concat(metricPrefix, plugin.Name.ToLower()); try { _metricsClient.Time(() => plugin.Upgrade(context), metricName); } catch (Exception ex) { using (_logger.BeginScope(new Dictionary <string, object> { { "Context", context } })) _logger.LogError(ex, "Error calling upgrade in plugin {PluginName}: {Message}", plugin.Name, ex.Message); throw; } } }
public List<PersistentEvent> ParseEvents(string input, int apiVersion, string userAgent) { if (apiVersion != 1) return null; try { var ctx = new EventUpgraderContext(input); _manager.Upgrade(ctx); var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore, ContractResolver = new ExtensionContractResolver() }; return ctx.Documents.FromJson<PersistentEvent>(settings); } catch (Exception ex) { ex.ToExceptionless().AddObject(input, "Error").AddObject(apiVersion, "Api Version").Submit(); return null; } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 850)) return; JObject current = ctx.Document; while (current != null) { var extendedData = ctx.Document["ExtendedData"] as JObject; if (extendedData != null) { if (extendedData["ExtraExceptionProperties"] != null) extendedData.Rename("ExtraExceptionProperties", "__ExceptionInfo"); if (extendedData["ExceptionInfo"] != null) extendedData.Rename("ExceptionInfo", "__ExceptionInfo"); if (extendedData["TraceInfo"] != null) extendedData.Rename("TraceInfo", "TraceLog"); } current = current["Inner"] as JObject; } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(1, 0, 0, 844)) { return; } foreach (var doc in ctx.Documents) { if (!(doc["RequestInfo"] is JObject requestInfo) || !requestInfo.HasValues) { return; } if (requestInfo["Cookies"] != null && requestInfo["Cookies"].HasValues) { if (requestInfo["Cookies"] is JObject cookies) { cookies.Remove(""); } } if (requestInfo["Form"] != null && requestInfo["Form"].HasValues) { if (requestInfo["Form"] is JObject form) { form.Remove(""); } } if (requestInfo["QueryString"] != null && requestInfo["QueryString"].HasValues) { if (requestInfo["QueryString"] is JObject queryString) { queryString.Remove(""); } } } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version != null) { return; } if (ctx.Documents.Count == 0 || !ctx.Documents.First().HasValues) { ctx.Version = new Version(); return; } var doc = ctx.Documents.First(); var clientInfo = doc["ExceptionlessClientInfo"] as JObject; if (clientInfo == null || !clientInfo.HasValues || clientInfo["Version"] == null) { ctx.Version = new Version(); return; } if (clientInfo["Version"].ToString().Contains(" ")) { string version = clientInfo["Version"].ToString().Split(' ').First(); ctx.Version = new Version(version); return; } if (clientInfo["Version"].ToString().Contains("-")) { string version = clientInfo["Version"].ToString().Split('-').First(); ctx.Version = new Version(version); return; } // old version format ctx.Version = new Version(clientInfo["Version"].ToString()); }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(2, 0)) return; foreach (var doc in ctx.Documents.OfType<JObject>()) { bool isNotFound = doc.GetPropertyStringValue("Code") == "404"; if (ctx.IsMigration) { doc.Rename("ErrorStackId", "StackId"); } else { doc.RenameOrRemoveIfNullOrEmpty("Id", "ReferenceId"); doc.Remove("OrganizationId"); doc.Remove("ProjectId"); doc.Remove("ErrorStackId"); } doc.RenameOrRemoveIfNullOrEmpty("OccurrenceDate", "Date"); doc.Remove("ExceptionlessClientInfo"); if (!doc.RemoveIfNullOrEmpty("Tags")) { var tags = doc.GetValue("Tags"); if (tags.Type == JTokenType.Array) { foreach (JToken tag in tags.ToList()) { string t = tag.ToString(); if (String.IsNullOrEmpty(t) || t.Length > 255) tag.Remove(); } } } doc.RenameOrRemoveIfNullOrEmpty("RequestInfo", "@request"); bool hasRequestInfo = doc["@request"] != null; if (!isNotFound) doc.RenameOrRemoveIfNullOrEmpty("EnvironmentInfo", "@environment"); else doc.Remove("EnvironmentInfo"); doc.RenameAll("ExtendedData", "Data"); var extendedData = doc.Property("Data") != null ? doc.Property("Data").Value as JObject : null; if (extendedData != null) { if (!isNotFound) extendedData.RenameOrRemoveIfNullOrEmpty("TraceLog", "@trace"); else extendedData.Remove("TraceLog"); } if (isNotFound && hasRequestInfo) { doc.RemoveAll("Code", "Type", "Message", "Inner", "StackTrace", "TargetMethod", "Modules"); if (extendedData?["__ExceptionInfo"] != null) extendedData.Remove("__ExceptionInfo"); doc.Add("Type", new JValue("404")); } else { var error = new JObject(); if (!doc.RemoveIfNullOrEmpty("Message")) error.Add("Message", doc["Message"].Value<string>()); error.MoveOrRemoveIfNullOrEmpty(doc, "Code", "Type", "Inner", "StackTrace", "TargetMethod", "Modules"); // Copy the exception info from root extended data to the current errors extended data. if (extendedData?["__ExceptionInfo"] != null) { error.Add("Data", new JObject()); ((JObject)error["Data"]).MoveOrRemoveIfNullOrEmpty(extendedData, "__ExceptionInfo"); } string id = doc["Id"] != null ? doc["Id"].Value<string>(): null; string projectId = doc["ProjectId"] != null ? doc["ProjectId"].Value<string>() : null; RenameAndValidateExtraExceptionProperties(projectId, id, error); var inner = error["Inner"] as JObject; while (inner != null) { RenameAndValidateExtraExceptionProperties(projectId, id, inner); inner = inner["Inner"] as JObject; } doc.Add("Type", new JValue(isNotFound ? "404" : "error")); doc.Add("@error", error); } string emailAddress = doc.GetPropertyStringValueAndRemove("UserEmail"); string userDescription = doc.GetPropertyStringValueAndRemove("UserDescription"); if (!String.IsNullOrWhiteSpace(emailAddress) && !String.IsNullOrWhiteSpace(userDescription)) doc.Add("@user_description", JObject.FromObject(new UserDescription(emailAddress, userDescription))); string identity = doc.GetPropertyStringValueAndRemove("UserName"); if (!String.IsNullOrWhiteSpace(identity)) doc.Add("@user", JObject.FromObject(new UserInfo(identity))); doc.RemoveAllIfNullOrEmpty("Data", "GenericArguments", "Parameters"); } }
public void Upgrade(EventUpgraderContext ctx) { if (ctx.Version > new Version(2, 0)) { return; } foreach (var doc in ctx.Documents.OfType <JObject>()) { bool isNotFound = doc.GetPropertyStringValue("Code") == "404"; if (ctx.IsMigration) { doc.Rename("ErrorStackId", "StackId"); } else { doc.RenameOrRemoveIfNullOrEmpty("Id", "ReferenceId"); doc.Remove("OrganizationId"); doc.Remove("ProjectId"); doc.Remove("ErrorStackId"); } doc.RenameOrRemoveIfNullOrEmpty("OccurrenceDate", "Date"); doc.Remove("ExceptionlessClientInfo"); if (!doc.RemoveIfNullOrEmpty("Tags")) { var tags = doc.GetValue("Tags"); if (tags.Type == JTokenType.Array) { foreach (JToken tag in tags.ToList()) { string t = tag.ToString(); if (String.IsNullOrEmpty(t) || t.Length > 255) { tag.Remove(); } } } } doc.RenameOrRemoveIfNullOrEmpty("RequestInfo", "@request"); bool hasRequestInfo = doc["@request"] != null; if (!isNotFound) { doc.RenameOrRemoveIfNullOrEmpty("EnvironmentInfo", "@environment"); } else { doc.Remove("EnvironmentInfo"); } doc.RenameAll("ExtendedData", "Data"); var extendedData = doc.Property("Data") != null?doc.Property("Data").Value as JObject : null; if (extendedData != null) { if (!isNotFound) { extendedData.RenameOrRemoveIfNullOrEmpty("TraceLog", "@trace"); } else { extendedData.Remove("TraceLog"); } } if (isNotFound && hasRequestInfo) { doc.RemoveAll("Code", "Type", "Message", "Inner", "StackTrace", "TargetMethod", "Modules"); if (extendedData != null && extendedData["__ExceptionInfo"] != null) { extendedData.Remove("__ExceptionInfo"); } doc.Add("Type", new JValue("404")); } else { var error = new JObject(); if (!doc.RemoveIfNullOrEmpty("Message")) { error.Add("Message", doc["Message"].Value <string>()); } error.MoveOrRemoveIfNullOrEmpty(doc, "Code", "Type", "Inner", "StackTrace", "TargetMethod", "Modules"); // Copy the exception info from root extended data to the current errors extended data. if (extendedData != null && extendedData["__ExceptionInfo"] != null) { error.Add("Data", new JObject()); ((JObject)error["Data"]).MoveOrRemoveIfNullOrEmpty(extendedData, "__ExceptionInfo"); } string id = doc["Id"] != null ? doc["Id"].Value <string>(): null; string projectId = doc["ProjectId"] != null ? doc["ProjectId"].Value <string>() : null; RenameAndValidateExtraExceptionProperties(projectId, id, error); var inner = error["Inner"] as JObject; while (inner != null) { RenameAndValidateExtraExceptionProperties(projectId, id, inner); inner = inner["Inner"] as JObject; } doc.Add("Type", new JValue(isNotFound ? "404" : "error")); doc.Add("@error", error); } string emailAddress = doc.GetPropertyStringValueAndRemove("UserEmail"); string userDescription = doc.GetPropertyStringValueAndRemove("UserDescription"); if (!String.IsNullOrWhiteSpace(emailAddress) && !String.IsNullOrWhiteSpace(userDescription)) { doc.Add("@user_description", JObject.FromObject(new UserDescription(emailAddress, userDescription))); } string identity = doc.GetPropertyStringValueAndRemove("UserName"); if (!String.IsNullOrWhiteSpace(identity)) { doc.Add("@user", JObject.FromObject(new UserInfo(identity))); } doc.RemoveAllIfNullOrEmpty("Data", "GenericArguments", "Parameters"); } }
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; }