Skip to content

Commit

Permalink
New Features:
Browse files Browse the repository at this point in the history
1. Load Test AI finished
Bugs Corrected:
1. Load Test History, chart showing in disorder
To Be Corrected:
0. On product delete, delete trace results
1. On product delete, delete flamegraph result
  • Loading branch information
juanfranciscocis committed Sep 23, 2024
1 parent 8516468 commit 0392fa1
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { LoadTestHistoryPageRoutingModule } from './load-test-history-routing.mo
import { LoadTestHistoryPage } from './load-test-history.page';
import {ComponentsModule} from "../../../components/components.module";
import {NgxEchartsDirective} from "ngx-echarts";
import {MarkdownComponent} from "ngx-markdown";

@NgModule({
imports: [
Expand All @@ -17,7 +18,8 @@ import {NgxEchartsDirective} from "ngx-echarts";
IonicModule,
LoadTestHistoryPageRoutingModule,
ComponentsModule,
NgxEchartsDirective
NgxEchartsDirective,
MarkdownComponent
],
declarations: [LoadTestHistoryPage]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1


<ion-row class="lg:m-10 md:m-10">
<ion-col size="12" class="relative flex flex-row justify-center">
<div class="absolute z-10 w-full flex flex-row justify-end " >
<ion-avatar class="h-12 w-12 bg-purple-400 p-2" (click)="toggleAiModal('httpCodesOptions')">
<ion-icon class="w-full h-full" name="color-wand-outline"></ion-icon>
</ion-avatar>
</div>
<ion-card class="w-full p-6 flex flex-col justify-center items-center">
<ion-card-header>
<ion-card-title class="text-3xl">HTTP Status Codes</ion-card-title>
Expand All @@ -25,9 +31,16 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1
<div id="httpCodesChartHistory" echarts [options]="statusCodesOptions" class="demo-chart h-full w-full"></div>
</ion-card-content>
</ion-card>
</ion-col>
</ion-row>

<ion-row class="lg:m-10 md:m-10">
<ion-col size="12" class="relative flex flex-row justify-center">
<div class="absolute z-10 w-full flex flex-row justify-end " >
<ion-avatar class="h-12 w-12 bg-purple-400 p-2" (click)="toggleAiModal('httpResponseTimeOptions')">
<ion-icon class="w-full h-full" name="color-wand-outline"></ion-icon>
</ion-avatar>
</div>
<ion-card class="w-full p-6 flex flex-col justify-center items-center">
<ion-card-header>
<ion-card-title class="text-3xl">HTTP Response Time</ion-card-title>
Expand All @@ -36,9 +49,62 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1
<div id="httpResponseTimeChartHistory" echarts [options]="responseTimeOptions" class="demo-chart h-full w-full"></div>
</ion-card-content>
</ion-card>
</ion-col>
</ion-row>



</ion-grid>


@if(hasBeenOpened){
<ion-fab class="m-2 z-10" vertical="bottom" horizontal="end" slot="fixed" (click)="toggleAiModal()">
<ion-avatar class="bg-purple-300 p-1 lg:p-4 md:p-4">
<ion-icon class="w-full h-full" name="chatbubble-outline"></ion-icon>
</ion-avatar>
</ion-fab>
}

</ion-content>


<div class="fixed bottom-0 right-0 h-full w-full bg-black bg-opacity-60 z-10 r" id="ai-modal" [class.hidden]="!aiModal">
<div class="h-full md:h-3/4 lg:h-3/4 w-full bg-gray-900 p-4 absolute right-0 bottom-0 z-50 flex flex-col rounded-tl-2xl rounded-tr-2xl">

<div class="w-full bg-gray-500 flex flex-row justify-center items-center p-2 mb-2 rounded-3xl" >
<div class="flex flex-row p-2 items-center bg-gray-800 w-full rounded-3xl h-full">
<h1 class="text-white">DevProbe AI</h1>
</div>
<div class="m-2"></div>
<div class="flex flex-row justify-center items-center bg-gray-800 hover:bg-gray-600 w-1/6 h-full rounded-3xl" (click)="toggleAiModal()">
<ion-icon name="close-outline"></ion-icon>
</div>
</div>

<!-- El contenedor de mensajes con scroll -->
<div class="flex-grow overflow-y-auto bg-gray-400 p-2 rounded-3xl" #messagesContainer>
<div *ngFor="let msg of messages" class="flex flex-col">
<!-- Mensajes de usuario -->
<div *ngIf="msg.from === 'User'" class="rounded-3xl bg-gray-800 w-2/3 m-1 ml-auto p-2">
<markdown class="text-white p-4 m-2">{{ msg.message }}</markdown>
</div>

<!-- Mensajes de AI -->
<div *ngIf="msg.from === 'AI'" class="rounded-3xl bg-gray-500 w-2/3 m-1 p-2 pr-2">
<markdown id="mk-{{msg.id}}" class="text-white p-4 m-2">{{ msg.message }}</markdown>
</div>
</div>
</div>

<!-- Input y botón en la parte inferior -->
<div class="flex flex-row mt-2 p-2">
<ion-textarea placeholder="Ask..." class="flex-grow bg-gray-700 rounded-2xl" [(ngModel)]="message"></ion-textarea>
<div class="m-1"></div>
<div class="w-1/3 bg-gray-500 rounded-3xl flex flex-row justify-center items-center hover:bg-gray-300" (click)="sendMessage()">
<span class="text-white">Send</span>
</div>
</div>
</div>
</div>


127 changes: 120 additions & 7 deletions src/app/pages/load_test/load-test-history/load-test-history.page.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Component, OnInit } from '@angular/core';
import {Component, ElementRef, inject, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {LoadTestService} from "../../../services/load-test.service";
import {ArtilleryData} from "../../../classes/artillery-data";
import {EChartsOption} from "echarts";
import {getGenerativeModel, VertexAI} from "@angular/fire/vertexai-preview";
import {AiMessage} from "../../../interfaces/ai-message";
import {LoadingController} from "@ionic/angular";

@Component({
selector: 'app-load-test-history',
Expand Down Expand Up @@ -50,10 +53,48 @@ export class LoadTestHistoryPage implements OnInit {
}



@ViewChild('messagesContainer') private messagesContainer: ElementRef | undefined;
aiModal: boolean = false
message: string = '';
vertexAI: VertexAI = inject(VertexAI);
model = getGenerativeModel(this.vertexAI, { model: "gemini-1.5-flash" });
chat = this.model.startChat({
history: [
{
role: "user",
parts: [{text:"Hola, desde ahora en adelante quiero que seas un modelo experto en Software Quality Assurance y analista de datos, tu nombre es DevProbeAI, nunca lo puedes olvidar"}],
},
{
role: "model",
parts: [{text:"Soy un modelo experto en Software Quality Assurance, de igual forma tengo un masterado en anlaítica de datos ¿En qué puedo ayudarte?"}],
},
{
role: "user",
parts: [{text:"Gracias, te voy a entregar un json con datos en unos minutos, necesito que lo analices y me des un resumen de los datos, este json contiene datos de un load test" +
",tu analisis tiene que ser detallado, si encuentras inconsistencias en los datos, por favor mencionalas, en " +
"caso de que creas que puede haber un problema o que se encuentre el recurso no disponible por favor mencionalo, si encuentras algo interesante, por favor mencionalo, en resumen, necesito un analisis detallado de los datos"}],
},
{
role: "model",
parts: [{text:"Claro, envíame el json y yo me encargo de analizarlo"}]
},
],
});
messages:AiMessage[] = []
hasBeenOpened = false;







constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private loadTestService: LoadTestService
private loadTestService: LoadTestService,
private loadingCtrl:LoadingController
) { }

ngOnInit() {
Expand Down Expand Up @@ -99,7 +140,7 @@ export class LoadTestHistoryPage implements OnInit {
// @ts-ignore: Extrae la fecha del resultado
let date = this.loadTestResults[key].date;
// Filtra las claves que empiezan con "http.requests."
let httpCodesKeys = Object.keys(data).filter(keyCode => keyCode.startsWith('http.requests'));
let httpCodesKeys = Object.keys(data).filter(keyCode => keyCode.startsWith('http.responses'));

for (let keyCode of httpCodesKeys) {
if (!requests[date]) {
Expand All @@ -111,7 +152,7 @@ export class LoadTestHistoryPage implements OnInit {
}

for (let date of Object.keys(requests)) {
totalRequests += requests[date]['http.requests'];
totalRequests += requests[date]['http.responses'];
}
this.totalNumberOfRequests = totalRequests;

Expand Down Expand Up @@ -149,17 +190,20 @@ export class LoadTestHistoryPage implements OnInit {
return codes;
}
normalizarFecha(fecha: string): string {
const [year, month, day] = fecha.split('-').map(num => parseInt(num, 10)); // Convertimos a números para evitar ceros iniciales incorrectos
console.log('fecha',fecha);
const [year, month, day, hour, minute, second] = fecha.split('-').map(num => parseInt(num, 10)); // Convertimos a números para evitar ceros iniciales incorrectos
const mesNormalizado = month < 10 ? `0${month}` : month.toString(); // Agregar 0 si es necesario
const diaNormalizado = day < 10 ? `0${day}` : day.toString(); // Agregar 0 si es necesario
return `${year}-${mesNormalizado}-${diaNormalizado}`;
return `${year}-${mesNormalizado}-${diaNormalizado} ${hour}:${minute}:${second}`;
}
ordenarDiccionarioPorFechas(diccionario: { [key: string]: any }): { [key: string]: any } {
// Obtener las claves del diccionario (fechas)
const fechas = Object.keys(diccionario);

// Ordenar las fechas normalizadas
const fechasOrdenadas = fechas.sort((a, b) => {
console.log('a', this.normalizarFecha(a));
console.log('b', this.normalizarFecha(b));
const fechaA = new Date(this.normalizarFecha(a));
const fechaB = new Date(this.normalizarFecha(b));
return fechaA.getTime() - fechaB.getTime();
Expand All @@ -176,9 +220,12 @@ export class LoadTestHistoryPage implements OnInit {
}
async plotCodes() {
let codes = this.byCodes();
console.log(codes);
console.log('codess',codes);

let keys = Object.keys(codes);

console.log('llaves',keys);

let typesOfCodes = new Set() as Set<string>;

for (let key of keys) {
Expand All @@ -200,6 +247,7 @@ export class LoadTestHistoryPage implements OnInit {
}
}


let colors = [
'#36b311',
'#306fc6',
Expand Down Expand Up @@ -373,9 +421,74 @@ export class LoadTestHistoryPage implements OnInit {
responseTimeChart!.style.width = '100%';
responseTimeChart!.style.height = '25em';


return responseTimes;

}



async toggleAiModal(context?: string) {
await this.showLoading()

this.aiModal = !this.aiModal;
this.hasBeenOpened = true;

if (context === 'httpCodesOptions') {
this.message = 'En este caso el json tiene codigos de respuesta HTTP, por ejemplo, 404, 500, etc y cuantos requests devolvieron esos codigos:' + JSON.stringify(this.byCodes())
}
if (context === 'httpResponseTimeOptions') {
this.message = 'En este caso el json tiene tiempos de respuesta de los requests, por ejemplo, 500ms, 1000ms, etc: ' + JSON.stringify(this.responseTime())
}

if (this.message === '') {
console.log('Message is empty');
await this.hideLoading();
return;
}

let length = this.messages.length;
if (length > 0) {
this.messages.push({message: this.message, from: 'User', id: length.toString()});
}
const result = await this.chat.sendMessage(this.message);
length = this.messages.length;
this.messages.push({message: result.response.text(), from: 'AI', id: length.toString()});
this.message = '';
await this.hideLoading();
return;


}

sendMessage() {
let length = this.messages.length;
this.messages.push({message: this.message, from: 'User', id: length.toString()});
this.chat.sendMessage(this.message).then(async (result) => {
await this.showLoading()
length = this.messages.length;
this.messages.push({message: result.response.text(), from: 'AI', id: length.toString()});
await this.hideLoading();
});
this.message = '';
return;
}


/**
* Show a loading spinner.
*/
async showLoading() {
const loading = await this.loadingCtrl.create({
});
await loading.present();
}

/**
* Hide the loading spinner.
*/
async hideLoading() {
await this.loadingCtrl.dismiss();
}

}
21 changes: 11 additions & 10 deletions src/app/pages/load_test/load-test/load-test.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1


<ion-row class="lg:m-10 md:m-10">
<ion-col size="12" class="relative">
<div class="absolute z-10 flex justify-center items-center -right-5 -top-5" (click)="toggleAiModal('httpCodesOptions')">
<ion-avatar class="bg-purple-600 justify-center items-center flex">
<ion-icon size="large" name="color-wand-outline"></ion-icon>
<ion-col size="12" class="relative flex flex-row justify-center">
<div class="absolute z-10 w-full flex flex-row justify-end " >
<ion-avatar class="h-12 w-12 bg-purple-400 p-2" (click)="toggleAiModal('httpCodesOptions')">
<ion-icon class="w-full h-full" name="color-wand-outline"></ion-icon>
</ion-avatar>
</div>
<ion-card class="w-full p-6 flex flex-col justify-center items-center">
Expand All @@ -52,10 +52,10 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1
</ion-row>

<ion-row class="lg:m-10 md:m-10">
<ion-col size="12" class="relative">
<div class="absolute z-10 flex justify-center items-center -right-5 -top-5" (click)="toggleAiModal('httpResponseTimeOptions')">
<ion-avatar class="bg-purple-600 justify-center items-center flex">
<ion-icon size="large" name="color-wand-outline"></ion-icon>
<ion-col size="12" class="relative flex flex-row justify-center">
<div class="absolute z-10 w-full flex flex-row justify-end ">
<ion-avatar class="h-12 w-12 bg-purple-400 p-2" (click)="toggleAiModal('httpResponseTimeOptions')">
<ion-icon class="w-full h-full" name="color-wand-outline"></ion-icon>
</ion-avatar>
</div>
<ion-card class="w-full p-6 flex flex-col justify-center items-center">
Expand Down Expand Up @@ -84,12 +84,13 @@ <h1 class="text-2xl text-white">{{ totalNumberOfRequests | number:'1.0-0' }}</h1
</ion-grid>



@if(hasBeenOpened){
<ion-fab class="m-2 z-10" vertical="bottom" horizontal="end" slot="fixed" (click)="toggleAiModal()">
<ion-avatar class="bg-purple-300 p-4">
<ion-avatar class="bg-purple-300 p-1 lg:p-4 md:p-4">
<ion-icon class="w-full h-full" name="chatbubble-outline"></ion-icon>
</ion-avatar>
</ion-fab>
}


</ion-content>
Expand Down
Loading

0 comments on commit 0392fa1

Please sign in to comment.