def get(self, request, organization): all_plugins = dict([(p.slug, p) for p in plugins.all()]) if 'plugins' in request.GET: if request.GET.get('plugins') == '_all': return Response( serialize([p for p in plugins.all()], request.user, PluginSerializer())) desired_plugins = set(request.GET.getlist('plugins')) else: desired_plugins = set(all_plugins.keys()) # Ignore plugins that are not available to this Sentry install. desired_plugins = desired_plugins & set(all_plugins.keys()) # Each tuple represents an enabled Plugin (of only the ones we care # about) and its corresponding Project. enabled_plugins = ProjectOption.objects.filter( key__in=['%s:enabled' % slug for slug in desired_plugins], project__organization=organization, ).select_related('project') resources = [] for project_option in enabled_plugins: resources.append( serialize( all_plugins[project_option.key.split(':')[0]], request.user, OrganizationPluginSerializer(project_option.project), )) return Response(resources)
def manage_plugins(request, organization, project): if request.POST: enabled = set(request.POST.getlist('plugin')) for plugin in plugins.all(version=None): if plugin.can_enable_for_projects(): if plugin.slug in enabled: plugin.enable(project) else: plugin.disable(project) messages.add_message( request, messages.SUCCESS, _('Your settings were saved successfully.')) return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'organization': organization, 'team': project.team, 'page': 'plugins', 'project': project, }) return render_to_response('sentry/projects/plugins/list.html', context, request)
def _get_plugin_value(self, feature, actor): for plugin in plugins.all(version=2): for handler in (safe_execute(plugin.get_feature_hooks) or ()): rv = handler(feature, actor) if rv is not None: return rv return None
def notification_settings(request): forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None) if not form: continue helper = FormHelper() helper.form_tag = False forms.append((form, helper)) # Ensure our form comes first helper = FormHelper() helper.form_tag = False forms = [(NotificationSettingsForm(request.user, request.POST or None), helper)] + forms if request.POST: if all(f.is_valid() for f, h in forms): for form, helper in forms: form.save() messages.add_message(request, messages.SUCCESS, "Your settings were saved.") return HttpResponseRedirect(request.path) context = csrf(request) context.update({"forms": forms, "page": "notifications"}) return render_to_response("sentry/account/notifications.html", context, request)
def _get_plugin_value(self, feature, actor): for plugin in plugins.all(version=2): for handler in safe_execute(plugin.get_feature_hooks) or (): rv = handler(feature, actor) if rv is not None: return rv return None
def get_filters(model=None, project=None): filter_list = [] # Add builtins (specified with the FILTERS setting) for class_path in settings.FILTERS: if class_path not in FILTER_CACHE: module_name, class_name = class_path.rsplit('.', 1) try: module = __import__(module_name, {}, {}, class_name) cls = getattr(module, class_name) except Exception: logger = logging.getLogger('sentry.errors.filters') logger.exception('Unable to import %s' % (class_path, )) continue FILTER_CACHE[class_path] = cls filter_list.append(FILTER_CACHE[class_path]) # Add plugin-provided filters for plugin in plugins.all(): if not plugin.is_enabled(project): continue for filter_cls in plugin.get_filters(project): if filter_cls not in filter_list: filter_list.append(filter_cls) # yield all filters which support ``model`` for filter_cls in filter_list: if model and model not in filter_cls.types: continue yield filter_cls
def preprocess_event(cache_key=None, data=None, **kwargs): from sentry.plugins import plugins if cache_key: data = default_cache.get(cache_key) logger = preprocess_event.get_logger() if data is None: logger.error('Data not available in preprocess_event (cache_key=%s)', cache_key) return project = data['project'] # TODO(dcramer): ideally we would know if data changed by default has_changed = False for plugin in plugins.all(version=2): for processor in (safe_execute(plugin.get_event_preprocessors) or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data[ 'project'] == project, 'Project cannot be mutated by preprocessor' if has_changed and cache_key: default_cache.set(cache_key, data, 3600) if cache_key: data = None save_event.delay(cache_key=cache_key, data=data)
def get(self, request, organization): all_plugins = dict([ (p.slug, p) for p in plugins.all() ]) if 'plugins' in request.GET: desired_plugins = set(request.GET.getlist('plugins')) else: desired_plugins = set(all_plugins.keys()) # Ignore plugins that are not available to this Sentry install. desired_plugins = desired_plugins & set(all_plugins.keys()) # Each tuple represents an enabled Plugin (of only the ones we care # about) and its corresponding Project. enabled_plugins = ProjectOption.objects.filter( key__in=['%s:enabled' % slug for slug in desired_plugins], project__organization=organization, ).select_related('project') resources = [] for project_option in enabled_plugins: resources.append( serialize( all_plugins[project_option.key.split(':')[0]], request.user, OrganizationPluginSerializer(project_option.project), ) ) return Response(resources)
def _iter_plugins(self): for plugin in plugins.all(version=1): if not ( isinstance(plugin, IssueTrackingPlugin) or isinstance(plugin, IssueTrackingPlugin2) ): continue yield plugin
def preprocess_event(cache_key=None, data=None, start_time=None, **kwargs): from sentry.plugins import plugins if cache_key: data = default_cache.get(cache_key) if data is None: metrics.incr('events.failed', tags={'reason': 'cache', 'stage': 'pre'}) error_logger.error('preprocess.failed.empty', extra={'cache_key': cache_key}) return project = data['project'] Raven.tags_context({ 'project': project, }) # Iterate over all plugins looking for processors based on the input data # plugins should yield a processor function only if it actually can operate # on the input data, otherwise it should yield nothing for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_event_preprocessors, data=data, _with_transaction=False) for processor in (processors or ()): # On the first processor found, we just defer to the process_event # queue to handle the actual work. process_event.delay(cache_key=cache_key, start_time=start_time) return # If we get here, that means the event had no preprocessing needed to be done # so we can jump directly to save_event if cache_key: data = None save_event.delay(cache_key=cache_key, data=data, start_time=start_time)
def find_mail_plugin(): from sentry.plugins import plugins for plugin in plugins.all(): if type(plugin).__name__.endswith("MailPlugin"): return plugin assert False, "MailPlugin cannot be found"
def post_process_group(group, **kwargs): """ Fires post processing hooks for a group. """ for plugin in plugins.all(): if safe_execute(plugin.is_enabled, group.project): plugin_post_process_group.delay(plugin.slug, group=group, **kwargs)
def notification_settings(request): forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None) if not form: continue helper = FormHelper() helper.form_tag = False forms.append((form, helper)) # Ensure our form comes first helper = FormHelper() helper.form_tag = False forms = [ (NotificationSettingsForm(request.user, request.POST or None), helper), ] + forms if request.POST: if all(f.is_valid() for f, h in forms): for form, helper in forms: form.save() response = HttpResponseRedirect(reverse('sentry-account-settings-notifications') + '?success=1') return response context = csrf(request) context.update({ 'forms': forms, 'page': 'notifications', }) return render_to_response('sentry/account/notifications.html', context, request)
def manage_plugins(request, team, project): result = plugins.first('has_perm', request.user, 'configure_project_plugin', project) if result is False and not request.user.has_perm('sentry.can_change_project'): return HttpResponseRedirect(reverse('sentry')) if request.POST: enabled = set(request.POST.getlist('plugin')) for plugin in plugins.all(): if plugin.can_enable_for_projects(): plugin.set_option('enabled', plugin.slug in enabled, project) messages.add_message( request, messages.SUCCESS, _('Your settings were saved successfully.')) return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'team': team, 'page': 'plugins', 'project': project, 'SECTION': 'team', 'SUBSECTION': 'projects' }) return render_to_response('sentry/projects/plugins/list.html', context, request)
def get_filters(model=None, project=None): filter_list = [] # Add builtins (specified with the FILTERS setting) for class_path in settings.FILTERS: if class_path not in FILTER_CACHE: module_name, class_name = class_path.rsplit('.', 1) try: module = __import__(module_name, {}, {}, class_name) cls = getattr(module, class_name) except Exception: logger = logging.getLogger('sentry.errors.filters') logger.exception('Unable to import %s' % (class_path,)) continue FILTER_CACHE[class_path] = cls filter_list.append(FILTER_CACHE[class_path]) # Add plugin-provided filters for plugin in plugins.all(): if not plugin.is_enabled(project): continue for filter_cls in plugin.get_filters(project): if filter_cls not in filter_list: filter_list.append(filter_cls) # yield all filters which support ``model`` for filter_cls in filter_list: if model and model not in filter_cls.types: continue yield filter_cls
def notification_settings(request): forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None) if not form: continue helper = FormHelper() helper.form_tag = False forms.append((form, helper)) # Ensure our form comes first helper = FormHelper() helper.form_tag = False forms = [ (NotificationSettingsForm(request.user, request.POST or None), helper), ] + forms if request.POST: if all(f.is_valid() for f, h in forms): for form, helper in forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'forms': forms, 'page': 'notifications', }) return render_to_response('sentry/account/notifications.html', context, request)
def notification_settings(request): forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None) if not form: continue forms.append(form) # Ensure our form comes first forms = [ NotificationSettingsForm(request.user, request.POST or None), ] + forms if request.POST: if all(f.is_valid() for f in forms): for form in forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'forms': forms, 'page': 'notifications', }) return render_to_response('sentry/account/notifications.html', context, request)
def register_plugins(settings): from pkg_resources import iter_entry_points from sentry.plugins import plugins # entry_points={ # 'sentry.plugins': [ # 'phabricator = sentry_phabricator.plugins:PhabricatorPlugin' # ], # }, for ep in iter_entry_points('sentry.plugins'): try: plugin = ep.load() except Exception: import traceback click.echo("Failed to load plugin %r:\n%s" % (ep.name, traceback.format_exc()), err=True) else: plugins.register(plugin) for plugin in plugins.all(version=None): init_plugin(plugin) from sentry import integrations from sentry.utils.imports import import_string for integration_path in settings.SENTRY_DEFAULT_INTEGRATIONS: try: integration_cls = import_string(integration_path) except Exception: import traceback click.echo("Failed to load integration %r:\n%s" % (integration_path, traceback.format_exc()), err=True) else: integrations.register(integration_cls)
def process_event(cache_key, start_time=None, **kwargs): from sentry.plugins import plugins data = default_cache.get(cache_key) if data is None: metrics.incr('events.failed', tags={'reason': 'cache', 'stage': 'process'}) error_logger.error('process.failed.empty', extra={'cache_key': cache_key}) return project = data['project'] Raven.tags_context({ 'project': project, }) # TODO(dcramer): ideally we would know if data changed by default has_changed = False for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_event_preprocessors, data=data, _with_transaction=False) for processor in (processors or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data['project'] == project, 'Project cannot be mutated by preprocessor' if has_changed: default_cache.set(cache_key, data, 3600) save_event.delay(cache_key=cache_key, data=None, start_time=start_time)
def get_processors_for_stacktraces(data, infos): from sentry.plugins import plugins platforms = set() for info in infos: platforms.update(info.platforms or ()) processors = [] for plugin in plugins.all(version=2): processors.extend( safe_execute( plugin.get_stacktrace_processors, data=data, stacktrace_infos=infos, platforms=platforms, _with_transaction=False, ) or () ) if processors: project = Project.objects.get_from_cache(id=data["project"]) processors = [x(data, infos, project) for x in processors] return processors
def preprocess_event(cache_key=None, data=None, start_time=None, **kwargs): from sentry.plugins import plugins if cache_key: data = default_cache.get(cache_key) if data is None: metrics.incr('events.failed', tags={'reason': 'cache', 'stage': 'pre'}) logger.error('Data not available in preprocess_event (cache_key=%s)', cache_key) return project = data['project'] Raven.tags_context({ 'project': project, }) # TODO(dcramer): ideally we would know if data changed by default has_changed = False for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_event_preprocessors, _with_transaction=False) for processor in (processors or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data['project'] == project, 'Project cannot be mutated by preprocessor' if has_changed and cache_key: default_cache.set(cache_key, data, 3600) if cache_key: data = None save_event.delay(cache_key=cache_key, data=data, start_time=start_time)
def preprocess_event(cache_key=None, data=None, start_time=None, **kwargs): from sentry.plugins import plugins if cache_key: data = default_cache.get(cache_key) if data is None: metrics.incr('events.failed', tags={'reason': 'cache', 'stage': 'pre'}) logger.error('Data not available in preprocess_event (cache_key=%s)', cache_key) return project = data['project'] # TODO(dcramer): ideally we would know if data changed by default has_changed = False for plugin in plugins.all(version=2): for processor in (safe_execute(plugin.get_event_preprocessors) or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data['project'] == project, 'Project cannot be mutated by preprocessor' if has_changed and cache_key: default_cache.set(cache_key, data, 3600) if cache_key: data = None save_event.delay(cache_key=cache_key, data=data, start_time=start_time)
def get(self, request, organization): # Just load all Plugins once. all_plugins = dict([ (p.slug, p) for p in plugins.all() ]) if 'plugins' in request.GET: desired_plugins = set(request.GET.getlist('plugins')) else: desired_plugins = set(all_plugins.keys()) if not desired_plugins.issubset(set(all_plugins.keys())): return Response({'detail': 'Invalid plugins'}, status=422) # Each tuple represents an enabled Plugin (of only the ones we care # about) and its corresponding Project. enabled_plugins = ProjectOption.objects.filter( key__in=['%s:enabled' % slug for slug in desired_plugins], project__organization=organization, ).select_related('project') resources = [] for project_option in enabled_plugins: resources.append( serialize( all_plugins[project_option.key.split(':')[0]], request.user, OrganizationPluginSerializer(project_option.project), ) ) return Response(resources)
def _do_process_event(cache_key, start_time, event_id): from sentry.plugins import plugins data = default_cache.get(cache_key) if data is None: metrics.incr('events.failed', tags={ 'reason': 'cache', 'stage': 'process' }) error_logger.error('process.failed.empty', extra={'cache_key': cache_key}) return project = data['project'] Raven.tags_context({ 'project': project, }) has_changed = False # Stacktrace based event processors. These run before anything else. new_data = process_stacktraces(data) if new_data is not None: has_changed = True data = new_data # TODO(dcramer): ideally we would know if data changed by default # Default event processors. for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_event_preprocessors, data=data, _with_transaction=False) for processor in (processors or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data[ 'project'] == project, 'Project cannot be mutated by preprocessor' if has_changed: issues = data.get('processing_issues') if issues and create_failed_event(cache_key, project, list(issues.values()), event_id=event_id, start_time=start_time): return default_cache.set(cache_key, data, 3600) save_event.delay( cache_key=cache_key, data=None, start_time=start_time, event_id=event_id, )
def notification_settings(request): settings_form = NotificationSettingsForm(request.user, request.POST or None) # TODO(dcramer): this is an extremely bad pattern and we need a more optimal # solution for rendering this (that ideally plays well with the org data) project_list = [] organization_list = Organization.objects.get_for_user( user=request.user, ) for organization in organization_list: team_list = Team.objects.get_for_user( user=request.user, organization=organization, ) for team in team_list: project_list.extend( Project.objects.get_for_user( user=request.user, team=team, ) ) project_forms = [ (project, ProjectEmailOptionsForm( project, request.user, request.POST or None, prefix='project-%s' % (project.id,) )) for project in sorted(project_list, key=lambda x: ( x.team.name if x.team else None, x.name)) ] ext_forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None, prefix=plugin.slug) if not form: continue ext_forms.append(form) if request.POST: all_forms = list(itertools.chain( [settings_form], ext_forms, (f for _, f in project_forms) )) if all(f.is_valid() for f in all_forms): for form in all_forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'settings_form': settings_form, 'project_forms': project_forms, 'ext_forms': ext_forms, 'page': 'notifications', 'AUTH_PROVIDERS': get_auth_providers(), }) return render_to_response('sentry/account/notifications.html', context, request)
def _get_plugin_value(self, feature, actor): for plugin in plugins.all(version=2): handlers = safe_execute(plugin.get_feature_hooks, _with_transaction=False) for handler in handlers or (): rv = handler(feature, actor) if rv is not None: return rv return None
def send_group_processors(group, **kwargs): for inst in plugins.all(): try: inst.post_process(group=group, **kwargs) except: transaction.rollback_unless_managed(using=group._state.db) logger = logging.getLogger('sentry.plugins') logger.exception('Error processing post_process() on %r', inst.__class__)
def notification_settings(request): settings_form = NotificationSettingsForm(request.user, request.POST or None) project_list = list( Project.objects.filter( team__organizationmemberteam__organizationmember__user=request. user, team__organizationmemberteam__is_active=True, status=ProjectStatus.VISIBLE, ).distinct()) project_forms = [ (project, ProjectEmailOptionsForm(project, request.user, request.POST or None, prefix='project-%s' % (project.id, ))) for project in sorted(project_list, key=lambda x: (x.team.name if x.team else None, x.name)) ] ext_forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms, _with_transaction=False) or (): form = safe_execute(form, plugin, request.user, request.POST or None, prefix=plugin.slug, _with_transaction=False) if not form: continue ext_forms.append(form) if request.POST: all_forms = list( itertools.chain([settings_form], ext_forms, (f for _, f in project_forms))) if all(f.is_valid() for f in all_forms): for form in all_forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'settings_form': settings_form, 'project_forms': project_forms, 'ext_forms': ext_forms, 'page': 'notifications', 'AUTH_PROVIDERS': get_auth_providers(), }) return render_to_response('sentry/account/notifications.html', context, request)
def get(self, request): data = { 'modules': sorted([(p.project_name, p.version) for p in pkg_resources.working_set]), 'extensions': [ (p.get_title(), '%s.%s' % (p.__module__, p.__class__.__name__)) for p in plugins.all(version=None) ], } return Response(data)
def get_tags(group, request): tag_list = [] for inst in plugins.all(): try: tag_list = inst.tags(request, group, tag_list) except Exception, e: logger = logging.getLogger('sentry.plugins') logger.rror('Error processing tags() on %r: %s', inst.__class__, e, extra={ 'request': request, }, exc_info=True)
def post_process_group(group, **kwargs): """ Fires post processing hooks for a group. """ from sentry.plugins import plugins from sentry.utils.safe import safe_execute for plugin in plugins.all(): if safe_execute(plugin.is_enabled, group.project): safe_execute(plugin.post_process, group=group, **kwargs)
def get_widgets(group, request): project = group.project for plugin in plugins.all(): if not safe_execute(plugin.is_enabled, project): continue resp = safe_execute(plugin.widget, request, group) if resp: yield resp.render(request)
def handle_before_events(request, event_list): if not hasattr(event_list, '__iter__'): event_list = [event_list] for inst in plugins.all(): try: inst.before_events(request, event_list) except Exception, e: logger = logging.getLogger('sentry.plugins') logger.error('Error processing before_events() on %r: %s', inst.__class__, e, extra={ 'request': request, }, exc_info=True)
def handle(self, request): settings_form = self.notification_settings_form( request.user, request.POST or None) reports_form = NotificationReportSettingsForm( request.user, request.POST or None, prefix='reports') project_list = list(Project.objects.filter( team__organizationmemberteam__organizationmember__user=request.user, team__organizationmemberteam__is_active=True, status=ProjectStatus.VISIBLE, ).distinct()) project_forms = [ (project, ProjectEmailOptionsForm( project, request.user, request.POST or None, prefix='project-%s' % (project.id,) )) for project in sorted(project_list, key=lambda x: ( x.organization.name, x.name)) ] ext_forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms, _with_transaction=False) or (): form = safe_execute(form, plugin, request.user, request.POST or None, prefix=plugin.slug, _with_transaction=False) if not form: continue ext_forms.append(form) if request.POST: all_forms = list(itertools.chain( [settings_form, reports_form], ext_forms, (f for _, f in project_forms) )) if all(f.is_valid() for f in all_forms): for form in all_forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'settings_form': settings_form, 'project_forms': project_forms, 'reports_form': reports_form, 'ext_forms': ext_forms, 'page': 'notifications', 'AUTH_PROVIDERS': get_auth_providers(), }) return render_to_response('sentry/account/notifications.html', context, request)
def get_panels(group, request): panel_list = [] for inst in plugins.all(): try: panel_list = inst.panels(request, group, panel_list) except: logger = logging.getLogger('sentry.plugins') logger.error('Error processing panels() on %r', inst.__class__, extra={ 'request': request, }, exc_info=True) for panel in panel_list: yield panel[0], panel[1], request.path == panel[1]
def get_actions(group, request): action_list = [] for inst in plugins.all(): try: action_list = inst.actions(request, group, action_list) except: logger = logging.getLogger('sentry.plugins') logger.error('Error processing actions() on %r', inst.__class__, extra={ 'request': request, }, exc_info=True) for action in action_list: yield action[0], action[1], request.path == action[1]
def get_widgets(group, request): for inst in plugins.all(): try: resp = inst.widget(request, group) if resp: resp = resp.render(request) except: logger = logging.getLogger('sentry.plugins') logger.error('Error processing widget() on %r', inst.__class__, extra={ 'request': request, }, exc_info=True) continue if resp: yield resp
def should_process(data): """Quick check if processing is needed at all.""" from sentry.plugins import plugins for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_event_preprocessors, data=data, _with_transaction=False) if processors: return True if should_process_for_stacktraces(data): return True return False
def should_process_for_stacktraces(data): from sentry.plugins import plugins infos = find_stacktraces_in_data(data) platforms = set() for info in infos: platforms.update(info.platforms or ()) for plugin in plugins.all(version=2): processors = safe_execute(plugin.get_stacktrace_processors, data=data, stacktrace_infos=infos, platforms=platforms, _with_transaction=False) if processors: return True return False
def process(self, request, project, auth, data, **kwargs): event_received.send_robust(ip=request.META['REMOTE_ADDR'], sender=type(self)) rate_limits = [safe_execute(app.quotas.is_rate_limited, project=project)] for plugin in plugins.all(): rate_limit = safe_execute(plugin.is_rate_limited, project=project) # We must handle the case of plugins not returning new RateLimit objects if isinstance(rate_limit, bool): rate_limit = RateLimit(is_limited=rate_limit, retry_after=None) rate_limits.append(rate_limit) if any(limit.is_limited for limit in rate_limits): raise APIRateLimited(max(limit.retry_after for limit in rate_limits)) result = plugins.first('has_perm', request.user, 'create_event', project) if result is False: raise APIForbidden('Creation of this event was blocked') content_encoding = request.META.get('HTTP_CONTENT_ENCODING', '') if content_encoding == 'gzip': data = decompress_gzip(data) elif content_encoding == 'deflate': data = decompress_deflate(data) elif not data.startswith('{'): data = decode_and_decompress_data(data) data = safely_load_json_string(data) try: # mutates data validate_data(project, data, auth.client) except InvalidData as e: raise APIError(u'Invalid data: %s (%s)' % (unicode(e), type(e))) # mutates data Group.objects.normalize_event_data(data) # insert IP address if not available if auth.is_public: ensure_has_ip(data, request.META['REMOTE_ADDR']) event_id = data['event_id'] # mutates data (strips a lot of context if not queued) insert_data_to_database(data) logger.debug('New event from project %s/%s (id=%s)', project.team.slug, project.slug, event_id) return event_id
def init_registry(): from sentry.constants import SENTRY_RULES from sentry.plugins import plugins from sentry.utils.imports import import_string from sentry.utils.safe import safe_execute registry = RuleRegistry() for rule in SENTRY_RULES: cls = import_string(rule) registry.add(cls) for plugin in plugins.all(version=2): for cls in (safe_execute(plugin.get_rules) or ()): register.add(cls) return registry
def notification_settings(request): settings_form = NotificationSettingsForm(request.user, request.POST or None) project_list = Project.objects.get_for_user(request.user, access=MEMBER_USER) project_forms = [ (project, ProjectEmailOptionsForm(project, request.user, request.POST or None, prefix='project-%s' % (project.id, ))) for project in sorted(project_list, key=lambda x: (x.team.name, x.name)) ] ext_forms = [] for plugin in plugins.all(): for form in safe_execute(plugin.get_notification_forms) or (): form = safe_execute(form, plugin, request.user, request.POST or None, prefix=plugin.slug) if not form: continue ext_forms.append(form) if request.POST: all_forms = list( itertools.chain([settings_form], ext_forms, (f for _, f in project_forms))) if all(f.is_valid() for f in all_forms): for form in all_forms: form.save() messages.add_message(request, messages.SUCCESS, 'Your settings were saved.') return HttpResponseRedirect(request.path) context = csrf(request) context.update({ 'settings_form': settings_form, 'project_forms': project_forms, 'ext_forms': ext_forms, 'page': 'notifications', }) return render_to_response('sentry/account/notifications.html', context, request)
def manage_plugins(request, project): result = plugins.first("has_perm", request.user, "configure_project_plugin", project) if result is False and not request.user.has_perm("sentry.can_change_project"): return HttpResponseRedirect(reverse("sentry")) if request.POST: enabled = set(request.POST.getlist("plugin")) for plugin in plugins.all(): if plugin.can_enable_for_projects(): plugin.set_option("enabled", plugin.slug in enabled, project) return HttpResponseRedirect(request.path + "?success=1") context = csrf(request) context.update({"page": "plugins", "project": project}) return render_to_response("sentry/projects/plugins/list.html", context, request)
def get_panels(group, request): project = group.project panel_list = [] for plugin in plugins.all(): if not safe_execute(plugin.is_enabled, project): continue results = safe_execute(plugin.panels, request, group, panel_list) if not results: continue panel_list = results return [(p[0], p[1], request.path == p[1]) for p in panel_list]
def get_actions(group, request): project = group.project action_list = [] for plugin in plugins.all(): if not safe_execute(plugin.is_enabled, project): continue results = safe_execute(plugin.actions, request, group, action_list) if not results: continue action_list = results return [(a[0], a[1], request.path == a[1]) for a in action_list]
def preprocess_event(cache_key=None, data=None, **kwargs): from sentry.app import cache from sentry.plugins import plugins from sentry.tasks.fetch_source import expand_javascript_source if cache_key: data = cache.get(cache_key) logger = preprocess_event.get_logger() if data is None: logger.error('Data not available in preprocess_event (cache_key=%s)', cache_key) return project = data['project'] # TODO(dcramer): ideally we would know if data changed by default has_changed = False # TODO(dcramer): move js sourcemap processing into JS plugin if settings.SENTRY_SCRAPE_JAVASCRIPT_CONTEXT and data.get( 'platform') == 'javascript': try: expand_javascript_source(data) except Exception as e: logger.exception(u'Error fetching javascript source: %r [%s]', data['event_id'], e) else: has_changed = True for plugin in plugins.all(version=2): for processor in (safe_execute(plugin.get_event_preprocessors) or ()): result = safe_execute(processor, data) if result: data = result has_changed = True assert data[ 'project'] == project, 'Project cannot be mutated by preprocessor' if has_changed and cache_key: cache.set(cache_key, data, 3600) if cache_key: data = None save_event.delay(cache_key=cache_key, data=data)
def get_tags(group, request): project = group.project tag_list = [] for plugin in plugins.all(): if not safe_execute(plugin.is_enabled, project): continue results = safe_execute(plugin.tags, request, group, tag_list) if not results: continue tag_list = results for tag in tag_list: yield tag
def status_packages(request): config = [] for k in sorted(dir(settings)): if k == 'KEY': continue if k.startswith('_'): continue if k.upper() != k: continue config.append((k, getattr(settings, k))) return render_to_response('sentry/admin/status/packages.html', { 'modules': sorted([(p.project_name, p.version) for p in pkg_resources.working_set]), 'extensions': [ (p.get_title(), '%s.%s' % (p.__module__, p.__class__.__name__)) for p in plugins.all(version=None) ], }, request)