コード例 #1
0
    def handle_data(self, request, organization, project_ids, results):
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        if "transaction.status" in first_row:
            for row in results:
                row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(
                    row["transaction.status"])

        fields = request.GET.getlist("field")
        has_issues = "issue" in fields
        if has_issues:  # Look up the short ID and return that in the results
            if has_issues:
                issue_ids = set(row.get("issue.id") for row in results)
                issues = Group.issues_mapping(issue_ids, project_ids,
                                              organization)
            for result in results:
                if has_issues and "issue.id" in result:
                    result["issue"] = issues.get(result["issue.id"], "unknown")

        if not ("project.id" in first_row or "projectid" in first_row):
            return results

        for result in results:
            for key in ("projectid", "project.id"):
                if key in result:
                    if key not in fields:
                        del result[key]

        return results
コード例 #2
0
    def handle_data(
        self,
        request: Request,
        organization: Organization,
        project_ids: Sequence[int],
        results: Optional[Sequence[Any]],
    ) -> Optional[Sequence[Any]]:
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        if "transaction.status" in first_row:
            for row in results:
                row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(row["transaction.status"])

        fields = self.get_field_list(organization, request)
        if "issue" in fields:  # Look up the short ID and return that in the results
            self.handle_issues(results, project_ids, organization)

        if not ("project.id" in first_row or "projectid" in first_row):
            return results

        for result in results:
            for key in ("projectid", "project.id"):
                if key in result and key not in fields:
                    del result[key]

        return results
コード例 #3
0
 def full_dict(self, detailed: bool = False) -> FullResponse:
     result = cast(FullResponse, self.to_dict())
     if detailed and "transaction.status" in self.event:
         result.update({
             "transaction.status":
             SPAN_STATUS_CODE_TO_NAME.get(self.event["transaction.status"],
                                          "unknown"),
         })
     if self.nodestore_event:
         result["timestamp"] = self.nodestore_event.data.get("timestamp")
         result["start_timestamp"] = self.nodestore_event.data.get(
             "start_timestamp")
         if detailed:
             if "measurements" in self.nodestore_event.data:
                 result["measurements"] = self.nodestore_event.data.get(
                     "measurements")
             result["_meta"] = {}
             result["tags"], result["_meta"]["tags"] = get_tags_with_meta(
                 self.nodestore_event)
     # Only add children that have nodestore events, which may be missing if we're pruning for trace navigator
     result["children"] = [
         child.full_dict(detailed) for child in self.children
         if child.nodestore_event
     ]
     return result
コード例 #4
0
    def handle_data(self, request, organization, project_ids, results):
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        tests = {
            "transaction.status": "transaction.status" in first_row,
            "trace": "trace" in first_row,
        }
        if any(tests.values()):
            for row in results:
                if tests["transaction.status"]:
                    row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(
                        row["transaction.status"]
                    )
                if tests["trace"]:
                    row["trace"] = uuid.UUID(row["trace"]).hex

        fields = request.GET.getlist("field")
        issues = {}
        if "issue" in fields:  # Look up the short ID and return that in the results
            issue_ids = set(row["issue.id"] for row in results)
            issues = {
                i.id: i.qualified_short_id
                for i in Group.objects.filter(
                    id__in=issue_ids, project_id__in=project_ids, project__organization=organization
                )
            }
            for result in results:
                if "issue.id" in result:
                    result["issue"] = issues[result["issue.id"]]

        if not ("project.id" in first_row or "projectid" in first_row):
            return results

        projects = {
            p["id"]: p["slug"]
            for p in Project.objects.filter(organization=organization, id__in=project_ids).values(
                "id", "slug"
            )
        }
        for result in results:
            for key in ("projectid", "project.id"):
                if key in result:
                    # Handle bizarre empty case
                    if result[key] == 0:
                        result["project.name"] = ""
                    else:
                        result["project.name"] = projects[result[key]]
                    if key not in fields:
                        del result[key]

        return results
コード例 #5
0
 def serialize_event(self, event, *args, **kwargs):
     result = super().serialize_event(event, *args, **kwargs)
     if "transaction.status" in event:
         result.update({
             "transaction.status":
             SPAN_STATUS_CODE_TO_NAME.get(event["transaction.status"],
                                          "unknown"),
         })
     result.update({
         "children": [],
     })
     return result
コード例 #6
0
    def handle_data(self, request, organization, project_ids, results, omit_nan=False):
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        if "transaction.status" in first_row:
            for row in results:
                row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(row["transaction.status"])

        fields = request.GET.getlist("field")
        has_issues = "issue" in fields
        if has_issues or omit_nan:  # Look up the short ID and return that in the results
            if has_issues:
                issue_ids = set(row.get("issue.id") for row in results)
                issues = Group.issues_mapping(issue_ids, project_ids, organization)
            for result in results:
                if has_issues and "issue.id" in result:
                    result["issue"] = issues.get(result["issue.id"], "unknown")
                # Remove any potential NaN or Inf cause python json accepts either, but js doesn't
                if omit_nan:
                    for key in result.keys():
                        if isinstance(result[key], float) and (
                            math.isnan(result[key]) or math.isinf(result[key])
                        ):
                            result[key] = None

        if not ("project.id" in first_row or "projectid" in first_row):
            return results

        for result in results:
            for key in ("projectid", "project.id"):
                if key in result:
                    if key not in fields:
                        del result[key]

        return results
コード例 #7
0
ファイル: organization_events.py プロジェクト: jiangge/sentry
    def handle_data(self, request, organization, project_ids, results):
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        if "transaction.status" in first_row:
            for row in results:
                row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(
                    row["transaction.status"])

        fields = request.GET.getlist("field")
        issues = {}
        if "issue" in fields:  # Look up the short ID and return that in the results
            issue_ids = set(row["issue.id"] for row in results)
            issues = {
                i.id: i.qualified_short_id
                for i in Group.objects.filter(
                    id__in=issue_ids,
                    project_id__in=project_ids,
                    project__organization=organization)
            }
            for result in results:
                if "issue.id" in result:
                    result["issue"] = issues.get(result["issue.id"], "unknown")

        if not ("project.id" in first_row or "projectid" in first_row):
            return results

        for result in results:
            for key in ("projectid", "project.id"):
                if key in result:
                    if key not in fields:
                        del result[key]

        return results
コード例 #8
0
    def handle_data(self, request, organization, project_ids, results):
        if not results:
            return results

        first_row = results[0]

        # TODO(mark) move all of this result formatting into discover.query()
        # once those APIs are used across the application.
        tests = {
            "transaction.status": "transaction.status" in first_row,
            "trace": "trace" in first_row,
        }
        if any(tests.values()):
            for row in results:
                if tests["transaction.status"]:
                    row["transaction.status"] = SPAN_STATUS_CODE_TO_NAME.get(
                        row["transaction.status"]
                    )
                if tests["trace"]:
                    row["trace"] = uuid.UUID(row["trace"]).hex

        if not ("project.id" in first_row or "projectid" in first_row):
            return results
        fields = request.GET.getlist("field")
        projects = {
            p["id"]: p["slug"]
            for p in Project.objects.filter(organization=organization, id__in=project_ids).values(
                "id", "slug"
            )
        }
        for result in results:
            for key in ("projectid", "project.id"):
                if key in result:
                    result["project.name"] = projects[result[key]]
                    if key not in fields:
                        del result[key]

        return results
コード例 #9
0
    def get_tag_value_paginator_for_projects(
        self,
        projects,
        environments,
        key,
        start=None,
        end=None,
        query=None,
        order_by="-last_seen",
        include_transactions=False,
    ):
        from sentry.api.paginator import SequencePaginator

        if not order_by == "-last_seen":
            raise ValueError("Unsupported order_by: %s" % order_by)

        dataset = Dataset.Events
        if include_transactions:
            dataset = Dataset.Discover
        snuba_key = snuba.get_snuba_column_name(key, dataset=dataset)

        # We cannot search the values of these columns like we do other columns because they are
        # a different type, and as such, LIKE and != do not work on them. Furthermore, because the
        # use case for these values in autosuggestion is minimal, so we choose to disable them here.
        #
        # event_id:     This is a FixedString which disallows us to use LIKE on it when searching,
        #               but does work with !=. However, for consistency sake we disallow it
        #               entirely, furthermore, suggesting an event_id is not a very useful feature
        #               as they are not human readable.
        # timestamp:    This is a DateTime which disallows us to use both LIKE and != on it when
        #               searching. Suggesting a timestamp can potentially be useful but as it does
        #               work at all, we opt to disable it here. A potential solution can be to
        #               generate a time range to bound where they are searching. e.g. if a user
        #               enters 2020-07 we can generate the following conditions:
        #               >= 2020-07-01T00:00:00 AND <= 2020-07-31T23:59:59
        # time:         This is a column computed from timestamp so it suffers the same issues
        if snuba_key in {"event_id", "timestamp", "time"}:
            return SequencePaginator([])

        # These columns have fixed values and we don't need to emit queries to find out the
        # potential options.
        if key in {"error.handled", "error.unhandled"}:
            return SequencePaginator([
                (
                    1,
                    TagValue(key=key,
                             value="true",
                             times_seen=None,
                             first_seen=None,
                             last_seen=None),
                ),
                (
                    2,
                    TagValue(key=key,
                             value="false",
                             times_seen=None,
                             first_seen=None,
                             last_seen=None),
                ),
            ])

        conditions = []
        # transaction status needs a special case so that the user interacts with the names and not codes
        transaction_status = snuba_key == "transaction_status"
        if include_transactions and transaction_status:
            # Here we want to use the status codes during filtering,
            # but want to do this with names that include our query
            status_codes = [
                span_key
                for span_key, value in SPAN_STATUS_CODE_TO_NAME.items()
                if (query and query in value) or (not query)
            ]
            if status_codes:
                conditions.append([snuba_key, "IN", status_codes])
            else:
                return SequencePaginator([])
        elif key in FUZZY_NUMERIC_KEYS:
            converted_query = int(
                query) if query is not None and query.isdigit() else None
            if converted_query is not None:
                conditions.append([
                    snuba_key, ">=", converted_query - FUZZY_NUMERIC_DISTANCE
                ])
                conditions.append([
                    snuba_key, "<=", converted_query + FUZZY_NUMERIC_DISTANCE
                ])
        elif include_transactions and key == PROJECT_ALIAS:
            project_filters = {
                "id__in": projects,
            }
            if query:
                project_filters["slug__icontains"] = query
            project_queryset = Project.objects.filter(
                **project_filters).values("id", "slug")

            if not project_queryset.exists():
                return SequencePaginator([])

            project_slugs = {
                project["id"]: project["slug"]
                for project in project_queryset
            }
            projects = [project["id"] for project in project_queryset]
            snuba_key = "project_id"
        else:
            snuba_name = snuba_key

            is_user_alias = include_transactions and key == USER_DISPLAY_ALIAS
            if is_user_alias:
                # user.alias is a pseudo column in discover. It is computed by coalescing
                # together multiple user attributes. Here we get the coalese function used,
                # and resolve it to the corresponding snuba query
                resolver = snuba.resolve_column(dataset)
                snuba_name = FIELD_ALIASES[USER_DISPLAY_ALIAS].get_field()
                snuba.resolve_complex_column(snuba_name, resolver)
            elif snuba_name in BLACKLISTED_COLUMNS:
                snuba_name = f"tags[{key}]"

            if query:
                conditions.append([snuba_name, "LIKE", f"%{query}%"])
            else:
                conditions.append([snuba_name, "!=", ""])

        filters = {"project_id": projects}
        if environments:
            filters["environment"] = environments

        if dataset == Dataset.Events:
            conditions.append(DEFAULT_TYPE_CONDITION)

        results = snuba.query(
            dataset=dataset,
            start=start,
            end=end,
            groupby=[snuba_key],
            filter_keys=filters,
            aggregations=[
                ["count()", "", "times_seen"],
                ["min", "timestamp", "first_seen"],
                ["max", "timestamp", "last_seen"],
            ],
            conditions=conditions,
            orderby=order_by,
            # TODO: This means they can't actually paginate all TagValues.
            limit=1000,
            arrayjoin=snuba.get_arrayjoin(snuba_key),
            referrer="tagstore.get_tag_value_paginator_for_projects",
        )

        if include_transactions:
            # With transaction_status we need to map the ids back to their names
            if transaction_status:
                results = OrderedDict([
                    (SPAN_STATUS_CODE_TO_NAME[result_key], data)
                    for result_key, data in results.items()
                ])
            # With project names we map the ids back to the project slugs
            elif key == PROJECT_ALIAS:
                results = OrderedDict([(project_slugs[value], data)
                                       for value, data in results.items()
                                       if value in project_slugs])

        tag_values = [
            TagValue(key=key, value=str(value), **fix_tag_value_data(data))
            for value, data in results.items()
        ]

        desc = order_by.startswith("-")
        score_field = order_by.lstrip("-")
        return SequencePaginator(
            [(int(to_timestamp(getattr(tv, score_field)) * 1000), tv)
             for tv in tag_values],
            reverse=desc,
        )