def _needs_upgrade(): version_configured = options.get('sentry:version-configured') if not version_configured: # If we were never previously upgraded (being a new install) # we want to force an upgrade, even if the values are set. return True smtp_disabled = not is_smtp_enabled() # Check all required options to see if they've been set for key in options.filter(flag=options.FLAG_REQUIRED): # ignore required flags which can be empty if key.flags & options.FLAG_ALLOW_EMPTY: continue # Ignore mail.* keys if smtp is disabled if smtp_disabled and key.name[:5] == 'mail.': continue if not options.isset(key.name): return True if version_configured != sentry.get_version(): # Everything looks good, but version changed, so let's bump it options.set('sentry:version-configured', sentry.get_version()) return False
def test_simple(self, safe_urlread, safe_urlopen, mock_get_all_package_versions): mock_get_all_package_versions.return_value = {'foo': '1.0'} safe_urlread.return_value = json.dumps({ 'notices': [], 'version': {'stable': '1.0.0'}, }) assert options.set('system.admin-email', '*****@*****.**') send_beacon() install_id = options.get('sentry:install-id') assert install_id and len(install_id) == 40 safe_urlopen.assert_called_once_with(BEACON_URL, json={ 'install_id': install_id, 'version': sentry.get_version(), 'data': { 'organizations': 1, 'users': 0, 'projects': 1, 'teams': 1, 'events.24h': 0, }, 'admin_email': '*****@*****.**', 'packages': mock_get_all_package_versions.return_value, }, timeout=5) safe_urlread.assert_called_once_with(safe_urlopen.return_value) assert options.get('sentry:latest_version') == '1.0.0'
def put(self, request): # TODO(dcramer): this should validate options before saving them for k, v in six.iteritems(request.DATA): if v and isinstance(v, six.string_types): v = v.strip() try: option = options.lookup_key(k) except options.UnknownOption: # TODO(dcramer): unify API errors return Response({ 'error': 'unknown_option', 'errorDetail': { 'option': k, }, }, status=400) try: if not (option.flags & options.FLAG_ALLOW_EMPTY) and not v: options.delete(k) else: options.set(k, v) except TypeError as e: return Response({ 'error': 'invalid_type', 'errorDetail': { 'option': k, 'message': six.text_type(e), }, }, status=400) # TODO(dcramer): this has nothing to do with configuring options and # should not be set here options.set('sentry:version-configured', sentry.get_version()) return Response(status=200)
def test_simple(self, safe_urlread, safe_urlopen): self.create_project(platform='java') safe_urlread.return_value = json.dumps({ 'notices': [], 'version': {'stable': '1.0.0'}, }) with self.settings(SENTRY_ADMIN_EMAIL='*****@*****.**'): send_beacon() install_id = options.get('sentry:install-id') assert install_id and len(install_id) == 40 safe_urlopen.assert_called_once_with(BEACON_URL, json={ 'install_id': install_id, 'version': sentry.get_version(), 'data': { 'platforms': ['java'], 'organizations': 2, 'users': 2, 'projects': 2, 'teams': 2, 'events.24h': 0, }, 'admin_email': '*****@*****.**', }, timeout=5) safe_urlread.assert_called_once_with(safe_urlopen.return_value) assert options.get('sentry:latest_version') == '1.0.0'
def put(self, request): # TODO(dcramer): this should validate options before saving them for k, v in request.DATA.iteritems(): if v and isinstance(v, basestring): v = v.strip() try: if not v: options.delete(k) else: options.set(k, v) except options.UnknownOption: # TODO(dcramer): unify API errors return Response({ 'error': 'unknown_option', 'errorDetail': { 'option': k, }, }, status=400) except TypeError as e: return Response({ 'error': 'invalid_type', 'errorDetail': { 'option': k, 'message': unicode(e), }, }, status=400) # TODO(dcramer): this has nothing to do with configuring options and # should not be set here options.set('sentry:version-configured', sentry.get_version()) return Response(status=200)
def _needs_upgrade(): version_configured = options.get('sentry:version-configured') if not version_configured: # If we were never previously upgraded (being a new install) # we want to force an upgrade, even if the values are set. return True # Check all required options to see if they've been set for key in options.filter(flag=options.FLAG_REQUIRED): if not options.get(key.name): return True if version_configured != sentry.get_version(): # Everything looks good, but version changed, so let's bump it options.set('sentry:version-configured', sentry.get_version()) return False
def put(self, request): try: for k, v in request.DATA.iteritems(): options.set(k, v) except Exception as e: return Response(unicode(e), status=400) options.set('sentry:version-configured', sentry.get_version()) return Response(status=200)
def get_sentry_version(context): import sentry current = sentry.get_version() latest = Option.objects.get_value("sentry:latest_version", current) update_available = Version(latest) > Version(current) context["sentry_version"] = SentryVersion(current, latest, update_available) return ""
def get_sentry_version(context): import sentry current = sentry.get_version() latest = options.get("sentry:latest_version") or current update_available = Version(latest) > Version(current) context["sentry_version"] = SentryVersion(current, latest, update_available) return ""
def set_sentry_version(latest=None, **kwargs): import sentry current = sentry.get_version() version = options.get('sentry:latest_version') for ver in (current, version): if Version(ver) >= Version(latest): return options.set('sentry:latest_version', (latest or current))
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return # TODO(dcramer): move version code off of PyPi and into beacon install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().hex).hexdigest() options.set('sentry:install-id', install_id) internal_project_ids = filter(bool, [ settings.SENTRY_PROJECT, settings.SENTRY_FRONTEND_PROJECT, ]) platform_list = list(set(Project.objects.exclude( id__in=internal_project_ids, ).values_list('platform', flat=True))) payload = { 'install_id': install_id, 'version': sentry.get_version(), 'admin_email': settings.SENTRY_ADMIN_EMAIL, 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'platforms': platform_list, 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), } } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable'])
def set_sentry_version(latest=None, **kwargs): import sentry current = sentry.get_version() version = Option.objects.get_value(key='sentry:latest_version', default='') for ver in (current, version): if Version(ver) >= Version(latest): return Option.objects.set_value( key='sentry:latest_version', value=(latest or current))
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().hex).hexdigest() options.set('sentry:install-id', install_id) end = timezone.now() events_24h = tsdb.get_sums( model=tsdb.models.internal, keys=['events.total'], start=end - timedelta(hours=24), end=end, )['events.total'] payload = { 'install_id': install_id, 'version': sentry.get_version(), 'admin_email': settings.SENTRY_ADMIN_EMAIL, 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), 'events.24h': events_24h, } } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable'])
def put(self, request): # TODO(dcramer): this should validate options before saving them for k, v in request.DATA.iteritems(): try: options.set(k, v) except options.UnknownOption: # TODO(dcramer): unify API errors return Response({ 'error': 'unknown_option', 'errorDetail': { 'option': k, }, }, status=400) options.set('sentry:version-configured', sentry.get_version()) return Response(status=200)
def widget(self, request, group, **kwargs): resp = Responsibility.objects.filter(group=group) resp = resp.order_by('user__first_name', 'user__last_name', 'user__username') resp = list(resp) available = group.project.team.member_set.exclude( user__in=[x.user for x in resp]) if tuple(map(int, sentry.get_version().split('.')[:2])) >= (5, 3): # URL args changed in Sentry 5.3 args = (group.project.team.slug, group.project.slug, group.id, self.slug) else: args = (group.project.slug, group.id, self.slug) plugin_url = reverse('sentry-group-plugin-action', args=args) return self.render('sentry_responsible/widget.html', { 'responsible': resp, 'plugin_url': plugin_url, 'available': list(available), })
def test_simple(self, safe_urlread, safe_urlopen, mock_get_all_package_versions): mock_get_all_package_versions.return_value = {"foo": "1.0"} safe_urlread.return_value = json.dumps({"notices": [], "version": {"stable": "1.0.0"}}) with self.settings(SENTRY_ADMIN_EMAIL="*****@*****.**"): send_beacon() install_id = options.get("sentry:install-id") assert install_id and len(install_id) == 40 safe_urlopen.assert_called_once_with( BEACON_URL, json={ "install_id": install_id, "version": sentry.get_version(), "data": {"organizations": 1, "users": 0, "projects": 1, "teams": 1, "events.24h": 0}, "admin_email": "*****@*****.**", "packages": mock_get_all_package_versions.return_value, }, timeout=5, ) safe_urlread.assert_called_once_with(safe_urlopen.return_value) assert options.get("sentry:latest_version") == "1.0.0"
def sentry_version(): import sentry return sentry.get_version()
def mark_as_configured(): sentry.options.set('sentry:version-configured', sentry.get_version())
from __future__ import print_function import sys # Bootstrap the Sentry environment from sentry.utils.runner import configure configure() # Do something crazy import sentry from sentry.models import Team, Project, ProjectKey, User, Organization from sentry.web.frontend.project_settings import OriginsField from django.forms import ValidationError SENTRY_VERSION = tuple( map(lambda x: int(x) if x.isdigit() else x, sentry.get_version().split('.'))) def create_team(admin_username, team_name, organization_name=None): user = User.objects.get(username=admin_username) if organization_name is None: organization_name = team_name org, new_org = Organization.objects.get_or_create(name=organization_name, defaults={'owner': user}) team, new = Team.objects.get_or_create(name=team_name, defaults={ 'owner': user, 'organization': org }) return team, new
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Broadcast, Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().hex).hexdigest() options.set('sentry:install-id', install_id) end = timezone.now() events_24h = tsdb.get_sums( model=tsdb.models.internal, keys=['events.total'], start=end - timedelta(hours=24), end=end, )['events.total'] payload = { 'install_id': install_id, 'version': sentry.get_version(), 'admin_email': options.get('system.admin-email'), 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), 'events.24h': events_24h, }, 'packages': get_all_package_versions(), } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable']) if 'notices' in data: upstream_ids = set() for notice in data['notices']: upstream_ids.add(notice['id']) Broadcast.objects.create_or_update( upstream_id=notice['id'], defaults={ 'title': notice['title'], 'link': notice.get('link'), 'message': notice['message'], } ) Broadcast.objects.filter( upstream_id__isnull=False, ).exclude( upstream_id__in=upstream_ids, ).update( is_active=False, )
# encoding: utf-8 from __future__ import print_function import sys # Bootstrap the Sentry environment from sentry.utils.runner import configure configure() # Do something crazy import sentry from sentry.models import Team, Project, ProjectKey, User, Organization from sentry.web.frontend.project_settings import OriginsField from django.forms import ValidationError SENTRY_VERSION = tuple(map(lambda x: int(x) if x.isdigit() else x, sentry.get_version().split("."))) def create_team(admin_username, team_name, organization_name=None): user = User.objects.get(username=admin_username) if organization_name is None: organization_name = team_name org, new_org = Organization.objects.get_or_create(name=organization_name, defaults={"owner": user}) team, new = Team.objects.get_or_create(name=team_name, defaults={"organization": org}) return team, new def create_project(team_name, project_name, platform="python"): team = Team.objects.get(name=team_name) defaults = {"platform": platform, "organization": team.organization} project, new = Project.objects.get_or_create(name=project_name, team=team, defaults=defaults)
def sentry_version(): from sentry import get_version return get_version()
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Broadcast, Organization, Project, Team, User install_id = options.get('sentry:install-id') if not install_id: install_id = sha1(uuid4().bytes).hexdigest() logger.info('beacon.generated-install-id', extra={'install_id': install_id}) options.set('sentry:install-id', install_id) if not settings.SENTRY_BEACON: logger.info('beacon.skipped', extra={'install_id': install_id, 'reason': 'disabled'}) return if settings.DEBUG: logger.info('beacon.skipped', extra={'install_id': install_id, 'reason': 'debug'}) return end = timezone.now() events_24h = tsdb.get_sums( model=tsdb.models.internal, keys=['events.total'], start=end - timedelta(hours=24), end=end, )['events.total'] # we need this to be explicitly configured and it defaults to None, # which is the same as False anonymous = options.get('beacon.anonymous') is not False payload = { 'install_id': install_id, 'version': sentry.get_version(), 'docker': sentry.is_docker(), 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), 'events.24h': events_24h, }, 'packages': get_all_package_versions(), 'anonymous': anonymous, } if not anonymous: payload['admin_email'] = options.get('system.admin-email') # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('beacon.failed', exc_info=True, extra={'install_id': install_id}) return else: logger.info('beacon.sent', extra={'install_id': install_id}) data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable']) if 'notices' in data: upstream_ids = set() for notice in data['notices']: upstream_ids.add(notice['id']) Broadcast.objects.create_or_update( upstream_id=notice['id'], defaults={ 'title': notice['title'], 'link': notice.get('link'), 'message': notice['message'], } ) Broadcast.objects.filter( upstream_id__isnull=False, ).exclude( upstream_id__in=upstream_ids, ).update( is_active=False, )
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Broadcast, Organization, Project, Team, User install_id = options.get("sentry:install-id") if not install_id: install_id = sha1(uuid4().bytes).hexdigest() logger.info("beacon.generated-install-id", extra={"install_id": install_id}) options.set("sentry:install-id", install_id) if not settings.SENTRY_BEACON: logger.info("beacon.skipped", extra={ "install_id": install_id, "reason": "disabled" }) return if settings.DEBUG: logger.info("beacon.skipped", extra={ "install_id": install_id, "reason": "debug" }) return end = timezone.now() events_24h = tsdb.get_sums(model=tsdb.models.internal, keys=["events.total"], start=end - timedelta(hours=24), end=end)["events.total"] # we need this to be explicitly configured and it defaults to None, # which is the same as False anonymous = options.get("beacon.anonymous") is not False payload = { "install_id": install_id, "version": sentry.get_version(), "docker": sentry.is_docker(), "python_version": platform.python_version(), "data": { "users": User.objects.count(), "projects": Project.objects.count(), "teams": Team.objects.count(), "organizations": Organization.objects.count(), "events.24h": events_24h, }, "packages": get_all_package_versions(), "anonymous": anonymous, } if not anonymous: payload["admin_email"] = options.get("system.admin-email") # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning("beacon.failed", exc_info=True, extra={"install_id": install_id}) return else: logger.info("beacon.sent", extra={"install_id": install_id}) data = json.loads(response) if "version" in data: options.set("sentry:latest_version", data["version"]["stable"]) if "notices" in data: upstream_ids = set() for notice in data["notices"]: upstream_ids.add(notice["id"]) defaults = { "title": notice["title"], "link": notice.get("link"), "message": notice["message"], } # XXX(dcramer): we're missing a unique constraint on upstream_id # so we're using a lock to work around that. In the future we'd like # to have a data migration to clean up the duplicates and add the constraint lock = locks.get("broadcasts:{}".format(notice["id"]), duration=60) with lock.acquire(): affected = Broadcast.objects.filter( upstream_id=notice["id"]).update(**defaults) if not affected: Broadcast.objects.create(upstream_id=notice["id"], **defaults) Broadcast.objects.filter(upstream_id__isnull=False).exclude( upstream_id__in=upstream_ids).update(is_active=False)
def send_beacon(): """ Send a Beacon to a remote server operated by the Sentry team. See the documentation for more details. """ from sentry import options from sentry.models import Broadcast, Organization, Project, Team, User if not settings.SENTRY_BEACON: logger.info('Not sending beacon (disabled)') return install_id = options.get('sentry:install-id') if not install_id: logger.info('Generated installation ID: %s', install_id) install_id = sha1(uuid4().bytes).hexdigest() options.set('sentry:install-id', install_id) end = timezone.now() events_24h = tsdb.get_sums( model=tsdb.models.internal, keys=['events.total'], start=end - timedelta(hours=24), end=end, )['events.total'] payload = { 'install_id': install_id, 'version': sentry.get_version(), 'docker': sentry.is_docker(), 'admin_email': options.get('system.admin-email'), 'data': { # TODO(dcramer): we'd also like to get an idea about the throughput # of the system (i.e. events in 24h) 'users': User.objects.count(), 'projects': Project.objects.count(), 'teams': Team.objects.count(), 'organizations': Organization.objects.count(), 'events.24h': events_24h, }, 'packages': get_all_package_versions(), } # TODO(dcramer): relay the response 'notices' as admin broadcasts try: request = safe_urlopen(BEACON_URL, json=payload, timeout=5) response = safe_urlread(request) except Exception: logger.warning('Failed sending beacon', exc_info=True) return data = json.loads(response) if 'version' in data: options.set('sentry:latest_version', data['version']['stable']) if 'notices' in data: upstream_ids = set() for notice in data['notices']: upstream_ids.add(notice['id']) Broadcast.objects.create_or_update( upstream_id=notice['id'], defaults={ 'title': notice['title'], 'link': notice.get('link'), 'message': notice['message'], } ) Broadcast.objects.filter( upstream_id__isnull=False, ).exclude( upstream_id__in=upstream_ids, ).update( is_active=False, )