CSVファイルにテスト結果があります。最初のフィールドにはミリ秒単位のタイムスタンプがあります。
以下はCSVファイルのサンプルレコードです。
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
ランプアップ(開始時間から5分)およびランプダウン期間(過去5分)の間のテスト結果を削除し、フィルタリングされたテスト結果をCSVファイルに書きたいです。
ハードコードされた値を試してみました。
#!/usr/bin/awk -f
BEGIN {
endTime=1628689875326
startTime=1628689875326-300*1000
offset=1628689875326-3900*1000
FS=","
rowCount=0
}
{
if ($1> startTime && $1<offset){
rowCount++
print $0
}
}
答え1
awkを呼び出すためにshebangを使用する代わりに、shebangを使用してシェルを呼び出し、次にawkを呼び出します。バラよりhttps://stackoverflow.com/a/61002754/1745001なぜ。
私はあなたがしたいことをします:
#!/usr/bin/env bash
awk -F',' '
NR==FNR {
if (NR==2) {
fiveMins = 5*60*1000*1000
begTime = $1 + fiveMins
}
endTime = $1 - fiveMins
next
}
(FNR==1) || ( (begTime <= $1) && ($1 <= endTime) ) {
print
rowCount++
}
END {
print rowCount+0 | "cat>&2"
}
' "$1" "$1"
tail
または、次を使用して最後の行のタイムスタンプを取得できます。@GreenOnlineの返信)awkからファイルを2回読み取る代わりに:
#!/usr/bin/env bash
awk -v lastTime="$(tail -n 1 "$1" | cut -d',' -f1)" -F',' '
NR==2 {
fiveMins = 5*60*1000*1000
begTime = $1 + fiveMins
endTime = lastTime - fiveMins
}
(NR==1) || ( (begTime <= $1) && ($1 <= endTime) ) {
print
rowCount++
}
END {
print rowCount+0 | "cat>&2"
}
' "$1"
どちらにしても次のように呼び出すことができます。
scriptname input.csv > output.csv
> output.csv
または、出力ファイル名をハードコーディングしても問題ない場合は、シェルスクリプトのawkスクリプトの後に追加してください。
上記は、CSVに出力に印刷したいヘッダー行があると仮定しています。
Shebangを使用せずにawkを呼び出すと、シェルを使用して最良の操作、つまり別のコマンドを呼び出し、スクリプト引数を複数回使用し、次にawkを呼び出すことで最良の操作、つまりテキストを処理できます。起動率 他の方法は、よりクリーンで強力で効率的なスクリプトです。
答え2
ハードコーディングされたソリューション
ハードコーディングされた時間スクリプトでは、問題は次のとおりです。
offset
より小さいstartTime
のでif
条件は$1> startTime && $1<offset
できるいいえそれは真実だ。
その理由はまだ5分(=300秒)がstartTime
残っているのですが、まだ65分(=3900秒)が残っているからです。5*60
offset
65*60
解決策は、初期化プログラムを次に変更することです。
startTime=1628689875326-3900*1000*1000
offset=1628689875326-300*1000*1000
これにより、関連時間が次に設定されます。
endTime = 1628689875326
startTime = endTime - (3900*1000*1000) = 1624789875326
5 minutes before end = endTime - (300*1000*1000) = 1628389875326
これで、次のログファイルが提供されます。
1624789875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
走る
more test.log | ./filter.awk
希望の結果を提供します
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
より良いソリューション - 開始時間を確認する
しかし、あなたの質問を詳しく調べてみると、いくつかのことが明確に定義されていないことがわかりました。
スクリプトでは、
startTime
実際のログの開始ではなく、フィルタの開始である可能性があります。ログの開始時間は5分前です。1624789875326 - 300*1000*1000 = 1624489875326
時間はミリ秒単位だと言っ
*1000*1000
たけどマイクロ秒。
それにもかかわらず、開始時間(ログファイルの最初の行から始まる)を自動的に見つけ、ランプ時間を計算してフィルタの開始時間を計算するソリューションがあります。
また、フィルタ時間の終わりも計算します(ハードコードされたスクリプトと同じ方法)。終了時間を入力する必要がありますが、、これはログの最後のタイムスタンプです。
#!/usr/bin/awk -f
BEGIN {
rampTimeMins=5
rampTimeMillis=rampTimeMins*60*1000
rampTimeMicros=rampTimeMins*60*1000*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in microseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMicros
# Enter the end time (required)
endTime=1628689875326
# Calculate End filter time in microseconds
filterEndTime=endTime-rampTimeMicros
FS=","
rowCount=0
}
{
if (NR==1){
startTime=$1
filterStartTime=startTime+rampTimeMicros
}
if ($1> filterStartTime && $1<filterEndTime){
rowCount++
print $0
}
}
END {
print rowCount
}
注1:CSVの最初の行がヘッダーの場合は、NR==1
次のように変更してください。NR==2
ノート2:マイクロ秒の代わりにミリ秒を使用するには、rampTimeMicros
に変更しますrampTimeMillis
。
以下は、次を含むサンプルログファイルです。追加ログの実際の開始時間である初期時間(フィルタの開始時間ではない)
1624489875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624489875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628689875326,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
どちらで実行するか
more test.log | ./filter.awk
以前と同じ結果を提供します
1624789875327,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
1628389875325,327,3.1 HTTP Request /api/StaffPortal,200,OK,Concurrency Thread Group SignIn-ThreadStarter 1-5,text,true,,73018,17,17
2
しかし、追加の行があります。
最終ソリューション - 終了時間を取得する
行を変更すると
endTime=1628689875326
到着
"tail -1 test.log | cut -d, -f1" | getline endTime
これで最後のタイムスタンプが得られたので、スクリプトを編集する必要はありません。今後スクリプトが実行されます。一般用途で製作
"tail -1 "ARGV[1]" | cut -d, -f1" | getline endTime
あるいは、より良い方法は、(安全な側面を維持するために)次のように生成されたサブシェルに引用されたファイル名を渡すことです。エドのコメント:
生成されたサブシェルに引用符なしでファイル名を渡さないように変更します(これはすべてグロービング、トークン化、セキュリティなどを意味します
"tail -1 "ARGV[1]"
)。"tail -1 \047"ARGV[1]"\047
\047
一重引用符(FWIW:\042
二重引用符)はどこにありますか?
"tail -1 \047"ARGV[1]"\047 | cut -d, -f1" | getline endTime
したがって、最終スクリプトは次のようになります。
#!/usr/bin/awk -f
BEGIN {
rampTimeMins=5
rampTimeMillis=rampTimeMins*60*1000
rampTimeMicros=rampTimeMins*60*1000*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in microseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMicros
# Derive the end time
"tail -1 \047"ARGV[1]"\047 | cut -d, -f1" | getline endTime
# Calculate End filter time in microseconds
filterEndTime=endTime-rampTimeMicros
FS=","
rowCount=0
}
{
if (NR==1){
startTime=$1
filterStartTime=startTime+rampTimeMicros
}
if ($1> filterStartTime && $1<filterEndTime){
rowCount++
print $0
}
}
END {
print rowCount
}
注1:CSVの最初の行がヘッダーの場合は、NR==1
次のように変更してください。NR==2
次のコマンド(filter.awk
)を使用してスクリプトを実行します。
./filter.awk test.log
いいえ
more test.log | ./filter.awk
引用する:
答え3
与えられたサンプルスクリプトは、次の修正で更新されました。
- 入力ファイルの2行目の開始時刻に基づいて
filterStartTime
合計を計算します。filterEndTime
- さらなる分析のためにファイルに出力を書き込む
#!/usr/bin/awk -f
BEGIN {
testDurationMins=60
rampTimeMins=5
outputFileName="test-result-filtered-without-rampup.jtl"
rampTimeMillis=rampTimeMins*60*1000
# Enter the start time
# (not required, if NR conditional is used)
startTime=0
# Calculate Start filter time in milliseconds
# (not required, if NR conditional is used)
filterStartTime=startTime+rampTimeMillis
# Filter end time
filterEndTime=0
# Calculate the test duration in milliseconds
testDurationMillis=testDurationMins*60*1000
FS=","
rowCount=0
}
{
if (NR==1){
#Write header to the output file
print > outputFileName
}
if (NR==2){
#Set the filter start and end times
startTime=$1
filterStartTime=startTime+rampTimeMillis
filterEndTime=filterStartTime+testDurationMillis
}
if (NR>2 && $1> filterStartTime && $1<filterEndTime){
rowCount++
print >> outputFileName
}
}
END {
print "" rowCount
}