locust 日志记录并发送至指定服务器
新建文件
locust_log.py
from locust import events
import logging
from logging.handlers import RotatingFileHandler
import pytz
import datetime
import os
PERF_HOST = 'http://www.leontom.com' # 日志接收的服务地址
REPORT_LOCUST_LOGS_URL = '/test/logs' # 日志API url
LOGGING_SECURE = False # logging 发送请求方式 False ->http; True->https
class LocustLogHTTPHandler(logging.handlers.HTTPHandler):
"""用于发送日志"""
def __init__(self, host, url, method="POST", secure=False, credentials=None, context=None, report_id=None):
super().__init__(host, url, method=method, secure=secure, credentials=credentials, context=context)
self.report_id = report_id
def mapLogRecord(self, record):
tz = pytz.timezone('Asia/Shanghai')
asctime = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
if hasattr(record, 'name') and hasattr(record, 'message'):
data = {"asctime": asctime, "name": record.name, "message": record.message}
else:
data = {"asctime": asctime, "name": 'requests', "message": str(record)}
record_ = '%(asctime)s | %(name)s | %(message)s' % dict(data)
record_msg = {'record': record_}
return record_msg
class LocustLogger():
"""日志记录"""
def __init__(self, filePath, fileName):
self.filePath = filePath # 存放文件的路径
self.fileName = fileName # 存放文件的名字
# self.BACK_UP_COUNT = 5000 # 文件分割上限数
# self.MAX_LOG_BYTES = 1024 * 1024 * 10 # 单个文件最大记录数10M
self.create_handler() # 初始化创建日志handler
self.create_logger() # 初始化创建Logger
self.LocutHttpHandler = None
def create_handler(self):
"""建立handler"""
self.handler = RotatingFileHandler(filename=os.path.join(self.filePath, self.fileName),
# maxBytes=self.MAX_LOG_BYTES,
# backupCount=self.BACK_UP_COUNT,
delay=1
)
# 设定输出格式
formatter = logging.Formatter('%(asctime)s | %(name)s | %(message)s')
# formatter.converter = time.localtime # 时间转换
self.handler.setFormatter(formatter) # 格式加载到handler
log_host = PERF_HOST.replace('https://', '').replace('http://', '')
if not all([log_host, REPORT_LOCUST_LOGS_URL, LOGGING_SECURE]):
self.LocutHttpHandler = LocustLogHTTPHandler(log_host, url=REPORT_LOCUST_LOGS_URL, method="POST", secure=LOGGING_SECURE)
self.LocutHttpHandler.setFormatter(formatter)
def create_logger(self):
"""建立Logger"""
self.success_logger = logging.getLogger('Success')
self.success_logger.propagate = False
self.success_logger.addHandler(self.handler)
self.failure_logger = logging.getLogger('Failure')
self.failure_logger.propagate = False
self.failure_logger.addHandler(self.handler)
self.failure_logger = logging.getLogger('stderr')
self.failure_logger.propagate = False
self.failure_logger.addHandler(self.handler)
self.requests_logger = logging.getLogger('requests')
self.requests_logger.propagate = False
self.requests_logger.addHandler(self.handler)
if self.LocutHttpHandler:
self.add_httphandler()
def add_httphandler(self):
self.success_logger.addHandler(self.LocutHttpHandler)
self.failure_logger.addHandler(self.LocutHttpHandler)
self.requests_logger.addHandler(self.LocutHttpHandler)
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 failure_request(self, request_type, name, response_time, exception):
msg = ' | '.join([str(request_type), name, str(response_time), str(exception)])
self.failure_logger.info(msg)
def execpt_error(self, locust_instance, exception, tb, *args, **kwargs):
stderr_logger = logging.getLogger("stderr")
stderr_logger.exception(exception)
stderr_logger.exception('-' * 12)
def get_locust_Hook(self):
"""钩子挂载到Locust中"""
events.request_success += self.success_request
events.request_failure += self.failure_request
events.locust_error += self.execpt_error
def get_locust_success_Hook(self):
events.request_success += self.success_request
def get_locust_failure_Hook(self):
events.request_failure += self.failure_request
def get_locust_error_Hook(self):
events.locust_error += self.execpt_error
def get_requests_log(self, method, path, requests, response):
msg = ' | '.join([method, path, '请求数据: {}'.format(str(requests)), '返回数据: {}'.format(str(response))])
self.requests_logger.info(msg)
if self.LocutHttpHandler:
self.LocutHttpHandler.emit(record=msg) # 发送日志
# ------------------------------------------------------------------------
# 以上为封装好的Log日志输出
# 在并发时带入log日志输出为本地文件存放,代码如下:
from locust import TaskSet, task, HttpLocust
class UserBehaviorSet(TaskSet):
def on_start(self):
self.logger = LocustLogger(filePath='./', fileName='test.logs')
self.logger.get_locust_Hook()
@task(1)
def test(self):
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'Cache-Control': "no-cache",
'Postman-Token': "9889c0b4-b91c-4b23-a713-cae4d60e623a"
}
resp = self.client.get("/LeonTom/article/details/102842207", headers=headers, verify=False)
# 记录请求日志并发送到指定服务
self.logger.get_requests_log(method='GET', path='/', requests={}, response=resp.text)
class WebsiteUser(HttpLocust):
task_set = UserBehaviorSet
min_wait = 3000
max_wait = 5000
if __name__ == '__main__':
import os
os.system("locust -f ./locust_log.py --host=https://blog.csdn.net")