def get_attrs(self, item_list, user): from sentry.plugins.base import plugins from sentry.integrations import IntegrationFeatures from sentry.models import PlatformExternalIssue GroupMeta.objects.populate_cache(item_list) attach_foreignkey(item_list, Group.project) if user.is_authenticated() and item_list: bookmarks = set( GroupBookmark.objects.filter(user=user, group__in=item_list).values_list( "group_id", flat=True ) ) seen_groups = dict( GroupSeen.objects.filter(user=user, group__in=item_list).values_list( "group_id", "last_seen" ) ) subscriptions = self._get_subscriptions(item_list, user) else: bookmarks = set() seen_groups = {} subscriptions = defaultdict(lambda: (False, None)) assignees = { a.group_id: a.assigned_actor() for a in GroupAssignee.objects.filter(group__in=item_list) } resolved_assignees = Actor.resolve_dict(assignees) ignore_items = {g.group_id: g for g in GroupSnooze.objects.filter(group__in=item_list)} resolved_item_list = [i for i in item_list if i.status == GroupStatus.RESOLVED] if resolved_item_list: release_resolutions = { i[0]: i[1:] for i in GroupResolution.objects.filter(group__in=resolved_item_list).values_list( "group", "type", "release__version", "actor_id" ) } # due to our laziness, and django's inability to do a reasonable join here # we end up with two queries commit_results = list( Commit.objects.extra( select={"group_id": "sentry_grouplink.group_id"}, tables=["sentry_grouplink"], where=[ "sentry_grouplink.linked_id = sentry_commit.id", "sentry_grouplink.group_id IN ({})".format( ", ".join(six.text_type(i.id) for i in resolved_item_list) ), "sentry_grouplink.linked_type = %s", "sentry_grouplink.relationship = %s", ], params=[int(GroupLink.LinkedType.commit), int(GroupLink.Relationship.resolves)], ) ) commit_resolutions = { i.group_id: d for i, d in zip(commit_results, serialize(commit_results, user)) } else: release_resolutions = {} commit_resolutions = {} actor_ids = set(r[-1] for r in six.itervalues(release_resolutions)) actor_ids.update(r.actor_id for r in six.itervalues(ignore_items)) if actor_ids: users = list(User.objects.filter(id__in=actor_ids, is_active=True)) actors = {u.id: d for u, d in zip(users, serialize(users, user))} else: actors = {} share_ids = dict( GroupShare.objects.filter(group__in=item_list).values_list("group_id", "uuid") ) result = {} seen_stats = self._get_seen_stats(item_list, user) annotations_by_group_id = defaultdict(list) organization_id_list = list(set(item.project.organization_id for item in item_list)) # if no groups, then we can't proceed but this seems to be a valid use case if not item_list: return {} if len(organization_id_list) > 1: # this should never happen but if it does we should know about it logger.warn( "Found multiple organizations for groups: %s, with orgs: %s" % ([item.id for item in item_list], organization_id_list) ) # should only have 1 org at this point organization_id = organization_id_list[0] organization = Organization.objects.get_from_cache(id=organization_id) has_unhandled_flag = features.has( "organizations:unhandled-issue-flag", organization, actor=user ) # find all the integration installs that have issue tracking for integration in Integration.objects.filter(organizations=organization_id): if not ( integration.has_feature(IntegrationFeatures.ISSUE_BASIC) or integration.has_feature(IntegrationFeatures.ISSUE_SYNC) ): continue install = integration.get_installation(organization_id) local_annotations_by_group_id = ( safe_execute( install.get_annotations_for_group_list, group_list=item_list, _with_transaction=False, ) or {} ) merge_list_dictionaries(annotations_by_group_id, local_annotations_by_group_id) # find the external issues for sentry apps and add them in local_annotations_by_group_id = ( safe_execute( PlatformExternalIssue.get_annotations_for_group_list, group_list=item_list, _with_transaction=False, ) or {} ) merge_list_dictionaries(annotations_by_group_id, local_annotations_by_group_id) snuba_stats = {} if has_unhandled_flag: snuba_stats = self._get_group_snuba_stats(item_list, seen_stats) for item in item_list: active_date = item.active_at or item.first_seen annotations = [] annotations.extend(annotations_by_group_id[item.id]) # add the annotations for plugins # note that the model GroupMeta where all the information is stored is already cached at the top of this function # so these for loops doesn't make a bunch of queries for plugin in plugins.for_project(project=item.project, version=1): safe_execute(plugin.tags, None, item, annotations, _with_transaction=False) for plugin in plugins.for_project(project=item.project, version=2): annotations.extend( safe_execute(plugin.get_annotations, group=item, _with_transaction=False) or () ) resolution_actor = None resolution_type = None resolution = release_resolutions.get(item.id) if resolution: resolution_type = "release" resolution_actor = actors.get(resolution[-1]) if not resolution: resolution = commit_resolutions.get(item.id) if resolution: resolution_type = "commit" ignore_item = ignore_items.get(item.id) if ignore_item: ignore_actor = actors.get(ignore_item.actor_id) else: ignore_actor = None result[item] = { "id": item.id, "assigned_to": resolved_assignees.get(item.id), "is_bookmarked": item.id in bookmarks, "subscription": subscriptions[item.id], "has_seen": seen_groups.get(item.id, active_date) > active_date, "annotations": annotations, "ignore_until": ignore_item, "ignore_actor": ignore_actor, "resolution": resolution, "resolution_type": resolution_type, "resolution_actor": resolution_actor, "share_id": share_ids.get(item.id), } if has_unhandled_flag: result[item]["is_unhandled"] = bool(snuba_stats.get(item.id, {}).get("unhandled")) if seen_stats: result[item].update(seen_stats.get(item, {})) return result
def get_attrs(self, item_list, user): from sentry.plugins.base import plugins GroupMeta.objects.populate_cache(item_list) attach_foreignkey(item_list, Group.project) if user.is_authenticated() and item_list: bookmarks = set( GroupBookmark.objects.filter( user=user, group__in=item_list).values_list("group_id", flat=True)) seen_groups = dict( GroupSeen.objects.filter(user=user, group__in=item_list).values_list( "group_id", "last_seen")) subscriptions = self._get_subscriptions(item_list, user) else: bookmarks = set() seen_groups = {} subscriptions = defaultdict(lambda: (False, None)) assignees = { a.group_id: a.assigned_actor() for a in GroupAssignee.objects.filter(group__in=item_list) } resolved_assignees = Actor.resolve_dict(assignees) ignore_items = { g.group_id: g for g in GroupSnooze.objects.filter(group__in=item_list) } resolved_item_list = [ i for i in item_list if i.status == GroupStatus.RESOLVED ] if resolved_item_list: release_resolutions = { i[0]: i[1:] for i in GroupResolution.objects.filter( group__in=resolved_item_list).values_list( "group", "type", "release__version", "actor_id") } # due to our laziness, and django's inability to do a reasonable join here # we end up with two queries commit_results = list( Commit.objects.extra( select={"group_id": "sentry_grouplink.group_id"}, tables=["sentry_grouplink"], where=[ "sentry_grouplink.linked_id = sentry_commit.id", "sentry_grouplink.group_id IN ({})".format(", ".join( six.text_type(i.id) for i in resolved_item_list)), "sentry_grouplink.linked_type = %s", "sentry_grouplink.relationship = %s", ], params=[ int(GroupLink.LinkedType.commit), int(GroupLink.Relationship.resolves) ], )) commit_resolutions = { i.group_id: d for i, d in zip(commit_results, serialize( commit_results, user)) } else: release_resolutions = {} commit_resolutions = {} actor_ids = set(r[-1] for r in six.itervalues(release_resolutions)) actor_ids.update(r.actor_id for r in six.itervalues(ignore_items)) if actor_ids: users = list(User.objects.filter(id__in=actor_ids, is_active=True)) actors = {u.id: d for u, d in zip(users, serialize(users, user))} else: actors = {} share_ids = dict( GroupShare.objects.filter(group__in=item_list).values_list( "group_id", "uuid")) result = {} seen_stats = self._get_seen_stats(item_list, user) for item in item_list: active_date = item.active_at or item.first_seen annotations = [] for plugin in plugins.for_project(project=item.project, version=1): safe_execute(plugin.tags, None, item, annotations, _with_transaction=False) for plugin in plugins.for_project(project=item.project, version=2): annotations.extend( safe_execute(plugin.get_annotations, group=item, _with_transaction=False) or ()) from sentry.integrations import IntegrationFeatures for integration in Integration.objects.filter( organizations=item.project.organization_id): if not (integration.has_feature( IntegrationFeatures.ISSUE_BASIC) or integration.has_feature( IntegrationFeatures.ISSUE_SYNC)): continue install = integration.get_installation( item.project.organization_id) annotations.extend( safe_execute(install.get_annotations, group=item, _with_transaction=False) or ()) from sentry.models import PlatformExternalIssue annotations.extend( safe_execute(PlatformExternalIssue.get_annotations, group=item, _with_transaction=False) or ()) resolution_actor = None resolution_type = None resolution = release_resolutions.get(item.id) if resolution: resolution_type = "release" resolution_actor = actors.get(resolution[-1]) if not resolution: resolution = commit_resolutions.get(item.id) if resolution: resolution_type = "commit" ignore_item = ignore_items.get(item.id) if ignore_item: ignore_actor = actors.get(ignore_item.actor_id) else: ignore_actor = None result[item] = { "assigned_to": resolved_assignees.get(item.id), "is_bookmarked": item.id in bookmarks, "subscription": subscriptions[item.id], "has_seen": seen_groups.get(item.id, active_date) > active_date, "annotations": annotations, "ignore_until": ignore_item, "ignore_actor": ignore_actor, "resolution": resolution, "resolution_type": resolution_type, "resolution_actor": resolution_actor, "share_id": share_ids.get(item.id), } result[item].update(seen_stats.get(item, {})) return result
def get_attrs(self, item_list, user): from sentry.plugins import plugins GroupMeta.objects.populate_cache(item_list) attach_foreignkey(item_list, Group.project) if user.is_authenticated() and item_list: bookmarks = set( GroupBookmark.objects.filter( user=user, group__in=item_list, ).values_list('group_id', flat=True)) seen_groups = dict( GroupSeen.objects.filter( user=user, group__in=item_list, ).values_list('group_id', 'last_seen')) subscriptions = self._get_subscriptions(item_list, user) else: bookmarks = set() seen_groups = {} subscriptions = defaultdict(lambda: (False, None)) assignees = { a.group_id: a.assigned_actor() for a in GroupAssignee.objects.filter(group__in=item_list, ) } resolved_assignees = Actor.resolve_dict(assignees) try: environment = self.environment_func() except Environment.DoesNotExist: user_counts = {} first_seen = {} last_seen = {} times_seen = {} else: project_id = item_list[0].project_id item_ids = [g.id for g in item_list] user_counts = tagstore.get_groups_user_counts( project_id, item_ids, environment_id=environment and environment.id, ) first_seen = {} last_seen = {} times_seen = {} if environment is not None: environment_tagvalues = tagstore.get_group_list_tag_value( project_id, item_ids, environment.id, 'environment', environment.name, ) for item_id, value in environment_tagvalues.items(): first_seen[item_id] = value.first_seen last_seen[item_id] = value.last_seen times_seen[item_id] = value.times_seen else: for item in item_list: first_seen[item.id] = item.first_seen last_seen[item.id] = item.last_seen times_seen[item.id] = item.times_seen ignore_items = { g.group_id: g for g in GroupSnooze.objects.filter(group__in=item_list, ) } resolutions = { i[0]: i[1:] for i in GroupResolution.objects.filter(group__in=item_list, ).values_list( 'group', 'type', 'release__version', 'actor_id', ) } actor_ids = set(r[-1] for r in six.itervalues(resolutions)) actor_ids.update(r.actor_id for r in six.itervalues(ignore_items)) if actor_ids: users = list( User.objects.filter( id__in=actor_ids, is_active=True, )) actors = { u.id: d for u, d in itertools.izip(users, serialize(users, user)) } else: actors = {} share_ids = dict( GroupShare.objects.filter(group__in=item_list, ).values_list( 'group_id', 'uuid')) result = {} for item in item_list: active_date = item.active_at or item.first_seen annotations = [] for plugin in plugins.for_project(project=item.project, version=1): safe_execute(plugin.tags, None, item, annotations, _with_transaction=False) for plugin in plugins.for_project(project=item.project, version=2): annotations.extend( safe_execute(plugin.get_annotations, group=item, _with_transaction=False) or ()) resolution = resolutions.get(item.id) if resolution: resolution_actor = actors.get(resolution[-1]) else: resolution_actor = None ignore_item = ignore_items.get(item.id) if ignore_item: ignore_actor = actors.get(ignore_item.actor_id) else: ignore_actor = None result[item] = { 'assigned_to': resolved_assignees.get(item.id), 'is_bookmarked': item.id in bookmarks, 'subscription': subscriptions[item.id], 'has_seen': seen_groups.get(item.id, active_date) > active_date, 'annotations': annotations, 'user_count': user_counts.get(item.id, 0), 'ignore_until': ignore_item, 'ignore_actor': ignore_actor, 'resolution': resolution, 'resolution_actor': resolution_actor, 'share_id': share_ids.get(item.id), 'times_seen': times_seen.get(item.id, 0), 'first_seen': first_seen.get(item.id), # TODO: missing? 'last_seen': last_seen.get(item.id), } return result
def get_attrs(self, item_list, user): from sentry.plugins import plugins GroupMeta.objects.populate_cache(item_list) attach_foreignkey(item_list, Group.project) if user.is_authenticated() and item_list: bookmarks = set( GroupBookmark.objects.filter( user=user, group__in=item_list, ).values_list('group_id', flat=True) ) seen_groups = dict( GroupSeen.objects.filter( user=user, group__in=item_list, ).values_list('group_id', 'last_seen') ) subscriptions = self._get_subscriptions(item_list, user) else: bookmarks = set() seen_groups = {} subscriptions = defaultdict(lambda: (False, None)) assignees = { a.group_id: a.assigned_actor() for a in GroupAssignee.objects.filter( group__in=item_list, ) } resolved_assignees = Actor.resolve_dict(assignees) ignore_items = {g.group_id: g for g in GroupSnooze.objects.filter( group__in=item_list, )} resolved_item_list = [i for i in item_list if i.status == GroupStatus.RESOLVED] if resolved_item_list: release_resolutions = { i[0]: i[1:] for i in GroupResolution.objects.filter( group__in=resolved_item_list, ).values_list( 'group', 'type', 'release__version', 'actor_id', ) } # due to our laziness, and django's inability to do a reasonable join here # we end up with two queries commit_results = list(Commit.objects.extra( select={ 'group_id': 'sentry_grouplink.group_id', }, tables=['sentry_grouplink'], where=[ 'sentry_grouplink.linked_id = sentry_commit.id', 'sentry_grouplink.group_id IN ({})'.format( ', '.join(six.text_type(i.id) for i in resolved_item_list)), 'sentry_grouplink.linked_type = %s', 'sentry_grouplink.relationship = %s', ], params=[ int(GroupLink.LinkedType.commit), int(GroupLink.Relationship.resolves), ] )) commit_resolutions = { i.group_id: d for i, d in itertools.izip(commit_results, serialize(commit_results, user)) } else: release_resolutions = {} commit_resolutions = {} actor_ids = set(r[-1] for r in six.itervalues(release_resolutions)) actor_ids.update(r.actor_id for r in six.itervalues(ignore_items)) if actor_ids: users = list(User.objects.filter( id__in=actor_ids, is_active=True, )) actors = {u.id: d for u, d in itertools.izip(users, serialize(users, user))} else: actors = {} share_ids = dict(GroupShare.objects.filter( group__in=item_list, ).values_list('group_id', 'uuid')) result = {} seen_stats = self._get_seen_stats(item_list, user) for item in item_list: active_date = item.active_at or item.first_seen annotations = [] for plugin in plugins.for_project(project=item.project, version=1): safe_execute(plugin.tags, None, item, annotations, _with_transaction=False) for plugin in plugins.for_project(project=item.project, version=2): annotations.extend( safe_execute(plugin.get_annotations, group=item, _with_transaction=False) or () ) from sentry.integrations import IntegrationFeatures for integration in Integration.objects.filter( organizations=item.project.organization_id): if not (integration.has_feature(IntegrationFeatures.ISSUE_BASIC) or integration.has_feature( IntegrationFeatures.ISSUE_SYNC)): continue install = integration.get_installation(item.project.organization_id) annotations.extend( safe_execute(install.get_annotations, group=item, _with_transaction=False) or () ) resolution_actor = None resolution_type = None resolution = release_resolutions.get(item.id) if resolution: resolution_type = 'release' resolution_actor = actors.get(resolution[-1]) if not resolution: resolution = commit_resolutions.get(item.id) if resolution: resolution_type = 'commit' ignore_item = ignore_items.get(item.id) if ignore_item: ignore_actor = actors.get(ignore_item.actor_id) else: ignore_actor = None result[item] = { 'assigned_to': resolved_assignees.get(item.id), 'is_bookmarked': item.id in bookmarks, 'subscription': subscriptions[item.id], 'has_seen': seen_groups.get(item.id, active_date) > active_date, 'annotations': annotations, 'ignore_until': ignore_item, 'ignore_actor': ignore_actor, 'resolution': resolution, 'resolution_type': resolution_type, 'resolution_actor': resolution_actor, 'share_id': share_ids.get(item.id), } result[item].update(seen_stats.get(item, {})) return result
def get_attrs(self, item_list, user): from sentry.plugins import plugins GroupMeta.objects.populate_cache(item_list) attach_foreignkey(item_list, Group.project) if user.is_authenticated() and item_list: bookmarks = set( GroupBookmark.objects.filter( user=user, group__in=item_list, ).values_list('group_id', flat=True)) seen_groups = dict( GroupSeen.objects.filter( user=user, group__in=item_list, ).values_list('group_id', 'last_seen')) subscriptions = self._get_subscriptions(item_list, user) else: bookmarks = set() seen_groups = {} subscriptions = defaultdict(lambda: (False, None)) assignees = { a.group_id: a.assigned_actor() for a in GroupAssignee.objects.filter(group__in=item_list, ) } resolved_assignees = Actor.resolve_dict(assignees) try: environment = self.environment_func() except Environment.DoesNotExist: user_counts = {} first_seen = {} last_seen = {} times_seen = {} else: project_id = item_list[0].project_id item_ids = [g.id for g in item_list] user_counts = tagstore.get_groups_user_counts( project_id, item_ids, environment_id=environment and environment.id, ) first_seen = {} last_seen = {} times_seen = {} if environment is not None: environment_tagvalues = tagstore.get_group_list_tag_value( project_id, item_ids, environment.id, 'environment', environment.name, ) for item_id, value in environment_tagvalues.items(): first_seen[item_id] = value.first_seen last_seen[item_id] = value.last_seen times_seen[item_id] = value.times_seen else: for item in item_list: first_seen[item.id] = item.first_seen last_seen[item.id] = item.last_seen times_seen[item.id] = item.times_seen ignore_items = { g.group_id: g for g in GroupSnooze.objects.filter(group__in=item_list, ) } resolved_item_list = [ i for i in item_list if i.status == GroupStatus.RESOLVED ] if resolved_item_list: release_resolutions = { i[0]: i[1:] for i in GroupResolution.objects.filter( group__in=resolved_item_list, ).values_list( 'group', 'type', 'release__version', 'actor_id', ) } # due to our laziness, and django's inability to do a reasonable join here # we end up with two queries commit_results = list( Commit.objects.extra( select={ 'group_id': 'sentry_grouplink.group_id', }, tables=['sentry_grouplink'], where=[ 'sentry_grouplink.linked_id = sentry_commit.id', 'sentry_grouplink.group_id IN ({})'.format(', '.join( six.text_type(i.id) for i in resolved_item_list)), 'sentry_grouplink.linked_type = %s', 'sentry_grouplink.relationship = %s', ], params=[ int(GroupLink.LinkedType.commit), int(GroupLink.Relationship.resolves), ])) commit_resolutions = { i.group_id: d for i, d in itertools.izip(commit_results, serialize(commit_results, user)) } else: release_resolutions = {} commit_resolutions = {} actor_ids = set(r[-1] for r in six.itervalues(release_resolutions)) actor_ids.update(r.actor_id for r in six.itervalues(ignore_items)) if actor_ids: users = list( User.objects.filter( id__in=actor_ids, is_active=True, )) actors = { u.id: d for u, d in itertools.izip(users, serialize(users, user)) } else: actors = {} share_ids = dict( GroupShare.objects.filter(group__in=item_list, ).values_list( 'group_id', 'uuid')) result = {} for item in item_list: active_date = item.active_at or item.first_seen annotations = [] for plugin in plugins.for_project(project=item.project, version=1): safe_execute(plugin.tags, None, item, annotations, _with_transaction=False) for plugin in plugins.for_project(project=item.project, version=2): annotations.extend( safe_execute(plugin.get_annotations, group=item, _with_transaction=False) or ()) from sentry.integrations import IntegrationFeatures for integration in Integration.objects.filter( organizations=item.project.organization_id): if not (integration.has_feature( IntegrationFeatures.ISSUE_BASIC) or integration.has_feature( IntegrationFeatures.ISSUE_SYNC)): continue install = integration.get_installation( item.project.organization_id) annotations.extend( safe_execute(install.get_annotations, group=item, _with_transaction=False) or ()) resolution_actor = None resolution_type = None resolution = release_resolutions.get(item.id) if resolution: resolution_type = 'release' resolution_actor = actors.get(resolution[-1]) if not resolution: resolution = commit_resolutions.get(item.id) if resolution: resolution_type = 'commit' ignore_item = ignore_items.get(item.id) if ignore_item: ignore_actor = actors.get(ignore_item.actor_id) else: ignore_actor = None result[item] = { 'assigned_to': resolved_assignees.get(item.id), 'is_bookmarked': item.id in bookmarks, 'subscription': subscriptions[item.id], 'has_seen': seen_groups.get(item.id, active_date) > active_date, 'annotations': annotations, 'user_count': user_counts.get(item.id, 0), 'ignore_until': ignore_item, 'ignore_actor': ignore_actor, 'resolution': resolution, 'resolution_type': resolution_type, 'resolution_actor': resolution_actor, 'share_id': share_ids.get(item.id), 'times_seen': times_seen.get(item.id, 0), 'first_seen': first_seen.get(item.id), # TODO: missing? 'last_seen': last_seen.get(item.id), } return result