def group(request, team, project, group, event_id=None): # It's possible that a message would not be created under certain # circumstances (such as a post_save signal failing) activity_qs = Activity.objects.order_by('-datetime').select_related('user') if event_id: event = get_object_or_404(group.event_set, id=event_id) activity_qs = activity_qs.filter( Q(event=event) | Q(event__isnull=True), ) else: event = group.get_latest_event() or Event() # bind params to group in case they get hit event.group = group event.project = project if project in Project.objects.get_for_user(request.user, team=team): # update that the user has seen this group create_or_update(GroupSeen, group=group, user=request.user, project=project, defaults={ 'last_seen': timezone.now(), }) # filter out dupe activity items activity_items = set() activity = [] for item in activity_qs.filter(group=group)[:10]: sig = (item.event_id, item.type, item.ident, item.user_id) if sig not in activity_items: activity_items.add(sig) activity.append(item) # trim to latest 5 activity = activity[:5] seen_by = sorted(filter(lambda ls: ls[0] != request.user and ls[0].email, [ (gs.user, gs.last_seen) for gs in GroupSeen.objects.filter(group=group).select_related('user') ]), key=lambda ls: ls[1]) seen_by_extra = len(seen_by) - 5 if seen_by_extra < 0: seen_by_extra = 0 seen_by_faces = seen_by[:5] context = { 'page': 'details', 'activity': activity, 'seen_by': seen_by, 'seen_by_faces': seen_by_faces, 'seen_by_extra': seen_by_extra, } is_public = group_is_public(group, request.user) if is_public: template = 'sentry/groups/public_details.html' context['PROJECT_LIST'] = [project] else: template = 'sentry/groups/details.html' return render_with_group_context(group, template, context, request, event=event, is_public=is_public)
def create_or_update(self, **kwargs): return create_or_update(self.model, **kwargs)
def group(request, team, project, group, event_id=None): # It's possible that a message would not be created under certain # circumstances (such as a post_save signal failing) activity_qs = Activity.objects.order_by('-datetime').select_related('user') if event_id: event = get_object_or_404(group.event_set, id=event_id) activity_qs = activity_qs.filter( Q(event=event) | Q(event__isnull=True), ) else: event = group.get_latest_event() or Event() # bind params to group in case they get hit event.group = group event.project = project if project in Project.objects.get_for_user( request.user, team=team, superuser=False): # update that the user has seen this group create_or_update( GroupSeen, group=group, user=request.user, project=project, defaults={ 'last_seen': timezone.now(), } ) # filter out dupe activity items activity_items = set() activity = [] for item in activity_qs.filter(group=group)[:10]: sig = (item.event_id, item.type, item.ident, item.user_id) if sig not in activity_items: activity_items.add(sig) activity.append(item) # trim to latest 5 activity = activity[:5] seen_by = sorted(filter(lambda ls: ls[0] != request.user and ls[0].email, [ (gs.user, gs.last_seen) for gs in GroupSeen.objects.filter( group=group ).select_related('user') ]), key=lambda ls: ls[1], reverse=True) seen_by_extra = len(seen_by) - 5 if seen_by_extra < 0: seen_by_extra = 0 seen_by_faces = seen_by[:5] context = { 'page': 'details', 'activity': activity, 'seen_by': seen_by, 'seen_by_faces': seen_by_faces, 'seen_by_extra': seen_by_extra, } is_public = group_is_public(group, request.user) if is_public: template = 'sentry/groups/public_details.html' context['PROJECT_LIST'] = [project] else: template = 'sentry/groups/details.html' return render_with_group_context( group, template, context, request, event=event, is_public=is_public)
def forwards(self, orm): from django.db.models import F from collections import defaultdict from sentry.utils.models import create_or_update from sentry.utils.query import RangeQuerySetWrapper # We don't fully merge results because it's simply not worth it for group in RangeQuerySetWrapper(orm['sentry.Group'].objects.all()): # could be already migrated if not orm['sentry.Group'].objects.filter(id=group.id).exists(): continue matches = list(orm['sentry.Group'].objects.exclude( id=group.id).filter(checksum=group.checksum, project=group.project)) if not matches: continue print "Merging duplicate events for %r" % (group, ) updates = defaultdict(int) updates.update({ 'first_seen': group.first_seen, 'last_seen': group.last_seen, 'active_at': group.active_at, }) tag_updates = defaultdict(lambda: defaultdict(int)) counts = defaultdict(lambda: defaultdict(int)) for other in matches: # migrate events first orm['sentry.Event'].objects.filter(group=other).update( group=group) updates['times_seen'] += other.times_seen updates['users_seen'] += other.users_seen updates['time_spent_total'] += other.time_spent_total updates['time_spent_count'] += other.time_spent_count for datecol in ('active_at', 'last_seen', 'first_seen'): val = getattr(other, datecol) if val and updates[datecol]: updates[datecol] = max(val, updates[datecol]) elif val: updates[datecol] = val # determine missing tags for tag in RangeQuerySetWrapper( orm['sentry.MessageFilterValue'].objects.filter( group=other)): key = tag_updates[(tag.key, tag.value)] key['times_seen'] += other.times_seen for datecol in ('last_seen', 'first_seen'): val = getattr(other, datecol) if val and updates[datecol]: updates[datecol] = max(val, updates[datecol]) elif val: updates[datecol] = val # determine counts for count in RangeQuerySetWrapper( orm['sentry.MessageCountByMinute'].objects.filter( group=other)): key = counts[count.date] key['times_seen'] += count.times_seen key['time_spent_total'] += count.time_spent_total key['time_spent_count'] += count.time_spent_count # migrate tags for (key, value), data in tag_updates.iteritems(): defaults = { 'times_seen': F('times_seen') + data['times_seen'], } if 'last_seen' in data: defaults['last_seen'] = data['last_seen'] if 'first_seen' in data: defaults['first_seen'] = data['first_seen'] create_or_update(orm['sentry.MessageFilterValue'], project=group.project, group=group, key=key, value=value, defaults=defaults) orm['sentry.MessageFilterValue'].objects.filter( group__in=matches).delete() # migrate counts for date, data in counts.iteritems(): create_or_update( orm['sentry.MessageCountByMinute'], project=group.project, group=group, date=date, defaults={ 'times_seen': F('times_seen') + data['times_seen'], 'time_spent_total': F('time_spent_total') + data['time_spent_total'], 'time_spent_count': F('time_spent_count') + data['time_spent_count'], }) orm['sentry.MessageCountByMinute'].objects.filter( group__in=matches).delete() orm['sentry.Group'].objects.filter(id=group.id).update( times_seen=F('times_seen') + updates['times_seen'], users_seen=F('users_seen') + updates['user_seen'], time_spent_total=F('time_spent_total') + updates['time_spent_total'], time_spent_count=F('time_spent_count') + updates['time_spent_count'], last_seen=updates['last_seen'], first_seen=updates['first_seen'], active_at=updates['active_at'], ) for other in matches: other.delete()
def forwards(self, orm): from django.db.models import F from collections import defaultdict from sentry.utils.models import create_or_update from sentry.utils.query import RangeQuerySetWrapper # We don't fully merge results because it's simply not worth it for group in RangeQuerySetWrapper(orm['sentry.Group'].objects.all()): # could be already migrated if not orm['sentry.Group'].objects.filter(id=group.id).exists(): continue matches = list(orm['sentry.Group'].objects.exclude(id=group.id).filter( checksum=group.checksum, project=group.project)) if not matches: continue updates = defaultdict(int) updates.update({ 'first_seen': group.first_seen, 'last_seen': group.last_seen, 'active_at': group.active_at, }) tag_updates = defaultdict(lambda: defaultdict(int)) counts = defaultdict(lambda: defaultdict(int)) for other in matches: # migrate events first orm['sentry.Event'].objects.filter(group=other).update(group=group) updates['times_seen'] += other.times_seen updates['users_seen'] += other.users_seen updates['time_spent_total'] += other.time_spent_total updates['time_spent_count'] += other.time_spent_count for datecol in ('active_at', 'last_seen', 'first_seen'): val = getattr(other, datecol) if val and updates[datecol]: updates[datecol] = max(val, updates[datecol]) elif val: updates[datecol] = val # determine missing tags for tag in RangeQuerySetWrapper(orm['sentry.MessageFilterValue'].objects.filter(group=other)): key = tag_updates[(tag.key, tag.value)] key['times_seen'] += other.times_seen for datecol in ('last_seen', 'first_seen'): val = getattr(other, datecol) if val and updates[datecol]: updates[datecol] = max(val, updates[datecol]) elif val: updates[datecol] = val # determine counts for count in RangeQuerySetWrapper(orm['sentry.MessageCountByMinute'].objects.filter(group=other)): key = counts[count.date] key['times_seen'] += count.times_seen key['time_spent_total'] += count.time_spent_total key['time_spent_count'] += count.time_spent_count # migrate tags for (key, value), data in tag_updates.iteritems(): defaults = { 'times_seen': F('times_seen') + data['times_seen'], } if 'last_seen' in data: defaults['last_seen'] = data['last_seen'] if 'first_seen' in data: defaults['first_seen'] = data['first_seen'] create_or_update(orm['sentry.MessageFilterValue'], project=group.project, group=group, key=key, value=value, defaults=defaults ) orm['sentry.MessageFilterValue'].objects.filter(group__in=matches).delete() # migrate counts for date, data in counts.iteritems(): create_or_update(orm['sentry.MessageCountByMinute'], project=group.project, group=group, date=date, defaults={ 'times_seen': F('times_seen') + data['times_seen'], 'time_spent_total': F('time_spent_total') + data['time_spent_total'], 'time_spent_count': F('time_spent_count') + data['time_spent_count'], } ) orm['sentry.MessageCountByMinute'].objects.filter(group__in=matches).delete() orm['sentry.Group'].objects.filter(id=group.id).update( times_seen=F('times_seen') + updates['times_seen'], users_seen=F('users_seen') + updates['user_seen'], time_spent_total=F('time_spent_total') + updates['time_spent_total'], time_spent_count=F('time_spent_count') + updates['time_spent_count'], last_seen=updates['last_seen'], first_seen=updates['first_seen'], active_at=updates['active_at'], ) for other in matches: other.delete()