Method for real time obtaining Nginx log corresponding to task request by Python

  • 2021-11-14 06:33:12
  • OfStack

Requirements description

In the process of project requirements testing, it is necessary to send some use case requests to Nginx server, and then check the corresponding Nginx log to judge whether there are characteristic contents and whether the task is successfully executed. In order to improve efficiency, this process needs to be automated.

Practical environment

Python 3.6.5

Code design and implementation


#!/usr/bin/env python
# -*- coding:utf-8 -*-


'''
@CreateTime: 2021/06/26 9:05
@Author : shouke
'''


import time
import threading
import subprocess
from collections import deque


def collect_nginx_log():
    global nginx_log_queue
    global is_tasks_compete
    global task_status


    args = 'tail -0f /usr/local/openresty/nginx/logs/access.log'
    while task_status != 'req_log_got':
        with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines = True) as proc:
            log_for_req = ''
            outs, errs = '', ''

            try:
                outs, errs = proc.communicate(timeout=2)
            except subprocess.TimeoutExpired:
                print(' Get nginx Log timed out, retrying ')
                proc.kill()
                try:
                    outs, errs = proc.communicate(timeout=5)
                except subprocess.TimeoutExpired:
                    print(' Get nginx Log timeout, timeout again, stop retry ')
                    break
            finally:
                for line in outs.split('\n'):
                    flag = '\"client_ip\":\"10.118.0.77\"' #  Characteristic 
                    if flag in line: #  Find logs that contain feature content 
                        log_for_req += line

                if task_status == 'req_finished':
                    nginx_log_queue.append(log_for_req)
                    task_status = 'req_log_got'



def run_tasks(task_list):
    '''
     Run a task 
    :param task_list  Task list 
    '''

    global nginx_log_queue
    global is_tasks_compete
    global task_status


    for task in task_list:
        thread = threading.Thread(target=collect_nginx_log,
                                    name="collect_nginx_log")
        thread.start()
        time.sleep(1) #  Prepare the log collection thread before executing the task 

        print(' Ongoing mission: %s' % task.get('name'))

        #  Execute Nginx Task request 
        # ...

        task_status = 'req_finished'
        time_to_wait = 0.1
        while task_status != 'req_log_got': #  Request-triggered nginx Log collection incomplete 
            time.sleep(time_to_wait)
            time_to_wait += 0.01
        else:#  Object triggered by a use case request nginx Journal 
            if nginx_log_queue:
                nginx_log = nginx_log_queue.popleft()
                task_status = 'req_ready'
                #  Parse log 
                # do something here
                # ...
            else:
                print(' The queue for storing the request log is empty ')
                # do something here
                # ...


if __name__ == '__main__':
    nginx_log_queue = deque()
    is_tasks_compete = False #  Are all tasks completed 

    task_status = 'req_ready' # req_ready , req_finished , req_log_got  #  Object that stores the task that executes the secondary task 1 Some states 
    print('########################### Task commencement ###########################')

    tast_list = [{'name':'test_task', 'other':'...'}]
    run_tasks(tast_list)

    is_tasks_compete = True

    current_active_thread_num = len(threading.enumerate())
    while current_active_thread_num != 1:
        time.sleep(2)
        current_active_thread_num = len(threading.enumerate())
    print('########################### Task completion ###########################')

Note:

1. Why is the above code not in place in one step, directly tail -0f /usr/local/openresty/nginx/logs/access.log | grep "特征内容" What about? This is because you can't get the log to Nginx by doing so

2. It is found in practice that the first execution proc.communicate(timeout=2) When getting the log, it is always impossible to get it, it will time out, it needs to get it twice, and timeout Setting is too small (in practice, I tried to set it to 1秒 ) will also result in the Nginx log not being retrieved on the second execution.


Related articles: