123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- """
- These settings act as the default (base) settings for the Sentry-provided
- web-server
- """
- import logging
- import os.path
- from collections import OrderedDict, namedtuple
- from datetime import timedelta
- import six
- from django.conf import settings
- from django.utils.translation import gettext_lazy as _
- # from sentry.utils.integrationdocs import load_doc
- # from sentry.utils.geo import rust_geoip
- # import semaphore
- def get_all_languages():
- results = []
- for path in os.listdir(os.path.join(MODULE_ROOT, "locale")):
- if path.startswith("."):
- continue
- if "_" in path:
- pre, post = path.split("_", 1)
- path = "{}-{}".format(pre, post.lower())
- results.append(path)
- return results
- MODULE_ROOT = os.path.dirname(__import__("sentry").__file__)
- DATA_ROOT = os.path.join(MODULE_ROOT, "data")
- BAD_RELEASE_CHARS = "\n\f\t/"
- MAX_VERSION_LENGTH = 200
- MAX_COMMIT_LENGTH = 64
- COMMIT_RANGE_DELIMITER = ".."
- SORT_OPTIONS = OrderedDict(
- (
- ("priority", _("Priority")),
- ("date", _("Last Seen")),
- ("new", _("First Seen")),
- ("freq", _("Frequency")),
- )
- )
- SEARCH_SORT_OPTIONS = OrderedDict(
- (("score", _("Score")), ("date", _("Last Seen")), ("new", _("First Seen")))
- )
- # XXX: Deprecated: use GroupStatus instead
- STATUS_UNRESOLVED = 0
- STATUS_RESOLVED = 1
- STATUS_IGNORED = 2
- STATUS_CHOICES = {
- "resolved": STATUS_RESOLVED,
- "unresolved": STATUS_UNRESOLVED,
- "ignored": STATUS_IGNORED,
- # TODO(dcramer): remove in 9.0
- "muted": STATUS_IGNORED,
- }
- # Normalize counts to the 15 minute marker. This value MUST be less than 60. A
- # value of 0 would store counts for every minute, and is the lowest level of
- # accuracy provided.
- MINUTE_NORMALIZATION = 15
- MAX_TAG_KEY_LENGTH = 32
- MAX_TAG_VALUE_LENGTH = 200
- MAX_CULPRIT_LENGTH = 200
- MAX_EMAIL_FIELD_LENGTH = 75
- ENVIRONMENT_NAME_PATTERN = r"^[^\n\r\f\/]*$"
- ENVIRONMENT_NAME_MAX_LENGTH = 64
- SENTRY_APP_SLUG_MAX_LENGTH = 64
- # Team slugs which may not be used. Generally these are top level URL patterns
- # which we don't want to worry about conflicts on.
- RESERVED_ORGANIZATION_SLUGS = frozenset(
- (
- "admin",
- "manage",
- "login",
- "account",
- "register",
- "api",
- "accept",
- "organizations",
- "teams",
- "projects",
- "help",
- "docs",
- "logout",
- "404",
- "500",
- "_static",
- "out",
- "debug",
- "remote",
- "get-cli",
- "blog",
- "welcome",
- "features",
- "customers",
- "integrations",
- "signup",
- "pricing",
- "subscribe",
- "enterprise",
- "about",
- "jobs",
- "thanks",
- "guide",
- "privacy",
- "security",
- "terms",
- "from",
- "sponsorship",
- "for",
- "at",
- "platforms",
- "branding",
- "vs",
- "answers",
- "_admin",
- "support",
- "contact",
- "onboarding",
- "ext",
- "extension",
- "extensions",
- "plugins",
- "themonitor",
- "settings",
- "legal",
- "avatar",
- "organization-avatar",
- "project-avatar",
- "team-avatar",
- "careers",
- "_experiment",
- "sentry-apps",
- )
- )
- RESERVED_PROJECT_SLUGS = frozenset(
- (
- "api-keys",
- "audit-log",
- "auth",
- "members",
- "projects",
- "rate-limits",
- "repos",
- "settings",
- "teams",
- "billing",
- "payments",
- "legal",
- "subscription",
- "support",
- "integrations",
- "developer-settings",
- "usage",
- )
- )
- LOG_LEVELS = {
- logging.NOTSET: "sample",
- logging.DEBUG: "debug",
- logging.INFO: "info",
- logging.WARNING: "warning",
- logging.ERROR: "error",
- logging.FATAL: "fatal",
- }
- DEFAULT_LOG_LEVEL = "error"
- DEFAULT_LOGGER_NAME = ""
- LOG_LEVELS_MAP = {v: k for k, v in six.iteritems(LOG_LEVELS)}
- # Default alerting threshold values
- DEFAULT_ALERT_PROJECT_THRESHOLD = (500, 25) # 500%, 25 events
- DEFAULT_ALERT_GROUP_THRESHOLD = (1000, 25) # 1000%, 25 events
- # Default sort option for the group stream
- DEFAULT_SORT_OPTION = "date"
- # Setup languages for only available locales
- # _language_map = dict(settings.LANGUAGES)
- # LANGUAGES = [(k, _language_map[k]) for k in get_all_languages() if k in _language_map]
- # del _language_map
- # TODO(dcramer): We eventually want to make this user-editable
- TAG_LABELS = {
- "exc_type": "Exception Type",
- "sentry:user": "User",
- "sentry:release": "Release",
- "sentry:dist": "Distribution",
- "os": "OS",
- "url": "URL",
- "server_name": "Server",
- }
- PROTECTED_TAG_KEYS = frozenset(["environment", "release", "sentry:release"])
- # TODO(dcramer): once this is more flushed out we want this to be extendable
- SENTRY_RULES = (
- "sentry.rules.actions.notify_event.NotifyEventAction",
- "sentry.rules.actions.notify_event_service.NotifyEventServiceAction",
- "sentry.rules.conditions.every_event.EveryEventCondition",
- "sentry.rules.conditions.first_seen_event.FirstSeenEventCondition",
- "sentry.rules.conditions.regression_event.RegressionEventCondition",
- "sentry.rules.conditions.reappeared_event.ReappearedEventCondition",
- "sentry.rules.conditions.tagged_event.TaggedEventCondition",
- "sentry.rules.conditions.event_frequency.EventFrequencyCondition",
- "sentry.rules.conditions.event_frequency.EventUniqueUserFrequencyCondition",
- "sentry.rules.conditions.event_attribute.EventAttributeCondition",
- "sentry.rules.conditions.level.LevelCondition",
- )
- # methods as defined by http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html + PATCH
- HTTP_METHODS = (
- "GET",
- "POST",
- "PUT",
- "OPTIONS",
- "HEAD",
- "DELETE",
- "TRACE",
- "CONNECT",
- "PATCH",
- )
- # See https://github.com/getsentry/semaphore/blob/master/general/src/protocol/constants.rs
- # VALID_PLATFORMS = semaphore.VALID_PLATFORMS
- VALID_PLATFORMS = [
- "as3",
- "c",
- "cfml",
- "cocoa",
- "csharp",
- "elixir",
- "go",
- "groovy",
- "haskell",
- "java",
- "javascript",
- "native",
- "node",
- "objc",
- "other",
- "perl",
- "php",
- "python",
- "ruby",
- ]
- OK_PLUGIN_ENABLED = _("The {name} integration has been enabled.")
- OK_PLUGIN_DISABLED = _("The {name} integration has been disabled.")
- OK_PLUGIN_SAVED = _("Configuration for the {name} integration has been saved.")
- WARN_SESSION_EXPIRED = "Your session has expired." # TODO: translate this
- # Maximum length of a symbol
- MAX_SYM = 256
- # Known debug information file mimetypes
- KNOWN_DIF_FORMATS = {
- "text/x-breakpad": "breakpad",
- "application/x-mach-binary": "macho",
- "application/x-elf-binary": "elf",
- "application/x-dosexec": "pe",
- "application/x-ms-pdb": "pdb",
- "text/x-proguard+plain": "proguard",
- "application/x-sentry-bundle+zip": "sourcebundle",
- }
- NATIVE_UNKNOWN_STRING = "<unknown>"
- # Maximum number of release files that can be "skipped" (i.e., maximum paginator offset)
- # inside release files API endpoints.
- # If this number is too large, it may cause problems because of inefficient
- # LIMIT-OFFSET database queries.
- # These problems should be solved after we implement artifact bundles workflow.
- MAX_RELEASE_FILES_OFFSET = 20000
- # to go from an integration id (in _platforms.json) to the platform
- # data, such as documentation url or humanized name.
- # example: java-logback -> {"type": "framework",
- # "link": "https://docs.getsentry.com/hosted/clients/java/modules/logback/",
- # "id": "java-logback",
- # "name": "Logback"}
- INTEGRATION_ID_TO_PLATFORM_DATA = {}
- # def _load_platform_data():
- # INTEGRATION_ID_TO_PLATFORM_DATA.clear()
- # data = load_doc("_platforms")
- # if not data:
- # return
- # for platform in data["platforms"]:
- # integrations = platform.pop("integrations")
- # if integrations:
- # for integration in integrations:
- # integration_id = integration.pop("id")
- # if integration["type"] != "language":
- # integration["language"] = platform["id"]
- # INTEGRATION_ID_TO_PLATFORM_DATA[integration_id] = integration
- # _load_platform_data()
- # special cases where the marketing slug differs from the integration id
- # (in _platforms.json). missing values (for example: "java") should assume
- # the marketing slug is the same as the integration id:
- # javascript, node, python, php, ruby, go, swift, objc, java, perl, elixir
- MARKETING_SLUG_TO_INTEGRATION_ID = {
- "kotlin": "java",
- "scala": "java",
- "spring": "java",
- "android": "java-android",
- "react": "javascript-react",
- "angular": "javascript-angular",
- "angular2": "javascript-angular2",
- "ember": "javascript-ember",
- "backbone": "javascript-backbone",
- "vue": "javascript-vue",
- "express": "node-express",
- "koa": "node-koa",
- "django": "python-django",
- "flask": "python-flask",
- "sanic": "python-sanic",
- "tornado": "python-tornado",
- "celery": "python-celery",
- "rq": "python-rq",
- "bottle": "python-bottle",
- "pythonawslambda": "python-awslambda",
- "pyramid": "python-pyramid",
- "pylons": "python-pylons",
- "laravel": "php-laravel",
- "symfony": "php-symfony2",
- "rails": "ruby-rails",
- "sinatra": "ruby-sinatra",
- "dotnet": "csharp",
- }
- # to go from a marketing page slug like /for/android/ to the integration id
- # (in _platforms.json), for looking up documentation urls, etc.
- def get_integration_id_for_marketing_slug(slug):
- if slug in MARKETING_SLUG_TO_INTEGRATION_ID:
- return MARKETING_SLUG_TO_INTEGRATION_ID[slug]
- if slug in INTEGRATION_ID_TO_PLATFORM_DATA:
- return slug
- # special cases where the integration sent with the SDK differ from
- # the integration id (in _platforms.json)
- # {PLATFORM: {INTEGRATION_SENT: integration_id, ...}, ...}
- PLATFORM_INTEGRATION_TO_INTEGRATION_ID = {
- "java": {"java.util.logging": "java-logging"},
- # TODO: add more special cases...
- }
- # to go from event data to the integration id (in _platforms.json),
- # for example an event like:
- # {"platform": "java",
- # "sdk": {"name": "sentry-java",
- # "integrations": ["java.util.logging"]}} -> java-logging
- def get_integration_id_for_event(platform, sdk_name, integrations):
- if integrations:
- for integration in integrations:
- # check special cases
- if (
- platform in PLATFORM_INTEGRATION_TO_INTEGRATION_ID
- and integration in PLATFORM_INTEGRATION_TO_INTEGRATION_ID[platform]
- ):
- return PLATFORM_INTEGRATION_TO_INTEGRATION_ID[platform][integration]
- # try <platform>-<integration>, for example "java-log4j"
- integration_id = "%s-%s" % (platform, integration)
- if integration_id in INTEGRATION_ID_TO_PLATFORM_DATA:
- return integration_id
- # try sdk name, for example "sentry-java" -> "java" or "raven-java:log4j" -> "java-log4j"
- sdk_name = (
- sdk_name.lower().replace("sentry-", "").replace("raven-", "").replace(":", "-")
- )
- if sdk_name in INTEGRATION_ID_TO_PLATFORM_DATA:
- return sdk_name
- # try platform name, for example "java"
- if platform in INTEGRATION_ID_TO_PLATFORM_DATA:
- return platform
- class ObjectStatus(object):
- VISIBLE = 0
- HIDDEN = 1
- PENDING_DELETION = 2
- DELETION_IN_PROGRESS = 3
- ACTIVE = 0
- DISABLED = 1
- @classmethod
- def as_choices(cls):
- return (
- (cls.ACTIVE, "active"),
- (cls.DISABLED, "disabled"),
- (cls.PENDING_DELETION, "pending_deletion"),
- (cls.DELETION_IN_PROGRESS, "deletion_in_progress"),
- )
- class SentryAppStatus(object):
- UNPUBLISHED = 0
- PUBLISHED = 1
- INTERNAL = 2
- UNPUBLISHED_STR = "unpublished"
- PUBLISHED_STR = "published"
- INTERNAL_STR = "internal"
- @classmethod
- def as_choices(cls):
- return (
- (cls.UNPUBLISHED, cls.UNPUBLISHED_STR),
- (cls.PUBLISHED, cls.PUBLISHED_STR),
- (cls.INTERNAL, cls.INTERNAL_STR),
- )
- @classmethod
- def as_str(cls, status):
- if status == cls.UNPUBLISHED:
- return cls.UNPUBLISHED_STR
- elif status == cls.PUBLISHED:
- return cls.PUBLISHED_STR
- elif status == cls.INTERNAL:
- return cls.INTERNAL_STR
- class SentryAppInstallationStatus(object):
- PENDING = 0
- INSTALLED = 1
- PENDING_STR = "pending"
- INSTALLED_STR = "installed"
- @classmethod
- def as_choices(cls):
- return ((cls.PENDING, cls.PENDING_STR), (cls.INSTALLED, cls.INSTALLED_STR))
- @classmethod
- def as_str(cls, status):
- if status == cls.PENDING:
- return cls.PENDING_STR
- elif status == cls.INSTALLED:
- return cls.INSTALLED_STR
- StatsPeriod = namedtuple("StatsPeriod", ("segments", "interval"))
- LEGACY_RATE_LIMIT_OPTIONS = frozenset(
- ("sentry:project-rate-limit", "sentry:account-rate-limit")
- )
- # We need to limit the range of valid timestamps of an event because that
- # timestamp is used to control data retention.
- MAX_SECS_IN_FUTURE = 60
- MAX_SECS_IN_PAST = 2592000 # 30 days
- ALLOWED_FUTURE_DELTA = timedelta(seconds=MAX_SECS_IN_FUTURE)
- # DEFAULT_STORE_NORMALIZER_ARGS = dict(
- # geoip_lookup=rust_geoip,
- # stacktrace_frames_hard_limit=settings.SENTRY_STACKTRACE_FRAMES_HARD_LIMIT,
- # max_stacktrace_frames=settings.SENTRY_MAX_STACKTRACE_FRAMES,
- # max_secs_in_future=MAX_SECS_IN_FUTURE,
- # max_secs_in_past=MAX_SECS_IN_PAST,
- # enable_trimming=True,
- # )
- INTERNAL_INTEGRATION_TOKEN_COUNT_MAX = 20
- ALL_ACCESS_PROJECTS = {-1}
|