From 57f73cbe53f454da74f842babea0d722ab5ba9ab Mon Sep 17 00:00:00 2001 From: Ludek Novy <13610612+ludeknovy@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:48:35 +0200 Subject: [PATCH] Add comparison chart integration to item-detail component (#420) * Add comparison chart integration to item-detail component * Add date range to charts and refactor chart options Integrated start and end date parameters into the charts to allow for date range filtering. Refactored chart option handling by introducing the `ItemChartOption` class, improving code organization and readability. * Monitoring comparison chart * tests fixes --- src/app/_services/chart-service-utils.ts | 15 +- src/app/_services/comparison-chart.service.ts | 37 +++-- src/app/_services/item-chart.service.ts | 5 +- src/app/graphs/item-detail.ts | 9 +- .../analyze-charts.component.spec.ts | 9 +- .../chart-interval.component.ts | 2 +- src/app/item-detail/item-chart-option.ts | 23 +++ .../item-detail/item-detail.component.html | 34 +++++ src/app/item-detail/item-detail.component.ts | 132 +++++++++++++----- .../label-chart/label-chart.component.spec.ts | 5 +- .../label-chart/label-chart.component.ts | 4 +- src/app/item-detail/metrics.ts | 1 + .../monitoring-stats.component.css | 4 + .../monitoring-stats.component.html | 11 ++ .../monitoring-stats.component.ts | 49 ++++--- .../stats-compare/stats-compare.component.ts | 15 +- src/app/items.service.model.ts | 67 +++++---- 17 files changed, 304 insertions(+), 118 deletions(-) create mode 100644 src/app/item-detail/item-chart-option.ts 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 +}