File

src/alert/alert.service.ts

Index

Properties
Methods

Constructor

constructor(prismaService: PrismaService)
Parameters :
Name Type Optional
prismaService PrismaService No

Methods

checkValue
checkValue(value, thresholds)
Parameters :
Name Optional
value No
thresholds No
Returns : { valid: boolean; minBreach: boolean; maxBreach: boolean; }
Async create
create(createAlertInput: CreateAlertDto, userId: string)

Creates a new alert

Parameters :
Name Type Optional Description
createAlertInput CreateAlertDto No
  • The data object containing information to create the alert.
userId string No
Returns : Promise<Alert>

A Promise that resolves to the created alert object.

Async findAllByUserId
findAllByUserId(userId: string, queryOptions: literal type)

Retrieves alerts for a specific user with pagination.

Parameters :
Name Type Optional Default value Description
userId string No
  • The ID of the user to retrieve alerts for.
queryOptions literal type No {}
Returns : Promise<Alert[]>

A Promise that resolves to an array of alerts for the specified user.

Async findMany
findMany(query: Prisma.AlertWhereInput)

Finds and returns alerts based on query.

Parameters :
Name Type Optional Description
query Prisma.AlertWhereInput No
  • query
Returns : unknown

A Promise that resolves to an array of alerts associated with the project.

Async getAlert
getAlert(alertId: number)

Finds and returns the alert with the specified ID.

Parameters :
Name Type Optional Description
alertId number No
  • The ID of the alert to find.
Returns : Promise<Alert>

A Promise that resolves to the found alert object.

Async getAlertsByProjectID
getAlertsByProjectID(projectId: number)

Finds and returns alerts associated with the specified project ID.

Parameters :
Name Type Optional Description
projectId number No
  • The ID of the project for which to find alerts.
Returns : Promise<Alert[]>

A Promise that resolves to an array of alerts associated with the project.

Async getAlertTargets
getAlertTargets(alert: Alert)

Finds and returns alert targets.

Parameters :
Name Type Optional Description
alert Alert No
  • alert
Returns : Promise<literal type>

A Promise that resolves to an object.

Async getAlertTriggers
getAlertTriggers(query: literal type)

Finds and returns alert trigger events.

Parameters :
Name Type Optional Description
query literal type No
  • ALertTriggers query
Returns : Promise<AlertTrigger[]>

A Promise that resolves to an array of alerts.

getDiff
getDiff(alertParams: AlertParams, alertTrigger: AlertTrigger, pcc: boolean)
Parameters :
Name Type Optional Default value
alertParams AlertParams No
alertTrigger AlertTrigger No
pcc boolean No false
Returns : number
Async getDueAlerts
getDueAlerts()

Finds and returns alerts which are due to be checked. Returns alerts that have nextCheckAt less than current time.

Returns : Promise<Alert[]>

A Promise that resolves to an array of alerts.

getThresholds
getThresholds(alertParams: AlertParams, alertType: AlertType)

Returns thresholds for the given AlertParams

Parameters :
Name Type Optional Description
alertParams AlertParams No

The given AlertParams

alertType AlertType No
Returns : any

A Promise that resolves to thresholds

Async update
update(id: number, updateAlertInput: UpdateAlertDto)

Updates the alert with the specified changes.

Parameters :
Name Type Optional Description
id number No
  • The ID of the alert to update.
updateAlertInput UpdateAlertDto No
  • The data to be updated.
Returns : Promise<Alert>

A Promise that resolves to the updated alert object.

Async updateAlertCheckTimes
updateAlertCheckTimes(alert: Alert, checkTime: Date)

Updates the alert check times.

Parameters :
Name Type Optional Description
alert Alert No
  • alert
checkTime Date No
  • The time when the check was performed.
Returns : Promise<Alert>

A Promise that resolves to the updated alert object.

Async updateAlertStatus
updateAlertStatus(alertId: number, status: AlertStatus)

Updates the status of an alert with the specified ID.

Parameters :
Name Type Optional Description
alertId number No
  • The ID of the alert to update.
status AlertStatus No
  • The new status to assign to the alert.
Returns : Promise<Alert>

A Promise that resolves to the updated alert object.

validateAlertThresholds
validateAlertThresholds(alert: Alert, targets: any[])

Validates alert thresholds.

Parameters :
Name Type Optional Description
alert Alert No
  • alert
targets any[] No
  • target array
Returns : literal type[]

A Promise that resolves to an array.

Properties

Public alertCategoryToFieldMap
Type : object
Default value : { [AlertCategory.METRIC]: "value", DEFAULT: "value", }
Public alertCategoryToTableMap
Type : object
Default value : { [AlertCategory.METRIC]: "metricsData", }
import { Injectable } from "@nestjs/common";
import { PrismaService } from "../common/prisma/prisma.service";
import { CreateAlertDto } from "./dto/create-alert.dto";
import {
  Alert,
  AlertCategory,
  AlertCheckType,
  AlertStatus,
  AlertType,
} from "./entities/alert.entity";
import { UpdateAlertDto } from "./dto/update-alert.dto";
import { AlertParams } from "./types/alert-params.type";
import { Thresholds } from "./types/thresholds.type";
import { AlertTrigger } from "./entities/alert-trigger.entity";
import { Prisma } from "@prisma/client";

@Injectable()
export class AlertService {
  public alertCategoryToFieldMap = {
    [AlertCategory.METRIC]: "value",
    DEFAULT: "value",
  };

  public alertCategoryToTableMap = {
    [AlertCategory.METRIC]: "metricsData",
  };

  constructor(private readonly prismaService: PrismaService) {}

  /**
   * Returns thresholds for the given AlertParams
   * @param {AlertParams} alertParams The given AlertParams
   * @returns {Thresholds} A Promise that resolves to thresholds
   * @throws {Error} If there are issues during the threshold calculation
   */
  getThresholds(alertParams: AlertParams, alertType: AlertType) {
    let min = null;
    let max = null;

    if ([AlertType.MIN, AlertType.MIN_MAX].includes(alertType)) {
      min = alertParams.min;
    }
    if ([AlertType.MAX, AlertType.MIN_MAX].includes(alertType)) {
      max = alertParams.max;
    }

    if ([AlertType.PCC_MIN, AlertType.PCC].includes(alertType)) {
      min = (1 - alertParams.pcc / 100) * alertParams.initValue;
    }
    if ([AlertType.PCC_MAX, AlertType.PCC].includes(alertType)) {
      max = (1 + alertParams.pcc / 100) * alertParams.initValue;
    }

    return new Thresholds({ min: min, max: max });
  }

  getDiff(
    alertParams: AlertParams,
    alertTrigger: AlertTrigger,
    pcc: boolean = false,
  ) {
    let diffVal = alertTrigger.targetValue - alertParams.initValue;
    if (pcc) {
      diffVal = (diffVal / alertParams.initValue) * 100;
    }
    return diffVal;
  }

  /**
   * Creates a new alert
   * @param {CreateAlertDto} createAlertInput - The data object containing information to create the alert.
   * @returns {Promise<Alert>} A Promise that resolves to the created alert object.
   * @throws {Error} If there are issues during the alert creation process.
   */
  async create(
    createAlertInput: CreateAlertDto,
    userId: string,
  ): Promise<Alert> {
    const alertData = {
      name: createAlertInput.name,
      projectId: createAlertInput.projectId,
      userId: userId,
      category: createAlertInput.category,
      status: AlertStatus.ACTIVE,
      type: createAlertInput.type,
      checkType: AlertCheckType.VALUE,
      interval: createAlertInput.interval,
      targetTable: this.alertCategoryToTableMap[createAlertInput.category],
      targetField: this.alertCategoryToFieldMap.DEFAULT,
      targetFilter: JSON.stringify(createAlertInput.targetFilter),
      thresholds: JSON.stringify(
        this.getThresholds(createAlertInput.alertParams, createAlertInput.type),
      ),
      alertParams: JSON.stringify(createAlertInput.alertParams),
    };

    if (alertData.category == AlertCategory.METRIC) {
      alertData.checkType = AlertCheckType.WINDOW;
      alertData.targetField = this.alertCategoryToFieldMap[alertData.category];
    }

    const alert = await this.prismaService.alert.create({
      data: alertData,
    });
    return new Alert(alert);
  }

  /**
   * Updates the alert with the specified changes.
   * @param {number} id - The ID of the alert to update.
   * @param {UpdateAlertDto} updateAlertInput - The data to be updated.
   * @returns {Promise<Alert>} A Promise that resolves to the updated alert object.
   * @throws {Error} If there are issues updating the alert status.
   */
  async update(id: number, updateAlertInput: UpdateAlertDto): Promise<Alert> {
    const alert = await this.getAlert(id);
    const alertData = {
      name: updateAlertInput.name,
      interval: updateAlertInput.interval,
      status: updateAlertInput.status,
      type: updateAlertInput.type,
    };

    if (updateAlertInput.alertParams) {
      alertData["alertParams"] = JSON.stringify(updateAlertInput.alertParams);
      alertData["thresholds"] = JSON.stringify(
        this.getThresholds(updateAlertInput.alertParams, AlertType[alert.type]),
      );
    }

    const updatedAlert: Alert = new Alert(
      await this.prismaService.alert.update({
        where: {
          id: id,
        },
        data: alertData,
      }),
    );
    return updatedAlert;
  }

  /**
   * Updates the status of an alert with the specified ID.
   * @param {number} alertId - The ID of the alert to update.
   * @param {AlertStatus} status - The new status to assign to the alert.
   * @returns {Promise<Alert>} A Promise that resolves to the updated alert object.
   * @throws {Error} If there are issues updating the alert status.
   */
  async updateAlertStatus(
    alertId: number,
    status: AlertStatus,
  ): Promise<Alert> {
    const alert = await this.prismaService.alert.update({
      where: {
        id: alertId,
      },
      data: {
        status: status,
      },
    });
    return new Alert(alert);
  }

  /**
   * Updates the alert check times.
   * @param {Alert} alert - alert
   * @param {Date} checkTime - The time when the check was performed.
   * @returns {Promise<Alert>} A Promise that resolves to the updated alert object.
   * @throws {Error} If there are issues updating the alert status.
   */
  async updateAlertCheckTimes(alert: Alert, checkTime: Date): Promise<Alert> {
    const lastCheckAt = new Date(checkTime.getTime());
    const nextCheckAt = new Date(checkTime.getTime() + alert.interval * 1000);
    const updatedAlert = await this.prismaService.alert.update({
      where: {
        id: alert.id,
      },
      data: {
        lastCheckAt: lastCheckAt,
        nextCheckAt: nextCheckAt,
      },
    });
    return new Alert(updatedAlert);
  }

  /**
   * Finds and returns the alert with the specified ID.
   * @param {number} alertId - The ID of the alert to find.
   * @returns {Promise<Alert>} A Promise that resolves to the found alert object.
   * @throws {Error} If there are issues finding the alert.
   */
  async getAlert(alertId: number): Promise<Alert> {
    const alert = await this.prismaService.alert.findFirst({
      where: { id: alertId },
    });
    return new Alert(alert);
  }

  /**
   * Finds and returns alerts associated with the specified project ID.
   * @param {number} projectId - The ID of the project for which to find alerts.
   * @returns {Promise<Alert[]>} A Promise that resolves to an array of alerts associated with the project.
   * @throws {Error} If there are issues finding alerts for the project.
   */
  async getAlertsByProjectID(projectId: number): Promise<Alert[]> {
    const alerts = await this.prismaService.alert.findMany({
      where: {
        projectId: projectId,
        NOT: { status: { equals: AlertStatus.DELETED } },
      },
    });
    return alerts.map((alert) => new Alert(alert));
  }

  /**
   * Finds and returns alerts based on query.
   * @param {Prisma.AlertWhereInput} query - query
   * @returns {Promise<Alert[]>} A Promise that resolves to an array of alerts associated with the project.
   * @throws {Error} If there are issues finding alerts.
   */
  async findMany(query: Prisma.AlertWhereInput) {
    const alerts = await this.prismaService.alert.findMany({ where: query });
    return alerts.map((alert) => new Alert(alert));
  }

  /**
   * Finds and returns alerts which are due to be checked.
   * Returns alerts that have nextCheckAt less than current time.
   * @returns {Promise<Alert[]>} A Promise that resolves to an array of alerts.
   * @throws {Error} If there are issues finding alerts.
   */
  async getDueAlerts(): Promise<Alert[]> {
    const alerts = await this.prismaService.alert.findMany({
      where: {
        nextCheckAt: { lte: new Date() },
        NOT: {
          OR: [{ status: { equals: AlertStatus.INPROGRESS } }],
        },
      },
    });
    return alerts.map((alert) => new Alert(alert));
  }

  /**
   * Finds and returns alert trigger events.
   * @param {} query - ALertTriggers query
   * @returns {Promise<AlertTrigger[]>} A Promise that resolves to an array of alerts.
   * @throws {Error} If there are issues finding alerts.
   */
  async getAlertTriggers(query: {
    alertId?: number[];
    targetTable?: string[];
    targetField?: string[];
    targetId?: number[];
    startTime?: Date;
    endTime?: Date;
  }): Promise<AlertTrigger[]> {
    const queryOptions = {
      alertId: { in: query.alertId },
      targetTable: { in: query.targetTable },
      targetField: { in: query.targetField },
      targetId: { in: query.targetId },
    };

    const events = await this.prismaService.alertTrigger.findMany({
      where: {
        timestamp: { gte: query.startTime, lte: query.endTime },
        ...queryOptions,
      },
    });
    return events.map((event) => new AlertTrigger(event));
  }

  /**
   * Finds and returns alert targets.
   * @param {Alert} alert - alert
   * @returns {Promise<{targets: any[], targetTime: string, targetFilter: any}>} A Promise that resolves to an object.
   * @throws {Error} If there are issues finding target.
   */
  async getAlertTargets(
    alert: Alert,
  ): Promise<{ targets: any[]; targetTime: string; targetFilter: any }> {
    const checkTime = new Date();

    const targetFilter = JSON.parse(alert.targetFilter);
    const targetTable = alert.targetTable;

    if (alert.checkType == AlertCheckType.WINDOW) {
      targetFilter["createdAt"] = {
        gt: alert.lastCheckAt,
        lte: checkTime,
      };
    }

    const targets = await this.prismaService[targetTable].findMany({
      where: { ...targetFilter },
    });

    return {
      targets: targets,
      targetTime: checkTime.toString(),
      targetFilter: targetFilter,
    };
  }

  checkValue(value, thresholds) {
    let valid = true;
    let minBreach = false;
    let maxBreach = false;

    if (thresholds["min"]) {
      if (thresholds["min"] > value) {
        valid = false;
        minBreach = true;
      }
    }

    if (thresholds["max"]) {
      if (value > thresholds["max"]) {
        valid = false;
        maxBreach = true;
      }
    }

    return { valid, minBreach, maxBreach };
  }

  /**
   * Validates alert thresholds.
   * @param {Alert} alert - alert
   * @param {any[]} targets - target array
   * @returns {Promise<{valid: boolean, target: any}[]>} A Promise that resolves to an array.
   * @throws {Error} If there are issues finding target.
   */
  validateAlertThresholds(
    alert: Alert,
    targets: any[],
  ): { valid: boolean; target: any }[] {
    const thresholds = JSON.parse(alert.thresholds);
    return targets.map((target) => {
      const result = this.checkValue(target[alert.targetField], thresholds);
      return {
        ...result,
        target: target,
      };
    });
  }

  /**
   * Retrieves alerts for a specific user with pagination.
   *
   * @param {string} userId - The ID of the user to retrieve alerts for.
   * @param {number} page - The page number for pagination (default is 1).
   * @param {number} limit - The number of alerts per page (default is 10).
   * @returns {Promise<Alert[]>} A Promise that resolves to an array of alerts for the specified user.
   * @throws {Error} If there are issues during the alert search process.
   */
  async findAllByUserId(
    userId: string,
    queryOptions: {
      pageSize?: number;
      pageOffset?: number;
      startId?: number;
    } = {},
  ): Promise<Alert[]> {
    const pageSize = +queryOptions.pageSize || 30;
    const pageOffset = +queryOptions.pageOffset || 0;
    const findArgs = {
      where: {
        userId: userId,
        NOT: {
          OR: [{ status: { equals: AlertStatus.DELETED } }],
        },
      },
      take: Math.min(100, pageSize), // Limit the number of messages returned
      skip: pageOffset * pageSize, // Offset based on the page number and page size
    };
    const alerts = await this.prismaService.alert.findMany(findArgs);
    return alerts.map((alert) => new Alert(alert));
  }
}

results matching ""

    No results matching ""