Beispiel #1
0
def build_context(group: Group) -> Mapping[str, Any]:
    result, stats_24hr = get_serialized_and_stats(group, "24h")
    _, stats_14d = get_serialized_and_stats(group, "14d")

    first_release = group.get_first_release()
    if first_release is not None:
        last_release = group.get_last_release()
    else:
        last_release = None

    first_release_url = None
    if first_release:
        first_release_url = get_release_url(group, first_release)

    last_release_url = None
    if last_release:
        last_release_url = get_release_url(group, last_release)

    group_url = group.get_absolute_url(
        params={"referrer": "sentry-issues-glance"})

    return {
        "type": result.get("metadata", {}).get("type", "Unknown Error"),
        "title": group.title,
        "title_url": group_url,
        "first_seen": result["firstSeen"],
        "last_seen": result["lastSeen"],
        "first_release": first_release,
        "first_release_url": first_release_url,
        "last_release": last_release,
        "last_release_url": last_release_url,
        "stats_24hr": stats_24hr,
        "stats_14d": stats_14d,
    }
Beispiel #2
0
def get_title_link(
    group: Group,
    event: Optional[Event],
    link_to_event: bool,
    issue_details: bool,
    notification: Optional[BaseNotification],
) -> Any:
    if event and link_to_event:
        return group.get_absolute_url(params={"referrer": "slack"},
                                      event_id=event.event_id)

    if issue_details:
        referrer = re.sub("Notification$", "Slack",
                          notification.__class__.__name__)
        return group.get_absolute_url(params={"referrer": referrer})

    return group.get_absolute_url(params={"referrer": "slack"})
Beispiel #3
0
def new_note(request):
    org = Organization(
        id=1,
        slug='example',
        name='Example',
    )
    team = Team(
        id=1,
        slug='example',
        name='Example',
        organization=org,
    )
    project = Project(
        id=1,
        slug='example',
        name='Example',
        team=team,
        organization=org,
    )
    group = Group(
        id=1,
        project=project,
        message='This is an example event.',
    )
    event = Event(
        id=1,
        project=project,
        group=group,
        message=group.message,
        data=load_data('python'),
    )
    note = Activity(
        group=event.group,
        event=event,
        project=event.project,
        type=Activity.NOTE,
        user=request.user,
        data={'text': 'This is an example note!'},
    )

    preview = MailPreview(
        html_template='sentry/emails/activity/note.html',
        text_template='sentry/emails/activity/note.txt',
        context={
            'data': note.data,
            'author': note.user,
            'date': note.datetime,
            'group': group,
            'link': group.get_absolute_url(),
        },
    )

    return render_to_response('sentry/debug/mail/preview.html', {
        'preview': preview,
    })
Beispiel #4
0
def assigned(request):

    org = Organization(
        id=1,
        slug='example',
        name='Example',
    )
    team = Team(
        id=1,
        slug='example',
        name='Example',
        organization=org,
    )
    project = Project(
        id=1,
        slug='example',
        name='Example',
        team=team,
        organization=org,
    )
    group = Group(
        id=1,
        project=project,
        message='This is an example event.',
    )
    event = Event(
        id=1,
        project=project,
        group=group,
        message=group.message,
        data=load_data('python'),
    )
    assigned = Activity(
        group=event.group,
        project=event.project,
        type=Activity.ASSIGNED,
        user=request.user,
        data={
            'text': 'This is an example note!',
            'assignee': '*****@*****.**'
        },
    )

    return MailPreview(
        html_template='sentry/emails/activity/assigned.html',
        text_template='sentry/emails/activity/assigned.txt',
        context={
            'data': assigned.data,
            'author': assigned.user,
            'date': assigned.datetime,
            'group': group,
            'link': group.get_absolute_url(),
        },
    ).render()
Beispiel #5
0
def get_title_link(
    group: Group,
    event: Optional[Event],
    link_to_event: bool,
    issue_details: bool,
    notification: Optional[BaseNotification],
) -> str:
    if event and link_to_event:
        url = group.get_absolute_url(params={"referrer": "slack"}, event_id=event.event_id)

    elif issue_details:
        referrer = re.sub("Notification$", "Slack", notification.__class__.__name__)
        url = group.get_absolute_url(params={"referrer": referrer})

    else:
        url = group.get_absolute_url(params={"referrer": "slack"})

    # Explicitly typing to satisfy mypy.
    url_str: str = url
    return url_str
Beispiel #6
0
def get_title_link(
    group: Group,
    event: Event | None,
    link_to_event: bool,
    issue_details: bool,
    notification: BaseNotification | None,
) -> str:
    if event and link_to_event:
        url = group.get_absolute_url(params={"referrer": "slack"},
                                     event_id=event.event_id)

    elif issue_details and notification:
        referrer = notification.get_referrer(ExternalProviders.SLACK)
        url = group.get_absolute_url(params={"referrer": referrer})

    else:
        url = group.get_absolute_url(params={"referrer": "slack"})

    # Explicitly typing to satisfy mypy.
    url_str: str = url
    return url_str
Beispiel #7
0
def new_note(request):
    org = Organization(
        id=1,
        slug='example',
        name='Example',
    )
    team = Team(
        id=1,
        slug='example',
        name='Example',
        organization=org,
    )
    project = Project(
        id=1,
        slug='example',
        name='Example',
        team=team,
        organization=org,
    )
    group = Group(
        id=1,
        project=project,
        message='This is an example event.',
    )
    event = Event(
        id=1,
        project=project,
        group=group,
        message=group.message,
        data=load_data('python'),
    )
    note = Activity(
        group=event.group, event=event, project=event.project,
        type=Activity.NOTE, user=request.user,
        data={'text': 'This is an example note!'},
    )

    preview = MailPreview(
        html_template='sentry/emails/activity/note.html',
        text_template='sentry/emails/activity/note.txt',
        context={
            'data': note.data,
            'author': note.user,
            'date': note.datetime,
            'group': group,
            'link': group.get_absolute_url(),
        },
    )

    return render_to_response('sentry/debug/mail/preview.html', {
        'preview': preview,
    })
Beispiel #8
0
    def get_link_issue_config(self, group: Group,
                              **kwargs: Any) -> Sequence[Mapping[str, Any]]:
        default_repo, repo_choices = self.get_repository_choices(
            group, **kwargs)

        org = group.organization
        autocomplete_url = reverse("sentry-extensions-github-search",
                                   args=[org.slug, self.model.id])

        return [
            {
                "name": "repo",
                "label": "GitHub Repository",
                "type": "select",
                "default": default_repo,
                "choices": repo_choices,
                "url": autocomplete_url,
                "required": True,
                "updatesForm": True,
            },
            {
                "name": "externalIssue",
                "label": "Issue",
                "default": "",
                "choices": [],
                "type": "select",
                "url": autocomplete_url,
                "required": True,
            },
            {
                "name":
                "comment",
                "label":
                "Comment",
                "default":
                "Sentry issue: [{issue_id}]({url})".format(
                    url=absolute_uri(
                        group.get_absolute_url(
                            params={"referrer": "github_integration"})),
                    issue_id=group.qualified_short_id,
                ),
                "type":
                "textarea",
                "required":
                False,
                "autosize":
                True,
                "help":
                "Leave blank if you don't want to add a comment to the GitHub issue.",
            },
        ]
Beispiel #9
0
def assigned(request):

    org = Organization(
        id=1,
        slug='example',
        name='Example',
    )
    team = Team(
        id=1,
        slug='example',
        name='Example',
        organization=org,
    )
    project = Project(
        id=1,
        slug='example',
        name='Example',
        team=team,
        organization=org,
    )
    group = Group(
        id=1,
        project=project,
        message='This is an example event.',
    )
    event = Event(
        id=1,
        project=project,
        group=group,
        message=group.message,
        data=load_data('python'),
    )
    assigned = Activity(
        group=event.group, event=event, project=event.project,
        type=Activity.ASSIGNED, user=request.user,
        data={'text': 'This is an example note!'},
    )

    return MailPreview(
        html_template='sentry/emails/activity/assigned.html',
        text_template='sentry/emails/activity/assigned.txt',
        context={
            'data': assigned.data,
            'author': assigned.user,
            'date': assigned.datetime,
            'group': group,
            'link': group.get_absolute_url(),
        },
    ).render()
Beispiel #10
0
def get_group_settings_link(
    group: Group,
    environment: str | None,
    rule_details: Sequence[NotificationRuleDetails] | None = None,
    alert_timestamp: int | None = None,
) -> str:
    alert_type = str(AlertRuleTriggerAction.Type.EMAIL.name).lower()
    alert_timestamp_str = (str(round(time.time() * 1000))
                           if not alert_timestamp else str(alert_timestamp))
    alert_rule_id = str(
        rule_details[0].id) if rule_details and rule_details[0].id else None

    query_params = {"referrer": "alert_email"}
    if environment:
        query_params["environment"] = environment
    if alert_type:
        query_params["alert_type"] = alert_type
    if alert_timestamp:
        query_params["alert_timestamp"] = alert_timestamp_str
    if alert_rule_id:
        query_params["alert_rule_id"] = alert_rule_id
    return str(group.get_absolute_url(params=query_params))
Beispiel #11
0
def build_group_attachment(
    group: Group,
    event=None,
    tags: Mapping[str, str] = None,
    identity: Identity = None,
    actions=None,
    rules: List[Rule] = None,
    link_to_event: bool = False,
):
    # 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"))
    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,
        },
    ]

    # If an event is unspecified, use the tags of the latest event (if one exists).
    event_for_tags = event if event else group.get_latest_event()

    fallback_color = LEVEL_TO_COLOR["error"]
    color = (
        LEVEL_TO_COLOR.get(event_for_tags.get_tag("level"), fallback_color)
        if event_for_tags
        else fallback_color
    )

    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,
                }
            )

    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 = f"{group.qualified_short_id}"

    if rules:
        rule_url = build_rule_url(rules[0], group, project)
        footer += f" via <{rule_url}|{rules[0].label}>"

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

    obj = event if event is not None else group
    if event and link_to_event:
        title_link = group.get_absolute_url(params={"referrer": "slack"}, event_id=event.event_id)
    else:
        title_link = group.get_absolute_url(params={"referrer": "slack"})

    return {
        "fallback": f"[{project.slug}] {obj.title}",
        "title": build_attachment_title(obj),
        "title_link": title_link,
        "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,
    }
Beispiel #12
0
def get_link(group: Group, environment: Optional[str]) -> str:
    query_params = {"referrer": "alert_email"}
    if environment:
        query_params["environment"] = environment
    return str(group.get_absolute_url(params=query_params))
Beispiel #13
0
def build_group_attachment(
    group: Group,
    event=None,
    tags: Mapping[str, str] = None,
    identity: Identity = None,
    actions=None,
    rules: List[Rule] = None,
    link_to_event: bool = False,
    issue_alert: bool = False,
):
    # XXX(dcramer): options are limited to 100 choices, even when nested
    logo_url = absolute_uri(
        get_asset_url("sentry", "images/sentry-email-avatar.png"))
    text = build_attachment_text(group, event) or ""
    project = Project.objects.get_from_cache(id=group.project_id)

    # If an event is unspecified, use the tags of the latest event (if one exists).
    event_for_tags = event if event else group.get_latest_event()

    fallback_color = LEVEL_TO_COLOR["error"]
    color = (LEVEL_TO_COLOR.get(event_for_tags.get_tag("level"),
                                fallback_color)
             if event_for_tags else fallback_color)

    fields = build_tag_fields(event_for_tags, tags)

    ts = group.last_seen

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

    footer = build_footer(group, issue_alert, project, rules)

    obj = event if event is not None else group
    if event and link_to_event:
        title_link = group.get_absolute_url(params={"referrer": "slack"},
                                            event_id=event.event_id)
    elif issue_alert:
        title_link = group.get_absolute_url(
            params={"referrer": "IssueAlertSlack"})
    else:
        title_link = group.get_absolute_url(params={"referrer": "slack"})

    if not issue_alert:
        payload_actions, text, color = build_actions(group, project, text,
                                                     color, actions, identity)
    else:
        payload_actions = []

    return {
        "fallback": f"[{project.slug}] {obj.title}",
        "title": build_attachment_title(obj),
        "title_link": title_link,
        "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,
    }