- Remove Posthog = Insights alias from __init__.py - Remove PosthogContextMiddleware alias from django.py - Remove PostHogTracingProcessor alias from processor.py - Change $lib from "posthog-python" to "insights-python" - Change ingestion URLs from posthog.com to insights.hanzo.ai - Rename all posthog_* kwargs to insights_* across AI wrappers - Rename __posthog_exception_captured to __insights_exception_captured - Rename posthog_context_stack contextvar to insights_context_stack - Rename posthog🎏 Redis prefix to insights🎏 - Rename $$_posthog_redacted_* sentinels to $$_insights_redacted_* - Remove POSTHOG_MW_* Django settings fallback, X-POSTHOG-* headers - Rename Prompts(posthog=) param to Prompts(client=) - Update APP_ENDPOINT to us.insights.hanzo.ai - Update all tests, examples, docs, mypy config
112 lines
3.7 KiB
Python
112 lines
3.7 KiB
Python
"""
|
|
Test that verifies exception capture functionality.
|
|
|
|
These tests verify that exceptions are actually captured to Insights, not just that
|
|
500 responses are returned.
|
|
|
|
Without process_exception(), view exceptions are NOT captured to Insights (v6.7.11 and earlier).
|
|
With process_exception(), Django calls this method to capture exceptions before
|
|
converting them to 500 responses.
|
|
"""
|
|
|
|
import os
|
|
import django
|
|
|
|
# Setup Django before importing anything else
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testdjango.settings")
|
|
django.setup()
|
|
|
|
import pytest # noqa: E402
|
|
from httpx import AsyncClient, ASGITransport # noqa: E402
|
|
from django.core.asgi import get_asgi_application # noqa: E402
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def asgi_app():
|
|
"""Shared ASGI application for all tests."""
|
|
return get_asgi_application()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_exception_is_captured(asgi_app):
|
|
"""
|
|
Test that async view exceptions are captured to Insights.
|
|
|
|
The middleware's process_exception() method ensures exceptions are captured.
|
|
Without it (v6.7.11 and earlier), exceptions are NOT captured even though 500 is returned.
|
|
"""
|
|
from unittest.mock import patch
|
|
|
|
# Track captured exceptions
|
|
captured = []
|
|
|
|
def mock_capture(exception, **kwargs):
|
|
"""Mock capture_exception to record calls."""
|
|
captured.append(
|
|
{
|
|
"exception": exception,
|
|
"type": type(exception).__name__,
|
|
"message": str(exception),
|
|
}
|
|
)
|
|
|
|
# Patch at the hanzo_insights module level where middleware imports from
|
|
with patch("hanzo_insights.capture_exception", side_effect=mock_capture):
|
|
async with AsyncClient(
|
|
transport=ASGITransport(app=asgi_app), base_url="http://testserver"
|
|
) as ac:
|
|
response = await ac.get("/test/async-exception")
|
|
|
|
# Django returns 500
|
|
assert response.status_code == 500
|
|
|
|
# CRITICAL: Verify Insights captured the exception
|
|
assert len(captured) > 0, "Exception was NOT captured to Insights!"
|
|
|
|
# Verify it's the right exception
|
|
exception_data = captured[0]
|
|
assert exception_data["type"] == "ValueError"
|
|
assert "Test exception from Django 5 async view" in exception_data["message"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_sync_exception_is_captured(asgi_app):
|
|
"""
|
|
Test that sync view exceptions are captured to Insights.
|
|
|
|
The middleware's process_exception() method ensures exceptions are captured.
|
|
Without it (v6.7.11 and earlier), exceptions are NOT captured even though 500 is returned.
|
|
"""
|
|
from unittest.mock import patch
|
|
|
|
# Track captured exceptions
|
|
captured = []
|
|
|
|
def mock_capture(exception, **kwargs):
|
|
"""Mock capture_exception to record calls."""
|
|
captured.append(
|
|
{
|
|
"exception": exception,
|
|
"type": type(exception).__name__,
|
|
"message": str(exception),
|
|
}
|
|
)
|
|
|
|
# Patch at the hanzo_insights module level where middleware imports from
|
|
with patch("hanzo_insights.capture_exception", side_effect=mock_capture):
|
|
async with AsyncClient(
|
|
transport=ASGITransport(app=asgi_app), base_url="http://testserver"
|
|
) as ac:
|
|
response = await ac.get("/test/sync-exception")
|
|
|
|
# Django returns 500
|
|
assert response.status_code == 500
|
|
|
|
# CRITICAL: Verify Insights captured the exception
|
|
assert len(captured) > 0, "Exception was NOT captured to Insights!"
|
|
|
|
# Verify it's the right exception
|
|
exception_data = captured[0]
|
|
assert exception_data["type"] == "ValueError"
|
|
assert "Test exception from Django 5 sync view" in exception_data["message"]
|