Ejemplo n.º 1
0
def run_alert_query(alert: Alert) -> Optional[bool]:
    """
    Execute alert.sql and return value if any rows are returned
    """
    logger.info("Processing alert ID: %i", alert.id)
    database = alert.database
    if not database:
        logger.error("Alert database not preset")
        return None

    if not alert.sql:
        logger.error("Alert SQL not preset")
        return None

    parsed_query = ParsedQuery(alert.sql)
    sql = parsed_query.stripped()

    state = None
    dttm_start = datetime.utcnow()

    df = pd.DataFrame()
    try:
        logger.info("Evaluating SQL for alert %s", alert)
        df = database.get_df(sql)
    except Exception as exc:  # pylint: disable=broad-except
        state = AlertState.ERROR
        logging.exception(exc)
        logging.error("Failed at evaluating alert: %s (%s)", alert.label,
                      alert.id)

    dttm_end = datetime.utcnow()

    if state != AlertState.ERROR:
        alert.last_eval_dttm = datetime.utcnow()
        if not df.empty:
            # Looking for truthy cells
            for row in df.to_records():
                if any(row):
                    state = AlertState.TRIGGER
                    deliver_alert(alert)
                    break
        if not state:
            state = AlertState.PASS

    alert.last_state = state
    alert.logs.append(
        AlertLog(
            scheduled_dttm=dttm_start,
            dttm_start=dttm_start,
            dttm_end=dttm_end,
            state=state,
        ))
    db.session.commit()

    return None
Ejemplo n.º 2
0
def create_alert(
    dbsession,
    sql: str,
    validator_type: Optional[str] = None,
    validator_config: Optional[str] = None,
) -> Alert:
    alert = Alert(
        label="test_alert",
        active=True,
        crontab="* * * * *",
        slice_id=dbsession.query(Slice).all()[0].id,
        recipients="*****@*****.**",
        slack_channel="#test_channel",
    )
    dbsession.add(alert)
    dbsession.commit()

    sql_observer = SQLObserver(
        sql=sql,
        alert_id=alert.id,
        database_id=utils.get_example_database().id,
    )

    if validator_type and validator_config:
        validator = Validator(
            validator_type=validator_type,
            config=validator_config,
            alert_id=alert.id,
        )

        dbsession.add(validator)

    dbsession.add(sql_observer)
    dbsession.commit()
    return alert
Ejemplo n.º 3
0
def setup_database():
    with app.app_context():
        slice_id = db.session.query(Slice).all()[0].id
        database_id = utils.get_example_database().id

        alerts = [
            Alert(
                id=1,
                label="alert_1",
                active=True,
                crontab="*/1 * * * *",
                sql="SELECT 0",
                alert_type="email",
                slice_id=slice_id,
                database_id=database_id,
            ),
            Alert(
                id=2,
                label="alert_2",
                active=True,
                crontab="*/1 * * * *",
                sql="SELECT 55",
                alert_type="email",
                slice_id=slice_id,
                database_id=database_id,
            ),
            Alert(
                id=3,
                label="alert_3",
                active=False,
                crontab="*/1 * * * *",
                sql="UPDATE 55",
                alert_type="email",
                slice_id=slice_id,
                database_id=database_id,
            ),
            Alert(id=4, active=False, label="alert_4", database_id=-1),
            Alert(id=5, active=False, label="alert_5",
                  database_id=database_id),
        ]

        db.session.bulk_save_objects(alerts)
        db.session.commit()
        yield db.session

        db.session.query(AlertLog).delete()
        db.session.query(Alert).delete()
Ejemplo n.º 4
0
def setup_database():
    with app.app_context():
        slice_id = db.session.query(Slice).all()[0].id
        database_id = utils.get_example_database().id

        alert1 = Alert(
            id=1,
            label="alert_1",
            active=True,
            crontab="*/1 * * * *",
            sql="SELECT 0",
            alert_type="email",
            slice_id=slice_id,
            database_id=database_id,
        )
        alert2 = Alert(
            id=2,
            label="alert_2",
            active=True,
            crontab="*/1 * * * *",
            sql="SELECT 55",
            alert_type="email",
            slice_id=slice_id,
            database_id=database_id,
        )
        alert3 = Alert(
            id=3,
            label="alert_3",
            active=False,
            crontab="*/1 * * * *",
            sql="UPDATE 55",
            alert_type="email",
            slice_id=slice_id,
            database_id=database_id,
        )
        alert4 = Alert(id=4, active=False, label="alert_4", database_id=-1)
        alert5 = Alert(id=5, active=False, label="alert_5", database_id=database_id)

        for num in range(1, 6):
            eval(f"db.session.add(alert{num})")
        db.session.commit()
        yield db.session

        db.session.query(AlertLog).delete()
        db.session.query(Alert).delete()
Ejemplo n.º 5
0
def operator_validator(alert: Alert, validator_config: str) -> bool:
    """
    Returns True if a recent observation is greater than or equal to
    the value given in the validator config
    """
    observation = alert.get_last_observation()
    if not observation or observation.value in (None, np.nan):
        return False

    operator = json.loads(validator_config)["op"]
    threshold = json.loads(validator_config)["threshold"]
    return OPERATOR_FUNCTIONS[operator](observation.value, threshold)
Ejemplo n.º 6
0
def not_null_validator(
        alert: Alert,
        validator_config: str  # pylint: disable=unused-argument
) -> bool:
    """Returns True if a recent observation is not NULL"""

    observation = alert.get_last_observation()
    # TODO: Validate malformed observations/observations with errors separately
    if (not observation or observation.error_msg
            or observation.value in (0, None, np.nan)):
        return False
    return True
Ejemplo n.º 7
0
def setup_database():
    with app.app_context():
        example_database = utils.get_example_database()
        example_database.get_sqla_engine().execute(
            "CREATE TABLE test_table AS SELECT 1 as first, 2 as second")
        example_database.get_sqla_engine().execute(
            "INSERT INTO test_table (first, second) VALUES (3, 4)")

        no_observer_alert = Alert(crontab="* * * * *", label="No Observer")
        db.session.add(no_observer_alert)
        db.session.commit()
        yield db.session

        db.session.query(SQLObservation).delete()
        db.session.query(SQLObserver).delete()
        db.session.query(Validator).delete()
        db.session.query(AlertLog).delete()
        db.session.query(Alert).delete()
Ejemplo n.º 8
0
def create_alert(
    db_session: Session,
    sql: str,
    validator_type: AlertValidatorType = AlertValidatorType.OPERATOR,
    validator_config: str = "",
) -> Alert:
    db_session.commit()
    alert = Alert(
        label="test_alert",
        active=True,
        crontab="* * * * *",
        slice_id=db_session.query(Slice).all()[0].id,
        recipients="*****@*****.**",
        slack_channel="#test_channel",
        sql=sql,
        database_id=utils.get_example_database().id,
        validator_type=validator_type,
        validator_config=validator_config,
    )
    db_session.add(alert)
    db_session.commit()
    return alert