Esempio n. 1
0
def get_tags(event):
    tag_list = event.tags
    if not tag_list:
        return ""

    return ", ".join([": ".join([tagstore.get_tag_key_label(k), tagstore.get_tag_value_label(k, v)])
            for k, v in tag_list])
Esempio n. 2
0
    def _get_tags(self, event):
        tag_list = event.get_tags()
        if not tag_list:
            return ()

        return ((tagstore.get_tag_key_label(k), tagstore.get_tag_value_label(k, v))
                for k, v in tag_list)
Esempio n. 3
0
    def get_group_tag_keys_and_top_values(self, project_id, group_id, environment_id, user=None):
        from sentry import tagstore
        start, end = self.get_time_range()
        filters = {
            'project_id': [project_id],
            'environment': [environment_id],
            'issue': [group_id],
        }
        aggregations = [
            ['topK(10)', 'tags.value', 'top'],
            ['count', '', 'count'],
            ['uniq', 'tags.key', 'uniq'],
        ]
        results = snuba.query(start, end, ['tags.key'], None, filters,
                              aggregations, arrayjoin='tags')

        return [{
            'id': key,
            'name': tagstore.get_tag_key_label(key),
            'key': tagstore.get_standardized_key(key),
            'uniqueValues': res['uniq'],
            'totalValues': res['count'],
            'topValues': [{
                'id': val,
                'name': tagstore.get_tag_value_label(key, val),
                'key': tagstore.get_standardized_key(key),
                'value': val,
            } for val in res['top']],
        } for key, res in six.iteritems(results)]
        def data_fn(offset, limit):
            with sentry_sdk.start_span(op="discover.endpoint",
                                       description="discover_query"):
                referrer = "api.organization-events-facets-performance-histogram.top-tags"
                tag_data = query_tag_data(
                    filter_query=filter_query,
                    aggregate_column=aggregate_column,
                    referrer=referrer,
                    params=params,
                )

                if not tag_data:
                    return {"data": []}

                results = query_facet_performance_key_histogram(
                    tag_data=tag_data,
                    tag_key=tag_key,
                    filter_query=filter_query,
                    aggregate_column=aggregate_column,
                    referrer=referrer,
                    orderby=self.get_orderby(request),
                    params=params,
                    limit=limit,
                )

                if not results:
                    return {"data": []}

                for row in results["data"]:
                    row["tags_value"] = tagstore.get_tag_value_label(
                        row["tags_key"], row["tags_value"])
                    row["tags_key"] = tagstore.get_standardized_key(
                        row["tags_key"])

                return results
Esempio n. 5
0
 def get_attrs(self, item_list, user):
     result = {}
     for item in item_list:
         result[item] = {
             'name': tagstore.get_tag_value_label(item.key, item.value),
         }
     return result
Esempio n. 6
0
 def data_fn(offset, limit):
     with sentry_sdk.start_span(op="discover.endpoint", description="discover_query"):
         with self.handle_query_errors():
             facets = discover.get_performance_facets(
                 query=request.GET.get("query"),
                 params=params,
                 referrer="api.organization-events-facets-performance.top-tags",
                 aggregate_column=aggregate_column,
                 orderby=orderby,
                 offset=offset,
                 limit=limit,
             )
         with sentry_sdk.start_span(
             op="discover.endpoint", description="populate_results"
         ) as span:
             span.set_data("facet_count", len(facets or []))
             resp = defaultdict(lambda: {"key": "", "value": {}})
             for row in facets:
                 values = resp[row.key]
                 values["key"] = tagstore.get_standardized_key(row.key)
                 values["value"] = {
                     "name": tagstore.get_tag_value_label(row.key, row.value),
                     "value": row.value,
                     "count": row.count,
                     "frequency": row.frequency,
                     "aggregate": row.performance,
                     "comparison": row.comparison,
                     "sumdelta": row.sumdelta,
                 }
         return {"data": list(resp.values())}
Esempio n. 7
0
    def get_group_tag_keys_and_top_values(self, project_id, group_id, environment_id, user=None):
        from sentry import tagstore
        start, end = self.get_time_range()
        filters = {
            'project_id': [project_id],
            'environment': [environment_id],
            'issue': [group_id],
        }
        aggregations = [
            ['count()', '', 'count'],
            ['topK(10)', 'tags_value', 'top'],
            ['uniq', 'tags_value', 'uniq'],
        ]
        conditions = [
            ['tags_value', 'IS NOT NULL', None],
        ]
        results = snuba.query(start, end, ['tags_key'], conditions, filters, aggregations)

        return [{
            'id': key,
            'name': tagstore.get_tag_key_label(key),
            'key': tagstore.get_standardized_key(key),
            'uniqueValues': res['uniq'],
            'totalValues': res['count'],
            'topValues': [{
                'id': val,
                'name': tagstore.get_tag_value_label(key, val),
                'key': tagstore.get_standardized_key(key),
                'value': val,
            } for val in res['top']],
        } for key, res in six.iteritems(results)]
Esempio n. 8
0
    def _get_tags(self, event):
        tag_list = event.get_tags()
        if not tag_list:
            return ()

        return ((tagstore.get_tag_key_label(k),
                 tagstore.get_tag_value_label(k, v)) for k, v in tag_list)
Esempio n. 9
0
    def get(self, request, organization):
        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="filter_params") as span:
            span.set_data("organization", organization)
            if not features.has("organizations:discover-basic",
                                organization,
                                actor=request.user):
                return Response(status=404)
            try:
                params = self.get_filter_params(request, organization)
            except NoProjects:
                return Response([])
            params = self.quantize_date_params(request, params)
            self._validate_project_ids(request, organization, params)

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="discover_query"):
            try:
                facets = discover.get_facets(
                    query=request.GET.get("query"),
                    params=params,
                    referrer="api.organization-events-facets.top-tags",
                )
            except (discover.InvalidSearchQuery,
                    snuba.QueryOutsideRetentionError) as error:
                raise ParseError(detail=six.text_type(error))

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="populate_results") as span:
            span.set_data("facet_count", len(facets or []))
            resp = defaultdict(lambda: {"key": "", "topValues": []})
            for row in facets:
                values = resp[row.key]
                values["key"] = tagstore.get_standardized_key(row.key)
                values["topValues"].append({
                    "name":
                    tagstore.get_tag_value_label(row.key, row.value),
                    "value":
                    row.value,
                    "count":
                    row.count,
                })
            if "project" in resp:
                # Replace project ids with slugs as that is what we generally expose to users
                # and filter out projects that the user doesn't have access too.
                projects = {
                    p.id: p.slug
                    for p in self.get_projects(request, organization)
                }
                filtered_values = []
                for v in resp["project"]["topValues"]:
                    if v["value"] in projects:
                        name = projects[v["value"]]
                        v.update({"name": name})
                        filtered_values.append(v)

                resp["project"]["topValues"] = filtered_values

        return Response(resp.values())
Esempio n. 10
0
def get_tags(event):
    tag_list = event.tags
    if not tag_list:
        return ()

    return (
        (tagstore.get_tag_key_label(k), tagstore.get_tag_value_label(k, v)) for k, v in tag_list
    )
Esempio n. 11
0
    def get(self, request, organization):
        try:
            snuba_args = self.get_snuba_query_args(request, organization)
        except OrganizationEventsError as exc:
            return Response({'detail': exc.message}, status=400)
        except NoProjects:
            return Response({'detail': 'A valid project must be included.'}, status=400)

        try:
            key = self._validate_key(request)
            self._validate_project_ids(request, organization, snuba_args)
        except OrganizationEventsError as error:
            return Response({'detail': six.text_type(error)}, status=400)

        colname = get_snuba_column_name(key)

        if key == PROJECT_KEY:
            colname = 'project_id'

        top_values = raw_query(
            start=snuba_args['start'],
            end=snuba_args['end'],
            conditions=snuba_args['conditions'] + [[colname, 'IS NOT NULL', None]],
            filter_keys=snuba_args['filter_keys'],
            groupby=[colname],
            aggregations=[('count()', None, 'count')],
            orderby='-count',
            limit=TOP_VALUES_DEFAULT_LIMIT,
            referrer='api.organization-events-distribution',
        )['data']

        projects = {p.id: p.slug for p in self.get_projects(request, organization)}

        if key == PROJECT_KEY:
            resp = {
                'key': PROJECT_KEY,
                'topValues': [
                    {
                        'value': projects[v['project_id']],
                        'name': projects[v['project_id']],
                        'count': v['count'],
                    } for v in top_values
                ]
            }
        else:
            resp = {
                'key': key,
                'topValues': [
                    {
                        'value': v[colname],
                        'name': tagstore.get_tag_value_label(colname, v[colname]),
                        'count': v['count'],
                    }
                    for v in top_values
                ],
            }

        return Response(resp)
Esempio n. 12
0
    def get_attrs(self, item_list, user):
        from sentry import tagstore

        result = {}
        for item in item_list:
            result[item] = {
                'name': tagstore.get_tag_value_label(item.key, item.value),
            }
        return result
Esempio n. 13
0
    def get_attrs(self, item_list, user):
        from sentry import tagstore

        result = {}
        for item in item_list:
            result[item] = {
                "name": tagstore.get_tag_value_label(item.key, item.value)
            }
        return result
Esempio n. 14
0
    def get(self, request, organization):
        if not features.has("organizations:discover-basic",
                            organization,
                            actor=request.user):
            return Response(status=404)
        try:
            params = self.get_filter_params(request, organization)
        except OrganizationEventsError as error:
            raise ParseError(detail=six.text_type(error))
        except NoProjects:
            return Response({"detail": "A valid project must be included."},
                            status=400)
        try:
            self._validate_project_ids(request, organization, params)
        except OrganizationEventsError as error:
            return Response({"detail": six.text_type(error)}, status=400)

        try:
            facets = discover.get_facets(
                query=request.GET.get("query"),
                params=params,
                referrer="api.organization-events-facets.top-tags",
            )
        except discover.InvalidSearchQuery as error:
            raise ParseError(detail=six.text_type(error))

        resp = defaultdict(lambda: {"key": "", "topValues": []})
        for row in facets:
            values = resp[row.key]
            values["key"] = tagstore.get_standardized_key(row.key)
            values["topValues"].append({
                "name":
                tagstore.get_tag_value_label(row.key, row.value),
                "value":
                row.value,
                "count":
                row.count,
            })
        if "project" in resp:
            # Replace project ids with slugs as that is what we generally expose to users
            # and filter out projects that the user doesn't have access too.
            projects = {
                p.id: p.slug
                for p in self.get_projects(request, organization)
            }
            filtered_values = []
            for v in resp["project"]["topValues"]:
                if v["value"] in projects:
                    name = projects[v["value"]]
                    v.update({"name": name})
                    filtered_values.append(v)

            resp["project"]["topValues"] = filtered_values

        return Response(resp.values())
Esempio n. 15
0
    def serialize(self, obj, attrs, user):
        from sentry import tagstore

        return {
            'key': tagstore.get_standardized_key(obj.key),
            'name': tagstore.get_tag_value_label(obj.key, obj.value),
            'value': obj.value,
            'count': obj.times_seen,
            'lastSeen': obj.last_seen,
            'firstSeen': obj.first_seen,
        }
Esempio n. 16
0
    def serialize(self, obj, attrs, user):
        from sentry import tagstore

        return {
            'key': tagstore.get_standardized_key(obj.key),
            'name': tagstore.get_tag_value_label(obj.key, obj.value),
            'value': obj.value,
            'count': obj.times_seen,
            'lastSeen': obj.last_seen,
            'firstSeen': obj.first_seen,
        }
Esempio n. 17
0
    def get(self, request, organization):
        if not self.has_feature(organization, request):
            return Response(status=404)

        try:
            params = self.get_snuba_params(request, organization)
        except NoProjects:
            return Response([])

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="discover_query"):
            with self.handle_query_errors():
                facets = discover.get_facets(
                    query=request.GET.get("query"),
                    params=params,
                    referrer="api.organization-events-facets.top-tags",
                )

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="populate_results") as span:
            span.set_data("facet_count", len(facets or []))
            resp = defaultdict(lambda: {"key": "", "topValues": []})
            for row in facets:
                values = resp[row.key]
                values["key"] = tagstore.get_standardized_key(row.key)
                values["topValues"].append({
                    "name":
                    tagstore.get_tag_value_label(row.key, row.value),
                    "value":
                    row.value,
                    "count":
                    row.count,
                })
            if "project" in resp:
                # Replace project ids with slugs as that is what we generally expose to users
                # and filter out projects that the user doesn't have access too.
                projects = {
                    p.id: p.slug
                    for p in self.get_projects(request, organization)
                }
                filtered_values = []
                for v in resp["project"]["topValues"]:
                    if v["value"] in projects:
                        name = projects[v["value"]]
                        v.update({"name": name})
                        filtered_values.append(v)

                resp["project"]["topValues"] = filtered_values

        return Response(list(resp.values()))
Esempio n. 18
0
def build_tag_fields(event_for_tags, tags: Mapping[str, str] = None):
    fields = []
    if tags:
        event_tags = event_for_tags.tags if event_for_tags else []
        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append({
                "title": std_key.encode("utf-8"),
                "value": labeled_value.encode("utf-8"),
                "short": True,
            })
    return fields
Esempio n. 19
0
    def serialize(self, obj, attrs, user):
        from sentry import tagstore
        key = tagstore.get_standardized_key(obj.key)
        serialized = {
            'key': key,
            'name': tagstore.get_tag_value_label(obj.key, obj.value),
            'value': obj.value,
            'count': obj.times_seen,
            'lastSeen': obj.last_seen,
            'firstSeen': obj.first_seen,
        }

        query = convert_user_tag_to_query(key, obj.value)
        if query:
            serialized['query'] = query

        return serialized
Esempio n. 20
0
    def serialize(self, obj, attrs, user):
        from sentry import tagstore
        key = tagstore.get_standardized_key(obj.key)
        serialized = {
            'key': key,
            'name': tagstore.get_tag_value_label(obj.key, obj.value),
            'value': obj.value,
            'count': obj.times_seen,
            'lastSeen': obj.last_seen,
            'firstSeen': obj.first_seen,
        }

        query = convert_user_tag_to_query(key, obj.value)
        if query:
            serialized['query'] = query

        return serialized
Esempio n. 21
0
    def serialize(self, obj, attrs, user):
        from sentry import tagstore

        key = tagstore.get_standardized_key(obj.key)
        serialized = {
            "key": key,
            "name": tagstore.get_tag_value_label(obj.key, obj.value),
            "value": obj.value,
            "count": obj.times_seen,
            "lastSeen": obj.last_seen,
            "firstSeen": obj.first_seen,
        }

        query = convert_user_tag_to_query(key, obj.value)
        if query:
            serialized["query"] = query

        return serialized
Esempio n. 22
0
def build_tag_fields(
    event_for_tags: Any,
    tags: Optional[Set[str]] = None
) -> Sequence[Mapping[str, Union[str, bool]]]:
    fields = []
    if tags:
        event_tags = event_for_tags.tags if event_for_tags else []
        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append({
                "title": std_key.encode("utf-8"),
                "value": labeled_value.encode("utf-8"),
                "short": True,
            })
    return fields
Esempio n. 23
0
    def get(self, request, organization):
        if not self.has_feature(organization, request):
            return Response(status=404)

        try:
            params = self.get_snuba_params(request, organization)
        except NoProjects:
            return Response([])

        aggregate_column = request.GET.get("aggregateColumn", "duration")
        orderby = request.GET.getlist("order", None)

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="discover_query"):
            with self.handle_query_errors():
                facets = discover.get_performance_facets(
                    query=request.GET.get("query"),
                    params=params,
                    referrer=
                    "api.organization-events-facets-performance.top-tags",
                    aggregate_column=aggregate_column,
                    orderby=orderby,
                )

        with sentry_sdk.start_span(op="discover.endpoint",
                                   description="populate_results") as span:
            span.set_data("facet_count", len(facets or []))
            resp = defaultdict(lambda: {"key": "", "topValues": []})
            for row in facets:
                values = resp[row.key]
                values["key"] = tagstore.get_standardized_key(row.key)
                values["topValues"].append({
                    "name":
                    tagstore.get_tag_value_label(row.key, row.value),
                    "value":
                    row.value,
                    "count":
                    row.count,
                    "aggregate":
                    row.performance,
                })
        return Response(list(resp.values()))
Esempio n. 24
0
        def data_fn():
            with sentry_sdk.start_span(op="discover.endpoint",
                                       description="discover_query"):
                referrer = "api.organization-events-facets-performance-histogram"
                top_tags = query_top_tags(
                    tag_key=tag_key,
                    limit=tag_key_limit,
                    filter_query=filter_query,
                    aggregate_column=aggregate_column,
                    params=params,
                    orderby=self.get_orderby(request),
                    referrer=referrer,
                )

                if not top_tags:
                    return {"data": []}, []

                results = query_facet_performance_key_histogram(
                    top_tags=top_tags,
                    tag_key=tag_key,
                    filter_query=filter_query,
                    aggregate_column=aggregate_column,
                    referrer=referrer,
                    params=params,
                    limit=tag_key_limit,
                    num_buckets_per_key=num_buckets_per_key,
                )

                if not results:
                    return {"data": []}, top_tags

                for row in results["data"]:
                    row["tags_value"] = tagstore.get_tag_value_label(
                        row["tags_key"], row["tags_value"])
                    row["tags_key"] = tagstore.get_standardized_key(
                        row["tags_key"])

                return results, top_tags
Esempio n. 25
0
    def notify(self, notification, raise_exception=None):
        """
        notify
        Send Event Notifications
        """
        event = notification.event
        group = event.group
        project = group.project

        # Make sure we're configured
        if not self.is_configured(project):
            return

        webhook_url = self.get_option('webhook_url', project)
        project_name = project.get_full_name().encode('utf-8')
        notification_link = self.create_markdown_link(
            'Click Here',
            self.add_notification_referrer_param(group.get_absolute_url()))

        try:
            # Sentry 9
            title = event.message_short.encode('utf-8')
            error_message = event.error().encode('utf-8')
        except AttributeError:
            # Sentry 10
            title = event.title.encode('utf-8')
            error_message = event.message.encode('utf-8')

        message_facts = []

        message_facts.append({'name': 'Project', 'value': project_name})

        if error_message:
            message_facts.append({'name': 'Error', 'value': error_message})

        if group.times_seen:
            message_facts.append({
                'name': 'Times Seen',
                'value': 'Seen %s Times' % group.times_seen
            })

        if group.culprit and title != group.culprit:
            message_facts.append({
                'name': 'Culprit',
                'value': group.culprit.encode('utf-8')
            })

        message_object = {
            'sections': [{
                'activityTitle': '[%s] %s' % (project_name, title),
                'activityText':
                '%s to View this Event in Sentry' % notification_link,
                'facts': message_facts
            }],
            '@type':
            'MessageCard',
            'summary':
            '[%s] %s' % (project_name, title)
        }

        if self.get_option('show_tags', project):
            tags = []
            try:
                # Sentry 9
                sentry_tags = event.get_tags()
            except AttributeError:
                # Sentry 10
                sentry_tags = event.tags
            if sentry_tags:
                sentry_tag_tuples = ((tagstore.get_tag_key_label(tagname),
                                      tagstore.get_tag_value_label(
                                          tagname, tagvalue))
                                     for tagname, tagvalue in sentry_tags)
                for tag_name, tag_value in sentry_tag_tuples:
                    tags.append({
                        'name': tag_name.encode('utf-8'),
                        'value': tag_value.encode('utf-8')
                    })
                section = {
                    'activityTitle': 'Tags on Event',
                    'activityText':
                    'The following Tags were attached to the Event',
                    'facts': tags
                }
                message_object['sections'].append(section)

        return http.safe_urlopen(webhook_url,
                                 method='POST',
                                 data=json.dumps(message_object))
Esempio n. 26
0
    def get_label(self):
        from sentry import tagstore

        return tagstore.get_tag_value_label(self.key, self.value)
Esempio n. 27
0
    def get_label(self):
        from sentry import tagstore

        return tagstore.get_tag_value_label(self.key, self.value)
Esempio n. 28
0
def build_attachment(group, event=None, tags=None, identity=None, actions=None, rules=None):
    # XXX(dcramer): options are limited to 100 choices, even when nested
    status = group.get_status()

    members = get_member_assignees(group)
    teams = get_team_assignees(group)

    logo_url = absolute_uri(get_asset_url('sentry', 'images/sentry-email-avatar.png'))
    color = LEVEL_TO_COLOR.get(
        event.get_tag('level'),
        'error') if event else LEVEL_TO_COLOR['error']

    text = build_attachment_text(group, event) or ''

    if actions is None:
        actions = []

    assignee = get_assignee(group)

    resolve_button = {
        'name': 'resolve_dialog',
        'value': 'resolve_dialog',
        'type': 'button',
        'text': 'Resolve...',
    }

    ignore_button = {
        'name': 'status',
        'value': 'ignored',
        'type': 'button',
        'text': 'Ignore',
    }

    has_releases = Release.objects.filter(
        projects=group.project,
        organization_id=group.project.organization_id
    ).exists()

    if not has_releases:
        resolve_button.update({
            'name': 'status',
            'text': 'Resolve',
            'value': 'resolved',
        })

    if status == GroupStatus.RESOLVED:
        resolve_button.update({
            'name': 'status',
            'text': 'Unresolve',
            'value': 'unresolved',
        })

    if status == GroupStatus.IGNORED:
        ignore_button.update({
            'text': 'Stop Ignoring',
            'value': 'unresolved',
        })

    option_groups = []

    if teams:
        option_groups.append({
            'text': 'Teams',
            'options': teams,
        })

    if members:
        option_groups.append({
            'text': 'People',
            'options': members,
        })

    payload_actions = [
        resolve_button,
        ignore_button,
        {
            'name': 'assign',
            'text': 'Select Assignee...',
            'type': 'select',
            'selected_options': [assignee],
            'option_groups': option_groups,
        },
    ]

    fields = []

    if tags:
        event_tags = event.tags if event else group.get_latest_event().tags

        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append(
                {
                    'title': std_key.encode('utf-8'),
                    'value': labeled_value.encode('utf-8'),
                    'short': True,
                }
            )

    if actions:
        action_texts = filter(None, [build_action_text(group, identity, a) for a in actions])
        text += '\n' + '\n'.join(action_texts)

        color = ACTIONED_ISSUE_COLOR
        payload_actions = []

    ts = group.last_seen

    if event:
        event_ts = event.datetime
        ts = max(ts, event_ts)

    footer = u'{}'.format(group.qualified_short_id)

    if rules:
        footer += u' via {}'.format(rules[0].label)

        if len(rules) > 1:
            footer += u' (+{} other)'.format(len(rules) - 1)

    return {
        'fallback': u'[{}] {}'.format(group.project.slug, group.title),
        'title': build_attachment_title(group, event),
        'title_link': group.get_absolute_url(params={'referrer': 'slack'}),
        'text': text,
        'fields': fields,
        'mrkdwn_in': ['text'],
        'callback_id': json.dumps({'issue': group.id}),
        'footer_icon': logo_url,
        'footer': footer,
        'ts': to_timestamp(ts),
        'color': color,
        'actions': payload_actions,
    }
Esempio n. 29
0
def build_alert_payload(group, team_id=None, user_id=None, priority=None, event=None, tags=None, identity=None, actions=[], rules=None):

    priority = LEVEL_TO_PRIORITY.get(event.get_tag('level')) if not priority else priority
    description = build_attachment_text(group, event) or ''

    assignee = get_assignee(group)

    fields = []

    if tags:
        event_tags = event.tags if event else group.get_latest_event().tags

        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append('%s:%s' % (std_key.encode('utf-8'), labeled_value.encode('utf-8')))

    ts = group.last_seen

    if event:
        event_ts = event.datetime
        ts = max(ts, event_ts)

    footer = u'{}'.format(group.qualified_short_id)

    if rules:
        footer += u' via {}'.format(rules[0].label)

        if len(rules) > 1:
            footer += u' (+{} other)'.format(len(rules) - 1)

    return CreateAlertRequest(
        message = build_attachment_title(group, event),
        alias = 'sentry-%d' % group.id,
        description = description,
        responders = [
            {"id": team_id, "type": "team"},
            {"id": user_id, "type": "user"},
        ],
        actions = actions, # these are custom actions on opsgenie, example: ["Restart", "AnExampleAction"]
        tags = fields,
        details = {
            'Assignee': assignee or 'Not assigned to anyone yet',
            'Sentry ID': str(group.id),
            'Sentry Group': getattr(group, 'message_short', group.message).encode('utf-8'),
            'Checksum': group.checksum,
            'Project ID': group.project.slug,
            'Project Name': group.project.name,
            'Logger': group.logger,
            'Level': group.get_level_display(),
            'URL': group.get_absolute_url(params={'referrer': 'opsgenie'}), # don't foget to set system.url-prefix in config.yml
            'Timestamp': str(ts),
            'Trigerring Rules': footer
        },
        entity = group.culprit,
        source = 'Sentry',
        priority = priority
    )
Esempio n. 30
0
def build_group_attachment(group,
                           event=None,
                           tags=None,
                           identity=None,
                           actions=None,
                           rules=None):
    # XXX(dcramer): options are limited to 100 choices, even when nested
    status = group.get_status()

    members = get_member_assignees(group)
    teams = get_team_assignees(group)

    logo_url = absolute_uri(
        get_asset_url('sentry', 'images/sentry-email-avatar.png'))
    color = LEVEL_TO_COLOR.get(event.get_tag('level'),
                               'error') if event else LEVEL_TO_COLOR['error']

    text = build_attachment_text(group, event) or ''

    if actions is None:
        actions = []

    assignee = get_assignee(group)

    resolve_button = {
        'name': 'resolve_dialog',
        'value': 'resolve_dialog',
        'type': 'button',
        'text': 'Resolve...',
    }

    ignore_button = {
        'name': 'status',
        'value': 'ignored',
        'type': 'button',
        'text': 'Ignore',
    }

    has_releases = Release.objects.filter(
        projects=group.project,
        organization_id=group.project.organization_id).exists()

    if not has_releases:
        resolve_button.update({
            'name': 'status',
            'text': 'Resolve',
            'value': 'resolved',
        })

    if status == GroupStatus.RESOLVED:
        resolve_button.update({
            'name': 'status',
            'text': 'Unresolve',
            'value': 'unresolved',
        })

    if status == GroupStatus.IGNORED:
        ignore_button.update({
            'text': 'Stop Ignoring',
            'value': 'unresolved',
        })

    option_groups = []

    if teams:
        option_groups.append({
            'text': 'Teams',
            'options': teams,
        })

    if members:
        option_groups.append({
            'text': 'People',
            'options': members,
        })

    payload_actions = [
        resolve_button,
        ignore_button,
        {
            'name': 'assign',
            'text': 'Select Assignee...',
            'type': 'select',
            'selected_options': [assignee],
            'option_groups': option_groups,
        },
    ]

    fields = []

    if tags:
        event_tags = event.tags if event else group.get_latest_event().tags

        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append({
                'title': std_key.encode('utf-8'),
                'value': labeled_value.encode('utf-8'),
                'short': True,
            })

    if actions:
        action_texts = filter(
            None, [build_action_text(group, identity, a) for a in actions])
        text += '\n' + '\n'.join(action_texts)

        color = ACTIONED_ISSUE_COLOR
        payload_actions = []

    ts = group.last_seen

    if event:
        event_ts = event.datetime
        ts = max(ts, event_ts)

    footer = u'{}'.format(group.qualified_short_id)

    if rules:
        footer += u' via {}'.format(rules[0].label)

        if len(rules) > 1:
            footer += u' (+{} other)'.format(len(rules) - 1)

    return {
        'fallback': u'[{}] {}'.format(group.project.slug, group.title),
        'title': build_attachment_title(group, event),
        'title_link': group.get_absolute_url(params={'referrer': 'slack'}),
        'text': text,
        'fields': fields,
        'mrkdwn_in': ['text'],
        'callback_id': json.dumps({'issue': group.id}),
        'footer_icon': logo_url,
        'footer': footer,
        'ts': to_timestamp(ts),
        'color': color,
        'actions': payload_actions,
    }
    def get(self, request, organization):
        if not features.has(
                "organizations:events-v2", organization, actor=request.user):
            return Response(status=404)
        try:
            params = self.get_filter_params(request, organization)
            snuba_args = self.get_snuba_query_args(request, organization,
                                                   params)
        except OrganizationEventsError as exc:
            return Response({"detail": exc.message}, status=400)
        except NoProjects:
            return Response({"detail": "A valid project must be included."},
                            status=400)

        try:
            key = self._validate_key(request)
            self._validate_project_ids(request, organization, snuba_args)
        except OrganizationEventsError as error:
            return Response({"detail": six.text_type(error)}, status=400)

        if key == PROJECT_KEY:
            colname = "project_id"
            conditions = snuba_args["conditions"]
        else:
            colname = get_snuba_column_name(key)
            conditions = snuba_args["conditions"] + [[
                colname, "IS NOT NULL", None
            ]]

        top_values = raw_query(
            start=snuba_args["start"],
            end=snuba_args["end"],
            conditions=conditions,
            filter_keys=snuba_args["filter_keys"],
            groupby=[colname],
            aggregations=[("count()", None, "count")],
            orderby="-count",
            limit=TOP_VALUES_DEFAULT_LIMIT,
            referrer="api.organization-events-distribution",
        )["data"]

        projects = {
            p.id: p.slug
            for p in self.get_projects(request, organization)
        }

        if key == PROJECT_KEY:
            resp = {
                "key":
                PROJECT_KEY,
                "topValues": [{
                    "value": projects[v["project_id"]],
                    "name": projects[v["project_id"]],
                    "count": v["count"],
                } for v in top_values],
            }
        else:
            resp = {
                "key":
                key,
                "topValues": [{
                    "value":
                    v[colname],
                    "name":
                    tagstore.get_tag_value_label(colname, v[colname]),
                    "count":
                    v["count"],
                } for v in top_values],
            }

        return Response(resp)
    def get(self, request, organization):
        if not features.has(
                "organizations:events-v2", organization, actor=request.user):
            return Response(status=404)
        try:
            params = self.get_filter_params(request, organization)
        except OrganizationEventsError as error:
            raise ParseError(detail=six.text_type(error))
        except NoProjects:
            return Response({"detail": "A valid project must be included."},
                            status=400)

        try:
            key = self._validate_key(request)
            self._validate_project_ids(request, organization, params)
        except OrganizationEventsError as error:
            raise ParseError(detail=six.text_type(error))

        if key == PROJECT_KEY:
            colname = "project.id"
        elif key == "user":
            colname = "sentry:user"
        else:
            colname = key
        try:
            result = discover.query(
                selected_columns=[colname, "count()"],
                params=params,
                query=request.GET.get("query"),
                orderby="-count",
                limit=TOP_VALUES_DEFAULT_LIMIT,
                referrer="api.organization-events-distribution",
            )
        except discover.InvalidSearchQuery as error:
            raise ParseError(detail=six.text_type(error))

        if key == PROJECT_KEY:
            projects = {
                p.id: p.slug
                for p in self.get_projects(request, organization)
            }
            resp = {
                "key":
                PROJECT_KEY,
                "topValues": [{
                    "value": projects[v["project.id"]],
                    "name": projects[v["project.id"]],
                    "count": v["count"],
                } for v in result["data"]],
            }
        else:
            resp = {
                "key":
                key,
                "topValues": [{
                    "value":
                    v[colname],
                    "name":
                    tagstore.get_tag_value_label(colname, v[colname]),
                    "count":
                    v["count"],
                } for v in result["data"]],
            }

        return Response(resp)
Esempio n. 33
0
def build_group_attachment(group,
                           event=None,
                           tags=None,
                           identity=None,
                           actions=None,
                           rules=None):
    # XXX(dcramer): options are limited to 100 choices, even when nested
    status = group.get_status()

    members = get_member_assignees(group)
    teams = get_team_assignees(group)

    logo_url = absolute_uri(
        get_asset_url("sentry", "images/sentry-email-avatar.png"))
    color = (LEVEL_TO_COLOR.get(event.get_tag("level"), "error")
             if event else LEVEL_TO_COLOR["error"])

    text = build_attachment_text(group, event) or ""

    if actions is None:
        actions = []

    assignee = get_assignee(group)

    resolve_button = {
        "name": "resolve_dialog",
        "value": "resolve_dialog",
        "type": "button",
        "text": "Resolve...",
    }

    ignore_button = {
        "name": "status",
        "value": "ignored",
        "type": "button",
        "text": "Ignore"
    }

    project = Project.objects.get_from_cache(id=group.project_id)

    cache_key = "has_releases:2:%s" % (project.id)
    has_releases = cache.get(cache_key)
    if has_releases is None:
        has_releases = ReleaseProject.objects.filter(
            project_id=project.id).exists()
        if has_releases:
            cache.set(cache_key, True, 3600)
        else:
            cache.set(cache_key, False, 60)

    if not has_releases:
        resolve_button.update({
            "name": "status",
            "text": "Resolve",
            "value": "resolved"
        })

    if status == GroupStatus.RESOLVED:
        resolve_button.update({
            "name": "status",
            "text": "Unresolve",
            "value": "unresolved"
        })

    if status == GroupStatus.IGNORED:
        ignore_button.update({"text": "Stop Ignoring", "value": "unresolved"})

    option_groups = []

    if teams:
        option_groups.append({"text": "Teams", "options": teams})

    if members:
        option_groups.append({"text": "People", "options": members})

    payload_actions = [
        resolve_button,
        ignore_button,
        {
            "name": "assign",
            "text": "Select Assignee...",
            "type": "select",
            "selected_options": [assignee],
            "option_groups": option_groups,
        },
    ]

    fields = []

    if tags:
        event_tags = event.tags if event else group.get_latest_event().tags

        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append({
                "title": std_key.encode("utf-8"),
                "value": labeled_value.encode("utf-8"),
                "short": True,
            })

    if actions:
        action_texts = [
            _f
            for _f in [build_action_text(group, identity, a) for a in actions]
            if _f
        ]
        text += "\n" + "\n".join(action_texts)

        color = ACTIONED_ISSUE_COLOR
        payload_actions = []

    ts = group.last_seen

    if event:
        event_ts = event.datetime
        ts = max(ts, event_ts)

    footer = u"{}".format(group.qualified_short_id)

    if rules:
        footer += u" via {}".format(rules[0].label)

        if len(rules) > 1:
            footer += u" (+{} other)".format(len(rules) - 1)

    obj = event if event is not None else group
    return {
        "fallback": u"[{}] {}".format(project.slug, obj.title),
        "title": build_attachment_title(obj),
        "title_link": group.get_absolute_url(params={"referrer": "slack"}),
        "text": text,
        "fields": fields,
        "mrkdwn_in": ["text"],
        "callback_id": json.dumps({"issue": group.id}),
        "footer_icon": logo_url,
        "footer": footer,
        "ts": to_timestamp(ts),
        "color": color,
        "actions": payload_actions,
    }
def build_alert_payload(group,
                        routing_key,
                        severity=None,
                        event=None,
                        tags=None,
                        identity=None,
                        rules=None):

    severity = LEVEL_TO_SEVERITY.get(
        event.get_tag('level')) if not severity else severity
    description = build_attachment_text(group, event) or ''

    assignee = get_assignee(group)

    fields = []

    if tags:
        event_tags = event.tags if event else group.get_latest_event().tags

        for key, value in event_tags:
            std_key = tagstore.get_standardized_key(key)
            if std_key not in tags:
                continue

            labeled_value = tagstore.get_tag_value_label(key, value)
            fields.append(
                '%s:%s' %
                (std_key.encode('utf-8'), labeled_value.encode('utf-8')))

    ts = group.last_seen

    if event:
        event_ts = event.datetime
        ts = max(ts, event_ts)

    footer = u'{}'.format(group.qualified_short_id)

    if rules:
        footer += u' via {}'.format(rules[0].label)

        if len(rules) > 1:
            footer += u' (+{} other)'.format(len(rules) - 1)

    logo_url = absolute_uri(
        get_asset_url('sentry', 'images/sentry-email-avatar.png'))
    status = group.get_status()
    return {
        'payload': {
            'summary': build_attachment_title(group, event),
            'timestamp': ts.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
            'source': group.project.name,
            'severity': severity,
            'component': group.culprit,
            'group': group.project.slug,
            'class': group.title,
            'custom_details': {
                'Description':
                description,
                'Assignee':
                assignee or 'Not assigned to anyone yet',
                'Sentry ID':
                str(group.id),
                'Sentry Group':
                getattr(group, 'message_short', group.message).encode('utf-8'),
                'Checksum':
                group.checksum,
                'Project ID':
                group.project.slug,
                'Project Name':
                group.project.name,
                'Logger':
                group.logger,
                'Trigerring Rules':
                footer,
                'Tags':
                fields,
                'Status':
                GROUP_STATUS_VERBOSE.get(status, status),
                'Number of times seen':
                group.times_seen,
                'First seen':
                group.first_seen.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
                'Number of users seen':
                group.count_users_seen(),
            }
        },
        'images': [{
            'src': logo_url,
            'href': options.get("system.url-prefix"),
            'alt': group.title,
        }],
        'dedup_key':
        'sentry-%s-%d' % (group.project.slug, group.id),
        'event_action':
        'trigger',
        'client':
        'Sentry',
        'client_url':
        group.get_absolute_url(params={'referrer': 'pagerduty'}),
        'routing_key':
        routing_key,
    }