로그는 다음과 같습니다.
Company=XYZ
Req_id=1234
Time_taken=10 sec
Status=Success
Company=ABC
Req_id=3456
Time_taken=200 sec
Status=Failure
Company=DFG
Req_id=3001
Time_taken=15 sec
Status=Success
가장 오랜 시간이 걸린 상위 3개의 요청 ID를 가져와야 합니다.
요청 ID와 경과 시간을 가져오는 다음 솔루션을 사용해 보았지만 답변이 만족스럽지 않습니다.
awk -vRS= -F'[=\n]' '/Time_taken/{print $4,$6}' test.txt | sort -nr
어떻게 하면 더 잘할 수 있나요? 내장된 함수 대신 일부 논리를 사용하여 코딩하세요. 또한, 더 잘 이해해야 합니까 -F'[=\n]'
? 방금 이전 스크립트에서 복사했습니다.
출력은 다음과 같아야 합니다.
Below Request Id took more then expected
Request id 3456, Time Taken 200 sec
Request id 3001, Time Taken 15 sec
Request id 1234, Time Taken 10 sec
답변1
다음만 사용하세요 awk
:
function list_insert (value, id, tmp) {
for (i = 1; i <= list_length; ++i)
if (value > value_list[i]) {
tmp = value_list[i]
value_list[i] = value
value = tmp
tmp = id_list[i]
id_list[i] = id
id = tmp
}
}
BEGIN {
FS = "[= ]"
list_length = 3
}
$1 == "Req_id" { id = $2 }
$1 == "Time_taken" { list_insert($2, id) }
END {
printf("Below Request Id took more then expected\n")
for (i = 1; i <= list_length; ++i)
printf("Request id %d, time taken %d sec\n", id_list[i], value_list[i])
}
이 프로그램은 두 개의 배열 value_list
sum 을 유지 관리합니다 . id_list
둘 다 length 입니다 . list_length
배열 value_list
은 정렬되어 시간 값을 포함하고 배열 id_list
에는 첫 번째 목록의 값에 해당하는 요청 ID가 포함됩니다.
이 list_insert
함수는 배열의 순서를 유지하면서 두 배열에 새로운 값과 ID를 삽입합니다 value_list
(올바른 삽입 위치를 찾은 다음 나머지 항목을 끝까지 섞습니다).
프로그램의 나머지 부분에서는 =
필드가 공백으로 구분된 개행으로 구분된 레코드로 데이터를 읽습니다. 요청 ID를 찾으면 에 저장하고 id
, "소요 시간" 항목을 찾으면 해당 ID와 소요 시간 값을 배열에 삽입합니다.
마지막으로 이 두 배열은 출력을 생성하는 데 사용됩니다.
테스트해보세요:
$ awk -f script.awk file
Below Request Id took more then expected
Request id 3456, time taken 200 sec
Request id 3001, time taken 15 sec
Request id 1234, time taken 10 sec
답변2
단락 모드를 사용하여 이 작업을 수행할 수 있습니다. Perl
여기서는 단락 크기의 파일 청크를 레코드로 읽고 시간이 지남에 따라 ID와 값으로 키가 지정된 해시를 구축합니다. 파일 끝에서 경과 시간을 숫자로 역순으로 정렬한 다음 원하는 메시지를 인쇄합니다.
$ perl -ln -00 -e '
%h = (%h, /^Req_id=(\d+)\n.*^Time_taken=(\d+)/ms)}{
print "The below IDs took more than expected:" if scalar keys %h;
print join " ", "Req ID:", "$_," , "Time taken", $h{$_}, "sec"
for (sort { $h{$b} <=> $h{$a} } keys %h)[0..2];
' input.file
산출:
The below IDs took more than expected:
Req ID: 3456, Time taken 200 sec
Req ID: 3001, Time taken 15 sec
Req ID: 1234, Time taken 10 sec
답변3
요청번호를 기억해두셔야 합니다.
나는 사용할 것입니다 (이것은 행일 수 있습니다)
awk -F= '$1 == "Req_id" {r=$2 ; }
$1 == "Time_taken" { printf "Request id %s %s %s\n",r,$1,$2 ; }' file |
sort -r -n -k5 |
head -3
이것은
Request id 3456 Time_taken 200 sec
Request id 3001 Time_taken 15 sec
Request id 1234 Time_taken 10 sec
어디
-F=
=
구분자 로 사용$1 == "Req_id" {r=$2 ; }
마지막 요청 ID 가져오기$1 == "Time_taken"
해당 줄이 "시간 보내기"인 경우{ printf "Request id %s %s %s\n",r,$1,$2 ; }
인쇄 요청 ID 및 초| sort
파이프 정렬-r
역순으로-n
숫자 정렬(예: 200은 15보다 큽니다)-k5
필드 5에서| head -3
처음 3개 행 가져오기
답변4
나는 한 줄의 코드를 제외하고는 awk보다 Python을 선호합니다. Python 스크립트를 사용하면 잘못된 입력을 더 쉽게 처리하고 로깅 및 오류 처리를 수행할 수 있습니다.
다음은 예제 입력에 필요한 출력을 생성하는 기본 Python 스크립트이며, 해당 구조는 필요한 경우 추가로 빌드할 수 있는 방법에 대한 힌트를 제공합니다.
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""parse_log.py"""
import sys
from collections import OrderedDict
logfilepath = sys.argv[1]
# Define a function to parse a single block/entry in the log file
def parse_block(block):
parsed_block = dict()
lines = block.split("\n")
for line in lines:
if line.startswith("Company="):
parsed_block["Company"] = line[8:]
elif line.startswith("Req_id="):
parsed_block["Required_ID"] = line[7:]
elif line.startswith("Time_taken="):
parsed_block["Time_Taken"] = line[11:]
elif line.startswith("Status="):
parsed_block["Status"] = line[7:]
else:
pass
return parsed_block
# Initialize a list to store the processed entries
parsed_blocks = list()
# Populate the list
with open(logfilepath, "r") as logfile:
blocks = logfile.read().split("\n\n")
for block in blocks:
parsed_block = parse_block(block)
parsed_blocks.append(parsed_block)
# Print the results
print("Below Request Id took more then expected")
for parsed_block in parsed_blocks:
print("Request id {}, Time Taken: {}".format(parsed_block["Required_ID"], parsed_block["Time_Taken"]))
다음과 같이 실행할 수 있습니다.
python parse_log.py data.log
귀하의 입력 예에서는 요청에 따라 다음과 같은 출력을 생성합니다.
Below Request Id took more then expected
Request id 1234, Time Taken: 10 sec
Request id 3456, Time Taken: 200 sec
Request id 3001, Time Taken: 15 sec