private WebHookDataContext GetWebHookDataContext(Version version) { string json = File.ReadAllText(Path.GetFullPath(Path.Combine("..", "..", "..", "ErrorData", "1477.expected.json"))); var settings = GetService <JsonSerializerSettings>(); settings.Formatting = Formatting.Indented; var ev = JsonConvert.DeserializeObject <PersistentEvent>(json, settings); ev.OrganizationId = TestConstants.OrganizationId; ev.ProjectId = TestConstants.ProjectId; ev.StackId = TestConstants.StackId; ev.Id = TestConstants.EventId; var context = new WebHookDataContext(version, ev, OrganizationData.GenerateSampleOrganization(GetService <BillingManager>(), GetService <BillingPlans>()), ProjectData.GenerateSampleProject()) { Stack = StackData.GenerateStack(id: TestConstants.StackId, organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId, title: _formatter.GetStackTitle(ev), signatureHash: "722e7afd4dca4a3c91f4d94fec89dfdc") }; context.Stack.Tags = new TagSet { "Test" }; context.Stack.FirstOccurrence = context.Stack.LastOccurrence = ev.Date.UtcDateTime; return(context); }
public override async Task <object> CreateFromStackAsync(WebHookDataContext ctx) { if (ctx.Stack == null) { throw new ArgumentException("Stack cannot be null."); } if (ctx.Project == null) { ctx.Project = await _projectRepository.GetByIdAsync(ctx.Stack.ProjectId, o => o.Cache()).AnyContext(); } if (ctx.Project == null) { throw new ArgumentException("Project not found."); } if (ctx.Organization == null) { ctx.Organization = await _organizationRepository.GetByIdAsync(ctx.Stack.OrganizationId, o => o.Cache()).AnyContext(); } if (ctx.Organization == null) { throw new ArgumentException("Organization not found."); } return(null); }
private WebHookDataContext GetWebHookDataContext(Version version) { var json = File.ReadAllText(Path.GetFullPath(@"..\..\ErrorData\1477.expected.json")); var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore, ContractResolver = new ExtensionContractResolver() }; var ev = JsonConvert.DeserializeObject <PersistentEvent>(json, settings); ev.OrganizationId = TestConstants.OrganizationId; ev.ProjectId = TestConstants.ProjectId; ev.StackId = TestConstants.StackId; var context = new WebHookDataContext(version, ev, OrganizationData.GenerateSampleOrganization(), ProjectData.GenerateSampleProject()); context.Stack = StackData.GenerateStack(id: TestConstants.StackId, organizationId: TestConstants.OrganizationId, projectId: TestConstants.ProjectId, title: _formattingPluginManager.GetStackTitle(ev), signatureHash: "722e7afd4dca4a3c91f4d94fec89dfdc"); context.Stack.Tags = new TagSet { "Test" }; context.Stack.FirstOccurrence = context.Stack.LastOccurrence = ev.Date.DateTime; return(context); }
public override Task <object> CreateFromStackAsync(WebHookDataContext ctx) { if (!String.Equals(ctx.Version, Models.WebHook.KnownVersions.Version1)) { return(Task.FromResult <object>(null)); } return(Task.FromResult <object>(new VersionOneWebHookStack(_options.BaseURL) { Id = ctx.Stack.Id, Status = ctx.Stack.Status, Title = ctx.Stack.Title, Description = ctx.Stack.Description, Tags = ctx.Stack.Tags, RequestPath = ctx.Stack.SignatureInfo.ContainsKey("Path") ? ctx.Stack.SignatureInfo["Path"] : null, Type = ctx.Stack.SignatureInfo.ContainsKey("ExceptionType") ? ctx.Stack.SignatureInfo["ExceptionType"] : null, TargetMethod = ctx.Stack.SignatureInfo.ContainsKey("Method") ? ctx.Stack.SignatureInfo["Method"] : null, ProjectId = ctx.Stack.ProjectId, ProjectName = ctx.Project.Name, OrganizationId = ctx.Stack.OrganizationId, OrganizationName = ctx.Organization.Name, TotalOccurrences = ctx.Stack.TotalOccurrences, FirstOccurrence = ctx.Stack.FirstOccurrence, LastOccurrence = ctx.Stack.LastOccurrence, DateFixed = ctx.Stack.DateFixed, IsRegression = ctx.Stack.Status == StackStatus.Regressed, IsCritical = ctx.Stack.OccurrencesAreCritical || ctx.Stack.Tags != null && ctx.Stack.Tags.Contains("Critical"), FixedInVersion = ctx.Stack.FixedInVersion })); }
public override Task <object> CreateFromEventAsync(WebHookDataContext ctx) { if (!String.Equals(ctx.Version, Models.WebHook.KnownVersions.Version2)) { return(Task.FromResult <object>(null)); } return(Task.FromResult <object>(new WebHookEvent(_options.BaseURL) { Id = ctx.Event.Id, OccurrenceDate = ctx.Event.Date, Tags = ctx.Event.Tags, Message = ctx.Event.Message, Type = ctx.Event.Type, Source = ctx.Event.Source, ProjectId = ctx.Event.ProjectId, ProjectName = ctx.Project.Name, OrganizationId = ctx.Event.OrganizationId, OrganizationName = ctx.Organization.Name, StackId = ctx.Event.StackId, StackTitle = ctx.Stack.Title, StackDescription = ctx.Stack.Description, StackTags = ctx.Stack.Tags, TotalOccurrences = ctx.Stack.TotalOccurrences, FirstOccurrence = ctx.Stack.FirstOccurrence, LastOccurrence = ctx.Stack.LastOccurrence, DateFixed = ctx.Stack.DateFixed, IsRegression = ctx.IsRegression, IsNew = ctx.IsNew })); }
/// <summary> /// Runs all of the event plugins create method. /// </summary> public async Task <object> CreateFromStackAsync(WebHookDataContext context) { string metricPrefix = String.Concat(_metricPrefix, nameof(CreateFromStackAsync).ToLower(), "."); foreach (var plugin in Plugins.Values) { string metricName = String.Concat(metricPrefix, plugin.Name.ToLower()); try { object data = null; await _metricsClient.TimeAsync(async() => data = await plugin.CreateFromStackAsync(context).AnyContext(), metricName).AnyContext(); if (data == null) { continue; } return(data); } catch (Exception ex) { _logger.LogError(ex, "Error calling create from stack {stack} in plugin {PluginName}: {Message}", context.Stack.Id, plugin.Name, ex.Message); } } return(null); }
public override async Task ProcessAsync(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } // notifications are disabled or stack is hidden. if (ctx.Stack.DisableNotifications || ctx.Stack.IsHidden) { return; } if (ShouldQueueNotification(ctx)) { await _notificationQueue.EnqueueAsync(new EventNotificationWorkItem { EventId = ctx.Event.Id, IsNew = ctx.IsNew, IsRegression = ctx.IsRegression, TotalOccurrences = ctx.Stack.TotalOccurrences }).AnyContext(); } var webHooks = await _webHookRepository.GetByOrganizationIdOrProjectIdAsync(ctx.Event.OrganizationId, ctx.Event.ProjectId).AnyContext(); foreach (var hook in webHooks.Documents) { if (!ShouldCallWebHook(hook, ctx)) { continue; } var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); var notification = new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, WebHookId = hook.Id, Url = hook.Url, Type = WebHookType.General, Data = await _webHookDataPluginManager.CreateFromEventAsync(context).AnyContext() }; await _webHookNotificationQueue.EnqueueAsync(notification).AnyContext(); using (_logger.BeginScope(new Dictionary <string, object> { { "Web Hook Notification", notification } })) _logger.LogTrace("Web hook queued: project={project} url={Url}", ctx.Event.ProjectId, hook.Url); } }
public override Task <object> CreateFromEventAsync(WebHookDataContext ctx) { if (!String.Equals(ctx.Version, Models.WebHook.KnownVersions.Version1)) { return(Task.FromResult <object>(null)); } var error = ctx.Event.GetError(); if (error == null) { return(Task.FromResult <object>(null)); } var requestInfo = ctx.Event.GetRequestInfo(); var environmentInfo = ctx.Event.GetEnvironmentInfo(); return(Task.FromResult <object>(new VersionOneWebHookEvent(_options.BaseURL) { Id = ctx.Event.Id, OccurrenceDate = ctx.Event.Date, Tags = ctx.Event.Tags, MachineName = environmentInfo?.MachineName, RequestPath = requestInfo?.GetFullPath(), IpAddress = requestInfo != null ? requestInfo.ClientIpAddress : environmentInfo?.IpAddress, Message = error.Message, Type = error.Type, Code = error.Code, TargetMethod = error.TargetMethod?.GetFullName(), ProjectId = ctx.Event.ProjectId, ProjectName = ctx.Project.Name, OrganizationId = ctx.Event.OrganizationId, OrganizationName = ctx.Organization.Name, ErrorStackId = ctx.Event.StackId, ErrorStackStatus = ctx.Stack.Status, ErrorStackTitle = ctx.Stack.Title, ErrorStackDescription = ctx.Stack.Description, ErrorStackTags = ctx.Stack.Tags, TotalOccurrences = ctx.Stack.TotalOccurrences, FirstOccurrence = ctx.Stack.FirstOccurrence, LastOccurrence = ctx.Stack.LastOccurrence, DateFixed = ctx.Stack.DateFixed, IsRegression = ctx.IsRegression, IsNew = ctx.IsNew })); }
public async Task <IActionResult> PromoteAsync(string id) { if (String.IsNullOrEmpty(id)) { return(NotFound()); } var stack = await _stackRepository.GetByIdAsync(id); if (stack == null || !CanAccessOrganization(stack.OrganizationId)) { return(NotFound()); } if (!await _billingManager.HasPremiumFeaturesAsync(stack.OrganizationId)) { return(PlanLimitReached("Promote to External is a premium feature used to promote an error stack to an external system. Please upgrade your plan to enable this feature.")); } var promotedProjectHooks = (await _webHookRepository.GetByProjectIdAsync(stack.ProjectId)).Documents.Where(p => p.EventTypes.Contains(WebHookRepository.EventTypes.StackPromoted)).ToList(); if (!promotedProjectHooks.Any()) { return(NotImplemented("No promoted web hooks are configured for this project. Please add a promoted web hook to use this feature.")); } foreach (var hook in promotedProjectHooks) { var context = new WebHookDataContext(hook.Version, stack, isNew: stack.TotalOccurrences == 1, isRegression: stack.Status == StackStatus.Regressed); await _webHookNotificationQueue.EnqueueAsync(new WebHookNotification { OrganizationId = stack.OrganizationId, ProjectId = stack.ProjectId, WebHookId = hook.Id, Url = hook.Url, Type = WebHookType.General, Data = await _webHookDataPluginManager.CreateFromStackAsync(context) }); } return(Ok()); }
public override async Task ProcessAsync(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } if (ShouldQueueNotification(ctx)) { await _notificationQueue.EnqueueAsync(new EventNotificationWorkItem { EventId = ctx.Event.Id, IsNew = ctx.IsNew, IsCritical = ctx.Event.IsCritical(), IsRegression = ctx.IsRegression, TotalOccurrences = ctx.Stack.TotalOccurrences, ProjectName = ctx.Project.Name }).AnyContext(); } foreach (WebHook hook in (await _webHookRepository.GetByOrganizationIdOrProjectIdAsync(ctx.Event.OrganizationId, ctx.Event.ProjectId).AnyContext()).Documents) { if (!ShouldCallWebHook(hook, ctx)) { continue; } var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); var notification = new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, WebHookId = hook.Id, Url = hook.Url, Data = await _webHookDataPluginManager.CreateFromEventAsync(context).AnyContext() }; await _webHookNotificationQueue.EnqueueAsync(notification).AnyContext(); _logger.Trace().Project(ctx.Event.ProjectId).Message("Web hook queued: project={0} url={1}", ctx.Event.ProjectId, hook.Url).Property("Web Hook Notification", notification).Write(); } }
public IHttpActionResult Promote(string id) { if (String.IsNullOrEmpty(id)) { return(NotFound()); } Stack stack = _stackRepository.GetById(id); if (stack == null || !CanAccessOrganization(stack.OrganizationId)) { return(NotFound()); } if (!_billingManager.HasPremiumFeatures(stack.OrganizationId)) { return(PlanLimitReached("Promote to External is a premium feature used to promote an error stack to an external system. Please upgrade your plan to enable this feature.")); } List <WebHook> promotedProjectHooks = _webHookRepository.GetByProjectId(stack.ProjectId).Where(p => p.EventTypes.Contains(WebHookRepository.EventTypes.StackPromoted)).ToList(); if (!promotedProjectHooks.Any()) { return(NotImplemented("No promoted web hooks are configured for this project. Please add a promoted web hook to use this feature.")); } foreach (WebHook hook in promotedProjectHooks) { var context = new WebHookDataContext(hook.Version, stack, isNew: stack.TotalOccurrences == 1, isRegression: stack.IsRegressed); _webHookNotificationQueue.Enqueue(new WebHookNotification { OrganizationId = hook.OrganizationId, ProjectId = hook.ProjectId, Url = hook.Url, Data = _webHookDataPluginManager.CreateFromStack(context) }); // TODO: Add stats metrics for webhooks. } return(Ok()); }
public override void Process(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } _notificationQueue.Enqueue(new EventNotification { Event = ctx.Event, IsNew = ctx.IsNew, IsCritical = ctx.Event.IsCritical(), IsRegression = ctx.IsRegression, //TotalOccurrences = ctx.Stack.TotalOccurrences, ProjectName = ctx.Project.Name }); foreach (WebHook hook in _webHookRepository.GetByOrganizationIdOrProjectId(ctx.Event.OrganizationId, ctx.Event.ProjectId)) { bool shouldCall = hook.EventTypes.Contains(WebHookRepository.EventTypes.NewError) && ctx.IsNew || hook.EventTypes.Contains(WebHookRepository.EventTypes.ErrorRegression) && ctx.IsRegression || hook.EventTypes.Contains(WebHookRepository.EventTypes.CriticalError) && ctx.Event.Tags != null && ctx.Event.Tags.Contains("Critical"); if (!shouldCall) { continue; } Log.Trace().Project(ctx.Event.ProjectId).Message("Web hook queued: project={0} url={1}", ctx.Event.ProjectId, hook.Url).Write(); // TODO: Should we be using the hook's project id and organization id? var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); _webHookNotificationQueue.Enqueue(new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, Url = hook.Url, Data = _webHookDataPluginManager.CreateFromEvent(context) }); } }
public override void Process(EventContext ctx) { // if they don't have premium features, then we don't need to queue notifications if (!ctx.Organization.HasPremiumFeatures) { return; } if (ShouldQueueNotification(ctx)) { _notificationQueue.Enqueue(new EventNotification { Event = ctx.Event, IsNew = ctx.IsNew, IsCritical = ctx.Event.IsCritical(), IsRegression = ctx.IsRegression, TotalOccurrences = ctx.Stack.TotalOccurrences, ProjectName = ctx.Project.Name }); } foreach (WebHook hook in _webHookRepository.GetByOrganizationIdOrProjectId(ctx.Event.OrganizationId, ctx.Event.ProjectId)) { if (!ShouldCallWebHook(hook, ctx)) { continue; } var context = new WebHookDataContext(hook.Version, ctx.Event, ctx.Organization, ctx.Project, ctx.Stack, ctx.IsNew, ctx.IsRegression); _webHookNotificationQueue.Enqueue(new WebHookNotification { OrganizationId = ctx.Event.OrganizationId, ProjectId = ctx.Event.ProjectId, Url = hook.Url, Data = _webHookDataPluginManager.CreateFromEvent(context) }); Log.Trace().Project(ctx.Event.ProjectId).Message("Web hook queued: project={0} url={1}", ctx.Event.ProjectId, hook.Url).Write(); } }
public abstract Task <object> CreateFromEventAsync(WebHookDataContext ctx);