1. 程式人生 > >Locust 測試結果通過Matplotlib生成趨勢圖

Locust 測試結果通過Matplotlib生成趨勢圖

目的:

相信大家對於使用Loadrunner測試後的結果分析詳細程度還是有比較深刻的感受的,每個請求,每個事務點等都會有各自的趨勢指標,在同一張圖示中展示。如下圖:

 

而Locust自身提供的chart趨勢圖缺很簡單,如下圖:

那麼要達到Loadrunner對於每個請求的詳細的描述,用locust能否實現呢?

答案是肯定的,那麼我們想到就開始做!

思路:

我們整理一下思路,按照步驟去達到我們的目的:

1. 首先我們需要知道每個請求的響應時間

2. 我們需要把每個請求的響應時間進行資料整理和拆分

3. 我們需要把整理好的資料生成圖表

實施:

按照初步的思路,我們來按步驟進行實施:

1. 抓取每個請求的響應時間。

我們需要獲取每個請求的響應時間,可以通過Locust本身自帶的鉤子函式列印成日誌檔案。

具體程式碼如下:

#!/usr/bin/python3.6
# -*- coding: UTF-8 -*-
# author:Lucien
# 基礎包: 壓力Log日誌封裝
from locust import events
import os
import time
import logging
from logging.handlers import RotatingFileHandler


class loadLogger():
    def __init__(self, filePath, fileName):
        self.filePath 
= filePath # 存放檔案的路徑 self.fileName = fileName # 存放檔案的名字 self.BACK_UP_COUNT = 5000 # 檔案分割上限數 self.MAX_LOG_BYTES = 1024 * 1024 * 1 # 單個檔案最大記錄數1M self.create_handler() # 初始化建立日誌handler self.create_logger() # 初始化建立Logger def create_handler(self): # 建立handler
self.success_handler = RotatingFileHandler(filename=os.path.join(self.filePath, self.fileName), maxBytes=self.MAX_LOG_BYTES * 100, backupCount=self.BACK_UP_COUNT, delay=1) # 分割檔案處理按100m分割 formatter = logging.Formatter('%(asctime)s | %(name)s | %(levelname)s | %(message)s') # 設定輸出格式 formatter.converter = time.gmtime # 時間轉換 self.success_handler.setFormatter(formatter) # 格式載入到handler def create_logger(self): # 建立Logger self.success_logger = logging.getLogger('request_success') self.success_logger.propagate = False self.success_logger.addHandler(self.success_handler) def success_request(self, request_type, name, response_time, response_length): # 成功日誌輸出格式載入到Logger中 msg = ' | '.join([str(request_type), name, str(response_time), str(response_length)]) self.success_logger.info(msg) def get_locust_Hook(self): # 鉤子掛載到Locust中 events.request_success += self.success_request

以上為封裝好的Log日誌輸出

在併發時帶入log日誌輸出為本地檔案存放,程式碼如下:

# !/usr/bin/python3.6
# -*- coding: UTF-8 -*-
# author: lucien
# 基礎包: locust趨勢圖生成包
from locust import TaskSet, task, HttpLocust
from Performance_Core.performance_log import loadLogger
import os


class file_server_stress(TaskSet):
    def on_start(self):
        '''警號,部門編號等'''
        self.deptID = '520'
        self.pcMemberID = '10000001'
        self.phoneMemberID = '10000004'
        self.logger = loadLogger(filePath='E:\\PrintLog', fileName='11-12-logs')

    # 上傳檔案
    @task(1)
    def update_file(self):
        payload = "xxx"
        url = ':6061/file/upload/file'
        headers = {
            'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
            'Cache-Control': "no-cache",
            'Postman-Token': "9889c0b4-b91c-4b23-a713-cae4d60e623a"
        }
        response = self.client.post(url=url, data=payload, headers=headers, name='update_file', catch_response=True,
                                    timeout=20)
        print(response.text)
        # 驗證請求成功與失敗
        if response.status_code == 200:
            self.logger.get_locust_Hook() #重點!此處掛載Log日誌鉤子
            response.success()
        else:
            self.logger.get_locust_Hook()
            response.failure('上傳檔案失敗')

class userbehavior(HttpLocust):
    host = 'http://192.168.1.222'
    task_set = file_server_stress
    min_wait = 3000
    max_wait = 5000

if __name__ == '__main__':
    '''網頁啟動,在網頁中輸入127.0.0.1:8089'''
    os.system('locust -f file_server_stress.py --web-host=127.0.0.1')  

執行完測試後,我們將會得到一組log日誌檔案,樣式如下:

第一步順利完成!

2. 對日誌檔案進行資料分析和拆分

我們所得到的所有日誌記錄都會混合在日誌檔案中,我們需要把它提取出來,並且通過groupby來拆分不同的請求

提取日誌檔案,我們可以用到python的強項,資料分析支援庫Pandas和Numpy

首先,我們通過Pandas提取日誌檔案:

headers = ['time', 'label', 'loglevel', 'method', 'name', 'response_time', 'size']  
self.data = pandas.read_csv(filename, sep='|', names=headers)

讀取日誌檔案後生成DATAFRAME的pandas資料獨有格式

其次,我們通過對讀取的檔案處理後進行排序

self.sorted_data = self.data.sort_values(by=['time', 'name'], ascending=[True, True])

按時間和請求名稱,將序排列

最後,我們對排序後的資料進行分組

self.grouped_data = self.sorted_data.groupby('name')

自此,我們資料處理工作大體準備完成

3.把資料生成圖表

需要把資料生成圖表,自然離不開matplotlib了

按照matplolib裡,plot方法,把x軸和y軸 按照time 和 response_time 生成相應的折線圖,最後生成的趨勢圖如下:

大功告成!

最後附上實際程式碼,供有需要的同學參考,也可以自行改良:

# !/usr/bin/python3.6
# -*- coding: UTF-8 -*-
# author: lucien
# 基礎包: locust趨勢圖生成包
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import dates

hex_colors = [
    '#FF7500',
    '#F00056',
    '#0EB83A',
    '#00BC12',
    '#1BD1A5',
    '#0C8918',
    '#0AA344',
    '#2ADD9C',
    '#3DE1AD',
    '#424C50',
    '#DB5A6B',
    '#FF4E20',
    '#3EEDE7',
    '#4B5CC4',
    '#70F3FF',
    '#2E4E7E',
    '#3B2E7E',
    '#425066',
    '#8D4BBB',
    '#815476',
    '#808080',
    '#161823',
    '#50616D',
    '#725E82',
    '#A78E44',
    '#8C4356',
    '#F47983',
    '#B36D61',
    '#C93756',
    '#FF2121',
    '#C83C23',
    '#9D2933',
    '#FFF143',
    '#FF0097',
    '#A98175',
    '#C32136',
    '#6E511E',
    '#F20C00',
    '#F9906F',
    '#FF8936',
    '#DC3023',
    '#EAFF56',
    '#FFA400',
    '#60281E',
    '#44CEF6',
    '#F0C239',
    '#A88462',
    '#B35C44',
    '#B25D25',
    '#C89B40',
    '#D9B611',
    '#827100',
    '#C3272B',
    '#7C4B00',
    '#BDDD22',
    '#789262',
    '#FF8C31',
    '#C91F37',
    '#00E500',
    '#177CB0',
    '#065279',
]


class data_analyse():
    def __init__(self, filename):
        self.filename = filename
        self.xfmt = dates.DateFormatter('%m/%d %H:%M')
        self._init_graph()  # 初始化趨勢圖大小
        self._set_graph()  # 初始化趨勢圖樣式

        headers = ['time', 'label', 'loglevel', 'method', 'name', 'response_time', 'size']  # 命名欄位標題
        self.data = pd.read_csv(filename, sep='|', names=headers)  # 從檔案獲取內容為DATAFRAME格式
        for col in headers[-2:]:  # 轉換response_time和size為int型
            self.data[col] = self.data[col].apply(lambda x: int(x))
        for col in headers[0:-2]:  # 取消掉所有非int型的空格
            self.data[col] = self.data[col].apply(lambda x: x.strip())
        self.data['time'] = self.data['time'].apply(
            lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S,%f'))  # time轉化為時間格式
        self.sorted_data = self.data.sort_values(by=['time', 'name'], ascending=[True, True])  # 對資料按照time和name進行降序排列
        self.grouped_data = self.sorted_data.groupby('name')  # 對降序排列的資料,按名稱分組
        self.requests_counts = np.array([[key, len(group)] for key, group in self.grouped_data])  # 構建請求名和請求次數陣列

    def _init_graph(self):  # 設定趨勢圖大小
        left, width = 0.1, 0.8
        bottom, height = 0.1, 0.8
        self.trend_scatter = [left, bottom, width, height]

    def _set_graph(self):  # 生成基本趨勢圖樣式
        plt.clf()  # 清除figure中所有axes
        self.ax_plot = plt.axes(self.trend_scatter)  # 套用axes大小
        self.ax_plot.grid(True)  # 開啟網格
        self.ax_plot.set_ylabel('Response Time(ms)')  # 縱座標標題
        self.ax_plot.set_xlabel('time')  # 橫座標標題
        self.ax_plot.figure.set_size_inches(15, 8)  # 畫板大小
        self.ax_plot.xaxis.set_major_locator(dates.MinuteLocator(interval=5))  # 設定橫座標日期格式為5min間隔
        self.ax_plot.xaxis.set_major_formatter(self.xfmt)  # 設定橫座標格式

    def generate_trend(self):  # 生成趨勢圖
        start_index = 0
        legend_list = []
        for index, request in enumerate(self.requests_counts):  # 為陣列新增index標籤
            name, count = request[0], int(request[1])  # 獲取請求名和請求次數
            end_index = start_index + count
            x = self.grouped_data.get_group(name)['time'][start_index: end_index]  # 設定x軸資料
            y = self.grouped_data.get_group(name)['response_time'][start_index:end_index]  # 設定y軸資料
            self.ax_plot.plot(x, y, '-', color=hex_colors[index + 1])  # 畫圖
            legend_list.append(name)  # 新增請求名到legend中
        plt.legend(legend_list)  # 列印legend
        # plt.show()  # 列印趨勢圖
        plt.title(self.filename)
        plt.savefig(fname='.'.join([self.filename, 'png']), dpi=300, bbox_inches='tight')  # 儲存趨勢圖


if __name__ == '__main__':
    data = data_analyse('E:\\PrintLog\\logs')
    print(data.sorted_data.info())
    # data.generate_trend()

 如要轉載,請標明出處