test_sdk.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import uuid
  2. from unittest import mock
  3. import pytest
  4. import sentry_sdk
  5. from django.test.utils import override_settings
  6. from sentry_sdk import isolation_scope
  7. from sentry import eventstore
  8. from sentry.eventstore.models import Event
  9. from sentry.receivers import create_default_projects
  10. from sentry.silo.base import SiloMode
  11. from sentry.testutils.asserts import assert_mock_called_once_with_partial
  12. from sentry.testutils.pytest.fixtures import django_db_all
  13. from sentry.testutils.pytest.relay import adjust_settings_for_relay_tests
  14. from sentry.testutils.silo import assume_test_silo_mode, no_silo_test
  15. from sentry.testutils.skips import requires_kafka
  16. from sentry.users.models.userrole import manage_default_super_admin_role
  17. from sentry.utils.sdk import bind_organization_context, configure_sdk
  18. pytestmark = [requires_kafka]
  19. @pytest.fixture(autouse=True)
  20. def setup_fixtures():
  21. with assume_test_silo_mode(SiloMode.CONTROL):
  22. manage_default_super_admin_role()
  23. create_default_projects()
  24. @pytest.fixture
  25. def post_event_with_sdk(settings, relay_server, wait_for_ingest_consumer):
  26. adjust_settings_for_relay_tests(settings)
  27. settings.SENTRY_ENDPOINT = relay_server["url"]
  28. settings.SENTRY_PROJECT = 1
  29. configure_sdk()
  30. current_scope = sentry_sdk.Scope()
  31. isolation_scope = sentry_sdk.Scope()
  32. wait_for_ingest_consumer = wait_for_ingest_consumer(settings)
  33. def inner(*args, **kwargs):
  34. event_id = sentry_sdk.capture_event(*args, **kwargs)
  35. assert event_id is not None
  36. sentry_sdk.flush()
  37. with sentry_sdk.scope.use_scope(current_scope):
  38. with sentry_sdk.scope.use_isolation_scope(isolation_scope):
  39. return wait_for_ingest_consumer(
  40. lambda: eventstore.backend.get_event_by_id(settings.SENTRY_PROJECT, event_id)
  41. )
  42. yield inner
  43. @no_silo_test
  44. @override_settings(SENTRY_PROJECT=1)
  45. @django_db_all
  46. def test_simple(settings, post_event_with_sdk):
  47. event = post_event_with_sdk({"message": "internal client test"})
  48. assert event
  49. assert event.data["project"] == settings.SENTRY_PROJECT
  50. assert event.data["logentry"]["formatted"] == "internal client test"
  51. @no_silo_test
  52. @override_settings(SENTRY_PROJECT=1)
  53. @django_db_all
  54. def test_recursion_breaker(settings, post_event_with_sdk):
  55. # If this test terminates at all then we avoided recursion.
  56. settings.SENTRY_INGEST_CONSUMER_APM_SAMPLING = 1.0
  57. settings.SENTRY_PROJECT = 1
  58. event_id = uuid.uuid4().hex
  59. with mock.patch(
  60. "sentry.event_manager.EventManager.save", spec=Event, side_effect=ValueError("oh no!")
  61. ) as save:
  62. with pytest.raises(Exception):
  63. post_event_with_sdk({"message": "internal client test", "event_id": event_id})
  64. assert_mock_called_once_with_partial(save, settings.SENTRY_PROJECT, cache_key=f"e:{event_id}:1")
  65. @no_silo_test
  66. @django_db_all
  67. @override_settings(SENTRY_PROJECT=1)
  68. def test_encoding(settings, post_event_with_sdk):
  69. class NotJSONSerializable:
  70. pass
  71. with isolation_scope() as scope:
  72. scope.set_extra("request", NotJSONSerializable())
  73. event = post_event_with_sdk({"message": "check the req"})
  74. assert event.data["project"] == settings.SENTRY_PROJECT
  75. assert event.data["logentry"]["formatted"] == "check the req"
  76. assert "NotJSONSerializable" in event.data["extra"]["request"]
  77. @no_silo_test
  78. @override_settings(SENTRY_PROJECT=1)
  79. @django_db_all
  80. def test_bind_organization_context(default_organization):
  81. configure_sdk()
  82. bind_organization_context(default_organization)
  83. scope = sentry_sdk.Scope.get_isolation_scope()
  84. assert scope._tags["organization"] == default_organization.id
  85. assert scope._tags["organization.slug"] == default_organization.slug
  86. assert scope._contexts["organization"] == {
  87. "id": default_organization.id,
  88. "slug": default_organization.slug,
  89. }
  90. @no_silo_test
  91. @override_settings(SENTRY_PROJECT=1)
  92. @django_db_all
  93. def test_bind_organization_context_with_callback(default_organization):
  94. create_default_projects()
  95. configure_sdk()
  96. def add_context(scope, organization, **kwargs):
  97. scope.set_tag("organization.test", "1")
  98. with override_settings(SENTRY_ORGANIZATION_CONTEXT_HELPER=add_context):
  99. bind_organization_context(default_organization)
  100. scope = sentry_sdk.Scope.get_isolation_scope()
  101. assert scope._tags["organization.test"] == "1"
  102. @no_silo_test
  103. @override_settings(SENTRY_PROJECT=1)
  104. @django_db_all
  105. def test_bind_organization_context_with_callback_error(default_organization):
  106. configure_sdk()
  107. def add_context(scope, organization, **kwargs):
  108. 1 / 0
  109. with override_settings(SENTRY_ORGANIZATION_CONTEXT_HELPER=add_context):
  110. bind_organization_context(default_organization)
  111. scope = sentry_sdk.Scope.get_isolation_scope()
  112. assert scope._tags["organization"] == default_organization.id