Example #1
0
File: logic.py Project: zvrr/sentry
def bulk_get_incident_event_stats(incidents, query_params_list, data_points=50):
    snuba_params_list = [
        SnubaQueryParams(
            aggregations=[("count()", "", "count")],
            orderby="time",
            groupby=["time"],
            rollup=max(int(incident.duration.total_seconds() / data_points), 1),
            limit=10000,
            **query_param
        )
        for incident, query_param in zip(incidents, query_params_list)
    ]
    results = bulk_raw_query(snuba_params_list, referrer="incidents.get_incident_event_stats")
    return [
        SnubaTSResult(result, snuba_params.start, snuba_params.end, snuba_params.rollup)
        for snuba_params, result in zip(snuba_params_list, results)
    ]
Example #2
0
 def test_original_query_params_does_not_get_mutated(self):
     snuba_params = SnubaQueryParams(
         dataset=Dataset.Sessions,
         start=datetime.now() - timedelta(hours=1),
         end=datetime.now(),
         groupby=[],
         conditions=[[["environment", "IN", {"development", "abc"}]]],
         filter_keys={"release": [self.create_release(version="1.0.0").id]},
         aggregations=[],
         rollup=86400,
         is_grouprelease=False,
         **{"selected_columns": ["sessions"]},
     )
     conditions = [[["environment", "IN", {"development", "abc"}]]]
     kwargs = {"selected_columns": ["sessions"]}
     _prepare_query_params(snuba_params)
     assert conditions == snuba_params.conditions
     assert kwargs == snuba_params.kwargs
Example #3
0
def get_incident_aggregates(incident, start=None, end=None, windowed_stats=False):
    """
    Calculates aggregate stats across the life of an incident, or the provided range.
    - count: Total count of events
    - unique_users: Total number of unique users
    """
    query_params = build_incident_query_params(incident, start, end, windowed_stats)
    # We don't care about the specific aggregations here, we just want total event and
    # unique user counts
    query_params.pop("aggregations", None)
    snuba_params_list = [
        SnubaQueryParams(
            aggregations=[("count()", "", "count"), ("uniq", "tags[sentry:user]", "unique_users")],
            limit=10000,
            **query_params
        )
    ]
    results = bulk_raw_query(snuba_params_list, referrer="incidents.get_incident_aggregates")
    return [result["data"][0] for result in results][0]
Example #4
0
def get_incident_event_stats(incident, start=None, end=None, windowed_stats=False):
    """
    Gets event stats for an incident. If start/end are provided, uses that time
    period, otherwise uses the incident start/current_end.
    """
    query_params = build_incident_query_params(
        incident, start=start, end=end, windowed_stats=windowed_stats
    )
    aggregations = query_params.pop("aggregations")[0]
    snuba_params = SnubaQueryParams(
        aggregations=[(aggregations[0], aggregations[1], "count")],
        orderby="time",
        groupby=["time"],
        rollup=incident.alert_rule.snuba_query.time_window,
        limit=10000,
        **query_params
    )

    results = bulk_raw_query([snuba_params], referrer="incidents.get_incident_event_stats")
    return SnubaTSResult(results[0], snuba_params.start, snuba_params.end, snuba_params.rollup)
Example #5
0
def get_incident_aggregates(
    incident, start=None, end=None, windowed_stats=False, use_alert_aggregate=False
):
    """
    Calculates aggregate stats across the life of an incident, or the provided range.
    If `use_alert_aggregate` is True, calculates just the aggregate that the alert is
    for, and returns as the `count` key.
    If False, returns two values:
    - count: Total count of events
    - unique_users: Total number of unique users
    """
    query_params = build_incident_query_params(incident, start, end, windowed_stats)
    if not use_alert_aggregate:
        query_params["aggregations"] = [
            ("count()", "", "count"),
            ("uniq", "tags[sentry:user]", "unique_users"),
        ]
    else:
        query_params["aggregations"][0][2] = "count"
    snuba_params_list = [SnubaQueryParams(limit=10000, **query_params)]
    results = bulk_raw_query(snuba_params_list, referrer="incidents.get_incident_aggregates")
    return results[0]["data"][0]
Example #6
0
def bulk_get_incident_event_stats(incidents, query_params_list):
    snuba_params_list = [
        SnubaQueryParams(aggregations=[(
            query_aggregation_to_snuba[aggregate_to_query_aggregation[
                incident.alert_rule.snuba_query.aggregate]][0],
            query_aggregation_to_snuba[aggregate_to_query_aggregation[
                incident.alert_rule.snuba_query.aggregate]][1],
            "count",
        )],
                         orderby="time",
                         groupby=["time"],
                         rollup=incident.alert_rule.snuba_query.time_window,
                         limit=10000,
                         **query_param)
        for incident, query_param in zip(incidents, query_params_list)
    ]
    results = bulk_raw_query(snuba_params_list,
                             referrer="incidents.get_incident_event_stats")
    return [
        SnubaTSResult(result, snuba_params.start, snuba_params.end,
                      snuba_params.rollup)
        for snuba_params, result in zip(snuba_params_list, results)
    ]
Example #7
0
    def test_invalid_dataset_provided(self):
        query_params = SnubaQueryParams(dataset="invalid_dataset")

        with pytest.raises(UnqualifiedQueryError):
            _prepare_query_params(query_params)
Example #8
0
    def test_outcomes_dataset_with_no_org_id_given(self):
        query_params = SnubaQueryParams(dataset=Dataset.Outcomes)

        with pytest.raises(UnqualifiedQueryError):
            _prepare_query_params(query_params)
Example #9
0
    def test_outcomes_dataset_with_key_id(self):
        key = self.create_project_key(project=self.project)
        query_params = SnubaQueryParams(dataset=Dataset.Outcomes, filter_keys={"key_id": [key.id]})

        kwargs, _, _ = _prepare_query_params(query_params)
        assert kwargs["organization"] == self.organization.id
Example #10
0
def get_incident_event_stats(incident,
                             start=None,
                             end=None,
                             windowed_stats=False):
    """
    Gets event stats for an incident. If start/end are provided, uses that time
    period, otherwise uses the incident start/current_end.
    """
    query_params = build_incident_query_params(incident,
                                               start=start,
                                               end=end,
                                               windowed_stats=windowed_stats)
    time_window = incident.alert_rule.snuba_query.time_window
    aggregations = query_params.pop("aggregations")[0]
    snuba_params = [
        SnubaQueryParams(aggregations=[(aggregations[0], aggregations[1],
                                        "count")],
                         orderby="time",
                         groupby=["time"],
                         rollup=time_window,
                         limit=10000,
                         **query_params)
    ]

    # We make extra queries to fetch these buckets
    def build_extra_query_params(bucket_start):
        extra_bucket_query_params = build_incident_query_params(
            incident,
            start=bucket_start,
            end=bucket_start + timedelta(seconds=time_window))
        aggregations = extra_bucket_query_params.pop("aggregations")[0]
        return SnubaQueryParams(aggregations=[(aggregations[0],
                                               aggregations[1], "count")],
                                limit=1,
                                **extra_bucket_query_params)

    # We want to include the specific buckets for the incident start and closed times,
    # so that there's no need to interpolate to show them on the frontend. If they're
    # cleanly divisible by the `time_window` then there's no need to fetch, since
    # they'll be included in the standard results anyway.
    start_query_params = None
    extra_buckets = []
    if int(to_timestamp(incident.date_started)) % time_window:
        start_query_params = build_extra_query_params(incident.date_started)
        snuba_params.append(start_query_params)
        extra_buckets.append(incident.date_started)

    if incident.date_closed:
        date_closed = incident.date_closed.replace(second=0, microsecond=0)
        if int(to_timestamp(date_closed)) % time_window:
            snuba_params.append(build_extra_query_params(date_closed))
            extra_buckets.append(date_closed)

    results = bulk_raw_query(snuba_params,
                             referrer="incidents.get_incident_event_stats")
    # Once we receive the results, if we requested extra buckets we now need to label
    # them with timestamp data, since the query we ran only returns the count.
    for extra_start, result in zip(extra_buckets, results[1:]):
        result["data"][0]["time"] = int(to_timestamp(extra_start))
    merged_data = list(chain(*[r["data"] for r in results]))
    merged_data.sort(key=lambda row: row["time"])
    results[0]["data"] = merged_data
    # When an incident has just been created it's possible for the actual incident start
    # date to be greater than the latest bucket for the query. Get the actual end date
    # here.
    end_date = snuba_params[0].end
    if start_query_params:
        end_date = max(end_date, start_query_params.end)

    return SnubaTSResult(results[0], snuba_params[0].start, end_date,
                         snuba_params[0].rollup)
def query_trace_data(
    trace_id: str, params: Mapping[str, str]
) -> Tuple[Sequence[SnubaTransaction], Sequence[SnubaError]]:
    transaction_query = discover.prepare_discover_query(
        selected_columns=[
            "id",
            "transaction.status",
            "transaction.op",
            "transaction.duration",
            "transaction",
            "timestamp",
            # project gets the slug, and project.id gets added automatically
            "project",
            "trace.span",
            "trace.parent_span",
            'to_other(trace.parent_span, "", 0, 1) AS root',
        ],
        # We want to guarantee at least getting the root, and hopefully events near it with timestamp
        # id is just for consistent results
        orderby=["-root", "timestamp", "id"],
        params=params,
        query=f"event.type:transaction trace:{trace_id}",
    )
    error_query = discover.prepare_discover_query(
        selected_columns=[
            "id",
            "project",
            "timestamp",
            "trace.span",
            "transaction",
            "issue",
            "title",
            "tags[level]",
        ],
        # Don't add timestamp to this orderby as snuba will have to split the time range up and make multiple queries
        orderby=["id"],
        params=params,
        query=f"!event.type:transaction trace:{trace_id}",
        auto_fields=False,
    )
    snuba_params = [
        SnubaQueryParams(
            dataset=Dataset.Discover,
            start=snuba_filter.start,
            end=snuba_filter.end,
            groupby=snuba_filter.groupby,
            conditions=snuba_filter.conditions,
            filter_keys=snuba_filter.filter_keys,
            aggregations=snuba_filter.aggregations,
            selected_columns=snuba_filter.selected_columns,
            having=snuba_filter.having,
            orderby=snuba_filter.orderby,
            limit=MAX_TRACE_SIZE,
        )
        for snuba_filter in [transaction_query.filter, error_query.filter]
    ]
    results = bulk_raw_query(
        snuba_params,
        referrer="api.trace-view.get-events",
    )
    transformed_results = [
        discover.transform_results(result, query.fields["functions"], query.columns, query.filter)[
            "data"
        ]
        for result, query in zip(results, [transaction_query, error_query])
    ]
    return cast(Sequence[SnubaTransaction], transformed_results[0]), cast(
        Sequence[SnubaError], transformed_results[1]
    )