mock-replay 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python
  2. from io import BytesIO
  3. from zlib import compress
  4. from sentry.runner import configure
  5. from sentry.utils.json import dumps_htmlsafe
  6. configure()
  7. import pathlib
  8. import uuid
  9. from datetime import datetime, timedelta
  10. import click
  11. import requests
  12. from django.conf import settings
  13. from sentry.models.files.file import File
  14. from sentry.models.organization import Organization
  15. from sentry.models.project import Project
  16. from sentry.models.team import Team
  17. from sentry.replays.models import ReplayRecordingSegment
  18. from sentry.replays.testutils import (
  19. mock_replay,
  20. mock_rrweb_div_helloworld,
  21. mock_segment_click,
  22. mock_segment_console,
  23. mock_segment_fullsnapshot,
  24. mock_segment_init,
  25. mock_segment_nagivation,
  26. mock_segment_rageclick,
  27. )
  28. def store_replay(replay):
  29. response = requests.post(
  30. settings.SENTRY_SNUBA + "/tests/entities/replays/insert", json=[replay]
  31. )
  32. assert response.status_code == 200
  33. def create_recording(replay_id, project_id, timestamp):
  34. segments = [
  35. mock_segment_init(timestamp),
  36. mock_segment_fullsnapshot(timestamp, [mock_rrweb_div_helloworld()]),
  37. mock_segment_console(timestamp),
  38. mock_segment_nagivation(timestamp + timedelta(seconds=1), hrefFrom="/", hrefTo="/home/"),
  39. mock_segment_nagivation(
  40. timestamp + timedelta(seconds=2), hrefFrom="/home/", hrefTo="/profile/"
  41. ),
  42. mock_segment_rageclick(
  43. timestamp + timedelta(seconds=2),
  44. "nav.app-65yvxw.e1upz5ks6[aria-label='Primary Navigation'] > div.app-1v175cc.e1upz5ks4",
  45. "sidebar-item-performance",
  46. "a",
  47. 24,
  48. ),
  49. mock_segment_click(
  50. timestamp + timedelta(seconds=2),
  51. "nav.app-65yvxw.e1upz5ks6[aria-label='Primary Navigation'] > div.app-1v175cc.e1upz5ks4",
  52. "sidebar-item-performance",
  53. "a",
  54. ),
  55. mock_segment_nagivation(
  56. timestamp + timedelta(seconds=6),
  57. hrefFrom="/profile/",
  58. hrefTo="/performance/",
  59. ),
  60. mock_segment_rageclick(
  61. timestamp + timedelta(seconds=6),
  62. "nav.app-65yvxw.e1upz5ks6[aria-label='Primary Navigation'] > div.app-1v175cc.e1upz5ks4",
  63. "sidebar-item-performance",
  64. "a",
  65. 24,
  66. ),
  67. ]
  68. for (segment_id, segment) in enumerate(segments):
  69. store_replay_segments(replay_id, project_id, segment_id, segment)
  70. def store_replay_segments(replay_id: str, project_id: int, segment_id: int, segment) -> None:
  71. f = File.objects.create(name="rr:{segment_id}", type="replay.recording")
  72. f.putfile(BytesIO(compress(dumps_htmlsafe(segment).encode())))
  73. ReplayRecordingSegment.objects.create(
  74. replay_id=replay_id,
  75. project_id=project_id,
  76. segment_id=segment_id,
  77. file_id=f.id,
  78. )
  79. def make_filename(filename: str) -> str:
  80. parent_dir = pathlib.Path(__file__).parent.resolve()
  81. return f"{parent_dir}/rrweb-output/{filename}"
  82. def main():
  83. project_name = "Replay Test Project"
  84. if not settings.SENTRY_FEATURES["organizations:session-replay"]:
  85. click.echo(
  86. 'Session Replays is currently turned off! \nTo enable, add the following line to your local sentry.conf.py file: \nSENTRY_FEATURES["organizations:session-replay"] = True'
  87. )
  88. exit()
  89. if settings.SENTRY_SINGLE_ORGANIZATION:
  90. org = Organization.get_default()
  91. click.echo(f"Mocking org {org.name}")
  92. else:
  93. click.echo("Mocking org {}".format("Default"))
  94. org, _ = Organization.objects.get_or_create(slug="default")
  95. click.echo(f" > Mocking project {project_name}")
  96. team, _ = Team.objects.get_or_create(
  97. organization=org, slug="sentry", defaults={"name": "Sentry"}
  98. )
  99. project, _ = Project.objects.get_or_create(
  100. name=project_name,
  101. defaults={
  102. "organization": org,
  103. "flags": Project.flags.has_replays,
  104. },
  105. platform="javascript",
  106. )
  107. project.add_team(team)
  108. replay_id = uuid.uuid4().hex
  109. seq1_timestamp = datetime.now() - timedelta(seconds=15)
  110. seq2_timestamp = datetime.now() - timedelta(seconds=5)
  111. click.echo("Creating Replay events entries...")
  112. store_replay(mock_replay(seq1_timestamp, project.id, replay_id, segment_id=0))
  113. store_replay(mock_replay(seq2_timestamp, project.id, replay_id, segment_id=1))
  114. click.echo("Creating Replay recording entries...")
  115. create_recording(replay_id, project.id, seq1_timestamp)
  116. if __name__ == "__main__":
  117. main()