# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. """Models for scheduled execution of jobs""" from datetime import datetime from flask_appbuilder import Model from sqlalchemy import ( Boolean, Column, DateTime, ForeignKey, Integer, String, Table, Text, ) from sqlalchemy.orm import backref, relationship from superset import security_manager metadata = Model.metadata # pylint: disable=no-member alert_owner = Table( "alert_owner", metadata, Column("id", Integer, primary_key=True), Column("user_id", Integer, ForeignKey("ab_user.id")), Column("alert_id", Integer, ForeignKey("alerts.id")), ) class Alert(Model): """Schedules for emailing slices / dashboards""" __tablename__ = "alerts" id = Column(Integer, primary_key=True) label = Column(String(150)) active = Column(Boolean, default=True, index=True) crontab = Column(String(50)) sql = Column(Text) alert_type = Column(String(50)) owners = relationship(security_manager.user_model, secondary=alert_owner) recipients = Column(Text) slack_channel = Column(Text) log_retention = Column(Integer, default=90) grace_period = Column(Integer, default=60 * 60 * 24) slice_id = Column(Integer, ForeignKey("slices.id")) slice = relationship("Slice", backref="alerts", foreign_keys=[slice_id]) dashboard_id = Column(Integer, ForeignKey("dashboards.id")) dashboard = relationship("Dashboard", backref="alert", foreign_keys=[dashboard_id]) database_id = Column(Integer, ForeignKey("dbs.id"), nullable=False) database = relationship( "Database", foreign_keys=[database_id], backref=backref("alerts", cascade="all, delete-orphan"), ) last_eval_dttm = Column(DateTime, default=datetime.utcnow) last_state = Column(String(10)) def __str__(self) -> str: return f"<{self.id}:{self.label}>" class AlertLog(Model): """Keeps track of alert-related operations""" __tablename__ = "alert_logs" id = Column(Integer, primary_key=True) scheduled_dttm = Column(DateTime) dttm_start = Column(DateTime, default=datetime.utcnow) dttm_end = Column(DateTime, default=datetime.utcnow) alert_id = Column(Integer, ForeignKey("alerts.id")) alert = relationship("Alert", backref="logs", foreign_keys=[alert_id]) state = Column(String(10)) @property def duration(self) -> int: return (self.dttm_end - self.dttm_start).total_seconds()