Grundsätzlich verhält sich ein Last- und Performancetest eines Chatbots nicht anders als eben andere Last- und Performancetest auch. Für einen einfachen weg habe ich ein Python Skript geschrieben, welches auf einfacher weise  einen gezielten Test auf ein Chatbot System durchführt. Aktuell wird hier nur eine GET-Anfrage ausgeführt, aber weiter unterhalb findet ihr auch eine geupdatete Version, das neben dem GET-Befehl auch den POST-Befehl ausführt. Anpassungen sind in Arbeit und ich würde mich freuen, wenn ihr dazu Vorschläge habt.

 

Wie nutzte ich das Skript?

 

Konfiguration:

  • Ändert die url Variable, um die URL eures Chatbots anzugeben.
  • Passt die num_users Variable an, um die Anzahl der simulierten Benutzer festzulegen.
  • Passt die num_threads Variable an, um die Anzahl der Threads festzulegen (obwohl diese Variable im aktuellen Skript nicht verwendet wird).
  • Passt die http_method Variable an, um die HTTP-Methode festzulegen (obwohl das Skript derzeit nur GET-Anfragen unterstützt).
  • Passt die think_time Variable an, um die Denkzeit zwischen den Anfragen festzulegen.

Ausführung:

  • Führt das Skript aus. Es wird die angegebene Anzahl von Benutzern simulieren, die Anfragen an den Chatbot senden.
  • Die Fortschrittsleiste zeigt den Fortschritt des Tests an.
  • Nach Abschluss des Tests werden statistische Daten wie Durchschnitt, Median, Varianz, Standardabweichung und die 95. und 99. Perzentile der Antwortzeiten angezeigt.
  • Ein Histogramm der Antwortzeiten wird ebenfalls angezeigt.

Analyse:

  • Überprüft die statistischen Daten, um zu verstehen, wie euer Chatbot unter Last reagiert.
  • Das Histogramm gibt euch eine visuelle Vorstellung von der Verteilung der Antwortzeiten.

Fehlerbehandlung:

  • Das Skript protokolliert Fehler in einer Datei namens logfile.log im Verzeichnis Load_and_Performance_Tooling/Logging/. Überprüft diese Datei, wenn während des Tests Fehler auftreten.
import aiohttp
import asyncio
import time
import statistics
import logging
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
from tqdm import tqdm

# Author: Frank Rentmeister 
# URL: https:meinchatbot.com
# Date: 2023-08-23
# Version: 2.0
# Description: Load and Performance Tooling (Asynchronous with Progressbar)

# Set the log level to DEBUG to log all messages
LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(threadName)s - %(thread)d - %(lineno)d - %(funcName)s'
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, filename='Load_and_Performance_Tooling/Logging/logfile.log', filemode='w')
logger = logging.getLogger()

# Configuration Parameters
url = "https://meinchatbot.com"
num_users = 200
num_threads = 10
http_method = "GET"
think_time = 2

# Define a function to calculate statistical data
def calculate_statistics(response_times):
    mean_response_time = statistics.mean(response_times)
    median_response_time = statistics.median(response_times)
    variance_response_time = statistics.variance(response_times)
    stddev_response_time = statistics.stdev(response_times)
    percentile_95 = np.percentile(response_times, 95)
    percentile_99 = np.percentile(response_times, 99)

    return {
        'mean': mean_response_time,
        'median': median_response_time,
        'variance': variance_response_time,
        'stddev': stddev_response_time,
        '95_percentile': percentile_95,
        '99_percentile': percentile_99
    }

# Define a function to simulate a user making a request
async def simulate_user_request(session, response_times, pbar):
    try:
        start_timestamp = datetime.now()
        async with session.get(url) as response:  # Assume only GET requests for simplicity
            response_time = datetime.now() - start_timestamp
            response.raise_for_status()
            response_times.append(response_time.total_seconds())

        pbar.update(1)  # Update the progress bar
        await asyncio.sleep(think_time)  # Implementing the think time
    except Exception as e:
        logger.error(f"An unexpected error occurred: {e}")
        pbar.update(1)  # Update the progress bar even if there's an error

# Define a function to run the load test asynchronously
async def run_load_test():
    start_timestamp = datetime.now()
    response_times = []

    with tqdm(total=num_users, desc="Progress", position=0, bar_format="{l_bar}{bar:20}{r_bar}{bar:-10b}", colour="green") as pbar:
        async with aiohttp.ClientSession() as session:
            tasks = [simulate_user_request(session, response_times, pbar) for _ in range(num_users)]
            await asyncio.gather(*tasks)

    num_successful_requests = len(response_times)
    num_failed_requests = num_users - num_successful_requests
    print(f"Number of successful requests: {num_successful_requests}")
    print(f"Number of failed requests: {num_failed_requests}")

    stats = calculate_statistics(response_times)
    print(f"Mean Response Time: {stats['mean']:.3f} seconds")
    print(f"Median Response Time: {stats['median']:.3f} seconds")
    print(f"Variance of Response Times: {stats['variance']:.3f}")
    print(f"Standard Deviation of Response Times: {stats['stddev']:.3f}")
    print(f"95th Percentile of Response Times: {stats['95_percentile']:.3f} seconds")
    print(f"99th Percentile of Response Times: {stats['99_percentile']:.3f} seconds")

    # Create a histogram of response times
    plt.figure(figsize=(8, 6))
    plt.hist(response_times, bins=20, color='skyblue', edgecolor='black')
    plt.title('Response Time Distribution')
    plt.xlabel('Response Time (seconds)')
    plt.ylabel('Frequency')
    plt.grid(True)
    plt.show()

# Run the load test asynchronously
asyncio.run(run_load_test())