Browse Source

Threshold is not a part of analytic unit #619 (#620)

pull/1/head
rozetko 5 years ago committed by GitHub
parent
commit
0e397b350f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      server/spec/segments.jest.ts
  2. 22
      server/src/controllers/analytics_controller.ts
  3. 2
      server/src/index.ts
  4. 21
      server/src/migrations.ts
  5. 2
      server/src/models/analytic_unit_cache_model.ts
  6. 244
      server/src/models/analytic_unit_model.ts
  7. 75
      server/src/models/analytic_units/analytic_unit_model.ts
  8. 89
      server/src/models/analytic_units/db.ts
  9. 26
      server/src/models/analytic_units/index.ts
  10. 78
      server/src/models/analytic_units/pattern_analytic_unit_model.ts
  11. 95
      server/src/models/analytic_units/threshold_analytic_unit_model.ts
  12. 64
      server/src/models/analytic_units/types.ts
  13. 38
      server/src/models/analytic_units/utils.ts
  14. 2
      server/src/models/analytics_task_model.ts
  15. 2
      server/src/models/detection_model.ts
  16. 2
      server/src/models/segment_model.ts
  17. 71
      server/src/models/threshold_model.ts
  18. 8
      server/src/routes/analytic_units_router.ts
  19. 2
      server/src/routes/data_router.ts
  20. 2
      server/src/routes/detections_router.ts
  21. 2
      server/src/routes/segments_router.ts
  22. 44
      server/src/routes/threshold_router.ts
  23. 2
      server/src/services/alert_service.ts
  24. 2
      server/src/services/data_puller.ts
  25. 2
      server/src/services/notification_service.ts

2
server/spec/segments.jest.ts

@ -1,5 +1,5 @@
import { deleteNonDetectedSegments } from '../src/controllers/analytics_controller';
import * as AnalyticUnit from '../src/models/analytic_unit_model';
import * as AnalyticUnit from '../src/models/analytic_units';
import * as Segment from '../src/models/segment_model';
import * as _ from 'lodash';

22
server/src/controllers/analytics_controller.ts

@ -2,9 +2,9 @@ import { AnalyticsMessageMethod, AnalyticsMessage } from '../models/analytics_me
import { AnalyticsTask, AnalyticsTaskType, AnalyticsTaskId } from '../models/analytics_task_model';
import * as AnalyticUnitCache from '../models/analytic_unit_cache_model';
import * as Segment from '../models/segment_model';
import * as Threshold from '../models/threshold_model';
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import * as Detection from '../models/detection_model';
import { ThresholdAnalyticUnit } from '../models/analytic_units/threshold_analytic_unit_model';
import { AnalyticsService } from '../services/analytics_service';
import { AlertService } from '../services/alert_service';
import { HASTIC_API_KEY } from '../config';
@ -226,8 +226,10 @@ export async function runLearning(id: AnalyticUnit.AnalyticUnitId) {
segmentObjs = _.concat(segmentObjs, deletedSegmentsObjs);
taskPayload.segments = segmentObjs;
} else if(detector === AnalyticUnit.DetectorType.THRESHOLD) {
const threshold = await Threshold.findOne(id);
taskPayload.threshold = threshold;
taskPayload.threshold = {
value: (analyticUnit as ThresholdAnalyticUnit).value,
condition: (analyticUnit as ThresholdAnalyticUnit).condition
};
}
const range = await getQueryRange(id, detector);
@ -420,11 +422,11 @@ export async function getActiveWebhooks() {
return analyticUnits.map(analyticUnit => analyticUnit.id);
}
export async function createAnalyticUnitFromObject(obj: any): Promise<AnalyticUnit.AnalyticUnitId> {
export async function saveAnalyticUnitFromObject(obj: any): Promise<AnalyticUnit.AnalyticUnitId> {
if(obj.datasource !== undefined) {
obj.metric.datasource = obj.datasource;
}
const unit: AnalyticUnit.AnalyticUnit = AnalyticUnit.AnalyticUnit.fromObject(obj);
const unit: AnalyticUnit.AnalyticUnit = AnalyticUnit.createAnalyticUnitFromObject(obj);
const id = await AnalyticUnit.create(unit);
return id;
@ -460,14 +462,6 @@ export async function updateSegments(
return { addedIds };
}
export async function updateThreshold(
id: AnalyticUnit.AnalyticUnitId,
value: number,
condition: Threshold.Condition
) {
await Threshold.updateThreshold(id, value, condition);
}
export async function runLearningWithDetection(id: AnalyticUnit.AnalyticUnitId) {
// TODO: move setting status somehow "inside" learning
await AnalyticUnit.setStatus(id, AnalyticUnit.AnalyticUnitStatus.PENDING);

2
server/src/index.ts

@ -1,6 +1,5 @@
import { router as analyticUnitsRouter } from './routes/analytic_units_router';
import { router as segmentsRouter } from './routes/segments_router';
import { router as thresholdRouter } from './routes/threshold_router';
import { router as dataRouter } from './routes/data_router';
import { router as detectionsRouter } from './routes/detections_router';
@ -56,7 +55,6 @@ async function init() {
const rootRouter = new Router();
rootRouter.use('/analyticUnits', analyticUnitsRouter.routes(), analyticUnitsRouter.allowedMethods());
rootRouter.use('/segments', segmentsRouter.routes(), segmentsRouter.allowedMethods());
rootRouter.use('/threshold', thresholdRouter.routes(), thresholdRouter.allowedMethods());
rootRouter.use('/query', dataRouter.routes(), dataRouter.allowedMethods());
rootRouter.use('/detections', detectionsRouter.routes(), detectionsRouter.allowedMethods());

21
server/src/migrations.ts

@ -6,6 +6,7 @@ import * as _ from 'lodash';
const metaDB = makeDBQ(Collection.DB_META);
const analyticUnitsDB = makeDBQ(Collection.ANALYTIC_UNITS);
const analyticUnitCachesDB = makeDBQ(Collection.ANALYTIC_UNIT_CACHES);
const thresholdsDB = makeDBQ(Collection.THRESHOLD);
const DB_META_ID = '0';
@ -15,7 +16,8 @@ type DbMeta = {
const REVISIONS = new Map<number, Function>([
[1, convertPanelUrlToPanelId],
[2, convertUnderscoreToCamelCase]
[2, convertUnderscoreToCamelCase],
[3, integrateThresholdsIntoAnalyticUnits]
]);
export async function applyDBMigrations() {
@ -38,9 +40,7 @@ export async function applyDBMigrations() {
async function convertPanelUrlToPanelId() {
const analyticUnits = await analyticUnitsDB.findMany({ panelUrl: { $exists: true } });
console.log(`Found ${analyticUnits.length} analytic units with panelUrl field`);
if(analyticUnits.length === 0) {
console.log('Nothing to migrate');
return;
}
@ -50,7 +50,6 @@ async function convertPanelUrlToPanelId() {
.map(analyticUnit => {
const parsedPanelUrl = analyticUnit.panelUrl.match(PANEL_URL_REGEX) || analyticUnit.panelUrl.match(NEW_PANEL_URL_REGEX);
if(parsedPanelUrl === null) {
console.log(`Cannot parse url: ${analyticUnit.panelUrl}`);
return null;
}
const grafanaUrl = parsedPanelUrl[1];
@ -95,3 +94,17 @@ async function convertUnderscoreToCamelCase() {
await Promise.all(promises);
}
async function integrateThresholdsIntoAnalyticUnits() {
const thresholds = await thresholdsDB.findMany({});
const promises = thresholds.map(threshold =>
analyticUnitsDB.updateOne(threshold._id, {
value: threshold.value,
condition: threshold.condition
})
);
await Promise.all(promises);
await thresholdsDB.removeMany({});
}

2
server/src/models/analytic_unit_cache_model.ts

@ -1,4 +1,4 @@
import { AnalyticUnitId } from "./analytic_unit_model";
import { AnalyticUnitId } from './analytic_units';
import { Collection, makeDBQ } from '../services/data_service';

244
server/src/models/analytic_unit_model.ts

@ -1,244 +0,0 @@
import { Collection, makeDBQ, SortingOrder } from '../services/data_service';
import { Metric } from 'grafana-datasource-kit';
import * as _ from 'lodash';
let db = makeDBQ(Collection.ANALYTIC_UNITS);
export const ANALYTIC_UNIT_TYPES = {
pattern: [
{
name: 'General',
value: 'GENERAL'
},
{
name: 'Peak',
value: 'PEAK'
},
{
name: 'Trough',
value: 'TROUGH'
},
{
name: 'Jump',
value: 'JUMP'
},
{
name: 'Drop',
value: 'DROP'
}
],
threshold: [
{
name: 'Threshold',
value: 'THRESHOLD'
}
]
};
export enum DetectorType {
PATTERN = 'pattern',
THRESHOLD = 'threshold'
};
export type AnalyticUnitId = string;
export enum AnalyticUnitStatus {
READY = 'READY',
PENDING = 'PENDING',
LEARNING = 'LEARNING',
SUCCESS = 'SUCCESS',
FAILED = 'FAILED'
}
export type FindManyQuery = {
name?: string,
grafanaUrl?: string,
panelId?: string,
type?: string,
metric?: Metric,
alert?: boolean,
id?: AnalyticUnitId,
lastDetectionTime?: number,
status?: AnalyticUnitStatus,
error?: string,
labeledColor?: string,
deletedColor?: string,
detectorType?: DetectorType,
visible?: boolean
};
export class AnalyticUnit {
constructor(
public name: string,
public grafanaUrl: string,
public panelId: string,
public type: string,
public metric?: Metric,
public alert?: boolean,
public id?: AnalyticUnitId,
public lastDetectionTime?: number,
public status?: AnalyticUnitStatus,
public error?: string,
public labeledColor?: string,
public deletedColor?: string,
public detectorType?: DetectorType,
public visible?: boolean
) {
if(name === undefined) {
throw new Error(`Missing field "name"`);
}
if(grafanaUrl === undefined) {
throw new Error(`Missing field "grafanaUrl"`);
}
if(type === undefined) {
throw new Error(`Missing field "type"`);
}
}
public toObject() {
let metric;
if(this.metric !== undefined) {
metric = this.metric.toObject();
}
return {
_id: this.id,
name: this.name,
grafanaUrl: this.grafanaUrl,
panelId: this.panelId,
type: this.type,
metric,
alert: this.alert,
lastDetectionTime: this.lastDetectionTime,
status: this.status,
error: this.error,
labeledColor: this.labeledColor,
deletedColor: this.deletedColor,
detectorType: this.detectorType,
visible: this.visible
};
}
public toPanelObject() {
return {
id: this.id,
name: this.name,
type: this.type,
alert: this.alert,
labeledColor: this.labeledColor,
deletedColor: this.deletedColor,
detectorType: this.detectorType,
visible: this.visible
};
}
static fromObject(obj: any): AnalyticUnit {
if(obj === undefined) {
throw new Error('obj is undefined');
}
let metric: Metric;
if(obj.metric !== undefined) {
metric = Metric.fromObject(obj.metric);
}
return new AnalyticUnit(
obj.name,
obj.grafanaUrl,
obj.panelId,
obj.type,
metric,
obj.alert,
obj._id,
obj.lastDetectionTime,
obj.status as AnalyticUnitStatus,
obj.error,
obj.labeledColor,
obj.deletedColor,
obj.detectorType,
obj.visible
);
}
}
export async function findById(id: AnalyticUnitId): Promise<AnalyticUnit> {
let obj = await db.findOne(id);
if(obj === null) {
return null;
}
return AnalyticUnit.fromObject(obj);
}
export async function findMany(query: FindManyQuery): Promise<AnalyticUnit[]> {
const analyticUnits = await db.findMany(query, {
createdAt: SortingOrder.ASCENDING,
name: SortingOrder.ASCENDING
});
if(analyticUnits === null) {
return [];
}
return analyticUnits.map(AnalyticUnit.fromObject);
}
/**
* Creates and updates new unit.id
*
* @param unit to create
* @returns unit.id
*/
export async function create(unit: AnalyticUnit): Promise<AnalyticUnitId> {
let obj = unit.toObject();
return db.insertOne(obj);
}
export async function remove(id: AnalyticUnitId): Promise<void> {
// TODO: remove it`s segments
// TODO: remove it`s cache
await db.removeOne(id);
}
export async function update(id: AnalyticUnitId, unit: AnalyticUnit) {
const updateObj = {
name: unit.name,
labeledColor: unit.labeledColor,
deletedColor: unit.deletedColor,
visible: unit.visible
};
return db.updateOne(id, updateObj);
}
export async function setStatus(id: AnalyticUnitId, status: string, error?: string) {
return db.updateOne(id, { status, error });
}
export async function setDetectionTime(id: AnalyticUnitId, lastDetectionTime: number) {
return db.updateOne(id, { lastDetectionTime });
}
export async function setAlert(id: AnalyticUnitId, alert: boolean) {
return db.updateOne(id, { alert });
}
export async function setMetric(id: AnalyticUnitId, metric: Metric) {
return db.updateOne(id, { metric });
}
export function getDetectorByType(analyticUnitType: string): DetectorType {
let detector;
_.forOwn(ANALYTIC_UNIT_TYPES, (types, detectorType) => {
if(_.find(types, { value: analyticUnitType }) !== undefined) {
detector = detectorType;
}
});
if(detector === undefined) {
throw new Error(`Can't find detector for analytic unit of type "${analyticUnitType}"`);
}
return detector;
}

75
server/src/models/analytic_units/analytic_unit_model.ts

@ -0,0 +1,75 @@
import { AnalyticUnitId, AnalyticUnitStatus, DetectorType } from './types';
import { Metric } from 'grafana-datasource-kit';
export abstract class AnalyticUnit {
constructor(
public name: string,
public grafanaUrl: string,
public panelId: string,
// TODO: enum type
// TODO: type -> subType
public type: string,
public metric?: Metric,
public alert?: boolean,
public id?: AnalyticUnitId,
public lastDetectionTime?: number,
public status?: AnalyticUnitStatus,
public error?: string,
public labeledColor?: string,
public deletedColor?: string,
// TODO: detectorType -> type
public detectorType?: DetectorType,
public visible?: boolean
) {
if(name === undefined) {
throw new Error(`Missing field "name"`);
}
if(grafanaUrl === undefined) {
throw new Error(`Missing field "grafanaUrl"`);
}
if(type === undefined) {
throw new Error(`Missing field "type"`);
}
}
public toObject() {
let metric;
if(this.metric !== undefined) {
metric = this.metric.toObject();
}
return {
_id: this.id,
name: this.name,
grafanaUrl: this.grafanaUrl,
panelId: this.panelId,
type: this.type,
metric,
alert: this.alert,
lastDetectionTime: this.lastDetectionTime,
status: this.status,
error: this.error,
labeledColor: this.labeledColor,
deletedColor: this.deletedColor,
detectorType: this.detectorType,
visible: this.visible
};
}
public toPanelObject() {
return {
id: this.id,
name: this.name,
type: this.type,
alert: this.alert,
labeledColor: this.labeledColor,
deletedColor: this.deletedColor,
detectorType: this.detectorType,
visible: this.visible
};
}
}

89
server/src/models/analytic_units/db.ts

@ -0,0 +1,89 @@
import { createAnalyticUnitFromObject } from './utils';
import { AnalyticUnit } from './analytic_unit_model';
import { AnalyticUnitId, FindManyQuery } from './types';
import { Collection, makeDBQ, SortingOrder } from '../../services/data_service';
import { Metric } from 'grafana-datasource-kit';
import * as _ from 'lodash';
const db = makeDBQ(Collection.ANALYTIC_UNITS);
export async function findById(id: AnalyticUnitId): Promise<AnalyticUnit> {
let obj = await db.findOne(id);
if (obj === null) {
return null;
}
return createAnalyticUnitFromObject(obj);
}
export async function findMany(query: FindManyQuery): Promise<AnalyticUnit[]> {
const analyticUnits = await db.findMany(query, {
createdAt: SortingOrder.ASCENDING,
name: SortingOrder.ASCENDING
});
if (analyticUnits === null) {
return [];
}
return analyticUnits.map(createAnalyticUnitFromObject);
}
/**
* Creates and updates new unit.id
*
* @param unit to create
* @returns unit.id
*/
export async function create(unit: AnalyticUnit): Promise<AnalyticUnitId> {
let obj = unit.toObject();
return db.insertOne(obj);
}
export async function remove(id: AnalyticUnitId): Promise<void> {
// TODO: remove it`s segments
// TODO: remove it`s cache
await db.removeOne(id);
}
/**
* Changes values of analytic unit fields to according values of obj
*
* @param id analytic unit id
* @param obj object with keys and values which need to be updated in analytic unit
*/
export async function update(id: AnalyticUnitId, obj: any) {
const analyticUnitObj = await db.findOne(id);
if(analyticUnitObj === null) {
throw new Error(`Analytic unit ${id} doesn't exist`);
}
const analyticUnit = createAnalyticUnitFromObject(analyticUnitObj);
let updateObj: any = analyticUnit.toPanelObject();
delete updateObj.id;
updateObj = _.mapValues(updateObj, (value, key) => {
if(_.has(obj, key)) {
return obj[key];
}
return value;
});
return db.updateOne(id, updateObj);
}
export async function setStatus(id: AnalyticUnitId, status: string, error?: string) {
return db.updateOne(id, { status, error });
}
export async function setDetectionTime(id: AnalyticUnitId, lastDetectionTime: number) {
return db.updateOne(id, { lastDetectionTime });
}
export async function setAlert(id: AnalyticUnitId, alert: boolean) {
return db.updateOne(id, { alert });
}
export async function setMetric(id: AnalyticUnitId, metric: Metric) {
return db.updateOne(id, { metric });
}

26
server/src/models/analytic_units/index.ts

@ -0,0 +1,26 @@
import { createAnalyticUnitFromObject, getDetectorByType } from './utils';
import { AnalyticUnitId, AnalyticUnitStatus, DetectorType, ANALYTIC_UNIT_TYPES } from './types';
import { AnalyticUnit } from './analytic_unit_model';
import { PatternAnalyticUnit } from './pattern_analytic_unit_model';
import { ThresholdAnalyticUnit } from './threshold_analytic_unit_model';
import {
findById,
findMany,
create,
remove,
update,
setStatus,
setDetectionTime,
setAlert,
setMetric
} from './db';
export {
AnalyticUnit, PatternAnalyticUnit, ThresholdAnalyticUnit,
AnalyticUnitId, AnalyticUnitStatus, DetectorType, ANALYTIC_UNIT_TYPES,
createAnalyticUnitFromObject, getDetectorByType,
findById, findMany,
create, remove, update,
setStatus, setDetectionTime, setAlert, setMetric
};

78
server/src/models/analytic_units/pattern_analytic_unit_model.ts

@ -0,0 +1,78 @@
import { AnalyticUnit } from './analytic_unit_model';
import { AnalyticUnitId, AnalyticUnitStatus, DetectorType } from './types';
import { Metric } from 'grafana-datasource-kit';
export class PatternAnalyticUnit extends AnalyticUnit {
constructor(
name: string,
grafanaUrl: string,
panelId: string,
type: string,
metric?: Metric,
alert?: boolean,
id?: AnalyticUnitId,
lastDetectionTime?: number,
status?: AnalyticUnitStatus,
error?: string,
labeledColor?: string,
deletedColor?: string,
visible?: boolean
) {
super(
name,
grafanaUrl,
panelId,
type,
metric,
alert,
id,
lastDetectionTime,
status,
error,
labeledColor,
deletedColor,
DetectorType.PATTERN,
visible
);
}
toObject() {
const baseObject = super.toObject();
return {
...baseObject
};
}
toPanelObject() {
const baseObject = super.toPanelObject();
return {
...baseObject
};
}
static fromObject(obj: any) {
// TODO: remove duplication
let metric: Metric;
if(obj.metric !== undefined) {
metric = Metric.fromObject(obj.metric);
}
return new PatternAnalyticUnit(
obj.name,
obj.grafanaUrl,
obj.panelId,
obj.type,
metric,
obj.alert,
obj._id,
obj.lastDetectionTime,
obj.status,
obj.error,
obj.labeledColor,
obj.deletedColor,
obj.visible
);
}
}

95
server/src/models/analytic_units/threshold_analytic_unit_model.ts

@ -0,0 +1,95 @@
import { AnalyticUnit } from './analytic_unit_model';
import { AnalyticUnitId, AnalyticUnitStatus, DetectorType } from './types';
import { Metric } from 'grafana-datasource-kit';
export enum Condition {
ABOVE = '>',
ABOVE_OR_EQUAL = '>=',
EQUAL = '=',
LESS_OR_EQUAL = '<=',
LESS = '<',
NO_DATA = 'NO_DATA'
};
export class ThresholdAnalyticUnit extends AnalyticUnit {
constructor(
name: string,
grafanaUrl: string,
panelId: string,
type: string,
public value: number,
public condition: Condition,
metric?: Metric,
alert?: boolean,
id?: AnalyticUnitId,
lastDetectionTime?: number,
status?: AnalyticUnitStatus,
error?: string,
labeledColor?: string,
deletedColor?: string,
visible?: boolean
) {
super(
name,
grafanaUrl,
panelId,
type,
metric,
alert,
id,
lastDetectionTime,
status,
error,
labeledColor,
deletedColor,
DetectorType.THRESHOLD,
visible
);
}
toObject() {
const baseObject = super.toObject();
return {
...baseObject,
value: this.value,
condition: this.condition
};
}
toPanelObject() {
const baseObject = super.toPanelObject();
return {
...baseObject,
value: this.value,
condition: this.condition
};
}
static fromObject(obj: any) {
// TODO: remove duplication
let metric: Metric;
if (obj.metric !== undefined) {
metric = Metric.fromObject(obj.metric);
}
return new ThresholdAnalyticUnit(
obj.name,
obj.grafanaUrl,
obj.panelId,
obj.type,
obj.value,
obj.condition,
metric,
obj.alert,
obj._id,
obj.lastDetectionTime,
obj.status,
obj.error,
obj.labeledColor,
obj.deletedColor,
obj.visible
);
}
}

64
server/src/models/analytic_units/types.ts

@ -0,0 +1,64 @@
import { Metric } from 'grafana-datasource-kit';
export type AnalyticUnitId = string;
export enum AnalyticUnitStatus {
READY = 'READY',
PENDING = 'PENDING',
LEARNING = 'LEARNING',
SUCCESS = 'SUCCESS',
FAILED = 'FAILED'
};
export type FindManyQuery = {
name?: string,
grafanaUrl?: string,
panelId?: string,
type?: string,
metric?: Metric,
alert?: boolean,
id?: AnalyticUnitId,
lastDetectionTime?: number,
status?: AnalyticUnitStatus,
error?: string,
labeledColor?: string,
deletedColor?: string,
detectorType?: DetectorType,
visible?: boolean
};
export const ANALYTIC_UNIT_TYPES = {
pattern: [
{
name: 'General',
value: 'GENERAL'
},
{
name: 'Peak',
value: 'PEAK'
},
{
name: 'Trough',
value: 'TROUGH'
},
{
name: 'Jump',
value: 'JUMP'
},
{
name: 'Drop',
value: 'DROP'
}
],
threshold: [
{
name: 'Threshold',
value: 'THRESHOLD'
}
]
};
export enum DetectorType {
PATTERN = 'pattern',
THRESHOLD = 'threshold'
};

38
server/src/models/analytic_units/utils.ts

@ -0,0 +1,38 @@
import { DetectorType, ANALYTIC_UNIT_TYPES } from './types';
import { AnalyticUnit } from './analytic_unit_model';
import { PatternAnalyticUnit } from './pattern_analytic_unit_model';
import { ThresholdAnalyticUnit } from './threshold_analytic_unit_model';
import * as _ from 'lodash';
export function createAnalyticUnitFromObject(obj: any): AnalyticUnit {
if (obj === undefined) {
throw new Error('obj is undefined');
}
const detectorType: DetectorType = obj.detectorType;
switch (detectorType) {
case DetectorType.PATTERN:
return PatternAnalyticUnit.fromObject(obj);
case DetectorType.THRESHOLD:
return ThresholdAnalyticUnit.fromObject(obj);
default:
throw new Error(`Can't create analytic unit with type "${detectorType}"`);
}
}
export function getDetectorByType(analyticUnitType: string): DetectorType {
let detector;
_.forOwn(ANALYTIC_UNIT_TYPES, (types, detectorType) => {
if(_.find(types, { value: analyticUnitType }) !== undefined) {
detector = detectorType;
}
});
if(detector === undefined) {
throw new Error(`Can't find detector for analytic unit of type "${analyticUnitType}"`);
}
return detector;
}

2
server/src/models/analytics_task_model.ts

@ -1,4 +1,4 @@
import { AnalyticUnitId } from "./analytic_unit_model";
import { AnalyticUnitId } from './analytic_units';
import { uid } from "../utils/uid";

2
server/src/models/detection_model.ts

@ -1,4 +1,4 @@
import { AnalyticUnitId } from './analytic_unit_model';
import { AnalyticUnitId } from './analytic_units';
import { Collection, makeDBQ } from '../services/data_service';
import * as _ from 'lodash';

2
server/src/models/segment_model.ts

@ -1,4 +1,4 @@
import { AnalyticUnitId } from './analytic_unit_model';
import { AnalyticUnitId } from './analytic_units';
import { Collection, makeDBQ } from '../services/data_service';

71
server/src/models/threshold_model.ts

@ -1,71 +0,0 @@
import { AnalyticUnitId } from './analytic_unit_model';
import { Collection, makeDBQ } from '../services/data_service';
import * as _ from 'lodash';
let db = makeDBQ(Collection.THRESHOLD);
export enum Condition {
ABOVE = '>',
ABOVE_OR_EQUAL = '>=',
EQUAL = '=',
LESS_OR_EQUAL = '<=',
LESS = '<',
NO_DATA = 'NO_DATA'
};
export class Threshold {
constructor(
public id: AnalyticUnitId,
public value: number,
public condition: Condition
) {
if(id === undefined) {
throw new Error('id is undefined');
}
if(value === undefined) {
throw new Error('condition is undefined');
}
if(condition === undefined) {
throw new Error('condition is undefined');
}
}
public toObject() {
return {
_id: this.id,
value: this.value,
condition: this.condition
};
}
static fromObject(obj: any): Threshold {
if(obj === undefined) {
throw new Error('obj is undefined');
}
return new Threshold(obj._id, +obj.value, obj.condition);
}
}
export async function findOne(id: AnalyticUnitId): Promise<Threshold | null> {
const threshold = await db.findOne(id);
if(threshold === null) {
return null;
}
return Threshold.fromObject(threshold);
}
export async function updateThreshold(id: AnalyticUnitId, value: number, condition: Condition) {
let threshold = await db.findOne(id);
if(threshold === null) {
threshold = new Threshold(id, value, condition);
return db.insertOne(threshold.toObject());
}
return db.updateOne(id, { value, condition });
}
export async function removeThreshold(id: AnalyticUnitId) {
return db.removeOne(id);
}

8
server/src/routes/analytic_units_router.ts

@ -1,7 +1,7 @@
import * as AnalyticsController from '../controllers/analytics_controller';
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import { createAnalyticUnitFromObject } from '../controllers/analytics_controller';
import { saveAnalyticUnitFromObject } from '../controllers/analytics_controller';
import * as Router from 'koa-router';
import * as _ from 'lodash';
@ -50,7 +50,7 @@ function getTypes(ctx: Router.IRouterContext) {
}
async function createUnit(ctx: Router.IRouterContext) {
const id = await createAnalyticUnitFromObject(ctx.request.body);
const id = await saveAnalyticUnitFromObject(ctx.request.body);
ctx.response.body = { id };
}
@ -61,7 +61,7 @@ async function updateUnit(ctx: Router.IRouterContext) {
throw new Error('Cannot update undefined id');
}
AnalyticUnit.update(analyticUnit.id, analyticUnit);
await AnalyticUnit.update(analyticUnit.id, analyticUnit);
ctx.response.body = {
code: 200,
message: 'Success'

2
server/src/routes/data_router.ts

@ -1,4 +1,4 @@
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import { HASTIC_API_KEY } from '../config';
import { getGrafanaUrl } from '../utils/grafana';

2
server/src/routes/detections_router.ts

@ -1,5 +1,5 @@
import * as AnalyticsController from '../controllers/analytics_controller';
import { AnalyticUnitId } from '../models/analytic_unit_model';
import { AnalyticUnitId } from '../models/analytic_units';
import { DetectionSpan } from '../models/detection_model';
import * as Router from 'koa-router';

2
server/src/routes/segments_router.ts

@ -1,6 +1,6 @@
import * as AnalyticsController from '../controllers/analytics_controller';
import { AnalyticUnitId } from '../models/analytic_unit_model';
import { AnalyticUnitId } from '../models/analytic_units';
import * as Segment from '../models/segment_model';
import * as Router from 'koa-router';

44
server/src/routes/threshold_router.ts

@ -1,44 +0,0 @@
import * as AnalyticsController from '../controllers/analytics_controller';
import { AnalyticUnitId } from '../models/analytic_unit_model';
import * as Threshold from '../models/threshold_model';
import * as Router from 'koa-router';
import * as _ from 'lodash';
async function getThresholds(ctx: Router.IRouterContext) {
const ids: AnalyticUnitId[] = ctx.request.query.ids.split(',');
if(ids === undefined) {
throw new Error('analyticUnitIds (ids) are missing');
}
const thresholds = await Promise.all(
_.map(ids, id => Threshold.findOne(id))
);
ctx.response.body = { thresholds };
}
async function updateThreshold(ctx: Router.IRouterContext) {
const {
id, value, condition
} = ctx.request.body as {
id: AnalyticUnitId, value: number, condition: Threshold.Condition
};
await AnalyticsController.updateThreshold(id, value, condition);
ctx.response.body = {
code: 200,
message: 'Success'
};
}
export const router = new Router();
router.get('/', getThresholds);
router.patch('/', updateThreshold);

2
server/src/services/alert_service.ts

@ -1,7 +1,7 @@
import { sendAnalyticWebhook, sendInfoWebhook, InfoAlert, AnalyticAlert, WebhookType } from './notification_service';
import * as _ from 'lodash';
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import { Segment } from '../models/segment_model';
import { availableReporter } from '../utils/reporter';

2
server/src/services/data_puller.ts

@ -1,5 +1,5 @@
import { AnalyticsTask, AnalyticsTaskType } from '../models/analytics_task_model';
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import * as AnalyticUnitCache from '../models/analytic_unit_cache_model';
import { AnalyticsService } from './analytics_service';
import { HASTIC_API_KEY } from '../config';

2
server/src/services/notification_service.ts

@ -1,4 +1,4 @@
import * as AnalyticUnit from '../models/analytic_unit_model';
import * as AnalyticUnit from '../models/analytic_units';
import { HASTIC_WEBHOOK_URL, HASTIC_WEBHOOK_TYPE, HASTIC_WEBHOOK_SECRET, HASTIC_INSTANCE_NAME } from '../config';
import axios from 'axios';

Loading…
Cancel
Save