def dashboard_PATCH(request): dashboard = request.context.resource allowed_keys = ["public", "resource_name", "layout_config"] for k, v in request.unsafe_json_body.items(): if k in allowed_keys: setattr(dashboard, k, v) else: return HTTPUnprocessableEntity() # ensure we don't have any leftover chart definitions present from # removed layout columns chart_ids = [] for row in dashboard.layout_config: for col in row["columns"]: chart_ids.append(col["chartId"]) for chart in dashboard.charts: if chart.uuid not in chart_ids: actions = AlertChannelActionService.by_other_id(chart.uuid) for action in actions: DBSession.delete(action) dashboard.charts.remove(chart) existing_ids = [c.uuid for c in dashboard.charts] for c_uuid in chart_ids: if c_uuid not in existing_ids: chart = DashboardChart(uuid=c_uuid, config=None) dashboard.charts.append(chart) request.session.flash("Dashboard updated") return dashboard.get_dict(request=request)
def __init__(self, request): self.__acl__ = [] self.used_uuid = False # used_uuid is set to true if user who is normally not authorized to # view the resource gains access to it because owner set it to public # and user knows the uuid of object alert_id = request.matchdict.get("alert_id", request.GET.get("alert_id")) self.alert = AlertChannelActionService.by_pkey(alert_id) if not self.alert: raise HTTPNotFound() self.chart = DashboardChartService.by_uuid(self.alert.other_id) if not self.chart: raise HTTPNotFound() self.resource = ResourceService.by_resource_id(self.chart.resource_id) if self.resource and request.user: self.__acl__ = self.resource.__acl__ permissions = ResourceService.perms_for_user( self.resource, request.user) for perm_user, perm_name in permission_to_04_acls(permissions): self.__acl__.append(rewrite_root_perm(perm_user, perm_name)) if self.resource and self.resource.public: if not request.has_permission("view", self): self.used_uuid = True self.__acl__.append((Allow, Everyone, "view")) add_root_superperm(request, self)
def alerting_charts(): """ loop that loads existing charting alert rules and issues checks """ alert_rules = AlertChannelActionService.by_type("chart") for rule in alert_rules: alert_chart.delay(rule.pkey, rule.other_id)
def dashboard_DELETE(request): dashboard = request.context.resource actions = AlertChannelActionService.by_resource_id(dashboard.resource_id) for action in actions: DBSession.delete(action) DBSession.delete(dashboard) request.session.flash("Dashboard removed") return True
def alert_channels_rule_DELETE(request): """ Removes specific alert channel rule """ user = request.user rule_action = AlertChannelActionService.by_owner_id_and_pkey( user.id, request.GET.get("pkey")) if rule_action: DBSession.delete(rule_action) return True return HTTPNotFound()
def charts_PATCH(request): dashboard = request.context.resource json_body = copy.deepcopy(request.unsafe_json_body) chart_config = json_body["config"] # for now just throw error in case something weird is found applications = UserService.resources_with_perms( request.user, ["view"], resource_types=["application"]) # CRITICAL - this ensures our resultset is limited to only the ones # user has view permissions all_possible_app_ids = set([app.resource_id for app in applications]) schema = ChartConfigSchema().bind(resources=all_possible_app_ids) schema.deserialize(chart_config) # some processing/normalizing for new/missing variables if "timeRange" not in chart_config: chart_config["timeRange"] = "1M" if "startMoment" not in chart_config: chart_config["startMoment"] = "now" if "startMomentUnit" not in chart_config: chart_config["startMomentUnit"] = "days" if "startMomentValue" not in chart_config: chart_config["startMomentValue"] = 0 # ensure we don't have any leftover chart definitions present from # removed layout columns chart_ids = [] for row in dashboard.layout_config: for col in row["columns"]: chart_ids.append(col["chartId"]) for chart in dashboard.charts: if chart.uuid not in chart_ids: actions = AlertChannelActionService.by_other_id(chart.uuid) for action in actions: DBSession.delete(action) dashboard.charts.remove(chart) chart_config["json_config_version"] = chart.json_config_version # make sure we set model field as dirty request.context.chart.name = json_body["name"] request.context.chart.config = None request.context.chart.config = chart_config session = DBSession() mark_changed(session) request.session.flash("Chart saved") return True
def alert_channels_actions_binds_DELETE(request): """ Removes alert action from users channels """ user = request.user channel = AlertChannelService.by_owner_id_and_pkey( user.id, request.GET.get("channel_pkey")) rule_action = AlertChannelActionService.by_owner_id_and_pkey( user.id, request.GET.get("action_pkey")) if channel and rule_action: if channel.pkey in [c.pkey for c in rule_action.channels]: rule_action.channels.remove(channel) return rule_action.get_dict(extended_info=True) return HTTPUnprocessableEntity()
def alert_channels_actions_binds_POST(request): """ Adds alert action to users channels """ user = request.user json_body = request.unsafe_json_body channel = AlertChannelService.by_owner_id_and_pkey( user.id, json_body.get("channel_pkey")) rule_action = AlertChannelActionService.by_owner_id_and_pkey( user.id, json_body.get("action_pkey")) if channel and rule_action: if channel.pkey not in [c.pkey for c in rule_action.channels]: rule_action.channels.append(channel) return rule_action.get_dict(extended_info=True) return HTTPUnprocessableEntity()
def alert_channels_rule_PATCH(request): """ Removes specific alert channel rule """ user = request.user json_body = request.unsafe_json_body schema = build_rule_schema(json_body["rule"], REPORT_TYPE_MATRIX) try: schema.deserialize(json_body["rule"]) except colander.Invalid as exc: return HTTPUnprocessableEntity(body=json.dumps(exc.asdict())) rule_action = AlertChannelActionService.by_owner_id_and_pkey( user.id, request.GET.get("pkey")) if rule_action: rule_action.rule = json_body["rule"] rule_action.resource_id = json_body["resource_id"] rule_action.action = json_body["action"] return rule_action.get_dict() return HTTPNotFound()
def charts_event_rules_GET(request): actions = AlertChannelActionService.by_other_id(request.context.chart.uuid) return [a.get_dict(extended_info=True) for a in actions]
def alert_chart(pkey, chart_uuid): start = datetime.utcnow() request = get_current_request() alert_action = AlertChannelActionService.by_pkey(pkey) chart = DashboardChartService.by_uuid(chart_uuid) chart.migrate_json_config() resource = chart.dashboard json_body = chart.config ids_to_override = [json_body["resource"]] filter_settings = build_filter_settings_from_chart_config( request, json_body, override_app_ids=ids_to_override ) log.warning("alert_chart, resource:{}, chart:{}".format(resource, chart_uuid)) # determine start and end date for dataset start_date, end_date = determine_date_boundries_json(json_body) if not filter_settings["start_date"]: filter_settings["start_date"] = start_date.replace( hour=0, minute=0, second=0, microsecond=0 ) if not filter_settings["end_date"]: filter_settings["end_date"] = end_date event_type = Event.types["chart_alert"] open_event = None latest_closed_event = None events_query = EventService.for_resource( [resource.resource_id], event_type=event_type, target_uuid=chart_uuid, limit=20 ) for event in events_query: if event.status == Event.statuses["active"] and not open_event: open_event = event if event.status == Event.statuses["closed"] and not latest_closed_event: latest_closed_event = event if latest_closed_event: filter_settings["start_date"] = latest_closed_event.end_date es_config = transform_json_to_es_config( request, json_body, filter_settings, ids_to_override=ids_to_override ) if not es_config["index_names"]: return result = Datastores.es.search( body=es_config["query"], index=es_config["index_names"], doc_type="log", size=0 ) series, info_dict = parse_es_result(result, es_config, json_config=json_body) # we need to make a deepcopy since we will mutate it rule_config = copy.deepcopy(alert_action.rule) field_mappings = alert_action.config rule_obj = RuleService.rule_from_config( rule_config, field_mappings, info_dict["system_labels"] ) matched_interval = None finished_interval = None for step in reversed(series): if rule_obj.match(step): log.info("matched start") if not matched_interval: matched_interval = step break else: finished_interval = step if matched_interval: if open_event: log.info("ALERT: PROGRESS: %s %s" % (event_type, resource)) if finished_interval: open_event.values = copy.deepcopy(open_event.values) end_interval = finished_interval["key"].strftime(DATE_FORMAT) open_event.values["end_interval"] = end_interval open_event.close() else: log.warning("ALERT: OPEN: %s %s" % (event_type, resource)) step_size = None parent_agg = json_body.get("parentAgg") if parent_agg and parent_agg["type"] == "time_histogram": step_size = time_deltas[parent_agg["config"]["interval"]][ "delta" ].total_seconds() matched_step_values = { "values": matched_interval, "labels": info_dict["system_labels"], } values_dict = { "matched_rule": alert_action.get_dict(), "matched_step_values": matched_step_values, "start_interval": step["key"], "end_interval": None, "resource": chart.config.get("resource"), "chart_name": chart.name, "chart_uuid": chart_uuid, "step_size": step_size, "action_name": alert_action.name, } new_event = Event( resource_id=resource.resource_id, event_type=event_type, status=Event.statuses["active"], values=values_dict, target_uuid=chart_uuid, ) DBSession.add(new_event) DBSession.flush() new_event.send_alerts(request=request, resource=resource) elif open_event: if finished_interval: open_event.values = copy.deepcopy(open_event.values) end_interval = finished_interval["key"].strftime(DATE_FORMAT) open_event.values["end_interval"] = end_interval open_event.close() took = datetime.utcnow() - start log.warning("chart alert rule check took: {}".format(took))