apm-optima 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/http.adapter.d.ts +12 -0
- package/dist/adapters/http.adapter.js +2 -0
- package/dist/adapters/websocket.adapter.d.ts +5 -0
- package/dist/adapters/websocket.adapter.js +2 -0
- package/dist/config/config.manager.d.ts +12 -0
- package/dist/config/config.manager.js +111 -0
- package/dist/config/config.types.d.ts +19 -0
- package/dist/config/config.types.js +2 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +18 -0
- package/dist/core/delivery/index.d.ts +2 -0
- package/dist/core/delivery/index.js +18 -0
- package/dist/core/delivery/metrics.publisher.d.ts +18 -0
- package/dist/core/delivery/metrics.publisher.js +36 -0
- package/dist/core/delivery/websocket.events.d.ts +12 -0
- package/dist/core/delivery/websocket.events.js +16 -0
- package/dist/core/domain/common.types.d.ts +44 -0
- package/dist/core/domain/common.types.js +20 -0
- package/dist/core/domain/dashboard.types.d.ts +108 -0
- package/dist/core/domain/dashboard.types.js +2 -0
- package/dist/core/domain/endpoints.types.d.ts +43 -0
- package/dist/core/domain/endpoints.types.js +2 -0
- package/dist/core/domain/index.d.ts +6 -0
- package/dist/core/domain/index.js +22 -0
- package/dist/core/domain/metrics.types.d.ts +119 -0
- package/dist/core/domain/metrics.types.js +2 -0
- package/dist/core/domain/system.types.d.ts +51 -0
- package/dist/core/domain/system.types.js +2 -0
- package/dist/core/domain/telemetry.types.d.ts +8 -0
- package/dist/core/domain/telemetry.types.js +2 -0
- package/dist/core/storage/index.d.ts +3 -0
- package/dist/core/storage/index.js +19 -0
- package/dist/core/storage/local.repository.d.ts +17 -0
- package/dist/core/storage/local.repository.js +52 -0
- package/dist/core/storage/stores/alert.store.d.ts +13 -0
- package/dist/core/storage/stores/alert.store.js +71 -0
- package/dist/core/storage/stores/analytics.store.d.ts +15 -0
- package/dist/core/storage/stores/analytics.store.js +59 -0
- package/dist/core/storage/stores/bucket.store.d.ts +40 -0
- package/dist/core/storage/stores/bucket.store.js +75 -0
- package/dist/core/storage/stores/dashboard.store.d.ts +15 -0
- package/dist/core/storage/stores/dashboard.store.js +78 -0
- package/dist/core/storage/stores/endpoint.store.d.ts +16 -0
- package/dist/core/storage/stores/endpoint.store.js +62 -0
- package/dist/core/storage/stores/health.store.d.ts +20 -0
- package/dist/core/storage/stores/health.store.js +133 -0
- package/dist/core/storage/stores/index.d.ts +8 -0
- package/dist/core/storage/stores/index.js +24 -0
- package/dist/core/storage/stores/metrics.store.d.ts +23 -0
- package/dist/core/storage/stores/metrics.store.js +49 -0
- package/dist/core/storage/stores/system.store.d.ts +8 -0
- package/dist/core/storage/stores/system.store.js +19 -0
- package/dist/core/storage/utility/histogram.d.ts +37 -0
- package/dist/core/storage/utility/histogram.js +91 -0
- package/dist/core/storage/utility/index.d.ts +2 -0
- package/dist/core/storage/utility/index.js +18 -0
- package/dist/core/storage/utility/ring-buffer.d.ts +12 -0
- package/dist/core/storage/utility/ring-buffer.js +47 -0
- package/dist/core/telemetry/collector.service.d.ts +18 -0
- package/dist/core/telemetry/collector.service.js +92 -0
- package/dist/core/telemetry/collectors/cpu.collector.d.ts +22 -0
- package/dist/core/telemetry/collectors/cpu.collector.js +39 -0
- package/dist/core/telemetry/collectors/event-loop.collector.d.ts +22 -0
- package/dist/core/telemetry/collectors/event-loop.collector.js +27 -0
- package/dist/core/telemetry/collectors/gc.collector.d.ts +61 -0
- package/dist/core/telemetry/collectors/gc.collector.js +86 -0
- package/dist/core/telemetry/collectors/handles.collector.d.ts +20 -0
- package/dist/core/telemetry/collectors/handles.collector.js +26 -0
- package/dist/core/telemetry/collectors/index.d.ts +6 -0
- package/dist/core/telemetry/collectors/index.js +22 -0
- package/dist/core/telemetry/collectors/interface.d.ts +3 -0
- package/dist/core/telemetry/collectors/interface.js +2 -0
- package/dist/core/telemetry/collectors/memory.collector.d.ts +18 -0
- package/dist/core/telemetry/collectors/memory.collector.js +24 -0
- package/dist/core/telemetry/collectors/runtime.collector.d.ts +32 -0
- package/dist/core/telemetry/collectors/runtime.collector.js +29 -0
- package/dist/core/telemetry/correlation.service.d.ts +9 -0
- package/dist/core/telemetry/correlation.service.js +72 -0
- package/dist/core/telemetry/logger.d.ts +11 -0
- package/dist/core/telemetry/logger.js +63 -0
- package/dist/core/telemetry/telemetry.service.d.ts +10 -0
- package/dist/core/telemetry/telemetry.service.js +36 -0
- package/dist/core/utility/base-math.d.ts +15 -0
- package/dist/core/utility/base-math.js +26 -0
- package/dist/core/utility/conversion.d.ts +31 -0
- package/dist/core/utility/conversion.js +74 -0
- package/dist/core/utility/index.d.ts +4 -0
- package/dist/core/utility/index.js +20 -0
- package/dist/core/utility/mocking.d.ts +21 -0
- package/dist/core/utility/mocking.js +40 -0
- package/dist/core/utility/pagination.d.ts +9 -0
- package/dist/core/utility/pagination.js +23 -0
- package/dist/core/utility/statistics.d.ts +140 -0
- package/dist/core/utility/statistics.js +349 -0
- package/dist/express/index.d.ts +6 -0
- package/dist/express/index.js +22 -0
- package/dist/express/metrics-websocket.adapter.d.ts +14 -0
- package/dist/express/metrics-websocket.adapter.js +70 -0
- package/dist/express/metrics.adapter.d.ts +12 -0
- package/dist/express/metrics.adapter.js +31 -0
- package/dist/express/metrics.bootstrap.d.ts +2 -0
- package/dist/express/metrics.bootstrap.js +35 -0
- package/dist/express/metrics.dashboard.d.ts +2 -0
- package/dist/express/metrics.dashboard.js +15 -0
- package/dist/express/metrics.middleware.d.ts +2 -0
- package/dist/express/metrics.middleware.js +29 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/nest/index.d.ts +4 -0
- package/dist/nest/index.js +11 -0
- package/dist/nest/metrics-websocket.adapter.d.ts +15 -0
- package/dist/nest/metrics-websocket.adapter.js +88 -0
- package/dist/nest/metrics.adapter.d.ts +12 -0
- package/dist/nest/metrics.adapter.js +33 -0
- package/dist/nest/metrics.bootstrap.service.d.ts +13 -0
- package/dist/nest/metrics.bootstrap.service.js +66 -0
- package/dist/nest/metrics.interceptor.d.ts +11 -0
- package/dist/nest/metrics.interceptor.js +57 -0
- package/dist/nest/metrics.module.d.ts +6 -0
- package/dist/nest/metrics.module.js +74 -0
- package/dist/simulation/config.d.ts +20 -0
- package/dist/simulation/config.js +54 -0
- package/dist/simulation/journey.d.ts +7 -0
- package/dist/simulation/journey.js +49 -0
- package/dist/simulation/scenarios.d.ts +17 -0
- package/dist/simulation/scenarios.js +96 -0
- package/dist/simulation/simulation.d.ts +24 -0
- package/dist/simulation/simulation.js +154 -0
- package/dist/simulation/utility.d.ts +23 -0
- package/dist/simulation/utility.js +50 -0
- package/package.json +71 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TrafficSimulator = void 0;
|
|
4
|
+
const local_repository_1 = require("../core/storage/local.repository");
|
|
5
|
+
const config_1 = require("./config");
|
|
6
|
+
const scenarios_1 = require("./scenarios");
|
|
7
|
+
const journey_1 = require("./journey");
|
|
8
|
+
const utility_1 = require("./utility");
|
|
9
|
+
function generateLatency(endpoint) {
|
|
10
|
+
const r = Math.random();
|
|
11
|
+
// 90% normal traffic
|
|
12
|
+
if (r < 0.90) {
|
|
13
|
+
return (0, utility_1.random)(endpoint.latency.normal * 0.7, endpoint.latency.normal * 1.3);
|
|
14
|
+
}
|
|
15
|
+
// p95 range
|
|
16
|
+
if (r < 0.99) {
|
|
17
|
+
return (0, utility_1.random)(endpoint.latency.normal, endpoint.latency.p95);
|
|
18
|
+
}
|
|
19
|
+
// p99 tail
|
|
20
|
+
return (0, utility_1.random)(endpoint.latency.p95, endpoint.latency.p99);
|
|
21
|
+
}
|
|
22
|
+
function applyDependencies(endpoint, latency, status) {
|
|
23
|
+
const now = Date.now();
|
|
24
|
+
// Database affects users and orders
|
|
25
|
+
if (now < scenarios_1.scenario.databaseSlowUntil && (endpoint.service === "USER" || endpoint.service === "ORDER")) {
|
|
26
|
+
latency *= (0, utility_1.random)(2, 3);
|
|
27
|
+
if ((0, utility_1.probability)(0.1)) {
|
|
28
|
+
status = 503;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Auth outage
|
|
32
|
+
if (now < scenarios_1.scenario.authDownUntil && (endpoint.service === "AUTH" || endpoint.service === "ORDER")) {
|
|
33
|
+
latency *= (0, utility_1.random)(2, 3);
|
|
34
|
+
if (endpoint.service === "AUTH") {
|
|
35
|
+
status = 401;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
status = 503;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Global latency spike
|
|
42
|
+
if (now < scenarios_1.scenario.latencySpikeUntil) {
|
|
43
|
+
latency *= (0, utility_1.random)(2, 3);
|
|
44
|
+
}
|
|
45
|
+
return { latency, status };
|
|
46
|
+
}
|
|
47
|
+
function generateStatus(endpoint) {
|
|
48
|
+
const r = Math.random();
|
|
49
|
+
// client errors
|
|
50
|
+
if (r < endpoint.errors.client) {
|
|
51
|
+
return (0, utility_1.random)(400, 499);
|
|
52
|
+
}
|
|
53
|
+
// server errors
|
|
54
|
+
if (r < endpoint.errors.client + endpoint.errors.server) {
|
|
55
|
+
return (0, utility_1.random)(500, 599);
|
|
56
|
+
}
|
|
57
|
+
return 200;
|
|
58
|
+
}
|
|
59
|
+
function findEndpoint(url) {
|
|
60
|
+
return config_1.endpoints.find(e => e.url === url) ?? config_1.endpoints[0];
|
|
61
|
+
}
|
|
62
|
+
function createRequest() {
|
|
63
|
+
(0, scenarios_1.updateScenarios)();
|
|
64
|
+
const journey = (0, journey_1.pickJourney)();
|
|
65
|
+
const url = journey.endpoints[(0, utility_1.random)(0, journey.endpoints.length - 1)];
|
|
66
|
+
const endpoint = findEndpoint(url);
|
|
67
|
+
const method = endpoint.methods[(0, utility_1.random)(0, endpoint.methods.length - 1)];
|
|
68
|
+
let latency = generateLatency(endpoint);
|
|
69
|
+
let status = generateStatus(endpoint);
|
|
70
|
+
// apply service failures
|
|
71
|
+
const result = applyDependencies(endpoint, latency, status);
|
|
72
|
+
latency = result.latency;
|
|
73
|
+
status = result.status;
|
|
74
|
+
// memory leak simulation
|
|
75
|
+
// increases response time slowly
|
|
76
|
+
if (scenarios_1.scenario.memoryLeak) {
|
|
77
|
+
latency *= (0, utility_1.random)(1, 2);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
timestamp: Date.now(),
|
|
81
|
+
endpoint: endpoint.url,
|
|
82
|
+
method,
|
|
83
|
+
statusCode: status,
|
|
84
|
+
responseTime: Math.round(latency),
|
|
85
|
+
clientIp: (0, utility_1.randomIp)(),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function generateStableLatency(endpoint) {
|
|
89
|
+
// 2% chance of a spike in latency, simulating a rare event
|
|
90
|
+
if ((0, utility_1.random)(0, 1) < 0.02) {
|
|
91
|
+
return (0, utility_1.random)(endpoint.latency.normal * 5, endpoint.latency.normal * 8.5);
|
|
92
|
+
}
|
|
93
|
+
return (0, utility_1.random)(endpoint.latency.normal * 0.85, endpoint.latency.normal * 1.15);
|
|
94
|
+
}
|
|
95
|
+
function createStableRequest() {
|
|
96
|
+
const journey = (0, journey_1.pickJourney)();
|
|
97
|
+
const url = journey.endpoints[(0, utility_1.random)(0, journey.endpoints.length - 1)];
|
|
98
|
+
const endpoint = config_1.endpoints.find(e => e.url === url) ?? config_1.endpoints[0];
|
|
99
|
+
const method = endpoint.methods[(0, utility_1.random)(0, endpoint.methods.length - 1)];
|
|
100
|
+
const latency = generateStableLatency(endpoint);
|
|
101
|
+
return {
|
|
102
|
+
timestamp: Date.now(),
|
|
103
|
+
endpoint: endpoint.url,
|
|
104
|
+
method,
|
|
105
|
+
statusCode: 200,
|
|
106
|
+
responseTime: Math.round(latency),
|
|
107
|
+
clientIp: (0, utility_1.randomIp)(),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const IS_STABLE = true;
|
|
111
|
+
class TrafficSimulator {
|
|
112
|
+
repository;
|
|
113
|
+
timer;
|
|
114
|
+
running = false;
|
|
115
|
+
constructor(repository = local_repository_1.storage) {
|
|
116
|
+
this.repository = repository;
|
|
117
|
+
}
|
|
118
|
+
start(options) {
|
|
119
|
+
if (this.running) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.running = true;
|
|
123
|
+
const interval = options?.intervalMs ?? 100;
|
|
124
|
+
const baseRequests = options?.requestsPerTick ?? 20;
|
|
125
|
+
console.log("Traffic simulation started!");
|
|
126
|
+
this.timer = setInterval(() => {
|
|
127
|
+
if (IS_STABLE) {
|
|
128
|
+
const request = createStableRequest();
|
|
129
|
+
this.repository.record(request);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const multiplier = scenarios_1.scenario.trafficMultiplier;
|
|
133
|
+
const amount = Math.floor(baseRequests * multiplier);
|
|
134
|
+
for (let i = 0; i < amount; i++) {
|
|
135
|
+
const request = createRequest();
|
|
136
|
+
this.repository.record(request);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}, interval);
|
|
140
|
+
}
|
|
141
|
+
stop() {
|
|
142
|
+
if (!this.timer) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
clearInterval(this.timer);
|
|
146
|
+
this.timer = undefined;
|
|
147
|
+
this.running = false;
|
|
148
|
+
console.log("Traffic simulation stopped!");
|
|
149
|
+
}
|
|
150
|
+
isRunning() {
|
|
151
|
+
return this.running;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
exports.TrafficSimulator = TrafficSimulator;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a random integer between min and max (inclusive).
|
|
3
|
+
* @param min Minimum integer value (inclusive).
|
|
4
|
+
* @param max Maximum integer value (inclusive).
|
|
5
|
+
* @returns A random integer between min and max.
|
|
6
|
+
*/
|
|
7
|
+
export declare function random(min: number, max: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* Generates a random boolean value based on the given probability.
|
|
10
|
+
* @param value A number between 0 and 1 representing the probability of returning true.
|
|
11
|
+
* @returns A boolean value that is true with the specified probability and false otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export declare function probability(value: number): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Picks a random endpoint from the list of endpoints based on their weights.
|
|
16
|
+
* @returns The selected endpoint object.
|
|
17
|
+
*/
|
|
18
|
+
export declare function pickEndpoint(): import("./config").EndpointConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Generates a random IP address in the format of "X.X.X.X", where each octet is a random integer within specified ranges.
|
|
21
|
+
* @returns A string representing the generated IP address.
|
|
22
|
+
*/
|
|
23
|
+
export declare function randomIp(): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.random = random;
|
|
4
|
+
exports.probability = probability;
|
|
5
|
+
exports.pickEndpoint = pickEndpoint;
|
|
6
|
+
exports.randomIp = randomIp;
|
|
7
|
+
const config_1 = require("./config");
|
|
8
|
+
/**
|
|
9
|
+
* Generates a random integer between min and max (inclusive).
|
|
10
|
+
* @param min Minimum integer value (inclusive).
|
|
11
|
+
* @param max Maximum integer value (inclusive).
|
|
12
|
+
* @returns A random integer between min and max.
|
|
13
|
+
*/
|
|
14
|
+
function random(min, max) {
|
|
15
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generates a random boolean value based on the given probability.
|
|
19
|
+
* @param value A number between 0 and 1 representing the probability of returning true.
|
|
20
|
+
* @returns A boolean value that is true with the specified probability and false otherwise.
|
|
21
|
+
*/
|
|
22
|
+
function probability(value) {
|
|
23
|
+
return Math.random() < value;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Picks a random endpoint from the list of endpoints based on their weights.
|
|
27
|
+
* @returns The selected endpoint object.
|
|
28
|
+
*/
|
|
29
|
+
function pickEndpoint() {
|
|
30
|
+
let r = Math.random() * config_1.TOTAL_WEIGHT;
|
|
31
|
+
for (const endpoint of config_1.endpoints) {
|
|
32
|
+
r -= endpoint.weight;
|
|
33
|
+
if (r <= 0) {
|
|
34
|
+
return endpoint;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return config_1.endpoints[0];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Generates a random IP address in the format of "X.X.X.X", where each octet is a random integer within specified ranges.
|
|
41
|
+
* @returns A string representing the generated IP address.
|
|
42
|
+
*/
|
|
43
|
+
function randomIp() {
|
|
44
|
+
return [
|
|
45
|
+
random(10, 250),
|
|
46
|
+
random(0, 255),
|
|
47
|
+
random(0, 255),
|
|
48
|
+
random(1, 254)
|
|
49
|
+
].join(".");
|
|
50
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "apm-optima",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./express": {
|
|
15
|
+
"types": "./dist/express/index.d.ts",
|
|
16
|
+
"default": "./dist/express/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./nest": {
|
|
19
|
+
"types": "./dist/nest/index.d.ts",
|
|
20
|
+
"default": "./dist/nest/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"typesVersions": {
|
|
25
|
+
"*": {
|
|
26
|
+
"express": [
|
|
27
|
+
"dist/express/index.d.ts"
|
|
28
|
+
],
|
|
29
|
+
"nest": [
|
|
30
|
+
"dist/nest/index.d.ts"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md",
|
|
37
|
+
"package.json"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc",
|
|
41
|
+
"test": "jest"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"express": "^4.0.0",
|
|
45
|
+
"@nestjs/websockets": "^10.0.0 || ^11.0.0",
|
|
46
|
+
"socket.io": "^4.0.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"express": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
52
|
+
"@nestjs/websockets": {
|
|
53
|
+
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"socket.io": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@nestjs/websockets": "^11.2.1",
|
|
61
|
+
"express": "^4.19.2",
|
|
62
|
+
"socket.io": "^4.8.3",
|
|
63
|
+
"@types/express": "^4.17.21",
|
|
64
|
+
"@types/jest": "^29.5.14",
|
|
65
|
+
"@types/node": "^20.0.0",
|
|
66
|
+
"@types/socket.io": "^3.0.1",
|
|
67
|
+
"jest": "^29.0.0",
|
|
68
|
+
"ts-jest": "^29.0.0",
|
|
69
|
+
"typescript": "^5.0.0"
|
|
70
|
+
}
|
|
71
|
+
}
|