您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

176 行
5.4 KiB

  1. import uuid
  2. from datetime import datetime, timezone
  3. from sentry_sdk.utils import format_timestamp
  4. from typing import TYPE_CHECKING
  5. if TYPE_CHECKING:
  6. from typing import Optional
  7. from typing import Union
  8. from typing import Any
  9. from typing import Dict
  10. from sentry_sdk._types import SessionStatus
  11. def _minute_trunc(ts):
  12. # type: (datetime) -> datetime
  13. return ts.replace(second=0, microsecond=0)
  14. def _make_uuid(
  15. val, # type: Union[str, uuid.UUID]
  16. ):
  17. # type: (...) -> uuid.UUID
  18. if isinstance(val, uuid.UUID):
  19. return val
  20. return uuid.UUID(val)
  21. class Session:
  22. def __init__(
  23. self,
  24. sid=None, # type: Optional[Union[str, uuid.UUID]]
  25. did=None, # type: Optional[str]
  26. timestamp=None, # type: Optional[datetime]
  27. started=None, # type: Optional[datetime]
  28. duration=None, # type: Optional[float]
  29. status=None, # type: Optional[SessionStatus]
  30. release=None, # type: Optional[str]
  31. environment=None, # type: Optional[str]
  32. user_agent=None, # type: Optional[str]
  33. ip_address=None, # type: Optional[str]
  34. errors=None, # type: Optional[int]
  35. user=None, # type: Optional[Any]
  36. session_mode="application", # type: str
  37. ):
  38. # type: (...) -> None
  39. if sid is None:
  40. sid = uuid.uuid4()
  41. if started is None:
  42. started = datetime.now(timezone.utc)
  43. if status is None:
  44. status = "ok"
  45. self.status = status
  46. self.did = None # type: Optional[str]
  47. self.started = started
  48. self.release = None # type: Optional[str]
  49. self.environment = None # type: Optional[str]
  50. self.duration = None # type: Optional[float]
  51. self.user_agent = None # type: Optional[str]
  52. self.ip_address = None # type: Optional[str]
  53. self.session_mode = session_mode # type: str
  54. self.errors = 0
  55. self.update(
  56. sid=sid,
  57. did=did,
  58. timestamp=timestamp,
  59. duration=duration,
  60. release=release,
  61. environment=environment,
  62. user_agent=user_agent,
  63. ip_address=ip_address,
  64. errors=errors,
  65. user=user,
  66. )
  67. @property
  68. def truncated_started(self):
  69. # type: (...) -> datetime
  70. return _minute_trunc(self.started)
  71. def update(
  72. self,
  73. sid=None, # type: Optional[Union[str, uuid.UUID]]
  74. did=None, # type: Optional[str]
  75. timestamp=None, # type: Optional[datetime]
  76. started=None, # type: Optional[datetime]
  77. duration=None, # type: Optional[float]
  78. status=None, # type: Optional[SessionStatus]
  79. release=None, # type: Optional[str]
  80. environment=None, # type: Optional[str]
  81. user_agent=None, # type: Optional[str]
  82. ip_address=None, # type: Optional[str]
  83. errors=None, # type: Optional[int]
  84. user=None, # type: Optional[Any]
  85. ):
  86. # type: (...) -> None
  87. # If a user is supplied we pull some data form it
  88. if user:
  89. if ip_address is None:
  90. ip_address = user.get("ip_address")
  91. if did is None:
  92. did = user.get("id") or user.get("email") or user.get("username")
  93. if sid is not None:
  94. self.sid = _make_uuid(sid)
  95. if did is not None:
  96. self.did = str(did)
  97. if timestamp is None:
  98. timestamp = datetime.now(timezone.utc)
  99. self.timestamp = timestamp
  100. if started is not None:
  101. self.started = started
  102. if duration is not None:
  103. self.duration = duration
  104. if release is not None:
  105. self.release = release
  106. if environment is not None:
  107. self.environment = environment
  108. if ip_address is not None:
  109. self.ip_address = ip_address
  110. if user_agent is not None:
  111. self.user_agent = user_agent
  112. if errors is not None:
  113. self.errors = errors
  114. if status is not None:
  115. self.status = status
  116. def close(
  117. self, status=None # type: Optional[SessionStatus]
  118. ):
  119. # type: (...) -> Any
  120. if status is None and self.status == "ok":
  121. status = "exited"
  122. if status is not None:
  123. self.update(status=status)
  124. def get_json_attrs(
  125. self, with_user_info=True # type: Optional[bool]
  126. ):
  127. # type: (...) -> Any
  128. attrs = {}
  129. if self.release is not None:
  130. attrs["release"] = self.release
  131. if self.environment is not None:
  132. attrs["environment"] = self.environment
  133. if with_user_info:
  134. if self.ip_address is not None:
  135. attrs["ip_address"] = self.ip_address
  136. if self.user_agent is not None:
  137. attrs["user_agent"] = self.user_agent
  138. return attrs
  139. def to_json(self):
  140. # type: (...) -> Any
  141. rv = {
  142. "sid": str(self.sid),
  143. "init": True,
  144. "started": format_timestamp(self.started),
  145. "timestamp": format_timestamp(self.timestamp),
  146. "status": self.status,
  147. } # type: Dict[str, Any]
  148. if self.errors:
  149. rv["errors"] = self.errors
  150. if self.did is not None:
  151. rv["did"] = self.did
  152. if self.duration is not None:
  153. rv["duration"] = self.duration
  154. attrs = self.get_json_attrs()
  155. if attrs:
  156. rv["attrs"] = attrs
  157. return rv