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, )
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
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()
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(), )
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
def _notify_of_slow_query_failure(tags: Dict[str, Any]): tags["failed"] = True tags["reason"] = "timeout" incr("clickhouse_sync_execution_failure", tags=tags)
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()