constants.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. """
  2. These settings act as the default (base) settings for the Sentry-provided
  3. web-server
  4. """
  5. import logging
  6. import os.path
  7. from collections import OrderedDict, namedtuple
  8. from datetime import timedelta
  9. import six
  10. from django.utils.translation import gettext_lazy as _
  11. def get_all_languages():
  12. results = []
  13. for path in os.listdir(os.path.join(MODULE_ROOT, "locale")):
  14. if path.startswith("."):
  15. continue
  16. if "_" in path:
  17. pre, post = path.split("_", 1)
  18. path = "{}-{}".format(pre, post.lower())
  19. results.append(path)
  20. return results
  21. MODULE_ROOT = os.path.dirname(__import__("sentry").__file__)
  22. DATA_ROOT = os.path.join(MODULE_ROOT, "data")
  23. BAD_RELEASE_CHARS = "\n\f\t/"
  24. MAX_VERSION_LENGTH = 200
  25. MAX_COMMIT_LENGTH = 64
  26. COMMIT_RANGE_DELIMITER = ".."
  27. SORT_OPTIONS = OrderedDict(
  28. (
  29. ("priority", _("Priority")),
  30. ("date", _("Last Seen")),
  31. ("new", _("First Seen")),
  32. ("freq", _("Frequency")),
  33. )
  34. )
  35. SEARCH_SORT_OPTIONS = OrderedDict(
  36. (("score", _("Score")), ("date", _("Last Seen")), ("new", _("First Seen")))
  37. )
  38. # XXX: Deprecated: use GroupStatus instead
  39. STATUS_UNRESOLVED = 0
  40. STATUS_RESOLVED = 1
  41. STATUS_IGNORED = 2
  42. STATUS_CHOICES = {
  43. "resolved": STATUS_RESOLVED,
  44. "unresolved": STATUS_UNRESOLVED,
  45. "ignored": STATUS_IGNORED,
  46. # TODO(dcramer): remove in 9.0
  47. "muted": STATUS_IGNORED,
  48. }
  49. # Normalize counts to the 15 minute marker. This value MUST be less than 60. A
  50. # value of 0 would store counts for every minute, and is the lowest level of
  51. # accuracy provided.
  52. MINUTE_NORMALIZATION = 15
  53. MAX_TAG_KEY_LENGTH = 32
  54. MAX_TAG_VALUE_LENGTH = 200
  55. MAX_CULPRIT_LENGTH = 200
  56. MAX_EMAIL_FIELD_LENGTH = 75
  57. ENVIRONMENT_NAME_PATTERN = r"^[^\n\r\f\/]*$"
  58. ENVIRONMENT_NAME_MAX_LENGTH = 64
  59. SENTRY_APP_SLUG_MAX_LENGTH = 64
  60. LOG_LEVELS = {
  61. logging.NOTSET: "sample",
  62. logging.DEBUG: "debug",
  63. logging.INFO: "info",
  64. logging.WARNING: "warning",
  65. logging.ERROR: "error",
  66. logging.FATAL: "fatal",
  67. }
  68. DEFAULT_LOG_LEVEL = "error"
  69. DEFAULT_LOGGER_NAME = ""
  70. LOG_LEVELS_MAP = {v: k for k, v in six.iteritems(LOG_LEVELS)}
  71. # Default alerting threshold values
  72. DEFAULT_ALERT_PROJECT_THRESHOLD = (500, 25) # 500%, 25 events
  73. DEFAULT_ALERT_GROUP_THRESHOLD = (1000, 25) # 1000%, 25 events
  74. # Default sort option for the group stream
  75. DEFAULT_SORT_OPTION = "date"
  76. # Setup languages for only available locales
  77. # _language_map = dict(settings.LANGUAGES)
  78. # LANGUAGES = [(k, _language_map[k]) for k in get_all_languages() if k in _language_map]
  79. # del _language_map
  80. # TODO(dcramer): We eventually want to make this user-editable
  81. TAG_LABELS = {
  82. "exc_type": "Exception Type",
  83. "sentry:user": "User",
  84. "sentry:release": "Release",
  85. "sentry:dist": "Distribution",
  86. "os": "OS",
  87. "url": "URL",
  88. "server_name": "Server",
  89. }
  90. PROTECTED_TAG_KEYS = frozenset(["environment", "release", "sentry:release"])
  91. # TODO(dcramer): once this is more flushed out we want this to be extendable
  92. SENTRY_RULES = (
  93. "sentry.rules.actions.notify_event.NotifyEventAction",
  94. "sentry.rules.actions.notify_event_service.NotifyEventServiceAction",
  95. "sentry.rules.conditions.every_event.EveryEventCondition",
  96. "sentry.rules.conditions.first_seen_event.FirstSeenEventCondition",
  97. "sentry.rules.conditions.regression_event.RegressionEventCondition",
  98. "sentry.rules.conditions.reappeared_event.ReappearedEventCondition",
  99. "sentry.rules.conditions.tagged_event.TaggedEventCondition",
  100. "sentry.rules.conditions.event_frequency.EventFrequencyCondition",
  101. "sentry.rules.conditions.event_frequency.EventUniqueUserFrequencyCondition",
  102. "sentry.rules.conditions.event_attribute.EventAttributeCondition",
  103. "sentry.rules.conditions.level.LevelCondition",
  104. )
  105. # Maximum length of a symbol
  106. MAX_SYM = 256
  107. # Known debug information file mimetypes
  108. KNOWN_DIF_FORMATS = {
  109. "text/x-breakpad": "breakpad",
  110. "application/x-mach-binary": "macho",
  111. "application/x-elf-binary": "elf",
  112. "application/x-dosexec": "pe",
  113. "application/x-ms-pdb": "pdb",
  114. "text/x-proguard+plain": "proguard",
  115. "application/x-sentry-bundle+zip": "sourcebundle",
  116. }
  117. NATIVE_UNKNOWN_STRING = "<unknown>"
  118. # Maximum number of release files that can be "skipped" (i.e., maximum paginator offset)
  119. # inside release files API endpoints.
  120. # If this number is too large, it may cause problems because of inefficient
  121. # LIMIT-OFFSET database queries.
  122. # These problems should be solved after we implement artifact bundles workflow.
  123. MAX_RELEASE_FILES_OFFSET = 20000
  124. # to go from an integration id (in _platforms.json) to the platform
  125. # data, such as documentation url or humanized name.
  126. # example: java-logback -> {"type": "framework",
  127. # "link": "https://docs.getsentry.com/hosted/clients/java/modules/logback/",
  128. # "id": "java-logback",
  129. # "name": "Logback"}
  130. INTEGRATION_ID_TO_PLATFORM_DATA = {}
  131. # def _load_platform_data():
  132. # INTEGRATION_ID_TO_PLATFORM_DATA.clear()
  133. # data = load_doc("_platforms")
  134. # if not data:
  135. # return
  136. # for platform in data["platforms"]:
  137. # integrations = platform.pop("integrations")
  138. # if integrations:
  139. # for integration in integrations:
  140. # integration_id = integration.pop("id")
  141. # if integration["type"] != "language":
  142. # integration["language"] = platform["id"]
  143. # INTEGRATION_ID_TO_PLATFORM_DATA[integration_id] = integration
  144. # _load_platform_data()
  145. # special cases where the marketing slug differs from the integration id
  146. # (in _platforms.json). missing values (for example: "java") should assume
  147. # the marketing slug is the same as the integration id:
  148. # javascript, node, python, php, ruby, go, swift, objc, java, perl, elixir
  149. MARKETING_SLUG_TO_INTEGRATION_ID = {
  150. "kotlin": "java",
  151. "scala": "java",
  152. "spring": "java",
  153. "android": "java-android",
  154. "react": "javascript-react",
  155. "angular": "javascript-angular",
  156. "angular2": "javascript-angular2",
  157. "ember": "javascript-ember",
  158. "backbone": "javascript-backbone",
  159. "vue": "javascript-vue",
  160. "express": "node-express",
  161. "koa": "node-koa",
  162. "django": "python-django",
  163. "flask": "python-flask",
  164. "sanic": "python-sanic",
  165. "tornado": "python-tornado",
  166. "celery": "python-celery",
  167. "rq": "python-rq",
  168. "bottle": "python-bottle",
  169. "pythonawslambda": "python-awslambda",
  170. "pyramid": "python-pyramid",
  171. "pylons": "python-pylons",
  172. "laravel": "php-laravel",
  173. "symfony": "php-symfony2",
  174. "rails": "ruby-rails",
  175. "sinatra": "ruby-sinatra",
  176. "dotnet": "csharp",
  177. }
  178. # to go from a marketing page slug like /for/android/ to the integration id
  179. # (in _platforms.json), for looking up documentation urls, etc.
  180. def get_integration_id_for_marketing_slug(slug):
  181. if slug in MARKETING_SLUG_TO_INTEGRATION_ID:
  182. return MARKETING_SLUG_TO_INTEGRATION_ID[slug]
  183. if slug in INTEGRATION_ID_TO_PLATFORM_DATA:
  184. return slug
  185. # special cases where the integration sent with the SDK differ from
  186. # the integration id (in _platforms.json)
  187. # {PLATFORM: {INTEGRATION_SENT: integration_id, ...}, ...}
  188. PLATFORM_INTEGRATION_TO_INTEGRATION_ID = {
  189. "java": {"java.util.logging": "java-logging"},
  190. # TODO: add more special cases...
  191. }
  192. # to go from event data to the integration id (in _platforms.json),
  193. # for example an event like:
  194. # {"platform": "java",
  195. # "sdk": {"name": "sentry-java",
  196. # "integrations": ["java.util.logging"]}} -> java-logging
  197. def get_integration_id_for_event(platform, sdk_name, integrations):
  198. if integrations:
  199. for integration in integrations:
  200. # check special cases
  201. if (
  202. platform in PLATFORM_INTEGRATION_TO_INTEGRATION_ID
  203. and integration in PLATFORM_INTEGRATION_TO_INTEGRATION_ID[platform]
  204. ):
  205. return PLATFORM_INTEGRATION_TO_INTEGRATION_ID[platform][integration]
  206. # try <platform>-<integration>, for example "java-log4j"
  207. integration_id = "%s-%s" % (platform, integration)
  208. if integration_id in INTEGRATION_ID_TO_PLATFORM_DATA:
  209. return integration_id
  210. # try sdk name, for example "sentry-java" -> "java" or "raven-java:log4j" -> "java-log4j"
  211. sdk_name = (
  212. sdk_name.lower().replace("sentry-", "").replace("raven-", "").replace(":", "-")
  213. )
  214. if sdk_name in INTEGRATION_ID_TO_PLATFORM_DATA:
  215. return sdk_name
  216. # try platform name, for example "java"
  217. if platform in INTEGRATION_ID_TO_PLATFORM_DATA:
  218. return platform
  219. class ObjectStatus(object):
  220. VISIBLE = 0
  221. HIDDEN = 1
  222. PENDING_DELETION = 2
  223. DELETION_IN_PROGRESS = 3
  224. ACTIVE = 0
  225. DISABLED = 1
  226. @classmethod
  227. def as_choices(cls):
  228. return (
  229. (cls.ACTIVE, "active"),
  230. (cls.DISABLED, "disabled"),
  231. (cls.PENDING_DELETION, "pending_deletion"),
  232. (cls.DELETION_IN_PROGRESS, "deletion_in_progress"),
  233. )
  234. class SentryAppStatus(object):
  235. UNPUBLISHED = 0
  236. PUBLISHED = 1
  237. INTERNAL = 2
  238. UNPUBLISHED_STR = "unpublished"
  239. PUBLISHED_STR = "published"
  240. INTERNAL_STR = "internal"
  241. @classmethod
  242. def as_choices(cls):
  243. return (
  244. (cls.UNPUBLISHED, cls.UNPUBLISHED_STR),
  245. (cls.PUBLISHED, cls.PUBLISHED_STR),
  246. (cls.INTERNAL, cls.INTERNAL_STR),
  247. )
  248. @classmethod
  249. def as_str(cls, status):
  250. if status == cls.UNPUBLISHED:
  251. return cls.UNPUBLISHED_STR
  252. elif status == cls.PUBLISHED:
  253. return cls.PUBLISHED_STR
  254. elif status == cls.INTERNAL:
  255. return cls.INTERNAL_STR
  256. class SentryAppInstallationStatus(object):
  257. PENDING = 0
  258. INSTALLED = 1
  259. PENDING_STR = "pending"
  260. INSTALLED_STR = "installed"
  261. @classmethod
  262. def as_choices(cls):
  263. return ((cls.PENDING, cls.PENDING_STR), (cls.INSTALLED, cls.INSTALLED_STR))
  264. @classmethod
  265. def as_str(cls, status):
  266. if status == cls.PENDING:
  267. return cls.PENDING_STR
  268. elif status == cls.INSTALLED:
  269. return cls.INSTALLED_STR
  270. StatsPeriod = namedtuple("StatsPeriod", ("segments", "interval"))
  271. LEGACY_RATE_LIMIT_OPTIONS = frozenset(
  272. ("sentry:project-rate-limit", "sentry:account-rate-limit")
  273. )
  274. # We need to limit the range of valid timestamps of an event because that
  275. # timestamp is used to control data retention.
  276. MAX_SECS_IN_FUTURE = 60
  277. MAX_SECS_IN_PAST = 2592000 # 30 days
  278. ALLOWED_FUTURE_DELTA = timedelta(seconds=MAX_SECS_IN_FUTURE)
  279. # DEFAULT_STORE_NORMALIZER_ARGS = dict(
  280. # geoip_lookup=rust_geoip,
  281. # stacktrace_frames_hard_limit=settings.SENTRY_STACKTRACE_FRAMES_HARD_LIMIT,
  282. # max_stacktrace_frames=settings.SENTRY_MAX_STACKTRACE_FRAMES,
  283. # max_secs_in_future=MAX_SECS_IN_FUTURE,
  284. # max_secs_in_past=MAX_SECS_IN_PAST,
  285. # enable_trimming=True,
  286. # )
  287. INTERNAL_INTEGRATION_TOKEN_COUNT_MAX = 20
  288. ALL_ACCESS_PROJECTS = {-1}