def post(self, request, group_id): group = Group.objects.get( id=group_id, ) assert_perm(group, request.user, request.auth) now = timezone.now() group.resolved_at = now happened = Group.objects.filter( id=group.id, ).exclude(status=STATUS_RESOLVED).update( status=STATUS_RESOLVED, resolved_at=now, ) if happened: create_or_update( Activity, project=group.project, group=group, type=Activity.SET_RESOLVED, user=request.user, ) return Response()
def _set_bytes(self, id, data, ttl=None): create_or_update(Node, id=id, values={ "data": compress(data), "timestamp": timezone.now() })
def set(self, id, data, ttl=None): create_or_update(Node, id=id, values={ "data": data, "timestamp": timezone.now() })
def post(self, request, group_id): group = Group.objects.get(id=group_id) assert_perm(group, request.user, request.auth) serializer = GroupAssigneeSerializer(data=request.DATA) if serializer.is_valid(): user = serializer.object.user now = timezone.now() assignee, created = GroupAssignee.objects.get_or_create( group=group, defaults={"project": group.project, "user": user, "date_added": now} ) if not created: affected = ( GroupAssignee.objects.filter(group=group).exclude(user=user).update(user=user, date_added=now) ) else: affected = True if affected: create_or_update( Activity, project=group.project, group=group, type=Activity.ASSIGNED, user=request.user ) return Response() return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def set(self, id, data, ttl=None): create_or_update( Node, id=id, values={ 'data': data, 'timestamp': timezone.now(), }, )
def set(self, id, data): create_or_update( Node, id=id, values={ 'data': data, 'timestamp': timezone.now(), }, )
def set(self, id, data): create_or_update( Node, id=id, defaults={ 'data': data, 'timestamp': timezone.now(), }, )
def set(self, id, data, ttl=None): create_or_update(Node, id=id, values={ "data": data, "timestamp": timezone.now() }) cache_on_save = options.get("nodedata.cache-on-save") if cache_on_save: self._set_cache_item(id, data)
def handle(self, **options): page_path = os.path.join(DATA_ROOT, 'help_pages') for filename in os.listdir(page_path): file_path = os.path.join(page_path, filename) if not os.path.isfile(file_path): continue with open(file_path) as fp: content = fp.read() options, body = self.__split_content(content) print('Loading help page {key}'.format( key=filename, )) assert 'title' in options page, created = create_or_update( HelpPage, key=filename, values={ 'title': options['title'], 'priority': options.get('priority', 50), 'content': body, } )
def handle(self, **options): page_path = os.path.join(DATA_ROOT, 'help_pages') for filename in os.listdir(page_path): file_path = os.path.join(page_path, filename) if not os.path.isfile(file_path): continue with open(file_path) as fp: content = fp.read() options, body = self.__split_content(content) print('Loading help page {key}'.format(key=filename, )) assert 'title' in options page, created = create_or_update(HelpPage, key=filename, values={ 'title': options['title'], 'priority': options.get('priority', 50), 'content': body, })
def post(self, request, group_id): group = Group.objects.get( id=group_id, ) assert_perm(group, request.user, request.auth) serializer = GroupAssigneeSerializer(data=request.DATA) if serializer.is_valid(): user = serializer.object.user now = timezone.now() assignee, created = GroupAssignee.objects.get_or_create( group=group, defaults={ 'project': group.project, 'user': user, 'date_added': now, } ) if not created: affected = GroupAssignee.objects.filter( group=group, ).exclude(user=user).update( user=user, date_added=now ) else: affected = True if affected: create_or_update( Activity, project=group.project, group=group, type=Activity.ASSIGNED, user=request.user, ) return Response() return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def post(self, request, group_id): group = Group.objects.get(id=group_id, ) assert_perm(group, request.user, request.auth) instance, created = create_or_update(GroupSeen, group=group, user=extract_lazy_object( request.user), project=group.project, defaults={ 'last_seen': timezone.now(), }) if created: return Response(status=201) return Response(status=204)
def post(self, request, group_id): group = Group.objects.get( id=group_id, ) assert_perm(group, request.user, request.auth) instance, created = create_or_update( GroupSeen, group=group, user=extract_lazy_object(request.user), project=group.project, defaults={ 'last_seen': timezone.now(), } ) if created: return Response(status=201) return Response(status=204)
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) if event_id: event = get_object_or_404(group.event_set, id=event_id) else: event = group.get_latest_event() or Event() Event.objects.bind_nodes([event], 'data') # bind params to group in case they get hit event.group = group event.project = project if request.POST.get('o') == 'note' and request.user.is_authenticated(): add_note_form = NewNoteForm(request.POST) if add_note_form.is_valid(): add_note_form.save(event, request.user) return HttpResponseRedirect(request.path) else: add_note_form = NewNoteForm() activity_qs = Activity.objects.order_by('-datetime').select_related('user') # if event_id: # activity_qs = activity_qs.filter( # Q(event=event) | Q(event__isnull=True), # ) 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)[:20]: sig = (item.event_id, item.type, item.ident, item.user_id) # TODO: we could just generate a signature (hash(text)) for notes # so theres no special casing if item.type == Activity.NOTE: activity.append(item) elif sig not in activity_items: activity_items.add(sig) activity.append(item) activity.append( Activity(project=project, group=group, type=Activity.FIRST_SEEN, datetime=group.first_seen)) # trim to latest 5 activity = activity[:7] 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 = { 'add_note_form': add_note_form, '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 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) if event_id: event = get_object_or_404(group.event_set, id=event_id) else: event = group.get_latest_event() or Event() Event.objects.bind_nodes([event], "data") # bind params to group in case they get hit event.group = group event.project = project if request.POST.get("o") == "note" and request.user.is_authenticated(): add_note_form = NewNoteForm(request.POST) if add_note_form.is_valid(): add_note_form.save(event, request.user) return HttpResponseRedirect(request.path) else: add_note_form = NewNoteForm() 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()} ) activity_qs = Activity.objects.filter(group=group).order_by("-datetime").select_related("user") # filter out dupe activity items activity_items = set() activity = [] for item in activity_qs[:20]: sig = (item.event_id, item.type, item.ident, item.user_id) # TODO: we could just generate a signature (hash(text)) for notes # so there's no special casing if item.type == Activity.NOTE: activity.append(item) elif sig not in activity_items: activity_items.add(sig) activity.append(item) activity.append(Activity(project=project, group=group, type=Activity.FIRST_SEEN, datetime=group.first_seen)) # trim to latest 5 activity = activity[:7] 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 = { "add_note_form": add_note_form, "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 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) if event_id: event = get_object_or_404(group.event_set, id=event_id) else: event = group.get_latest_event() or Event() # bind params to group in case they get hit event.group = group event.project = project if request.POST.get('o') == 'note' and request.user.is_authenticated(): add_note_form = NewNoteForm(request.POST) if add_note_form.is_valid(): activity = Activity.objects.create( group=group, event=event, project=project, type=Activity.NOTE, user=request.user, data=add_note_form.cleaned_data ) activity.send_notification() return HttpResponseRedirect(request.path) else: add_note_form = NewNoteForm() activity_qs = Activity.objects.order_by('-datetime').select_related('user') if event: activity_qs = activity_qs.filter( Q(event=event) | Q(event__isnull=True), ) 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)[:20]: sig = (item.event_id, item.type, item.ident, item.user_id) # TODO: we could just generate a signature (hash(text)) for notes # so theres no special casing if item.type == Activity.NOTE: activity.append(item) elif sig not in activity_items: activity_items.add(sig) activity.append(item) activity.append(Activity( project=project, group=group, type=Activity.FIRST_SEEN, datetime=group.first_seen)) # trim to latest 5 activity = activity[:7] 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 = { 'add_note_form': add_note_form, '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.db.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.db.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 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 group_details(request, organization, 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) if event_id: event = get_object_or_404(group.event_set, id=event_id) else: event = group.get_latest_event() or Event() Event.objects.bind_nodes([event], 'data') GroupMeta.objects.populate_cache([group]) # bind params to group in case they get hit event.group = group event.project = project if request.POST.get('o') == 'note' and request.user.is_authenticated(): add_note_form = NewNoteForm(request.POST) if add_note_form.is_valid(): add_note_form.save(event, request.user) return HttpResponseRedirect(request.path) else: add_note_form = NewNoteForm() if request.user.is_authenticated() and project.has_access(request.user): # update that the user has seen this group try: create_or_update( GroupSeen, group=group, user=request.user, project=project, values={ 'last_seen': timezone.now(), } ) except DatabaseError as exc: logging.warn(unicode(exc), exc_info=True) activity_qs = Activity.objects.filter( group=group, ).order_by('-datetime').select_related('user') # filter out dupe activity items activity_items = set() activity = [] for item in activity_qs[:20]: sig = (item.event_id, item.type, item.ident, item.user_id) # TODO: we could just generate a signature (hash(text)) for notes # so there's no special casing if item.type == Activity.NOTE: activity.append(item) elif sig not in activity_items: activity_items.add(sig) activity.append(item) activity.append(Activity( project=project, group=group, type=Activity.FIRST_SEEN, datetime=group.first_seen)) # trim to latest 5 activity = activity[:7] 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 = { 'add_note_form': add_note_form, '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 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)