Example #1
0
def generate_exception_response(
    endpoint: str,
    detail: str,
    code: str = "invalid",
    type: str = "validation_error",
    attr: Optional[str] = None,
    status_code: int = status.HTTP_400_BAD_REQUEST,
) -> JsonResponse:
    """
    Generates a friendly JSON error response in line with drf-exceptions-hog for endpoints not under DRF.
    """

    from posthog.internal_metrics import incr

    incr(f"posthog_cloud_raw_endpoint_exception",
         tags={
             "endpoint": endpoint,
             "code": code,
             "type": type,
             "attr": attr
         })
    return JsonResponse(
        {
            "type": type,
            "code": code,
            "detail": detail,
            "attr": attr
        },
        status=status_code,
    )
Example #2
0
    def __call__(self, request: HttpRequest):
        """ Install monkey-patch on demand.

        If monkey-patch has not been run in for this process (assuming multiple preforked processes),
        then do it now.

        """
        from ee.clickhouse import client

        route = resolve(request.path)
        route_id = f"{route.route} ({route.func.__name__})"
        client._request_information = {
            "save": (request.user.pk and (request.user.is_staff or is_impersonated_session(request) or settings.DEBUG)),
            "user_id": request.user.pk,
            "kind": "request",
            "id": route_id,
        }

        response: HttpResponse = self.get_response(request)

        if "api/" in route_id and "capture" not in route_id:
            incr("http_api_request_response", tags={"id": route_id, "status_code": response.status_code})

        client._request_information = None

        return response
Example #3
0
def test_methods_capture_disabled(db, mock_capture_internal,
                                  mocker: MockerFixture):
    mocker.patch.object(settings, "CAPTURE_INTERNAL_METRICS", False)

    timing("foo_metric", 100, tags={"team_id": 15})
    gauge("bar_metric", 20, tags={"team_id": 15})
    incr("zeta_metric")

    mock_capture_internal.assert_not_called()
Example #4
0
def test_methods_capture_enabled(db, mock_capture_internal):
    timing("foo_metric", 100, tags={"team_id": 15})
    gauge("bar_metric", 20, tags={"team_id": 15})
    incr("zeta_metric")

    mock_capture_internal.assert_any_call(
        {
            "event": "$$foo_metric",
            "properties": {
                "value": 100,
                "team_id": 15
            }
        },
        "machine_id",
        None,
        None,
        mock.ANY,
        mock.ANY,
        get_internal_metrics_team_id(),
    )

    mock_capture_internal.assert_any_call(
        {
            "event": "$$bar_metric",
            "properties": {
                "value": 20,
                "team_id": 15
            }
        },
        "machine_id",
        None,
        None,
        mock.ANY,
        mock.ANY,
        get_internal_metrics_team_id(),
    )

    mock_capture_internal.assert_any_call(
        {
            "event": "$$zeta_metric",
            "properties": {
                "value": 1
            }
        },
        "machine_id",
        None,
        None,
        mock.ANY,
        mock.ANY,
        get_internal_metrics_team_id(),
    )
Example #5
0
    def sync_execute(query, args=None, settings=None, with_column_types=False):
        with ch_pool.get_client() as client:
            start_time = perf_counter()
            tags = {}
            if app_settings.SHELL_PLUS_PRINT_SQL:
                print()
                print(format_sql(query, args))

            sql, tags = _annotate_tagged_query(query, args)
            timeout_task = QUERY_TIMEOUT_THREAD.schedule(
                _notify_of_slow_query_failure, tags)

            try:
                result = client.execute(sql,
                                        args,
                                        settings=settings,
                                        with_column_types=with_column_types)
            except Exception as err:
                tags["failed"] = True
                tags["reason"] = type(err).__name__
                incr("clickhouse_sync_execution_failure", tags=tags)

                raise _wrap_api_error(err)
            finally:
                execution_time = perf_counter() - start_time

                if not timeout_task.done:
                    QUERY_TIMEOUT_THREAD.cancel(timeout_task)
                    timing("clickhouse_sync_execution_time",
                           execution_time * 1000.0,
                           tags=tags)

                if app_settings.SHELL_PLUS_PRINT_SQL:
                    print("Execution time: %.6fs" % (execution_time, ))
                if _request_information is not None and _request_information.get(
                        "save", False):
                    save_query(query, args, execution_time)
        return result
Example #6
0
def _notify_of_slow_query_failure(tags: Dict[str, Any]):
    tags["failed"] = True
    tags["reason"] = "timeout"
    incr("clickhouse_sync_execution_failure", tags=tags)
Example #7
0
def _deliver_subscription_report(subscription_id: int,
                                 previous_value: Optional[str] = None,
                                 invite_message: Optional[str] = None) -> None:

    subscription = (Subscription.objects.prefetch_related(
        "dashboard__insights").select_related(
            "created_by",
            "insight",
            "dashboard",
        ).get(pk=subscription_id))

    is_new_subscription_target = False
    if previous_value is not None:
        # If previous_value is set we are triggering a "new" or "invite" message
        is_new_subscription_target = subscription.target_value != previous_value

        if not is_new_subscription_target:
            # Same value as before so nothing to do
            return

    if subscription.target_type == "email":
        insights, assets = generate_assets(subscription)

        # Send emails
        emails = subscription.target_value.split(",")
        if is_new_subscription_target:
            previous_emails = previous_value.split(
                ",") if previous_value else []
            emails = list(set(emails) - set(previous_emails))

        for email in emails:
            try:
                send_email_subscription_report(
                    email,
                    subscription,
                    assets,
                    invite_message=invite_message or ""
                    if is_new_subscription_target else None,
                    total_asset_count=len(insights),
                )
                incr("subscription_email_send_success")
            except Exception as e:
                logger.error(e)
                capture_exception(e)
                incr("subscription_email_send_failure")

    elif subscription.target_type == "slack":
        insights, assets = generate_assets(subscription)
        try:
            send_slack_subscription_report(
                subscription,
                assets,
                total_asset_count=len(insights),
                is_new_subscription=is_new_subscription_target)
            incr("subscription_slack_send_success")
        except Exception as e:
            incr("subscription_slack_send_failure")
            logger.error(e)
    else:
        raise NotImplementedError(
            f"{subscription.target_type} is not supported")

    if not is_new_subscription_target:
        subscription.set_next_delivery_date(subscription.next_delivery_date)
        subscription.save()