"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Windows = void 0;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const types_1 = require("./types");
/**
 * Encapsulates the properties of SLO alerting windows and provides a set of presets
 * that we'll commonly use.
 */
class Windows {
}
exports.Windows = Windows;
/**
 * 2% of 30 Day window in 5 minutes
 */
Windows.twoPercentShort = {
    percent: 2,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.minutes(5),
    get burnRateThreshold() {
        return Windows.burnRate(Windows.twoPercentLong);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 2% of 30 Day window in 1 hour
 */
Windows.twoPercentLong = {
    percent: 2,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.hours(1),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * Experimental!
 * 2% of 30 Day window in 2 hours
 */
Windows.twoPercentExtraLong = {
    percent: 2,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.hours(2),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 5% of 30 Day window in 30 minutes
 */
Windows.fivePercentShort = {
    percent: 5,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.minutes(30),
    get burnRateThreshold() {
        return Windows.burnRate(Windows.fivePercentLong);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 5% of 30 Day window in 6 hours
 */
Windows.fivePercentLong = {
    percent: 5,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.hours(6),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * Experimental!
 * 5% of 30 Day window in 12 hours
 */
Windows.fivePercentExtraLong = {
    percent: 5,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.hours(12),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * Experimental!
 * 3.3333% of 30 Day window in 1 day. Useful for low % SLOs, but should not be used if you can avoid
 * it since it will be more sensitive to false positives.
 */
Windows.oneDaySensitive = {
    percent: 10 / 3,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.days(1),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 10% of 30 Day window in 6 hours.
 */
Windows.tenPercentShort = {
    percent: 10,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.hours(6),
    get burnRateThreshold() {
        return Windows.burnRate(Windows.tenPercentLong);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 10% of 30 Day window in 1 day.
 * Note: Google recommends 3 days for 10% long window, but since
 * we cannot do a 3 day alarm for the long window, we're making
 * a 1 day period
 */
Windows.tenPercentMedium = {
    percent: 10,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.days(1),
    get burnRateThreshold() {
        return Windows.burnRate(Windows.tenPercentLong);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 10% of 30 Day window in 3 days.
 * NOTE: This one can only be used for graphing in a widget. Cloudwatch Alerts are currently limited to metrics <= 1 day
 */
Windows.tenPercentLong = {
    percent: 10,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.days(3),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * 100% of 30 Day window in 30 days.
 * NOTE: This one can only be used for graphing in a widget. Cloudwatch Alerts are currently limited to metrics <= 1 day
 */
Windows.thirtyDays = {
    percent: 100,
    period: aws_cdk_lib_1.Duration.days(30),
    alertWindow: aws_cdk_lib_1.Duration.days(30),
    get burnRateThreshold() {
        return Windows.burnRate(this);
    },
    get description() {
        return Windows.description(this);
    },
};
/**
 * The golden standards from Google.
 */
Windows.standardWindows = [Windows.twoPercentLong, Windows.fivePercentLong, Windows.tenPercentLong];
/**
 * The multi-window golden standards from Google.
 */
Windows.standardMultiWindows = [
    { windows: [Windows.twoPercentShort, Windows.twoPercentLong], severity: types_1.Severity.HIGH },
    { windows: [Windows.fivePercentShort, Windows.fivePercentLong], severity: types_1.Severity.HIGH },
    { windows: [Windows.tenPercentShort, Windows.tenPercentLong], severity: types_1.Severity.LOW },
];
/**
 * The golden standards from Google, limited to one day for AWS alarms.
 */
Windows.standardAlarmWindows = [
    Windows.twoPercentLong,
    Windows.fivePercentLong,
    Windows.tenPercentMedium,
];
/**
 * The multi-window golden standards from Google, limited to one day for AWS alarms.
 */
Windows.standardAlarmMultiWindows = [
    { windows: [Windows.twoPercentShort, Windows.twoPercentLong], severity: types_1.Severity.HIGH },
    { windows: [Windows.fivePercentShort, Windows.fivePercentLong], severity: types_1.Severity.HIGH },
    { windows: [Windows.tenPercentShort, Windows.tenPercentMedium], severity: types_1.Severity.LOW },
];
/**
 * Experimental!
 * Useful for SLOs between 90 and 93%.
 */
Windows.doubleWindows = [
    Windows.twoPercentExtraLong,
    Windows.fivePercentExtraLong,
    Windows.tenPercentLong,
];
/**
 * Experimental!
 * Useful for SLOs between 90 and 93%, limited to one day for AWS alarms.
 */
Windows.doubleAlarmWindows = [
    Windows.twoPercentExtraLong,
    Windows.fivePercentExtraLong,
    Windows.tenPercentShort,
];
/**
 * Experimental!
 * Useful for SLOs like 70%, 50% etc. The smallest window we can use is one day here.
 */
Windows.lowPercentWindows = [Windows.oneDaySensitive, Windows.tenPercentLong];
/**
 * Experimental!
 * Useful for SLOs like 70%, 50% etc, limited to one day for AWS alarms. The smallest window we can use is one day here.
 */
Windows.lowPercentAlarmWindows = [Windows.oneDaySensitive];
/**
 * Calculates a target burn rate threshold for an alert config
 */
Windows.burnRate = (alertConfig) => ((alertConfig.period.toHours() * (alertConfig.percent / 100)) / alertConfig.alertWindow.toMinutes()) * 60;
/**
 * Ex: "X% of Y Day budget burned in Z hours"
 */
Windows.description = (alertConfig) => `${alertConfig.percent.toFixed(2)}% of ${alertConfig.period.toHumanString()} budget burned in ${alertConfig.alertWindow.toHumanString()}`;
/**
 * Allows defining a custom alert config if none of the predefined values work
 */
Windows.custom = (percent, period, alertWindow) => {
    return {
        percent,
        period,
        alertWindow,
        get burnRateThreshold() {
            return Windows.burnRate(this);
        },
        get description() {
            return Windows.description(this);
        },
    };
};
/**
 * Experimental!
 * Helper for selecting what windows to use for a given threshold. We can't always use the standard windows that Google defines.
 * Their windows work well for 99.x%, but not for thresholds 93% and below. This will help generate a list of windows to use
 * based on the SLO.
 */
Windows.alarmWindowSelector = (sloThreshold) => {
    // This is the lowest threshold we can use before we exceed what can be measured for 2% of 30 day budget within a 1 hour window
    const stdWindowLowerLimit = 1 - 1 / (0.02 * 30 * 24); // .930555...
    // This is the lowest threshold we can use before we exceed what can be measured for 2% of 30 day budget within a 2 hour window
    const dblWindowLowerLimit = 1 - 2 / (0.02 * 30 * 24); // .86111...
    if (sloThreshold > stdWindowLowerLimit) {
        return Windows.standardAlarmWindows;
    }
    else if (sloThreshold > dblWindowLowerLimit) {
        return Windows.doubleAlarmWindows;
    }
    else {
        return Windows.lowPercentAlarmWindows;
    }
};
/**
 * Helper for selecting what windows to use for a given threshold. We can't always use the standard windows that Google defines.
 * Their windows work well for 99.x%, but not for thresholds 93% and below. This will help generate a list of windows to use
 * based on the SLO.
 */
Windows.dashWindowSelector = (sloThreshold) => {
    // This is the lowest threshold we can use before we exceed what can be measured for 2% of 30 day budget within a 1 hour window
    const stdWindowLowerLimit = 1 - 1 / (0.02 * 30 * 24); // .930555...
    // This is the lowest threshold we can use before we exceed what can be measured for 2% of 30 day budget within a 2 hour window
    const dblWindowLowerLimit = 1 - 2 / (0.02 * 30 * 24); // .86111...
    if (sloThreshold > stdWindowLowerLimit) {
        return Windows.standardWindows;
    }
    else if (sloThreshold > dblWindowLowerLimit) {
        return Windows.doubleWindows;
    }
    else {
        return Windows.lowPercentWindows;
    }
};
