k6-perf-reporter 1.6.6 → 1.7.0
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/.claude/settings.local.json +18 -0
- package/.config.example.json +3 -0
- package/dist/cache.d.ts +11 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +61 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.js +36 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +12 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +33 -8
- package/dist/config.js.map +1 -1
- package/dist/data-collector.d.ts +7 -10
- package/dist/data-collector.d.ts.map +1 -1
- package/dist/data-collector.js +68 -58
- package/dist/data-collector.js.map +1 -1
- package/dist/datasources/datasource.d.ts +13 -0
- package/dist/datasources/datasource.d.ts.map +1 -0
- package/dist/datasources/datasource.js +3 -0
- package/dist/datasources/datasource.js.map +1 -0
- package/dist/datasources/factory.d.ts +4 -0
- package/dist/datasources/factory.d.ts.map +1 -0
- package/dist/datasources/factory.js +19 -0
- package/dist/datasources/factory.js.map +1 -0
- package/dist/datasources/index.d.ts +4 -0
- package/dist/datasources/index.d.ts.map +1 -0
- package/dist/datasources/index.js +9 -0
- package/dist/datasources/index.js.map +1 -0
- package/dist/datasources/influx/index.d.ts +3 -0
- package/dist/datasources/influx/index.d.ts.map +1 -0
- package/dist/datasources/influx/index.js +8 -0
- package/dist/datasources/influx/index.js.map +1 -0
- package/dist/datasources/influx/influx-client.d.ts +16 -0
- package/dist/datasources/influx/influx-client.d.ts.map +1 -0
- package/dist/datasources/influx/influx-client.js +40 -0
- package/dist/datasources/influx/influx-client.js.map +1 -0
- package/dist/datasources/influx/influx-datasource.d.ts +18 -0
- package/dist/datasources/influx/influx-datasource.d.ts.map +1 -0
- package/dist/datasources/influx/influx-datasource.js +247 -0
- package/dist/datasources/influx/influx-datasource.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +47 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics/computations.d.ts +11 -0
- package/dist/metrics/computations.d.ts.map +1 -0
- package/dist/metrics/computations.js +247 -0
- package/dist/metrics/computations.js.map +1 -0
- package/dist/metrics/index.d.ts +2 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +18 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/reporters/cli-reporter.d.ts.map +1 -1
- package/dist/reporters/cli-reporter.js +22 -60
- package/dist/reporters/cli-reporter.js.map +1 -1
- package/dist/reporters/markdown-reporter.d.ts.map +1 -1
- package/dist/reporters/markdown-reporter.js +19 -54
- package/dist/reporters/markdown-reporter.js.map +1 -1
- package/dist/reporters/slack-reporter.d.ts +5 -0
- package/dist/reporters/slack-reporter.d.ts.map +1 -1
- package/dist/reporters/slack-reporter.js +54 -84
- package/dist/reporters/slack-reporter.js.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/metrics.d.ts +130 -0
- package/dist/types/metrics.d.ts.map +1 -0
- package/dist/types/metrics.js +3 -0
- package/dist/types/metrics.js.map +1 -0
- package/package.json +2 -2
- package/src/cache.ts +73 -0
- package/src/cli.ts +37 -12
- package/src/config.ts +47 -9
- package/src/data-collector.ts +102 -83
- package/src/datasources/datasource.ts +23 -0
- package/src/datasources/factory.ts +18 -0
- package/src/datasources/index.ts +3 -0
- package/src/datasources/influx/index.ts +2 -0
- package/src/{influx-client.ts → datasources/influx/influx-client.ts} +6 -1
- package/src/datasources/influx/influx-datasource.ts +355 -0
- package/src/logger.ts +49 -0
- package/src/metrics/computations.ts +315 -0
- package/src/metrics/index.ts +1 -0
- package/src/reporters/cli-reporter.ts +25 -65
- package/src/reporters/markdown-reporter.ts +22 -59
- package/src/reporters/slack-reporter.ts +62 -89
- package/src/types/index.ts +1 -0
- package/src/types/metrics.ts +150 -0
- package/src/influx-data-extractor.ts +0 -911
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm run *)",
|
|
5
|
+
"Bash(npx tsc *)",
|
|
6
|
+
"Bash(git checkout *)",
|
|
7
|
+
"Bash(git add *)",
|
|
8
|
+
"Bash(git commit -m ' *)",
|
|
9
|
+
"Bash(git push *)",
|
|
10
|
+
"Bash(xargs cat *)",
|
|
11
|
+
"Bash(npm test *)",
|
|
12
|
+
"Bash(git commit *)",
|
|
13
|
+
"Bash(git pull *)",
|
|
14
|
+
"Bash(git stash *)",
|
|
15
|
+
"Bash(wc *)"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
package/.config.example.json
CHANGED
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReporterResponse } from "./data-collector";
|
|
2
|
+
export declare class Cache {
|
|
3
|
+
private cacheDir;
|
|
4
|
+
private ttlMs;
|
|
5
|
+
constructor(ttlSeconds: number, cacheDir?: string);
|
|
6
|
+
private getCacheKey;
|
|
7
|
+
private getCachePath;
|
|
8
|
+
get(runId: string, startTime: string, endTime: string): ReporterResponse | null;
|
|
9
|
+
set(runId: string, startTime: string, endTime: string, data: ReporterResponse): void;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAQpD,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;gBAEV,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKjD,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAIpB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IA2B/E,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;CAgBrF"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Cache = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
class Cache {
|
|
12
|
+
constructor(ttlSeconds, cacheDir) {
|
|
13
|
+
this.ttlMs = ttlSeconds * 1000;
|
|
14
|
+
this.cacheDir = cacheDir || path_1.default.resolve(".cache");
|
|
15
|
+
}
|
|
16
|
+
getCacheKey(runId, startTime, endTime) {
|
|
17
|
+
const raw = `${runId}:${startTime}:${endTime}`;
|
|
18
|
+
return crypto_1.default.createHash("md5").update(raw).digest("hex");
|
|
19
|
+
}
|
|
20
|
+
getCachePath(key) {
|
|
21
|
+
return path_1.default.join(this.cacheDir, `${key}.json`);
|
|
22
|
+
}
|
|
23
|
+
get(runId, startTime, endTime) {
|
|
24
|
+
const key = this.getCacheKey(runId, startTime, endTime);
|
|
25
|
+
const filePath = this.getCachePath(key);
|
|
26
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
27
|
+
logger_1.logger.debug(`Cache.get: miss (no file) key=${key}`);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const raw = fs_1.default.readFileSync(filePath, "utf-8");
|
|
32
|
+
const entry = JSON.parse(raw);
|
|
33
|
+
if (Date.now() - entry.timestamp > this.ttlMs) {
|
|
34
|
+
logger_1.logger.debug(`Cache.get: expired key=${key}, age=${Math.round((Date.now() - entry.timestamp) / 1000)}s, ttl=${Math.round(this.ttlMs / 1000)}s`);
|
|
35
|
+
fs_1.default.unlinkSync(filePath);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
logger_1.logger.debug(`Cache.get: hit key=${key}, age=${Math.round((Date.now() - entry.timestamp) / 1000)}s`);
|
|
39
|
+
return entry.data;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
logger_1.logger.warn(`Cache.get: failed to read cache file ${filePath}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
set(runId, startTime, endTime, data) {
|
|
47
|
+
const key = this.getCacheKey(runId, startTime, endTime);
|
|
48
|
+
const filePath = this.getCachePath(key);
|
|
49
|
+
if (!fs_1.default.existsSync(this.cacheDir)) {
|
|
50
|
+
fs_1.default.mkdirSync(this.cacheDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
const entry = {
|
|
53
|
+
timestamp: Date.now(),
|
|
54
|
+
data,
|
|
55
|
+
};
|
|
56
|
+
fs_1.default.writeFileSync(filePath, JSON.stringify(entry, null, 2), "utf-8");
|
|
57
|
+
logger_1.logger.debug(`Cache.set: wrote key=${key} to ${filePath}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.Cache = Cache;
|
|
61
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -4,11 +4,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const config_1 = require("./config");
|
|
6
6
|
const data_collector_1 = require("./data-collector");
|
|
7
|
+
const datasources_1 = require("./datasources");
|
|
7
8
|
const reporters_1 = require("./reporters");
|
|
8
9
|
function main() {
|
|
9
10
|
commander_1.program
|
|
10
11
|
.name("k6-reporter")
|
|
11
|
-
.description("Generate CLI reports from k6 tests
|
|
12
|
+
.description("Generate CLI reports from k6 performance tests")
|
|
12
13
|
.version("1.6.0");
|
|
13
14
|
commander_1.program
|
|
14
15
|
.command("generate")
|
|
@@ -17,12 +18,17 @@ function main() {
|
|
|
17
18
|
.option("-st, --start-time <time>", "Start time in ISO 8601 format or relative like '-1h'")
|
|
18
19
|
.option("-et, --end-time <time>", "End time in ISO 8601 format (defaults to now)")
|
|
19
20
|
.option("-c, --config <path>", "Path to config file", ".config.json")
|
|
21
|
+
.option("-d, --datasource <type>", "Data source: 'influxdb' or 'prometheus'")
|
|
20
22
|
.option("-f, --format <format>", "Output format: 'json', 'cli', 'markdown', or 'slack'", "cli")
|
|
21
23
|
.option("-o, --output <path>", "Output file path (for json format)")
|
|
24
|
+
.option("--no-cache", "Disable cache, always fetch fresh data")
|
|
22
25
|
.action(async (options) => {
|
|
23
26
|
try {
|
|
24
|
-
const
|
|
25
|
-
const
|
|
27
|
+
const configInstance = config_1.Config.getInstance(options.config);
|
|
28
|
+
const dsType = (options.datasource || configInstance.getDataSourceType());
|
|
29
|
+
const dataSource = (0, datasources_1.createDataSource)(dsType, configInstance);
|
|
30
|
+
const cacheTtl = options.cache ? configInstance.getCacheConfig().ttl : 0;
|
|
31
|
+
const collector = new data_collector_1.DataCollector(dataSource, cacheTtl);
|
|
26
32
|
const report = await collector.collect(options.runId, options.startTime || "-1h", options.endTime || "now()");
|
|
27
33
|
if (options.format === "json") {
|
|
28
34
|
const jsonReporter = new reporters_1.JsonReporter();
|
|
@@ -33,7 +39,7 @@ function main() {
|
|
|
33
39
|
markdownReporter.report(report, options.output);
|
|
34
40
|
}
|
|
35
41
|
else if (options.format === "slack") {
|
|
36
|
-
const slackConfig =
|
|
42
|
+
const slackConfig = configInstance.getSlackConfig();
|
|
37
43
|
if (!slackConfig) {
|
|
38
44
|
throw new Error("Slack token not configured. Set SLACK_TOKEN environment variable or configure in config file.");
|
|
39
45
|
}
|
|
@@ -56,7 +62,7 @@ function main() {
|
|
|
56
62
|
.description("Show help and examples")
|
|
57
63
|
.action(() => {
|
|
58
64
|
console.log(`
|
|
59
|
-
k6-reporter - Generate
|
|
65
|
+
k6-reporter - Generate reports from k6 performance tests
|
|
60
66
|
|
|
61
67
|
USAGE:
|
|
62
68
|
k6-reporter <command> [options]
|
|
@@ -73,8 +79,10 @@ OPTIONS:
|
|
|
73
79
|
-st, --start-time Start time (relative: -1h, -30m, or ISO 8601)
|
|
74
80
|
-et, --end-time End time (ISO 8601 format, defaults to now)
|
|
75
81
|
-c, --config Path to config file (default: .config.json)
|
|
82
|
+
-d, --datasource Data source: 'influxdb' or 'prometheus' (default: influxdb)
|
|
76
83
|
-f, --format Output format: 'json', 'cli', 'markdown', or 'slack' (default: cli)
|
|
77
84
|
-o, --output Output file path (for json and markdown formats)
|
|
85
|
+
--no-cache Disable cache, always fetch fresh data
|
|
78
86
|
-h, --help Show command help
|
|
79
87
|
-V, --version Show version
|
|
80
88
|
|
|
@@ -101,7 +109,10 @@ EXAMPLES:
|
|
|
101
109
|
7. Use custom config file:
|
|
102
110
|
k6-reporter generate --run-id 123456790121 -c /path/to/config.json
|
|
103
111
|
|
|
104
|
-
8.
|
|
112
|
+
8. Use Prometheus datasource:
|
|
113
|
+
k6-reporter generate --run-id 123456790121 -d prometheus
|
|
114
|
+
|
|
115
|
+
9. Get help for generate command:
|
|
105
116
|
k6-reporter generate --help
|
|
106
117
|
|
|
107
118
|
TIME FORMAT:
|
|
@@ -117,14 +128,28 @@ TIME FORMAT:
|
|
|
117
128
|
|
|
118
129
|
CONFIG FILE:
|
|
119
130
|
|
|
120
|
-
The config file (.config.json)
|
|
131
|
+
The config file (.config.json) supports multiple datasources:
|
|
121
132
|
|
|
122
133
|
{
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
|
|
126
|
-
|
|
134
|
+
"dataSource": "influxdb",
|
|
135
|
+
"influx": {
|
|
136
|
+
"url": "https://influxdb.example.com",
|
|
137
|
+
"token": "your-influx-token",
|
|
138
|
+
"org": "your-org",
|
|
139
|
+
"bucket": "your-bucket"
|
|
140
|
+
}
|
|
127
141
|
}
|
|
142
|
+
|
|
143
|
+
ENVIRONMENT VARIABLES:
|
|
144
|
+
|
|
145
|
+
DATASOURCE Data source type (influxdb, prometheus)
|
|
146
|
+
INFLUX_URL InfluxDB URL
|
|
147
|
+
INFLUX_TOKEN InfluxDB token
|
|
148
|
+
INFLUX_ORG InfluxDB organization
|
|
149
|
+
INFLUX_BUCKET InfluxDB bucket
|
|
150
|
+
SLACK_TOKEN Slack bot token
|
|
151
|
+
SLACK_CHANNEL Slack channel ID
|
|
152
|
+
CACHE_TTL Cache TTL in seconds (default: 3600)
|
|
128
153
|
`);
|
|
129
154
|
});
|
|
130
155
|
commander_1.program.parse();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type DataSourceType = "influxdb" | "prometheus";
|
|
1
2
|
export interface InfluxConfig {
|
|
2
3
|
url: string;
|
|
3
4
|
token: string;
|
|
@@ -8,18 +9,26 @@ export interface SlackConfig {
|
|
|
8
9
|
token: string;
|
|
9
10
|
channel: string;
|
|
10
11
|
}
|
|
12
|
+
export interface CacheConfig {
|
|
13
|
+
ttl: number;
|
|
14
|
+
}
|
|
11
15
|
export declare class Config {
|
|
12
16
|
private static instance;
|
|
13
|
-
private
|
|
17
|
+
private dataSourceType;
|
|
18
|
+
private rawInflux;
|
|
14
19
|
private slackConfig;
|
|
20
|
+
private cacheConfig;
|
|
15
21
|
private configPath;
|
|
16
22
|
private constructor();
|
|
17
23
|
private loadRawConfig;
|
|
18
|
-
private
|
|
24
|
+
private parseDataSourceType;
|
|
25
|
+
getInfluxConfig(): InfluxConfig;
|
|
19
26
|
private parseSlackConfig;
|
|
27
|
+
private parseCacheConfig;
|
|
20
28
|
private resolveValue;
|
|
21
29
|
static getInstance(configPath?: string): Config;
|
|
22
|
-
|
|
30
|
+
getDataSourceType(): DataSourceType;
|
|
23
31
|
getSlackConfig(): SlackConfig | null;
|
|
32
|
+
getCacheConfig(): CacheConfig;
|
|
24
33
|
}
|
|
25
34
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AASD,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAsC;IACvD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO;IASP,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,mBAAmB;IAS3B,eAAe,IAAI,YAAY;IAgB/B,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,YAAY;IAWpB,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAO/C,iBAAiB,IAAI,cAAc;IAInC,cAAc,IAAI,WAAW,GAAG,IAAI;IAIpC,cAAc,IAAI,WAAW;CAG9B"}
|
package/dist/config.js
CHANGED
|
@@ -11,8 +11,10 @@ class Config {
|
|
|
11
11
|
this.slackConfig = null;
|
|
12
12
|
this.configPath = configPath || ".config.json";
|
|
13
13
|
const rawConfig = this.loadRawConfig();
|
|
14
|
-
this.
|
|
14
|
+
this.dataSourceType = this.parseDataSourceType(rawConfig.dataSource);
|
|
15
|
+
this.rawInflux = rawConfig.influx;
|
|
15
16
|
this.slackConfig = this.parseSlackConfig(rawConfig.slack);
|
|
17
|
+
this.cacheConfig = this.parseCacheConfig(rawConfig.cache);
|
|
16
18
|
}
|
|
17
19
|
loadRawConfig() {
|
|
18
20
|
const fullPath = path_1.default.resolve(this.configPath);
|
|
@@ -27,11 +29,19 @@ class Config {
|
|
|
27
29
|
}
|
|
28
30
|
return {};
|
|
29
31
|
}
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
parseDataSourceType(raw) {
|
|
33
|
+
const envValue = process.env["DATASOURCE"];
|
|
34
|
+
const value = envValue || raw || "influxdb";
|
|
35
|
+
if (value !== "influxdb" && value !== "prometheus") {
|
|
36
|
+
throw new Error(`Unknown datasource type: '${value}'. Supported: influxdb, prometheus`);
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
getInfluxConfig() {
|
|
41
|
+
const url = this.resolveValue(this.rawInflux?.url, "INFLUX_URL");
|
|
42
|
+
const token = this.resolveValue(this.rawInflux?.token, "INFLUX_TOKEN");
|
|
43
|
+
const org = this.resolveValue(this.rawInflux?.org, "INFLUX_ORG");
|
|
44
|
+
const bucket = this.resolveValue(this.rawInflux?.bucket, "INFLUX_BUCKET");
|
|
35
45
|
if (!url || !token || !org || !bucket) {
|
|
36
46
|
throw new Error("InfluxDB configuration is incomplete. " +
|
|
37
47
|
"Set INFLUX_URL, INFLUX_TOKEN, INFLUX_ORG, INFLUX_BUCKET via environment variables or config file.");
|
|
@@ -50,6 +60,18 @@ class Config {
|
|
|
50
60
|
}
|
|
51
61
|
return { token, channel };
|
|
52
62
|
}
|
|
63
|
+
parseCacheConfig(rawConfig) {
|
|
64
|
+
const DEFAULT_TTL = 3600;
|
|
65
|
+
const envTtl = process.env["CACHE_TTL"];
|
|
66
|
+
if (envTtl) {
|
|
67
|
+
return { ttl: parseInt(envTtl, 10) };
|
|
68
|
+
}
|
|
69
|
+
const ttl = rawConfig?.ttl;
|
|
70
|
+
if (typeof ttl === "number") {
|
|
71
|
+
return { ttl };
|
|
72
|
+
}
|
|
73
|
+
return { ttl: DEFAULT_TTL };
|
|
74
|
+
}
|
|
53
75
|
resolveValue(configValue, envVar) {
|
|
54
76
|
// First check environment variable (takes priority)
|
|
55
77
|
const envValue = process.env[envVar];
|
|
@@ -65,12 +87,15 @@ class Config {
|
|
|
65
87
|
}
|
|
66
88
|
return Config.instance;
|
|
67
89
|
}
|
|
68
|
-
|
|
69
|
-
return this.
|
|
90
|
+
getDataSourceType() {
|
|
91
|
+
return this.dataSourceType;
|
|
70
92
|
}
|
|
71
93
|
getSlackConfig() {
|
|
72
94
|
return this.slackConfig;
|
|
73
95
|
}
|
|
96
|
+
getCacheConfig() {
|
|
97
|
+
return this.cacheConfig;
|
|
98
|
+
}
|
|
74
99
|
}
|
|
75
100
|
exports.Config = Config;
|
|
76
101
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AA2BxB,MAAa,MAAM;IAQjB,YAAoB,UAAmB;QAJ/B,gBAAW,GAAuB,IAAI,CAAC;QAK7C,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,cAAc,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACvC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC;IAEO,aAAa;QACnB,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE/C,qCAAqC;QACrC,IAAI,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAc,CAAC;YACrE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3H,CAAC;QACH,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;IAEO,mBAAmB,CAAC,GAAuB;QACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,QAAQ,IAAI,GAAG,IAAI,UAAU,CAAC;QAC5C,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,oCAAoC,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,GAAyB,EAAE,YAAY,CAAC,CAAC;QACvF,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,KAA2B,EAAE,cAAc,CAAC,CAAC;QAC7F,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,GAAyB,EAAE,YAAY,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,MAA4B,EAAE,eAAe,CAAC,CAAC;QAEhG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CACb,wCAAwC;gBACxC,mGAAmG,CACpG,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACrC,CAAC;IAEO,gBAAgB,CAAC,SAA8C;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,KAA2B,EAAE,aAAa,CAAC,CAAC;QACvF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,OAA6B,EAAE,eAAe,CAAC,CAAC;QAC7F,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,iDAAiD;gBACjD,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5B,CAAC;IAEO,gBAAgB,CAAC,SAA8C;QACrE,MAAM,WAAW,GAAG,IAAI,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACxC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;QACvC,CAAC;QACD,MAAM,GAAG,GAAG,SAAS,EAAE,GAAG,CAAC;QAC3B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;IAC9B,CAAC;IAEO,YAAY,CAAC,WAA+B,EAAE,MAAc;QAClE,oDAAoD;QACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,4BAA4B;QAC5B,OAAO,WAAW,IAAI,IAAI,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,UAAmB;QACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,CAAC,QAAQ,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF;AApHD,wBAoHC"}
|
package/dist/data-collector.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
startTime: string;
|
|
5
|
-
endTime: string;
|
|
6
|
-
timestamp: string;
|
|
7
|
-
data: unknown;
|
|
8
|
-
}
|
|
1
|
+
import { DataSource } from "./datasources";
|
|
2
|
+
import { ReporterResponse } from "./types";
|
|
3
|
+
export { ReporterResponse } from "./types";
|
|
9
4
|
export declare class DataCollector {
|
|
10
|
-
private
|
|
5
|
+
private dataSource;
|
|
11
6
|
private loader;
|
|
12
|
-
|
|
7
|
+
private cache;
|
|
8
|
+
constructor(dataSource: DataSource, cacheTtl?: number);
|
|
9
|
+
private formatElapsed;
|
|
13
10
|
collect(runId: string, startTime?: string, endTime?: string, data?: unknown): Promise<ReporterResponse>;
|
|
14
11
|
}
|
|
15
12
|
//# sourceMappingURL=data-collector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-collector.d.ts","sourceRoot":"","sources":["../src/data-collector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-collector.d.ts","sourceRoot":"","sources":["../src/data-collector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAe3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAe;gBAEhB,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKrD,OAAO,CAAC,aAAa;IAQf,OAAO,CACX,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAc,EACzB,OAAO,GAAE,MAAgB,EACzB,IAAI,GAAE,OAAY,GACjB,OAAO,CAAC,gBAAgB,CAAC;CAqG7B"}
|
package/dist/data-collector.js
CHANGED
|
@@ -1,65 +1,72 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DataCollector = void 0;
|
|
4
|
-
const
|
|
4
|
+
const metrics_1 = require("./metrics");
|
|
5
5
|
const loader_1 = require("./loader");
|
|
6
|
+
const cache_1 = require("./cache");
|
|
7
|
+
const logger_1 = require("./logger");
|
|
6
8
|
class DataCollector {
|
|
7
|
-
constructor(
|
|
9
|
+
constructor(dataSource, cacheTtl) {
|
|
8
10
|
this.loader = new loader_1.Loader();
|
|
9
|
-
this.
|
|
11
|
+
this.dataSource = dataSource;
|
|
12
|
+
this.cache = cacheTtl != null && cacheTtl > 0 ? new cache_1.Cache(cacheTtl) : null;
|
|
13
|
+
}
|
|
14
|
+
formatElapsed(ms) {
|
|
15
|
+
const seconds = Math.floor(ms / 1000);
|
|
16
|
+
if (seconds < 60)
|
|
17
|
+
return `${seconds}s`;
|
|
18
|
+
const minutes = Math.floor(seconds / 60);
|
|
19
|
+
const remainingSeconds = seconds % 60;
|
|
20
|
+
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
10
21
|
}
|
|
11
22
|
async collect(runId, startTime = "-1h", endTime = "now()", data = {}) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.loader.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.loader.success(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.loader.success("Extracted RPS per URL");
|
|
60
|
-
this.loader.start("Extracting RPS aggregated (5s intervals)...");
|
|
61
|
-
const rpsAggregated = await this.extractor.extractRpsAggregated(runId, startTime, endTime);
|
|
62
|
-
this.loader.success("Extracted RPS aggregated");
|
|
23
|
+
logger_1.logger.info(`DataCollector.collect: runId=${runId}, range=[${startTime}, ${endTime}]`);
|
|
24
|
+
if (this.cache) {
|
|
25
|
+
const cached = this.cache.get(runId, startTime, endTime);
|
|
26
|
+
if (cached) {
|
|
27
|
+
logger_1.logger.info("DataCollector.collect: cache hit, skipping data fetch");
|
|
28
|
+
this.loader.success("Loaded report from cache");
|
|
29
|
+
return cached;
|
|
30
|
+
}
|
|
31
|
+
logger_1.logger.debug("DataCollector.collect: cache miss, fetching from datasource");
|
|
32
|
+
}
|
|
33
|
+
// Phase 1: Parallel bulk fetch — all independent queries at once
|
|
34
|
+
this.loader.start("Fetching all data in parallel...");
|
|
35
|
+
const fetchStart = Date.now();
|
|
36
|
+
logger_1.logger.info("DataCollector.collect: starting parallel data fetch (9 queries)");
|
|
37
|
+
const [httpReqsData, httpReqDurationData, duration, vus, vusMax, iterations, checks, iterationDuration, errorResponsesText,] = await Promise.all([
|
|
38
|
+
this.dataSource.fetchHttpReqsData(runId, startTime, endTime),
|
|
39
|
+
this.dataSource.fetchHttpReqDurationData(runId, startTime, endTime),
|
|
40
|
+
this.dataSource.calculateTestDuration(runId, startTime, endTime),
|
|
41
|
+
this.dataSource.extractVus(runId, startTime, endTime),
|
|
42
|
+
this.dataSource.extractVusMax(runId, startTime, endTime),
|
|
43
|
+
this.dataSource.extractIterations(runId, startTime, endTime),
|
|
44
|
+
this.dataSource.extractChecks(runId, startTime, endTime),
|
|
45
|
+
this.dataSource.extractIterationDuration(runId, startTime, endTime),
|
|
46
|
+
this.dataSource.extractErrorResponsesText(runId, startTime, endTime),
|
|
47
|
+
]);
|
|
48
|
+
const fetchElapsed = Date.now() - fetchStart;
|
|
49
|
+
logger_1.logger.info(`DataCollector.collect: parallel fetch completed in ${fetchElapsed}ms`);
|
|
50
|
+
logger_1.logger.debug(`DataCollector.collect: fetched rows — httpReqs=${httpReqsData.length}, httpReqDuration=${httpReqDurationData.length}, ` +
|
|
51
|
+
`errorResponsesText=${errorResponsesText.responses.length}`);
|
|
52
|
+
this.loader.success(`Data fetching finished in ${this.formatElapsed(fetchElapsed)}`);
|
|
53
|
+
// Phase 2: Derive metrics from cached data (no additional queries)
|
|
54
|
+
this.loader.start("Computing metrics...");
|
|
55
|
+
logger_1.logger.info("DataCollector.collect: computing derived metrics");
|
|
56
|
+
// Update iterations with duration info
|
|
57
|
+
if (iterations.total > 0 && duration.durationSeconds > 0) {
|
|
58
|
+
iterations.rate = iterations.total / duration.durationSeconds;
|
|
59
|
+
}
|
|
60
|
+
const httpReqs = (0, metrics_1.extractHttpReqsFromData)(httpReqsData, duration);
|
|
61
|
+
const httpReqFailed = (0, metrics_1.extractHttpReqFailedFromData)(httpReqsData);
|
|
62
|
+
const httpReqDuration = (0, metrics_1.extractHttpReqDurationFromData)(httpReqDurationData);
|
|
63
|
+
const httpReqDurationSuccess = (0, metrics_1.extractHttpReqDurationSuccessFromData)(httpReqDurationData);
|
|
64
|
+
const errorResponses = (0, metrics_1.extractErrorResponsesFromData)(httpReqsData, duration);
|
|
65
|
+
const errorRequests = (0, metrics_1.extractErrorRequestsFromData)(httpReqsData, httpReqDurationData);
|
|
66
|
+
const requests = (0, metrics_1.extractRequestsFromData)(httpReqsData, httpReqDurationData);
|
|
67
|
+
const rpsAggregated = (0, metrics_1.extractRpsAggregatedFromData)(httpReqsData);
|
|
68
|
+
logger_1.logger.info("DataCollector.collect: all metrics computed");
|
|
69
|
+
this.loader.success("Computed all metrics");
|
|
63
70
|
const reportData = {
|
|
64
71
|
...(typeof data === "object" && data !== null ? data : {}),
|
|
65
72
|
httpReqs,
|
|
@@ -73,20 +80,23 @@ class DataCollector {
|
|
|
73
80
|
httpReqDurationSuccess,
|
|
74
81
|
iterationDuration,
|
|
75
82
|
errorResponses,
|
|
76
|
-
|
|
77
|
-
topSlowUrls,
|
|
83
|
+
requests,
|
|
78
84
|
errorRequests,
|
|
79
|
-
successRequests,
|
|
80
85
|
errorResponsesText,
|
|
81
86
|
rpsAggregated,
|
|
82
87
|
};
|
|
83
|
-
|
|
88
|
+
const result = {
|
|
84
89
|
runId,
|
|
85
90
|
startTime: duration.startTime || startTime,
|
|
86
91
|
endTime: duration.endTime || endTime,
|
|
87
92
|
timestamp: new Date().toISOString(),
|
|
88
93
|
data: reportData,
|
|
89
94
|
};
|
|
95
|
+
if (this.cache) {
|
|
96
|
+
this.cache.set(runId, startTime, endTime, result);
|
|
97
|
+
logger_1.logger.debug("DataCollector.collect: result cached");
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
90
100
|
}
|
|
91
101
|
}
|
|
92
102
|
exports.DataCollector = DataCollector;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-collector.js","sourceRoot":"","sources":["../src/data-collector.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"data-collector.js","sourceRoot":"","sources":["../src/data-collector.ts"],"names":[],"mappings":";;;AAEA,uCASmB;AACnB,qCAAkC;AAClC,mCAAgC;AAChC,qCAAkC;AAIlC,MAAa,aAAa;IAKxB,YAAY,UAAsB,EAAE,QAAiB;QAH7C,WAAM,GAAG,IAAI,eAAM,EAAE,CAAC;QAI5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,QAAQ,IAAI,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,aAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,CAAC;IAEO,aAAa,CAAC,EAAU;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACtC,IAAI,OAAO,GAAG,EAAE;YAAE,OAAO,GAAG,OAAO,GAAG,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACzC,MAAM,gBAAgB,GAAG,OAAO,GAAG,EAAE,CAAC;QACtC,OAAO,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,gBAAgB,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;IACnF,CAAC;IAED,KAAK,CAAC,OAAO,CACX,KAAa,EACb,YAAoB,KAAK,EACzB,UAAkB,OAAO,EACzB,OAAgB,EAAE;QAElB,eAAM,CAAC,IAAI,CAAC,gCAAgC,KAAK,YAAY,SAAS,KAAK,OAAO,GAAG,CAAC,CAAC;QAEvF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACzD,IAAI,MAAM,EAAE,CAAC;gBACX,eAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;gBACrE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;gBAChD,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,eAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAC9E,CAAC;QAED,iEAAiE;QACjE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,eAAM,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;QAC/E,MAAM,CACJ,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,GAAG,EACH,MAAM,EACN,UAAU,EACV,MAAM,EACN,iBAAiB,EACjB,kBAAkB,EACnB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACpB,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YAC5D,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YACnE,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YAChE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YACrD,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YACxD,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YAC5D,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YACxD,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;YACnE,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;SACrE,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;QAC7C,eAAM,CAAC,IAAI,CAAC,sDAAsD,YAAY,IAAI,CAAC,CAAC;QACpF,eAAM,CAAC,KAAK,CACV,kDAAkD,YAAY,CAAC,MAAM,qBAAqB,mBAAmB,CAAC,MAAM,IAAI;YACxH,sBAAsB,kBAAkB,CAAC,SAAS,CAAC,MAAM,EAAE,CAC5D,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,6BAA6B,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAErF,mEAAmE;QACnE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,eAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QAEhE,uCAAuC;QACvC,IAAI,UAAU,CAAC,KAAK,GAAG,CAAC,IAAI,QAAQ,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YACzD,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC;QAChE,CAAC;QAED,MAAM,QAAQ,GAAG,IAAA,iCAAuB,EAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACjE,MAAM,aAAa,GAAG,IAAA,sCAA4B,EAAC,YAAY,CAAC,CAAC;QACjE,MAAM,eAAe,GAAG,IAAA,wCAA8B,EAAC,mBAAmB,CAAC,CAAC;QAC5E,MAAM,sBAAsB,GAAG,IAAA,+CAAqC,EAAC,mBAAmB,CAAC,CAAC;QAC1F,MAAM,cAAc,GAAG,IAAA,uCAA6B,EAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC7E,MAAM,aAAa,GAAG,IAAA,sCAA4B,EAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;QACtF,MAAM,QAAQ,GAAG,IAAA,iCAAuB,EAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;QAC5E,MAAM,aAAa,GAAG,IAAA,sCAA4B,EAAC,YAAY,CAAC,CAAC;QAEjE,eAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAE5C,MAAM,UAAU,GAAG;YACjB,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,QAAQ;YACR,GAAG;YACH,MAAM;YACN,UAAU;YACV,QAAQ;YACR,MAAM;YACN,aAAa;YACb,eAAe;YACf,sBAAsB;YACtB,iBAAiB;YACjB,cAAc;YACd,QAAQ;YACR,aAAa;YACb,kBAAkB;YAClB,aAAa;SACd,CAAC;QAEF,MAAM,MAAM,GAAqB;YAC/B,KAAK;YACL,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,SAAS;YAC1C,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,OAAO;YACpC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,UAAU;SACjB,CAAC;QAEF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YAClD,eAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA5HD,sCA4HC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HttpReqsRow, HttpReqDurationRow, DurationMetric, VusMetric, VusMaxMetric, IterationsMetric, ChecksMetric, IterationDurationMetric, ErrorResponsesTextMetric } from "../types";
|
|
2
|
+
export interface DataSource {
|
|
3
|
+
fetchHttpReqsData(runId: string, startTime: string, endTime: string): Promise<HttpReqsRow[]>;
|
|
4
|
+
fetchHttpReqDurationData(runId: string, startTime: string, endTime: string): Promise<HttpReqDurationRow[]>;
|
|
5
|
+
calculateTestDuration(runId: string, startTime: string, endTime: string): Promise<DurationMetric>;
|
|
6
|
+
extractVus(runId: string, startTime: string, endTime: string): Promise<VusMetric>;
|
|
7
|
+
extractVusMax(runId: string, startTime: string, endTime: string): Promise<VusMaxMetric>;
|
|
8
|
+
extractIterations(runId: string, startTime: string, endTime: string): Promise<IterationsMetric>;
|
|
9
|
+
extractChecks(runId: string, startTime: string, endTime: string): Promise<ChecksMetric>;
|
|
10
|
+
extractIterationDuration(runId: string, startTime: string, endTime: string): Promise<IterationDurationMetric>;
|
|
11
|
+
extractErrorResponsesText(runId: string, startTime: string, endTime: string): Promise<ErrorResponsesTextMetric>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=datasource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datasource.d.ts","sourceRoot":"","sources":["../../src/datasources/datasource.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,UAAU;IACzB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7F,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC3G,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAClG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClF,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACxF,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACxF,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC9G,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACjH"}
|