Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anomaly detector detection re running in inspect mode #757 #759

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 70 additions & 63 deletions server/spec/analytic_controller.jest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jest.mock('grafana-datasource-kit', () => (
}
));

import { saveAnalyticUnitFromObject, runDetect, onDetect } from '../src/controllers/analytics_controller';
import { saveAnalyticUnitFromObject, runDetect, onDetect, getHSR } from '../src/controllers/analytics_controller';
import * as AnalyticUnit from '../src/models/analytic_units';
import * as AnalyticUnitCache from '../src/models/analytic_unit_cache_model';
import * as Segment from '../src/models/segment_model';
Expand All @@ -16,71 +16,69 @@ import { buildSegments, clearSegmentsDB, convertSegmentsToTimeRanges } from './u

import { HASTIC_API_KEY } from '../src/config';


describe('Check detection range', function() {
const analyticUnitObj = {
_id: 'test',
name: "test",
grafanaUrl: "http://127.0.0.1:3000",
panelId: "ZLc0KfNZk/2",
type: "GENERAL",
metric: {
datasource: {
url: "api/datasources/proxy/5/query",
method: "GET",
data: null,
params: {
db:"dbname",
q: "SELECT mean(\"value\") FROM \"autogen\".\"tcpconns_value\" WHERE time >= now() - 6h GROUP BY time(20s) fill(null)",
epoch: "ms"
},
type: "influxdb"
const analyticUnitObj = {
name: "test",
grafanaUrl: "http://127.0.0.1:3000",
panelId: "ZLc0KfNZk/2",
type: "GENERAL",
metric: {
datasource: {
url: "api/datasources/proxy/5/query",
method: "GET",
data: null,
params: {
db:"dbname",
q: "SELECT mean(\"value\") FROM \"autogen\".\"tcpconns_value\" WHERE time >= now() - 6h GROUP BY time(20s) fill(null)",
epoch: "ms"
},
targets: [
{
groupBy: [
{
params: ["$__interval"],
type: "time"
},
{
params: ["null"],
type: "fill"
}
],
measurement: "tcpconns_value",
orderByTime: "ASC",
policy: "autogen",
refId: "A",
resultFormat: "time_series",
select: [[{"params":["value"],"type":"field"},{"params":[],"type":"mean"}]],"tags":[]
}
]
type: "influxdb"
},
alert: false,
labeledColor: "#FF99FF",
deletedColor: "#00f0ff",
detectorType: "pattern",
visible: true,
collapsed: false,
createdAt: {"$$date":1564476040880},
updatedAt: {"$$date":1564476040880}
}

const WINDOW_SIZE = 10;
const TIME_STEP = 1000;

async function addTestUnitToDB(): Promise<string> {
const analyticUnitId = await saveAnalyticUnitFromObject(analyticUnitObj);
await AnalyticUnit.update(analyticUnitId, {lastDetectionTime: 1000});
await AnalyticUnitCache.create(analyticUnitId);
await AnalyticUnitCache.setData(analyticUnitId, {
windowSize: WINDOW_SIZE,
timeStep: TIME_STEP
});
return analyticUnitId;
};
targets: [
{
groupBy: [
{
params: ["$__interval"],
type: "time"
},
{
params: ["null"],
type: "fill"
}
],
measurement: "tcpconns_value",
orderByTime: "ASC",
policy: "autogen",
refId: "A",
resultFormat: "time_series",
select: [[{"params":["value"],"type":"field"},{"params":[],"type":"mean"}]],"tags":[]
}
]
},
alert: false,
labeledColor: "#FF99FF",
deletedColor: "#00f0ff",
detectorType: "pattern",
visible: true,
collapsed: false,
createdAt: {"$$date":1564476040880},
updatedAt: {"$$date":1564476040880}
}

const WINDOW_SIZE = 10;
const TIME_STEP = 1000;

async function addTestUnitToDB(): Promise<string> {
const analyticUnitId = await saveAnalyticUnitFromObject(analyticUnitObj);
await AnalyticUnit.update(analyticUnitId, {lastDetectionTime: 1000});
amper43 marked this conversation as resolved.
Show resolved Hide resolved
await AnalyticUnitCache.create(analyticUnitId);
await AnalyticUnitCache.setData(analyticUnitId, {
windowSize: WINDOW_SIZE,
timeStep: TIME_STEP
});
return analyticUnitId;
};

describe('Check detection range', function() {
it('check range >= 2 * window size * timeStep', async () => {
const from = 1500000000000;
const to = 1500000000001;
Expand Down Expand Up @@ -136,3 +134,12 @@ describe('onDetect', () => {
expect(detectedRanges).toEqual([[7, 8]]);
});
});

describe('getHSR', function() {
it('should return nothink if unit state is LEARNING', async () => {
amper43 marked this conversation as resolved.
Show resolved Hide resolved
const analyticUnitId = await addTestUnitToDB()
const unit = await AnalyticUnit.findById(analyticUnitId);
const result = await getHSR(unit, 9000, 100000);
expect(result.hsr).toBe(undefined);
rozetko marked this conversation as resolved.
Show resolved Hide resolved
});
});
rozetko marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 6 additions & 2 deletions server/src/controllers/analytics_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ export async function getHSR(
hsr: TableTimeSeries,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make a class for this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according TODOs we should make it in data-kit
related issue CorpGlory/grafana-datasource-kit#89

lowerBound?: TableTimeSeries,
upperBound?: TableTimeSeries
}> {
} | undefined> {
try {
const grafanaUrl = getGrafanaUrl(analyticUnit.grafanaUrl);
const data = await queryByMetric(analyticUnit.metric, grafanaUrl, from, to, HASTIC_API_KEY);
Expand All @@ -657,7 +657,11 @@ export async function getHSR(
}

let cache = await AnalyticUnitCache.findById(analyticUnit.id);
if(cache === null || cache.isCacheOutdated(analyticUnit)) {

if(cache === null || cache.data === null) {
rozetko marked this conversation as resolved.
Show resolved Hide resolved
if(analyticUnit.status === AnalyticUnit.AnalyticUnitStatus.LEARNING) {
return; // because we wait end of learning
}
await runLearning(analyticUnit.id, from, to);
cache = await AnalyticUnitCache.findById(analyticUnit.id);
}
Expand Down
6 changes: 0 additions & 6 deletions server/src/models/analytic_unit_cache_model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,6 @@ export class AnalyticUnitCache {
public getTimeStep(): number {
return this.data.timeStep;
}

public isCacheOutdated(analyticUnit: AnalyticUnit) {
return !_.every(
_.keys(analyticUnit.analyticProps).map(k => _.isEqual(analyticUnit.analyticProps[k], this.data[k]))
);
}
}

export async function findById(id: AnalyticUnitId): Promise<AnalyticUnitCache> {
Expand Down