diff --git a/src/app/_services/comparison-chart.service.ts b/src/app/_services/comparison-chart.service.ts index 37f066c..3174f41 100644 --- a/src/app/_services/comparison-chart.service.ts +++ b/src/app/_services/comparison-chart.service.ts @@ -1,19 +1,19 @@ import { Injectable } from "@angular/core"; import { BehaviorSubject } from "rxjs"; -import { ChartLines, getChartLines } from "./chart-service-utils"; +import { ChartLine, getChartLines } from "./chart-service-utils"; @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 +25,31 @@ export class ComparisonChartService { } resetPlot() { - this.plot$.next(null) + this.plot$.next(null); } - setComparisonPlot(defaultPlot, extraPlots) { + setComparisonPlot(defaultPlot: ChartLine, extraPlots, startDate, endDate) { 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).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/graphs/item-detail.ts b/src/app/graphs/item-detail.ts index 232a720..d5649c7 100644 --- a/src/app/graphs/item-detail.ts +++ b/src/app/graphs/item-detail.ts @@ -279,7 +279,7 @@ export const networkLineSettings: any = { name: Metrics.Network }; -export const scatterChart = { +export const scatterChart = () => ({ chart: { type: "scatter", zoomType: "xy", @@ -297,6 +297,8 @@ export const scatterChart = { }, xAxis: { showLastLabel: true, + min: null, + max: null, type: "datetime", legend: { enabled: false, @@ -339,4 +341,4 @@ export const scatterChart = { } } }, -}; +}); 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 0000000..d1e8081 --- /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 33699f6..d76e5db 100644 --- a/src/app/item-detail/item-detail.component.html +++ b/src/app/item-detail/item-detail.component.html @@ -402,11 +402,11 @@
Overall Chart style="width: 100%; height: 350px; display: block;"> - + -
+
-
@@ -430,14 +430,18 @@
style="width: 100%; height: 350px; display: block;"> - -
- + + +
+ + +
@@ -458,12 +462,12 @@
Status Codes Chart
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 0853624..712f049 100644 --- a/src/app/item-detail/item-detail.component.ts +++ b/src/app/item-detail/item-detail.component.ts @@ -18,7 +18,8 @@ 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 { ChartLines } from "../_services/chart-service-utils"; +import { ChartLine } from "../_services/chart-service-utils"; +import { ItemChartOption } from "./item-chart-option"; exporting(Highcharts); @@ -86,21 +87,13 @@ export class ItemDetailComponent implements OnInit, OnDestroy { zeroErrorValidation: null, minTestDurationValidation: null, }; - comparisonChartOptionsDefault = { - overallChart: null, - threadsPerThreadGroup: null, - scatterChartOptions: null, - statusChartOptions: null, - }; - comparisonLabelChartOptions = { - overallChart: null, - threadsPerThreadGroup: null, - scatterChartOptions: null, - statusChartOptions: null, - }; + comparisonItemChartOptions = new ItemChartOption() comparisonChart: Highcharts.Chart; - updateComparisonChartFlag; + scatterChart: Highcharts.Chart; + updateComparisonChartFlag = false; + updateComparisonScatterChartFlag = false; comparisonChartCallback; + comparisonScatterChartCallback constructor( private route: ActivatedRoute, @@ -119,6 +112,9 @@ export class ItemDetailComponent implements OnInit, OnDestroy { this.comparisonChartCallback = chart => { this.comparisonChart = chart; }; + this.comparisonScatterChartCallback = chart => { + this.scatterChart = chart; + }; } @@ -182,7 +178,7 @@ export class ItemDetailComponent implements OnInit, OnDestroy { private selectedPlotSubscription() { this.itemChartService.selectedPlot$.subscribe((value) => { this.chartLines = value.chartLines; - const chartOptions = this.prepareChartOptions(value) + const chartOptions = this.prepareChartOptions(value.chartLines) this.threadsPerThreadGroup = chartOptions.threadsPerThreadGroup this.overallChartOptions = chartOptions.overallChart this.statusChartOptions = chartOptions.statusChartOptions @@ -204,54 +200,67 @@ export class ItemDetailComponent implements OnInit, OnDestroy { private comparisonSubscription() { this.comparisonChartService.selectedPlot$.subscribe((plot) => { + this.comparisonItemChartOptions.resetChartOptions(); if (!plot) { - if (this.comparisonChart) { - this.comparisonLabelChartOptions = this.comparisonChartOptionsDefault; - this.comparisonChart = null; - } + this.comparisonChart = null; return; + } else { + this.comparisonItemChartOptions.setChartsOptions(this.prepareChartOptions(plot.chartLines, plot.startDate, plot.endDate)); } - this.comparisonLabelChartOptions = this.prepareChartOptions(plot) - this.updateChartFlag = true; - this.updateScatterChartFlag = true; + this.updateComparisonChartFlag = true; + this.updateComparisonScatterChartFlag = true }); } - private prepareChartOptions(plot: ChartLines) { - const chartOptions = this.comparisonChartOptionsDefault - if (plot.chartLines) { - const overallChartSeries = Array.from(this.chartLines?.overall?.values()); - if (plot.chartLines.threadsPerThreadGroup.has(Metrics.Threads)) { - chartOptions.threadsPerThreadGroup = plot.chartLines.threadsPerThreadGroup.get(Metrics.Threads); - } + 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)) - }; + 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() + } - const scatterResponseTimeData = plot.chartLines.scatter.get(Metrics.ResponseTimeRaw); - if (plot.chartLines?.scatter?.has(Metrics.ResponseTimeRaw)) { - chartOptions.scatterChartOptions = scatterChart; - chartOptions.scatterChartOptions.series = [{ - data: scatterResponseTimeData, name: "Response Time", marker: { - radius: 1 - }, - }]; } - if (plot.chartLines?.statusCodes?.has(Metrics.StatusCodeInTime)) { + if (plot?.statusCodes?.has(Metrics.StatusCodeInTime)) { // initialize the chart options only when there are the status codes data chartOptions.statusChartOptions = { ...commonGraphSettings("") }; - const statusCodesLines = plot.chartLines?.statusCodes.get(Metrics.StatusCodeInTime); + const statusCodesLines = plot?.statusCodes.get(Metrics.StatusCodeInTime); chartOptions.statusChartOptions.series = JSON.parse(JSON.stringify(statusCodesLines.data)); } - return chartOptions; } + + return chartOptions; } private updateMinMaxOfCharts(min, max) { 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 f0a0b76..efe9d52 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/stats-compare/stats-compare.component.ts b/src/app/item-detail/stats-compare/stats-compare.component.ts index dc2904b..bda4874 100644 --- a/src/app/item-detail/stats-compare/stats-compare.component.ts +++ b/src/app/item-detail/stats-compare/stats-compare.component.ts @@ -84,7 +84,9 @@ export class StatsCompareComponent implements OnInit { environment: _.environment, plot: _.plot, histogramPlotData: _.histogramPlotData, - extraPlotData: _.extraPlotData + extraPlotData: _.extraPlotData, + startDate: _.overview.startDate, + endDate: _.overview.endDate, }); this.page = 0; this.modalService.dismissAll(); @@ -103,13 +105,15 @@ export class StatsCompareComponent implements OnInit { plot: _.plot, histogramPlotData: _.histogramPlotData, extraPlotData: _.extraPlotData, + startDate: _.overview.startDate, + endDate: _.overview.endDate, id })); } itemToCompare(data) { this.resetStatsData(); - this.comparisonChartService.setComparisonPlot(data.plot, data.extraPlotData); + this.comparisonChartService.setComparisonPlot(data.plot, data.extraPlotData, data.startDate, data.endDate); this.comparisonChartService.setHistogramPlot(data.histogramPlotData); this.comparingData = data; this.comparedMetadata = { id: data.id, maxVu: data.maxVu };