Skip to content

Commit

Permalink
Merge pull request #311 from amosproj/302-alerting-endpoint-has-to-se…
Browse files Browse the repository at this point in the history
…t-filtering-dates-to-start-of-dayend-of-day
  • Loading branch information
flo0852 authored Jan 30, 2025
2 parents bd8e997 + e5edbaf commit 814e39e
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 17 deletions.
81 changes: 81 additions & 0 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Backend Readme
## Setup
- `npm ci`: dependency install
- copy `.env.example` file in backend and rename to `.env` (adjust database properties according to database setup if necessary)
- `npm run be`: run backend individually
- `nx run metadata-analyzer-backend:test`: Run backend tests

## Backend Structure
- `src/app`: contains the main application
- Utility functionality is located in the `src/app/utils` folder
- migrations are located in the `migrations` folder, DO NOT Touch them and do not create them manually
- `db-config.service.ts`: contains the configuration for the database connection
- The other directories contain the different modules of the application

### Modules
- Controller: Defines the endpoints
- Service: Contains the logic
- Module: Contains the configuration for the module (defines imports and exports)
- Dto directory: Contains the data transfer objects
- Entity directory: Contains the entities for the database

#### BackupData
- Stores the backup data we need to display in the frontend
- Multiple Endpoints for delivering Backups to frontend with filter, sorting and pagination functionality
- Endpoints for preparing chart data for the frontend

#### Data Stores
- Stores the data stores we need to display in the frontend
- Stores also the estimated storage overflow time for each data store

#### Tasks
- Stores the tasks according to the backup data
- We need this for filtering and sorting in the frontend

#### Information
- Delivers general facts about the number of backups

#### Alerting
- Stores the alert types we have (e.g. Size Alerts)
- All Alert Types have to be named as followed [...]_ALERT and the according Table has to be named [...]Alert (camelCase)
- Each Alert Type has its own repository
- Each Alert Type has a severity (INFO, WARNING, CRITICAL) and can be deactivated by user and master (via endpoint)
- All alert entities extend the Alert Entity, which contains the common fields for all alerts
- The alerts are being created via api calls from the analyzer

#### Analyzer Service
- Provides endpoint for refresh, which triggers the analysis of the analyzer via api calls
- Waits until the calls return -> analysis is finished -> frontend request new data via api calls
- Doesn't trigger Overflow Time Calculation, because it lasts too long

#### Backup Alerts Overview
- Delivers the status of the backups (OK, INFO, WARNING, CRITICAL)

#### Utils: Mail
- Handles the mailing functionality
- Contains the mail templates
- Handles the dynamic Mail Receiver Functionality

#### Utils: Pagination
- Handles the pagination functionality
- Contains generic pagination functionality, which can be used for every repository
- Contains specific pagination functionality for alerting (Because of complexity):
- Pagination for all alert types and therefore all alert repositories
- Offers filter and order functionality for alerting

## Backend Development
### Generating database migrations:
- the entity files need to be annotated with `@Entity(<table-name>)`
- append the entity file to the `entities` array in `db-config.service.ts`
- run the following command to generate a migration file:
- `nx run metadata-analyzer-backend:migrations:generate --name <migration-name>`
- append the generated file to the `migrations` array in `db-config.service.ts`
- DO NOT Delete any migration files, which have been already applied to the database -> just create a new migration, which reverts the changes of the migration you want to delete

### Mailing
Fill the `.env` file with the mailing information
Hint: For gmail you have to generate an app password, which you have to use as password in the `.env` file
For changes in templates being used, you have to restart the backend



88 changes: 79 additions & 9 deletions apps/backend/src/app/alerting/alerting.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ import { CreateMissingBackupAlertDto } from './dto/alerts/createMissingBackupAle
import { AdditionalBackupAlertEntity } from './entity/alerts/additionalBackupAlert.entity';
import { CreateAdditionalBackupAlertDto } from './dto/alerts/createAdditionalBackupAlert.dto';
import {
ADDITIONAL_BACKUP_ALERT,
CREATION_DATE_ALERT,
MISSING_BACKUP_ALERT,
SIZE_ALERT,
STORAGE_FILL_ALERT,
MISSING_BACKUP_ALERT,
ADDITIONAL_BACKUP_ALERT,
} from '../utils/constants';
import { SeverityType } from './dto/severityType';
import { PaginationDto } from '../utils/pagination/PaginationDto';
Expand Down Expand Up @@ -160,13 +160,34 @@ export class AlertingService extends PaginationService implements OnModuleInit {
};
for (const repo of this.alertRepositories) {
const infoAlerts = await repo.count({
where: { ...filter, alertType: { severity: SeverityType.INFO } },
where: {
...filter,
alertType: {
severity: SeverityType.INFO,
user_active: true,
master_active: true,
},
},
});
const warningAlerts = await repo.count({
where: { ...filter, alertType: { severity: SeverityType.WARNING } },
where: {
...filter,
alertType: {
severity: SeverityType.WARNING,
user_active: true,
master_active: true,
},
},
});
const criticalAlerts = await repo.count({
where: { ...filter, alertType: { severity: SeverityType.CRITICAL } },
where: {
...filter,
alertType: {
severity: SeverityType.CRITICAL,
user_active: true,
master_active: true,
},
},
});
alertStatisticsDto.infoAlerts += infoAlerts;
alertStatisticsDto.warningAlerts += warningAlerts;
Expand Down Expand Up @@ -326,6 +347,13 @@ export class AlertingService extends PaginationService implements OnModuleInit {
alertOrderOptionsDto: AlertOrderOptionsDto,
alertFilterDto: AlertFilterDto
): Promise<PaginationDto<Alert>> {
const { from, to } = this.transformDates(
alertFilterDto.fromDate,
alertFilterDto.toDate
);
alertFilterDto.fromDate = from?.toISOString();
alertFilterDto.toDate = to?.toISOString();

return this.paginateAlerts<Alert>(
this.alertRepositories,
this.alertTypeRepository,
Expand Down Expand Up @@ -519,7 +547,9 @@ export class AlertingService extends PaginationService implements OnModuleInit {
name: MISSING_BACKUP_ALERT,
});
if (!alertType) {
throw new NotFoundException(`Alert type ${MISSING_BACKUP_ALERT} not found`);
throw new NotFoundException(
`Alert type ${MISSING_BACKUP_ALERT} not found`
);
}
alert.alertType = alertType;

Expand All @@ -534,9 +564,11 @@ export class AlertingService extends PaginationService implements OnModuleInit {
createAdditionalBackupAlertDto: CreateAdditionalBackupAlertDto
) {
// Check if alert already exists
const existingAlertEntity = await this.additionalBackupRepository.findOneBy({
backup: { id: createAdditionalBackupAlertDto.backupId },
});
const existingAlertEntity = await this.additionalBackupRepository.findOneBy(
{
backup: { id: createAdditionalBackupAlertDto.backupId },
}
);

if (existingAlertEntity) {
console.log('Alert already exists -> ignoring it');
Expand Down Expand Up @@ -701,4 +733,42 @@ export class AlertingService extends PaginationService implements OnModuleInit {

return where;
}

/**
* Transform dates to Date objects.
* Sets fromDate to first millisecond of the day and toDate to last millisecond of the day.
* @param fromDate
* @param toDate
*/
private transformDates(
fromDate?: string,
toDate?: string
): { from: Date | null; to: Date | null } {
let from: Date | null = null;
let to: Date | null = null;
if (fromDate) {
from = new Date(fromDate);
if (Number.isNaN(from.getTime())) {
throw new BadRequestException('parameter fromDate is not a valid date');
}
//Set time to first millisecond of the day
from.setHours(0);
from.setMinutes(0);
from.setSeconds(0);
from.setMilliseconds(0);
}
if (toDate) {
to = new Date(toDate);
if (Number.isNaN(to.getTime())) {
throw new BadRequestException('parameter toDate is not a valid date');
}
//Set time to last millisecond of the day
to.setHours(0);
to.setMinutes(0);
to.setSeconds(0);
to.setDate(to.getDate() + 1);
to.setMilliseconds(-1);
}
return { from, to };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class AlertComponent implements OnInit, OnDestroy {
});

this.alerts$.pipe(takeUntil(this.destroy$)).subscribe((alerts) => {
this.status = this.getStatus();
this.setStatus();
});
}

Expand Down Expand Up @@ -133,18 +133,16 @@ export class AlertComponent implements OnInit, OnDestroy {
*
* @returns Status of alerts as string
*/
getStatus(): 'OK' | 'Warning' | 'Critical' {
let status: 'OK' | 'Warning' | 'Critical' = 'OK';

setStatus() {
this.alertCounts$.subscribe((counts) => {
if (counts.criticalAlerts > 0) {
status = 'Critical';
this.status = 'Critical';
} else if (counts.warningAlerts > 0) {
status = 'Warning';
this.status = 'Warning';
} else {
this.status = 'OK';
}
});

return status;
}

getAlertClass = (alert: Alert): string =>
Expand Down

0 comments on commit 814e39e

Please sign in to comment.