Skip to content

Commit

Permalink
perf analysis (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeknovy authored Mar 5, 2021
1 parent ff86adc commit efcb0db
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 22 deletions.
61 changes: 48 additions & 13 deletions src/app/item-detail/item-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,19 @@
<div class="row">
<div class="col">
<ng-template #tipContent>
<p>90 percentile decrease toleration: {{itemData.thresholds.thresholds.percentile}} %
</p>
<p>
Througput decrease toleration: {{itemData.thresholds.thresholds.throughput}}%
</p>
<p>
Error rate increase toleration: {{itemData.thresholds.thresholds.errorRate}}%
</p>
<p>90 percentile decrease toleration: {{itemData.thresholds.thresholds.percentile}} %
</p>
<p>
Througput decrease toleration: {{itemData.thresholds.thresholds.throughput}}%
</p>
<p>
Error rate increase toleration: {{itemData.thresholds.thresholds.errorRate}}%
</p>
</ng-template>
<div *ngIf="itemData.thresholds && !itemData.thresholds?.passed" class="card perf-issue">
<div class="card-body perf-issue">
<div class="card-body">
<h6 class="card-title text-alizarin">Performance regression issue detected! <i class="ttp text-secondary"
placement="bottom"
[ngbTooltip]="tipContent"><i
class="far fa-question-circle icon"></i></i></h6>
placement="bottom" [ngbTooltip]="tipContent"><i class="far fa-question-circle icon"></i></i></h6>
<ul>
<li *ngIf="!itemData.thresholds.result.percentile.passed"> 90 percentile response time is about {{
Math.round(itemData.thresholds.result.percentile.diffValue - 100) }}% slower than the average.
Expand All @@ -87,6 +85,42 @@ <h6 class="card-title text-alizarin">Performance regression issue detected! <i c
</div>
</div>

<div class="row">
<div class="col">
<div class="card" [ngClass]="(perfAnalysis.onePerc.failed || perfAnalysis.variability.failed) ? 'performance-analysis-warning' : 'performance-analysis-success'">
<div class="card-body">
<h6 class="overview-body">Performance Analysis</h6>
<div>
<div><i
[ngClass]="(perfAnalysis.onePerc.failed===true) ? 'fas fa-exclamation-triangle text-warning' : 'far fa-check-circle text-success'"></i>
Slowest responses</div>
<div *ngIf="perfAnalysis.onePerc.failed===false" class="perf-analaysis-desc text-secondary">
The 1% of slowest responses do not have a significant deviation from the average response time.
</div>
<div *ngIf="perfAnalysis.onePerc.failed===true" class="perf-analaysis-desc text-secondary">
The 1% of response times shows up to {{ perfAnalysis.onePerc.value }}x slower response times than the
average. This might mean a performance issue for some clients and indicates that SUT might have been
overloaded.
</div>
</div>

<div class="perf-analysis-check">
<div><i
[ngClass]="(perfAnalysis.variability.failed===true) ? 'fas fa-exclamation-triangle text-warning' : 'far fa-check-circle text-success'"></i>
Steady performance</div>
<div *ngIf="perfAnalysis.variability.failed===true" class="perf-analaysis-desc text-secondary">
Increased variability between the fastest and the average response time was detected (up to {{perfAnalysis.variability.value}}x). The SUT might have been overloaded.
</div>
<div *ngIf="perfAnalysis.variability.failed===false" class="perf-analaysis-desc text-secondary">
The SUT was providing balanced response times across all labels.
</div>
</div>
</div>
</div>
</div>

</div>

<div class="row">
<div class="col-sm">
<div class="card">
Expand Down Expand Up @@ -180,7 +214,8 @@ <h2 *ngIf="itemData.overview.avgConnect < 1000 && itemData.overview.avgConnect >
<div class="col-sm" *ngIf="itemData.overview.bytesPerSecond && itemData.overview.bytesPerSecond !== 0">
<div class="card">
<div class="card-body overview-body">
<h2 class="card-title text-latency">{{bytesToMbps(itemData.overview.bytesPerSecond)}} <span class="unit-desc">Mbps</span>
<h2 class="card-title text-latency">{{bytesToMbps(itemData.overview.bytesPerSecond)}} <span
class="unit-desc">Mbps</span>
</h2>
</div>
<div class="card-footer bg-transparent card-footer-overview">Network data</div>
Expand Down
19 changes: 18 additions & 1 deletion src/app/item-detail/item-detail.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,26 @@ thead .hd {
}

.perf-issue {
border-left: 2px solid #e74c3c;
border-left: 4px solid #e74c3c;
}

.perf-issue .card-body h6 {
font-size: 1rem !important;
}

.perf-analysis-check {
margin-top: 10px;
}

.perf-analaysis-desc {
margin-left: 20px;
}

.performance-analysis-warning{
border-left: 4px solid #ffc107;

}

.performance-analysis-success{
border-left: 4px solid #28a745;
}
42 changes: 38 additions & 4 deletions src/app/item-detail/item-detail.component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ItemsApiService } from '../items-api.service';
import { ItemDetail } from '../items.service.model';
import { ItemDetail, ItemStatistics } from '../items.service.model';
import { NgxSpinnerService } from 'ngx-spinner';
import { DecimalPipe } from '@angular/common';
import * as Highcharts from 'highcharts';
Expand Down Expand Up @@ -57,6 +57,7 @@ export class ItemDetailComponent implements OnInit {
comparisonWarning = [];
token: string;
isAnonymous = false;
perfAnalysis = { variability: null, onePerc: null };

constructor(
private route: ActivatedRoute,
Expand Down Expand Up @@ -87,8 +88,8 @@ export class ItemDetailComponent implements OnInit {
this.itemParams.projectName,
this.itemParams.scenarioName,
this.itemParams.id,
{ token: this.token}
)
{ token: this.token }
)
.pipe(catchError(r => {
this.spinner.hide();
return of(r);
Expand All @@ -97,6 +98,7 @@ export class ItemDetailComponent implements OnInit {
this.itemData = results;
this.labelsData = this.itemData.statistics;
this.hasErrorsAttachment = this.itemData.attachements.find((_) => _ === 'error');
this.performanceAnalaysis();
this.monitoringAlerts();
this.generateCharts();
this.spinner.hide();
Expand Down Expand Up @@ -243,7 +245,39 @@ export class ItemDetailComponent implements OnInit {
return Math.round(number * 100) / 100;
}

private performanceAnalaysis() {
const output = [];
this.itemData.statistics.forEach(_ => {
const variability = this.roundNumberTwoDecimals(_.avgResponseTime / _.minResponseTime);
const onePerc = this.roundNumberTwoDecimals(_.n9 / _.avgResponseTime);
output.push({
variability,
onePerc,
minResponseTime: _.minResponseTime,
avgResponseTime: _.avgResponseTime,
label: _.label
});
});

const variabilitySorted = output.sort((a, b) => b.variablity - a.variablity);
const onePercSorted = output.sort((a, b) => b.onePerc - a.onePerc);

this.perfAnalysis = {
variability: {
value: variabilitySorted[0].variability,
avgResponseTime: variabilitySorted[0].avgResponseTime,
minResponseTime: variabilitySorted[0].minResponseTime,
failed: variabilitySorted[0].variability > 2.5
},
onePerc: {
value: onePercSorted[0].onePerc,
avgResponseTime: onePercSorted[0].onePerc.avgResponseTime,
failed: onePercSorted[0].onePerc > 2.5
},
};
}

bytesToMbps(bytes) {
return this.roundNumberTwoDecimals(bytes / Math.pow(1024, 2));
}
}
}
22 changes: 18 additions & 4 deletions src/app/items.service.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface ItemDetail {
throughput: number
};
reportStatus: ReportStatus;
monitoringData: { cpu: [], mem: [], maxCpu?: number, maxMem?: number};
monitoringData: { cpu: [], mem: [], maxCpu?: number, maxMem?: number };
baseId: string;
testName: string;
note: string;
Expand All @@ -55,18 +55,32 @@ export interface ItemDetail {
threads: any;

};
statistics: any;
statistics: ItemStatistics[];
attachements: [];
thresholds?: {
passed: boolean,
diff: {
errorRateDiff: number,
percentileRateDiff: number,
throughputRateDiff: number
percentileRateDiff: number,
throughputRateDiff: number
}
};
}

export interface ItemStatistics {
avgResponseTime: number;
bytes: number;
errorRate: number;
label: string;
maxResponseTime: number;
minResponseTime: number;
n0: number;
n5: number;
n9: number;
samples: number;
throughput: number;
}

interface MonitoringData {
'bytes-recv'?: string;
'bytes-sent'?: string;
Expand Down

0 comments on commit efcb0db

Please sign in to comment.