diff --git a/src/app/_services/chart-service-utils.ts b/src/app/_services/chart-service-utils.ts index 7cf255cb..680a51be 100644 --- a/src/app/_services/chart-service-utils.ts +++ b/src/app/_services/chart-service-utils.ts @@ -1,8 +1,9 @@ import { errorLineSettings, networkLineSettings, threadLineSettings, throughputLineSettings } from "../graphs/item-detail"; import { bytesToMbps } from "../item-detail/calculations"; import { Metrics } from "../item-detail/metrics"; +import { MonitoringData } from "../items.service.model"; -export const getChartLines = (plot): ChartLines => { +export const getChartLines = (plot, monitoringPlot: MonitoringData[]): ChartLines => { const { threads, overallTimeResponse, overallThroughput, overAllFailRate, overAllNetworkV2, @@ -20,6 +21,7 @@ export const getChartLines = (plot): ChartLines => { labels: new Map(), statusCodes: new Map(), scatter: new Map(), + monitoring: new Map(), }; if (overAllNetworkV2) { @@ -48,6 +50,10 @@ export const getChartLines = (plot): ChartLines => { chartLines.scatter.set(Metrics.ResponseTimeRaw, scatterPlotData) } + if (monitoringPlot && monitoringPlot.length > 0) { + chartLines.monitoring.set(Metrics.Monitoring, monitoringPlot) + } + if (networkV2) { const networkMbps = networkV2.map((_) => { _.data = _.data.map(__ => [__[0], bytesToMbps(__[1])]); @@ -83,7 +89,6 @@ export const getChartLines = (plot): ChartLines => { chartLines.labels.set(Metrics.Throughput, throughput.map((label) => ({ ...label, suffix: " reqs/s" }))); return { chartLines }; - }; @@ -95,10 +100,14 @@ export interface ChartLine { labels: Map; overall: Map; scatter: Map -} + threadsPerThreadGroup: Map + statusCodes:Map; + monitoring: Map +} export interface LabelChartLine { name: string data: [], suffix: string } + diff --git a/src/app/_services/comparison-chart.service.ts b/src/app/_services/comparison-chart.service.ts index 37f066cb..8d93f6d7 100644 --- a/src/app/_services/comparison-chart.service.ts +++ b/src/app/_services/comparison-chart.service.ts @@ -1,19 +1,20 @@ import { Injectable } from "@angular/core"; import { BehaviorSubject } from "rxjs"; -import { ChartLines, getChartLines } from "./chart-service-utils"; +import { ChartLine, getChartLines } from "./chart-service-utils"; +import { MonitoringData } from "../items.service.model"; @Injectable({ - providedIn: "root" + providedIn: 'root' }) export class ComparisonChartService { - private plot$ = new BehaviorSubject({ chartLines: null }); - private histogramPlot$ = new BehaviorSubject<{ responseTimePerLabelDistribution: []}>(null); + private plot$ = new BehaviorSubject({ chartLines: null, startDate: null, endDate: null }); + private histogramPlot$ = new BehaviorSubject<{ responseTimePerLabelDistribution: [] }>(null); private interval$ = new BehaviorSubject(null); selectedPlot$ = this.plot$.asObservable(); - histogram$ = this.histogramPlot$.asObservable() + histogram$ = this.histogramPlot$.asObservable(); setInterval(interval) { @@ -25,21 +26,31 @@ export class ComparisonChartService { } resetPlot() { - this.plot$.next(null) + this.plot$.next(null); } - setComparisonPlot(defaultPlot, extraPlots) { + setComparisonPlot(defaultPlot: ChartLine, extraPlots, startDate, endDate, monitoring: MonitoringData[]) { this.interval$.subscribe(interval => { - let comparisonPlot = null + let comparisonPlot: ChartLine = null; if (!interval || interval === "Auto") { - comparisonPlot = defaultPlot + comparisonPlot = defaultPlot; } else { - const extraPlotIntervalData = extraPlots?.find(extraPlot => extraPlot.interval === interval)?.data - comparisonPlot = extraPlotIntervalData || defaultPlot + const extraPlotIntervalData = extraPlots?.find(extraPlot => extraPlot.interval === interval)?.data; + comparisonPlot = extraPlotIntervalData || defaultPlot; } - this.plot$.next(comparisonPlot ? getChartLines(comparisonPlot): null) - }) + this.plot$.next({ + chartLines: comparisonPlot ? getChartLines(comparisonPlot, monitoring).chartLines : null, + startDate: startDate ? new Date(startDate) : null, + endDate: endDate ? new Date(endDate) : null, + }); + }); } } + +export interface ComparisonChartLines { + chartLines?: ChartLine; + startDate: Date; + endDate: Date; +} diff --git a/src/app/_services/item-chart.service.ts b/src/app/_services/item-chart.service.ts index 615ef1e7..2c5a5d32 100644 --- a/src/app/_services/item-chart.service.ts +++ b/src/app/_services/item-chart.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@angular/core"; import { BehaviorSubject } from "rxjs"; import { ChartLines, getChartLines } from "./chart-service-utils"; +import { MonitoringData } from "../items.service.model"; @Injectable({ providedIn: "root" @@ -13,8 +14,8 @@ export class ItemChartService { selectedPlot$ = this.plot.asObservable(); plotRange$ = this.plotRange.asObservable(); - setCurrentPlot(plot) { - this.plot.next(getChartLines(plot)); + setCurrentPlot(plot, monitoringPlot: MonitoringData[]) { + this.plot.next(getChartLines(plot, monitoringPlot)); } setPlotRange(plotRange: PlotRange) { diff --git a/src/app/graphs/item-detail.ts b/src/app/graphs/item-detail.ts index 29af6e25..d5649c74 100644 --- a/src/app/graphs/item-detail.ts +++ b/src/app/graphs/item-detail.ts @@ -279,10 +279,11 @@ export const networkLineSettings: any = { name: Metrics.Network }; -export const scatterChart = { +export const scatterChart = () => ({ chart: { type: "scatter", - zoomType: "xy" + zoomType: "xy", + marginTop: 50, }, title: { text: "" @@ -296,6 +297,8 @@ export const scatterChart = { }, xAxis: { showLastLabel: true, + min: null, + max: null, type: "datetime", legend: { enabled: false, @@ -338,4 +341,4 @@ export const scatterChart = { } } }, -}; +}); diff --git a/src/app/item-detail/analyze-charts/analyze-charts.component.spec.ts b/src/app/item-detail/analyze-charts/analyze-charts.component.spec.ts index e610ecbd..ffe8ef5b 100644 --- a/src/app/item-detail/analyze-charts/analyze-charts.component.spec.ts +++ b/src/app/item-detail/analyze-charts/analyze-charts.component.spec.ts @@ -33,7 +33,14 @@ describe("AnalyzeChartsComponent", () => { beforeEach(() => { fixture = TestBed.createComponent(AnalyzeChartsComponent); component = fixture.componentInstance; - component.chartLines = { labels: new Map([["test", [{ name: "test", data: [], suffix: " ms" }]]]), overall: new Map(), scatter: new Map() }; + component.chartLines = { + labels: new Map([["test", [{ name: "test", data: [], suffix: " ms" }]]]), + overall: new Map(), + scatter: new Map(), + threadsPerThreadGroup: new Map(), + monitoring: new Map(), + statusCodes: new Map(), + }; component.params = { projectName: "test-project", scenarioName: "test-scenario", id: "test-item" }; fixture.detectChanges(); }); diff --git a/src/app/item-detail/chart-interval/chart-interval.component.ts b/src/app/item-detail/chart-interval/chart-interval.component.ts index 508a026e..8dbfb2c3 100644 --- a/src/app/item-detail/chart-interval/chart-interval.component.ts +++ b/src/app/item-detail/chart-interval/chart-interval.component.ts @@ -29,7 +29,7 @@ export class ChartIntervalComponent implements OnInit { } else { newPlotData = this.intervals.extraIntervals.find(interval => interval.interval === inputInterval)?.data } - this.itemChartService.setCurrentPlot(newPlotData) + this.itemChartService.setCurrentPlot(newPlotData, null) } } diff --git a/src/app/item-detail/item-chart-option.ts b/src/app/item-detail/item-chart-option.ts new file mode 100644 index 00000000..d1e8081c --- /dev/null +++ b/src/app/item-detail/item-chart-option.ts @@ -0,0 +1,23 @@ +export class ItemChartOption { + public overallChart = null + public threadsPerThreadGroup = null + public scatterChartOptions = null + public statusChartOptions = null + + setChartsOptions(options: { overallChart: any, threadsPerThreadGroup: any, scatterChartOptions: any, statusChartOptions: any }) { + if (!options) { + return + } + this.overallChart = options.overallChart + this.threadsPerThreadGroup = options.threadsPerThreadGroup + this.scatterChartOptions = options.scatterChartOptions + this.statusChartOptions = options.statusChartOptions + } + + resetChartOptions() { + this.overallChart = null + this.threadsPerThreadGroup = null + this.scatterChartOptions = null + this.statusChartOptions = null + } +} diff --git a/src/app/item-detail/item-detail.component.html b/src/app/item-detail/item-detail.component.html index dc726020..d76e5db0 100644 --- a/src/app/item-detail/item-detail.component.html +++ b/src/app/item-detail/item-detail.component.html @@ -401,6 +401,16 @@
Overall Chart [(update)]="updateOverallChartFlag" style="width: 100%; height: 350px; display: block;"> + + + +
+ + +
+ @@ -419,6 +429,20 @@
[(update)]="updateScatterChartFlag" style="width: 100%; height: 350px; display: block;"> + + + + + + + +
+ + + +
@@ -437,6 +461,16 @@
Status Codes Chart
[(update)]="updateChartFlag" style="width: 100%; height: 350px; display: block;"> + + + + +
+ + +
diff --git a/src/app/item-detail/item-detail.component.ts b/src/app/item-detail/item-detail.component.ts index 65df30fc..39a0d906 100644 --- a/src/app/item-detail/item-detail.component.ts +++ b/src/app/item-detail/item-detail.component.ts @@ -17,19 +17,22 @@ import { Metrics } from "./metrics"; import { AnalyzeChartService } from "../analyze-chart.service"; import { getValidationResults } from "../utils/showZeroErrorTolerance"; import { ItemChartService } from "../_services/item-chart.service"; +import { ComparisonChartService } from "../_services/comparison-chart.service"; +import { ChartLine } from "../_services/chart-service-utils"; +import { ItemChartOption } from "./item-chart-option"; exporting(Highcharts); @Component({ - selector: "app-item-detail", - templateUrl: "./item-detail.component.html", - styleUrls: ["./item-detail.component.scss", "../shared-styles.css"], + selector: 'app-item-detail', + templateUrl: './item-detail.component.html', + styleUrls: ['./item-detail.component.scss', '../shared-styles.css'], providers: [DecimalPipe] }) export class ItemDetailComponent implements OnInit, OnDestroy { - @ViewChild("overallChart") componentRef; + @ViewChild('overallChart') componentRef; Highcharts: typeof Highcharts = Highcharts; chart: Highcharts.Chart; @@ -84,7 +87,13 @@ export class ItemDetailComponent implements OnInit, OnDestroy { zeroErrorValidation: null, minTestDurationValidation: null, }; - + comparisonItemChartOptions = new ItemChartOption() + comparisonChart: Highcharts.Chart; + scatterChart: Highcharts.Chart; + updateComparisonChartFlag = false; + updateComparisonScatterChartFlag = false; + comparisonChartCallback; + comparisonScatterChartCallback constructor( private route: ActivatedRoute, @@ -94,11 +103,18 @@ export class ItemDetailComponent implements OnInit, OnDestroy { private toastr: ToastrService, private analyzeChartService: AnalyzeChartService, private itemChartService: ItemChartService, + private comparisonChartService: ComparisonChartService, ) { this.Math = Math; this.overallChartCallback = chart => { this.overallChart = chart; }; + this.comparisonChartCallback = chart => { + this.comparisonChart = chart; + }; + this.comparisonScatterChartCallback = chart => { + this.scatterChart = chart; + }; } @@ -129,15 +145,17 @@ export class ItemDetailComponent implements OnInit, OnDestroy { .subscribe((results) => { this.itemData = results; this.monitoringAlerts(); - this.itemChartService.setCurrentPlot(this.itemData.plot); + this.itemChartService.setCurrentPlot(this.itemData.plot, this.itemData.monitoring.cpu.data); this.selectedPlotSubscription(); this.plotRangeSubscription(); + this.comparisonSubscription(); this.calculateTotalRequests(); const validations = this.showValidationWarning(this.itemData); this.validations = { zeroErrorValidation: validations.zeroErrorToleranceValidation, minTestDurationValidation: validations.minTestDurationValidation }; + this; this.spinner.hide(); }); this.analyzeChartService.currentData.subscribe(data => { @@ -154,41 +172,18 @@ export class ItemDetailComponent implements OnInit, OnDestroy { ngOnDestroy() { this.toastr.clear(); + this.comparisonChartService.resetPlot() } private selectedPlotSubscription() { this.itemChartService.selectedPlot$.subscribe((value) => { this.chartLines = value.chartLines; - if (this.chartLines) { - const overallChartSeries = Array.from(this.chartLines?.overall?.values()); - if (this.chartLines.threadsPerThreadGroup.has(Metrics.Threads)) { - this.threadsPerThreadGroup = this.chartLines.threadsPerThreadGroup.get(Metrics.Threads); - } - - - this.overallChartOptions.series = JSON.parse(JSON.stringify(overallChartSeries)); - const scatterResponseTimeData = value.chartLines.scatter.get(Metrics.ResponseTimeRaw); - - if (this.chartLines?.scatter?.has(Metrics.ResponseTimeRaw)) { - this.scatterChartOptions = scatterChart; - this.scatterChartOptions.series = [{ - data: scatterResponseTimeData, name: "Response Time", marker: { - radius: 1 - }, - }]; - this.updateScatterChartFlag = true; - } - - if (this.chartLines?.statusCodes?.has(Metrics.StatusCodeInTime)) { - // initialize the chart options only when there are the status codes data - this.statusChartOptions = { - ...commonGraphSettings("") - }; - const statusCodesLines = this.chartLines?.statusCodes.get(Metrics.StatusCodeInTime); - this.statusChartOptions.series = JSON.parse(JSON.stringify(statusCodesLines.data)); - } - } - + const chartOptions = this.prepareChartOptions(value.chartLines) + this.threadsPerThreadGroup = chartOptions.threadsPerThreadGroup + this.overallChartOptions = chartOptions.overallChart + this.statusChartOptions = chartOptions.statusChartOptions + this.scatterChartOptions = chartOptions.scatterChartOptions + this.updateScatterChartFlag = true; this.updateChartFlag = true; }); } @@ -203,6 +198,71 @@ export class ItemDetailComponent implements OnInit, OnDestroy { }); } + private comparisonSubscription() { + this.comparisonChartService.selectedPlot$.subscribe((plot) => { + this.comparisonItemChartOptions.resetChartOptions(); + if (!plot) { + this.comparisonChart = null; + return; + } else { + this.comparisonItemChartOptions.setChartsOptions(this.prepareChartOptions(plot.chartLines, plot.startDate, plot.endDate)); + } + this.updateComparisonChartFlag = true; + this.updateComparisonScatterChartFlag = true + }); + } + + private prepareChartOptions(plot: ChartLine, startDate?: Date, endDate?: Date) { + const chartOptions = { + overallChart: null, + threadsPerThreadGroup: null, + scatterChartOptions: null, + statusChartOptions: null, + } + if (plot) { + if(plot.overall) { + const overallChartSeries = Array.from(plot.overall?.values()); + if (plot.threadsPerThreadGroup.has(Metrics.Threads)) { + chartOptions.threadsPerThreadGroup = plot.threadsPerThreadGroup.get(Metrics.Threads); + } + + chartOptions.overallChart = { + ...overallChartSettings("ms"), + series: JSON.parse(JSON.stringify(overallChartSeries)) + }; + } + + const scatterResponseTimeData = plot.scatter.get(Metrics.ResponseTimeRaw); + if (scatterResponseTimeData) { + chartOptions.scatterChartOptions = { + ...scatterChart(), + series: [{ + data: scatterResponseTimeData, name: "Response Time", marker: { + radius: 1 + }, + }] + }; + if (startDate && endDate) { + chartOptions.scatterChartOptions.xAxis.min = startDate.getTime() + chartOptions.scatterChartOptions.xAxis.max = endDate.getTime() + } + + + } + + if (plot?.statusCodes?.has(Metrics.StatusCodeInTime)) { + // initialize the chart options only when there are the status codes data + chartOptions.statusChartOptions = { + ...commonGraphSettings("") + }; + const statusCodesLines = plot?.statusCodes.get(Metrics.StatusCodeInTime); + chartOptions.statusChartOptions.series = JSON.parse(JSON.stringify(statusCodesLines.data)); + } + } + + return chartOptions; + } + private updateMinMaxOfCharts(min, max) { if (min && max) { this.plotRangeMin = min; diff --git a/src/app/item-detail/label-chart/label-chart.component.spec.ts b/src/app/item-detail/label-chart/label-chart.component.spec.ts index 766f7577..e88158f8 100644 --- a/src/app/item-detail/label-chart/label-chart.component.spec.ts +++ b/src/app/item-detail/label-chart/label-chart.component.spec.ts @@ -24,7 +24,10 @@ describe("LabelChartComponent", () => { component.chartLines = { labels: new Map([[Metrics.Network, [{ name: "name", suffix: "mbps", data: [] }] ]]), overall: new Map([[Metrics.Threads, { name: "virtual-users", data: [] }]]), - scatter: new Map([[Metrics.ResponseTimeRaw, [] ]]) + scatter: new Map([[Metrics.ResponseTimeRaw, [] ]]), + threadsPerThreadGroup: new Map([[Metrics.Threads, []]]), + monitoring: new Map([[Metrics.Monitoring, []]]), + statusCodes: new Map([[Metrics.StatusCodeInTime, { name: "name", data: [] }]]) }; fixture.detectChanges(); }); diff --git a/src/app/item-detail/label-chart/label-chart.component.ts b/src/app/item-detail/label-chart/label-chart.component.ts index f0a0b76d..efe9d527 100644 --- a/src/app/item-detail/label-chart/label-chart.component.ts +++ b/src/app/item-detail/label-chart/label-chart.component.ts @@ -150,7 +150,9 @@ export class LabelChartComponent implements OnChanges { this.labelCharts.set("Histogram", responseTimeDistribution(histogram.values)); } else { const histogram = histogramData.find(data => data.label === this.label); - this.comparisonLabelCharts.set("Histogram", responseTimeDistribution(histogram.values)); + if (histogram && histogram.data) { + this.comparisonLabelCharts.set("Histogram", responseTimeDistribution(histogram.values)); + } } } diff --git a/src/app/item-detail/metrics.ts b/src/app/item-detail/metrics.ts index f57e7549..51c16285 100644 --- a/src/app/item-detail/metrics.ts +++ b/src/app/item-detail/metrics.ts @@ -14,4 +14,5 @@ export enum Metrics { ResponseTimeRaw = "Raw Response Time", LatencyAvg = "Latency [avg]", ConnectAvg = "Connection [avg]", + Monitoring = "Monitoring" } diff --git a/src/app/item-detail/monitoring-stats/monitoring-stats.component.css b/src/app/item-detail/monitoring-stats/monitoring-stats.component.css index db9e4665..f1d7a1a9 100644 --- a/src/app/item-detail/monitoring-stats/monitoring-stats.component.css +++ b/src/app/item-detail/monitoring-stats/monitoring-stats.component.css @@ -16,3 +16,7 @@ .card { margin-top: 20px; } + +.compare-chart{ + margin-top: 3rem; +} diff --git a/src/app/item-detail/monitoring-stats/monitoring-stats.component.html b/src/app/item-detail/monitoring-stats/monitoring-stats.component.html index df506f4b..d7511f39 100644 --- a/src/app/item-detail/monitoring-stats/monitoring-stats.component.html +++ b/src/app/item-detail/monitoring-stats/monitoring-stats.component.html @@ -9,6 +9,17 @@
Monitoring
[(update)]="updateFlag" [constructorType]="chartConstructor" style="width: auto; height: 400px; display: block;"> + + + + +
+ +
+ + diff --git a/src/app/item-detail/monitoring-stats/monitoring-stats.component.ts b/src/app/item-detail/monitoring-stats/monitoring-stats.component.ts index 000de2e4..0c7485d1 100644 --- a/src/app/item-detail/monitoring-stats/monitoring-stats.component.ts +++ b/src/app/item-detail/monitoring-stats/monitoring-stats.component.ts @@ -1,14 +1,16 @@ import { Component, OnInit, Input, } from "@angular/core"; -import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; import * as Highcharts from "highcharts"; import { monitoringGraphSettings } from "src/app/graphs/monitoring"; import { from } from "rxjs"; +import { ComparisonChartService } from "../../_services/comparison-chart.service"; +import { MonitoringData } from "../../items.service.model"; +import { Metrics } from "../metrics"; @Component({ - selector: "app-monitoring-stats", - templateUrl: "./monitoring-stats.component.html", - styleUrls: ["./monitoring-stats.component.css", "../item-detail.component.scss", "../../shared-styles.css"] + selector: 'app-monitoring-stats', + templateUrl: './monitoring-stats.component.html', + styleUrls: ['./monitoring-stats.component.css', '../item-detail.component.scss', '../../shared-styles.css'] }) export class MonitoringStatsComponent implements OnInit { Highcharts: typeof Highcharts = Highcharts; @@ -16,26 +18,44 @@ export class MonitoringStatsComponent implements OnInit { chartConstructor = "chart"; chartCallback; updateFlag = false; + updateComparisonChartFlag = false; + monitoringComparisonChartOptions; chart; - constructor( - private modalService: NgbModal, + constructor( + private comparisonChartService: ComparisonChartService, ) { this.chartCallback = chart => { this.chart = chart; }; } - @Input() data: [{ name: string, timestamp: Date, avgCpu: number, avgMem: number }]; + @Input() data: MonitoringData[]; ngOnInit() { - this.prepareChart() + const series = this.prepareChartSeries(this.data); + from(new Promise(resolve => setTimeout(resolve, 50))).subscribe((val: any) => { + this.monitoringChartOptions = { + ...monitoringGraphSettings(), series: series + }; + this.updateFlag = true; + }); + this.comparisonChartService.selectedPlot$.subscribe(plot => { + if (plot && plot?.chartLines?.monitoring.has(Metrics.Monitoring)) { + const comparisonSeries = this.prepareChartSeries(plot?.chartLines.monitoring.get(Metrics.Monitoring)); + this.monitoringComparisonChartOptions = { + ...monitoringGraphSettings(), + series: comparisonSeries, + }; + this.updateComparisonChartFlag = true; + } + }); } - prepareChart() { - const workers = Array.from(new Set(this.data.map(data => data.name))); - const series = workers.map((worker) => this.data + prepareChartSeries(data: MonitoringData[]) { + const workers = Array.from(new Set(data.map(data => data.name))); + return workers.map((worker) => data .filter(data => data.name === worker) .reduce((acc, current) => { acc.data.cpu.push([current.timestamp, current.avgCpu]); @@ -45,12 +65,5 @@ export class MonitoringStatsComponent implements OnInit { }, { data: { cpu: [], mem: [] }, name: null })) .map((worker) => [{ data: worker.data.cpu, name: worker.name + " - cpu" }, { data: worker.data.mem, name: worker.name + " - mem" }]) .flat(); - - from(new Promise(resolve => setTimeout(resolve, 50))).subscribe((val: any) => { - this.monitoringChartOptions = { - ...monitoringGraphSettings(), series: series - }; - this.updateFlag = true; - }); } } diff --git a/src/app/item-detail/stats-compare/stats-compare.component.ts b/src/app/item-detail/stats-compare/stats-compare.component.ts index dc2904bf..122c28a7 100644 --- a/src/app/item-detail/stats-compare/stats-compare.component.ts +++ b/src/app/item-detail/stats-compare/stats-compare.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit, Output, EventEmitter, Input } from "@angular/core"; +import { Component, OnInit, Input } from "@angular/core"; import { NgbModal } from "@ng-bootstrap/ng-bootstrap"; import { ItemsService } from "src/app/items.service"; import { ActivatedRoute, Params } from "@angular/router"; -import { Observable, Subscription } from "rxjs"; +import { Observable } from "rxjs"; import { IScenarios, ItemDetail, Items } from "src/app/items.service.model"; import { ItemsApiService } from "src/app/items-api.service"; import { ComparisonChartService } from "../../_services/comparison-chart.service"; @@ -84,7 +84,10 @@ export class StatsCompareComponent implements OnInit { environment: _.environment, plot: _.plot, histogramPlotData: _.histogramPlotData, - extraPlotData: _.extraPlotData + extraPlotData: _.extraPlotData, + startDate: _.overview.startDate, + endDate: _.overview.endDate, + monitoring: _.monitoring, }); this.page = 0; this.modalService.dismissAll(); @@ -103,13 +106,16 @@ export class StatsCompareComponent implements OnInit { plot: _.plot, histogramPlotData: _.histogramPlotData, extraPlotData: _.extraPlotData, + startDate: _.overview.startDate, + endDate: _.overview.endDate, + monitoring: _.monitoring, id })); } itemToCompare(data) { this.resetStatsData(); - this.comparisonChartService.setComparisonPlot(data.plot, data.extraPlotData); + this.comparisonChartService.setComparisonPlot(data.plot, data.extraPlotData, data.startDate, data.endDate, data.monitoring?.cpu?.data); this.comparisonChartService.setHistogramPlot(data.histogramPlotData); this.comparingData = data; this.comparedMetadata = { id: data.id, maxVu: data.maxVu }; @@ -145,7 +151,6 @@ export class StatsCompareComponent implements OnInit { } loadScenario(event) { - console.log(event.target.value) const scenario = event.target.value this.selectedScenario = scenario this.itemsService.fetchItems(this.params.projectName, scenario, { limit: LIMIT, offset: 0 }); diff --git a/src/app/items.service.model.ts b/src/app/items.service.model.ts index 31bb4161..2af41cda 100644 --- a/src/app/items.service.model.ts +++ b/src/app/items.service.model.ts @@ -31,7 +31,7 @@ export interface ItemDetail { zeroErrorToleranceEnabled: boolean; reportStatus: ReportStatus; monitoring: { - cpu: { data: { name: string, cpu: number, timestamp: number }[], max?: number } + cpu: { data: MonitoringData[], max?: number } }; baseId: string; name: string; @@ -62,9 +62,9 @@ export interface ItemDetail { userSettings: { requestStats: RequestStats }; - errorSummary: ErrorSummary - status: string - minTestDuration: number + errorSummary: ErrorSummary; + status: string; + minTestDuration: number; } interface TopMetricsSettings { @@ -78,7 +78,7 @@ interface TopMetricsSettings { percentile: boolean; // legacy setting percentile90: boolean; percentile95: boolean; - percentile99: boolean + percentile99: boolean; } interface ItemOverview { @@ -146,9 +146,9 @@ export interface ItemStatistics { satisfaction?: number toleration?: number }; - medianResponseTime?: number - bytesPerSecond?: number - bytesSentPerSecond?: number + medianResponseTime?: number; + bytesPerSecond?: number; + bytesSentPerSecond?: number; } interface ResponseMessageFailure { @@ -156,16 +156,6 @@ interface ResponseMessageFailure { responseMessage: string; } -interface MonitoringData { - "bytes-recv"?: string; - "bytes-sent"?: string; - "conn-all"?: string; - cpu?: string; - "diskSpace"?: string; - mem?: string; - ts?: string; -} - export interface ScenarioTrendsData { overview: { avgConnect: number; @@ -338,37 +328,46 @@ export interface ThresholdResult { errorRate: { diffValue: number, passed: boolean - } + }; percentile: { diffValue: number, passed: boolean - } + }; throughput: { diffValue: number, passed: boolean - } + }; } export interface ErrorSummary { - groupedErrors: Errors[] - topErrorsByLabel: Top5Errors[] + groupedErrors: Errors[]; + topErrorsByLabel: Top5Errors[]; } interface Errors { - count: number - statusCode: string - responseMessage: string - failureMessage: string + count: number; + statusCode: string; + responseMessage: string; + failureMessage: string; } interface Top5Errors { - label: string - error1: LabelError - error2: LabelError - error3: LabelError - error4: LabelError - error5: LabelError + label: string; + error1: LabelError; + error2: LabelError; + error3: LabelError; + error4: LabelError; + error5: LabelError; } -interface LabelError { count: number; error: string } +interface LabelError { + count: number; + error: string; +} +export interface MonitoringData { + name: string, + avgCpu: number, + avgMem?: number, + timestamp: number +}