前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用命令统计nginx日志access.log中某个接口的QPS

使用命令统计nginx日志access.log中某个接口的QPS

原创
作者头像
KunkkaWu
发布2023-11-13 17:37:34
1.3K0
发布2023-11-13 17:37:34
举报
文章被收录于专栏:算法协议算法协议

问题

我们在平时的工作和开发中,会经常遇到这个问题:

从nginx的日志access.log中统计getVideoInfo接口的QPS。日志格式为:2019-07-12T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1

日志内容大致为:

代码语言:txt
复制
2019-07-12T11:16:23+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1
2019-07-12T11:16:45+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1
2019-07-12T11:16:58+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1
2019-07-12T11:17:01+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1
2019-07-12T11:17:20+0800|127.0.0.1|-|-|GET|http|127.0.0.1|/getVideoInfo?id=1

解决思路

首先nginx的日志是按照时间顺序的。因此计算QPS,只需要先统计条数,再计算时间差,二者相除就可以得到。

思路一:使用wc命令

  1. 第一步: 使用wc命令获取条数
代码语言:shell
复制
wc -l access.log | awk '{print $1}'
  1. 统计第一条和最后一条的时间并格式化成时间戳
代码语言:shell
复制
// 第一条日志时间戳
date -d "$(head -n 1 access.log | awk -F "|" '/getVideoInfo/ {print $1}')" +%s

// 最后一条日志时间戳
date -d "$(tail -n 1 access.log | awk -F "|" '/getVideoInfo/ {print $1}')" +%s
  1. 计算QPS完整命令
代码语言:shell
复制
count=$(wc -l access.log | awk '{print $1}'); start=$(date -d "$(head -n 1 access.log | awk -F "|" '/getVideoInfo/ {print $1}')" +%s); end=$(date -d "$(tail -n 1 access.log | awk -F "|" '/getVideoInfo/ {print $1}')" +%s); t=$(($end-$start));  qps=$(echo "scale=2; $count/$t" | bc); printf "%.2f\n" $qps

思路二: 使用awk命令

  1. 第一步,遍历统计条数
代码语言:shell
复制
awk -F "|" '$8=="/getVideoInfo?id=1" {count++} END {print count}' access.log
  1. 加入统计第一条和最后一条时间计算
代码语言:shell
复制
-v start="$(date -d "$(head -n 1 access.log | grep "getVideoInfo" | cut -d "|" -f 1)" +%s)" -v end="$(date -d "$(tail -n 1 access.log | grep "getVideoInfo" | cut -d "|" -f 1)" +%s)"
  1. 计算QPS完整命令
代码语言:shell
复制
awk -F "|" -v start="$(date -d "$(head -n 1 access.log | grep "getVideoInfo" | cut -d "|" -f 1)" +%s)" -v end="$(date -d "$(tail -n 1 access.log | grep "getVideoInfo" | cut -d "|" -f 1)" +%s)" '$8=="/getVideoInfo?id=1" {count++} END {qps=count/(end-start); print qps}' access.log

使用脚本处理

使用Python脚本

代码语言:python
复制
import re
from datetime import datetime

log_file = "access.log"
target_api = "/getVideoInfo"

# 统计时间范围
start_time = datetime.strptime("2019-07-12T00:00:00+0800", "%Y-%m-%dT%H:%M:%S%z")
end_time = datetime.strptime("2019-07-12T23:59:59+0800", "%Y-%m-%dT%H:%M:%S%z")

# 统计请求数
qps = 0

with open(log_file, "r") as file:
    for line in file:
        # 解析日志行
        parts = line.split("|")
        timestamp = datetime.strptime(parts[0], "%Y-%m-%dT%H:%M:%S%z")
        request_method = parts[4]
        request_url = parts[7]

        # 判断是否为目标接口的 GET 请求
        if request_method == "GET" and request_url.startswith(target_api):
            # 判断时间范围
            if start_time <= timestamp <= end_time:
                qps += 1

print("QPS for", target_api, ":", qps)

在上述示例中,我们首先定义了日志文件路径(log_file)和目标接口路径(target_api)。然后,我们指定了统计的时间范围(start_time 和 end_time)。

接下来,我们打开日志文件并逐行解析每个日志条目。我们使用 "|" 分隔符将每行日志拆分为不同的字段,并提取时间戳、请求方法和请求URL。

然后,我们检查请求方法是否为 "GET",并且请求URL是否以目标接口路径开头。如果满足条件,我们进一步检查时间戳是否在指定的时间范围内,并将符合条件的请求计数加1。

最后,我们打印出统计结果,即目标接口的 QPS。

使用go来实现

代码语言:go
复制
package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
    "regexp"
    "strings"
    "time"
)

func main() {
    logFile := "access.log"
    targetAPI := "/getVideoInfo"

    // 统计时间范围
    startTime, _ := time.Parse("2006-01-02T15:04:05-0700", "2019-07-12T00:00:00+0800")
    endTime, _ := time.Parse("2006-01-02T15:04:05-0700", "2019-07-12T23:59:59+0800")

    // 统计请求数
    qps := 0

    file, err := os.Open(logFile)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()

        // 解析日志行
        parts := strings.Split(line, "|")
        timestamp, _ := time.Parse("2006-01-02T15:04:05-0700", parts[0])
        requestMethod := parts[4]
        requestURL := parts[7]

        // 判断是否为目标接口的 GET 请求
        if requestMethod == "GET" && strings.HasPrefix(requestURL, targetAPI) {
            // 判断时间范围
            if timestamp.After(startTime) && timestamp.Before(endTime) {
                qps++
            }
        }
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }

    fmt.Println("QPS for", targetAPI, ":", qps)
}

使用shell脚本实现

代码语言:shell
复制
#!/bin/bash

log_file="access.log"
target_api="/getVideoInfo"

# 统计时间范围
start_time=$(date -d "2019-07-12 00:00:00" +%s)
end_time=$(date -d "2019-07-12 23:59:59" +%s)

# 统计请求数
qps=0

while IFS= read -r line
do
    # 解析日志行
    timestamp=$(echo "$line" | awk -F '|' '{print $1}')
    request_method=$(echo "$line" | awk -F '|' '{print $5}')
    request_url=$(echo "$line" | awk -F '|' '{print $8}')

    # 判断是否为目标接口的 GET 请求
    if [[ "$request_method" == "GET" && "$request_url" == *"$target_api"* ]]; then
        # 判断时间范围
        timestamp=$(date -d "$timestamp" +%s)
        if [[ "$timestamp" -ge "$start_time" && "$timestamp" -le "$end_time" ]]; then
            ((qps++))
        fi
    fi
done < "$log_file"

echo "QPS for $target_api: $qps"

使用PHP实现

代码语言:php
复制
<?php

$logFile = "access.log";
$targetAPI = "/getVideoInfo";

// 统计时间范围
$startTime = strtotime("2019-07-12 00:00:00");
$endTime = strtotime("2019-07-12 23:59:59");

// 统计请求数
$qps = 0;

$file = fopen($logFile, "r");
if ($file) {
    while (($line = fgets($file)) !== false) {
        // 解析日志行
        $parts = explode("|", $line);
        $timestamp = strtotime($parts[0]);
        $requestMethod = $parts[4];
        $requestURL = $parts[7];

        // 判断是否为目标接口的 GET 请求
        if ($requestMethod == "GET" && strpos($requestURL, $targetAPI) !== false) {
            // 判断时间范围
            if ($timestamp >= $startTime && $timestamp <= $endTime) {
                $qps++;
            }
        }
    }

    fclose($file);
} else {
    echo "Failed to open the log file.";
    exit;
}

echo "QPS for $targetAPI: $qps\n";

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • 解决思路
    • 思路一:使用wc命令
      • 思路二: 使用awk命令
      • 使用脚本处理
        • 使用Python脚本
          • 使用go来实现
            • 使用shell脚本实现
              • 使用PHP实现
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
              http://www.vxiaotou.com