test_sdk.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import uuid
  2. from unittest import mock
  3. import pytest
  4. from django.test.utils import override_settings
  5. from sentry_sdk import Hub, push_scope
  6. from sentry import eventstore
  7. from sentry.eventstore.models import Event
  8. from sentry.models.userrole import manage_default_super_admin_role
  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.utils.sdk import bind_organization_context, configure_sdk
  17. pytestmark = [requires_kafka]
  18. @pytest.fixture(autouse=True)
  19. def setup_fixtures():
  20. with assume_test_silo_mode(SiloMode.CONTROL):
  21. manage_default_super_admin_role()
  22. create_default_projects()
  23. @pytest.fixture
  24. def post_event_with_sdk(settings, relay_server, wait_for_ingest_consumer):
  25. adjust_settings_for_relay_tests(settings)
  26. settings.SENTRY_ENDPOINT = relay_server["url"]
  27. settings.SENTRY_PROJECT = 1
  28. configure_sdk()
  29. hub = Hub.current # XXX: Hub.current gets reset, this is a workaround
  30. def bind_client(self, new, *, _orig=Hub.bind_client):
  31. if new is None:
  32. import sys
  33. import traceback
  34. print("!!! Hub client was reset to None !!!", file=sys.stderr) # noqa: S002
  35. traceback.print_stack()
  36. print("!!!", file=sys.stderr) # noqa: S002
  37. return _orig(self, new)
  38. # XXX: trying to figure out why it gets reset
  39. with mock.patch.object(Hub, "bind_client", bind_client):
  40. wait_for_ingest_consumer = wait_for_ingest_consumer(settings)
  41. def inner(*args, **kwargs):
  42. assert Hub.current.client is not None
  43. event_id = hub.capture_event(*args, **kwargs)
  44. assert hub.client is not None
  45. hub.client.flush()
  46. with push_scope():
  47. return wait_for_ingest_consumer(
  48. lambda: eventstore.backend.get_event_by_id(settings.SENTRY_PROJECT, event_id)
  49. )
  50. yield inner
  51. @no_silo_test
  52. @override_settings(SENTRY_PROJECT=1)
  53. @django_db_all
  54. def test_simple(settings, post_event_with_sdk):
  55. event = post_event_with_sdk({"message": "internal client test"})
  56. assert event
  57. assert event.data["project"] == settings.SENTRY_PROJECT
  58. assert event.data["logentry"]["formatted"] == "internal client test"
  59. @no_silo_test
  60. @override_settings(SENTRY_PROJECT=1)
  61. @django_db_all
  62. def test_recursion_breaker(settings, post_event_with_sdk):
  63. # If this test terminates at all then we avoided recursion.
  64. settings.SENTRY_INGEST_CONSUMER_APM_SAMPLING = 1.0
  65. settings.SENTRY_PROJECT = 1
  66. event_id = uuid.uuid4().hex
  67. with mock.patch(
  68. "sentry.event_manager.EventManager.save", spec=Event, side_effect=ValueError("oh no!")
  69. ) as save:
  70. with pytest.raises(ValueError):
  71. post_event_with_sdk({"message": "internal client test", "event_id": event_id})
  72. assert_mock_called_once_with_partial(save, settings.SENTRY_PROJECT, cache_key=f"e:{event_id}:1")
  73. @no_silo_test
  74. @django_db_all
  75. @override_settings(SENTRY_PROJECT=1)
  76. def test_encoding(settings, post_event_with_sdk):
  77. class NotJSONSerializable:
  78. pass
  79. with push_scope() as scope:
  80. scope.set_extra("request", NotJSONSerializable())
  81. event = post_event_with_sdk({"message": "check the req"})
  82. assert event.data["project"] == settings.SENTRY_PROJECT
  83. assert event.data["logentry"]["formatted"] == "check the req"
  84. assert "NotJSONSerializable" in event.data["extra"]["request"]
  85. @no_silo_test
  86. @override_settings(SENTRY_PROJECT=1)
  87. @django_db_all
  88. def test_bind_organization_context(default_organization):
  89. configure_sdk()
  90. bind_organization_context(default_organization)
  91. assert Hub.current.scope._tags["organization"] == default_organization.id
  92. assert Hub.current.scope._tags["organization.slug"] == default_organization.slug
  93. assert Hub.current.scope._contexts["organization"] == {
  94. "id": default_organization.id,
  95. "slug": default_organization.slug,
  96. }
  97. @no_silo_test
  98. @override_settings(SENTRY_PROJECT=1)
  99. @django_db_all
  100. def test_bind_organization_context_with_callback(default_organization):
  101. create_default_projects()
  102. configure_sdk()
  103. def add_context(scope, organization, **kwargs):
  104. scope.set_tag("organization.test", "1")
  105. with override_settings(SENTRY_ORGANIZATION_CONTEXT_HELPER=add_context):
  106. bind_organization_context(default_organization)
  107. assert Hub.current.scope._tags["organization.test"] == "1"
  108. @no_silo_test
  109. @override_settings(SENTRY_PROJECT=1)
  110. @django_db_all
  111. def test_bind_organization_context_with_callback_error(default_organization):
  112. configure_sdk()
  113. def add_context(scope, organization, **kwargs):
  114. 1 / 0
  115. with override_settings(SENTRY_ORGANIZATION_CONTEXT_HELPER=add_context):
  116. bind_organization_context(default_organization)
  117. assert Hub.current.scope._tags["organization"] == default_organization.id