blob: 90c29b43b117ef945abf16c32f67d8dc1be6f85d [file] [log] [blame]
#!/bin/bash
#
# Copyright 2024 Nordix Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -o errexit # Exit on most errors
set -o nounset # Disallow expansion of unset variables
set -o pipefail # Use last non-zero exit code in a pipeline
set -o xtrace # Trace logging
#############################################################################################################################
################################################ F U N C T I O N S ##########################################################
#############################################################################################################################
JENKINS_JOB_URL="https://jenkins.nordix.org/job/onap-cps-performance-test-k6"
latestRecordedBuild=""
formattedTimestampOfLatestRecordedBuild=""
# Get last completed build number
# The number has not been plotted on the graphs yet
getLastCompletedBuildNumber() {
curl -s "${JENKINS_JOB_URL}/lastCompletedBuild/buildNumber"
}
# Get the last recorded build number from local workspace of the jenkins
# The number has already been plotted on the graphs
getLastRecordedBuildNumber() {
local file_name="data/1.csv"
if [ -f "$file_name" ]; then
tail -n 1 "$file_name" | cut -d, -f1
else
echo 0
fi
}
# Get all builds numbers
getAllBuildNumbers() {
curl -s "${JENKINS_JOB_URL}/api/json?tree=allBuilds\[id\]" | jq -r '.allBuilds[].id' | sort -n
}
# Extract CSV results from the console text of k6 performance job
getSummaryCsv() {
buildToRead=$1
consoleURL="${JENKINS_JOB_URL}/${buildToRead}/consoleText"
# Extract summary CSV from Jenkins console output
curl -s "$consoleURL" | sed -n '/-- BEGIN CSV REPORT/, /-- END CSV REPORT/p' | grep "^[0-9].*,.*,.*,.*,.*$" || true
}
# Get and record the latest k6-job-results with the build number for all tests
getAndRecordPerformanceJobResultForBuild() {
buildNumber="$1"
getSummaryCsv "$buildNumber" > summary.csv
if [ -s summary.csv ]; then
# Store the test cases, names, and units
cut -d, -f1,2,3 summary.csv > test-cases.csv
# Process each row in the CSV, storing the limit cps_expectation and actual value for this build
while IFS=, read -r test_case test_name units limit cps_expectation actual; do
echo "$buildNumber,$limit,$cps_expectation,$actual" >> "data/$test_case.csv"
done < summary.csv
else
# No CSV data for this build, so record zeroes for this build in each existing data file
for dataFile in data/*.csv; do
echo "$buildNumber,0,0,0" >> "$dataFile"
done
fi
recordLatestRecordedBuild "$buildNumber"
}
# Format the date and time of the latest build
recordLatestRecordedBuild() {
local latestBuildToRecord="$1"
local timestampOfLatestRecordedBuild
timestampOfLatestRecordedBuild=$(curl -s "${JENKINS_JOB_URL}/${latestBuildToRecord}/api/json?tree=timestamp" | jq -r '.timestamp')
formattedTimestampOfLatestRecordedBuild=$(date -d "@$((timestampOfLatestRecordedBuild / 1000))" "+%B %e, %Y at %H:%M")
latestRecordedBuild=$latestBuildToRecord
}
# Plot the image (graph) in png format
buildPlotImage() {
dataFile="$1"
chartFileName="$2"
units="$3"
numberOfBuilds="$4"
y_max=$(findMaxPlotRange "$dataFile")
# Create a temporary Gnuplot script
cat <<EOT >gnuplot_script.gp
set datafile separator ","
set terminal pngcairo size 1500,600
set output "${chartFileName}"
set xlabel "Build"
set ylabel "${units}"
# Set y-axis range based on y_max
set yrange [0 : ${y_max}]
set style line 1 lc rgb '#d3d3d3' lt 1 lw 1 dashtype 2 # Grid style
set style line 2 lc rgb '#0000FF' lt 1 lw 1 # threshold - Blue
set style line 3 lc rgb '#00FF00' lt 1 lw 1 # cps-limit - Green
set style line 4 lc rgb '#800080' lt 1 lw 1 # measured - Purple
set grid ytics ls 1
set xtics rotate
# Use plot command with explicit column assignments and lines for all series
EOT
if [ "$numberOfBuilds" -eq 100 ]; then
cat <<EOT >>gnuplot_script.gp
plot '<(tail -n $numberOfBuilds $dataFile)' using 1:2 with lines linestyle 2 title "threshold", \
'<(tail -n $numberOfBuilds $dataFile)' using 1:3 with lines linestyle 3 title "cps-limit", \
'<(tail -n $numberOfBuilds $dataFile)' using 1:4:xtic(1) with linespoints linestyle 4 title "measured"
EOT
elif [ "$numberOfBuilds" -eq 168 ]; then
cat <<EOT >>gnuplot_script.gp
plot '<(tail -n $numberOfBuilds $dataFile | awk "NR % 2 == 0")' using 1:2 with lines linestyle 2 title "threshold", \
'<(tail -n $numberOfBuilds $dataFile | awk "NR % 2 == 0")' using 1:3 with lines linestyle 3 title "cps-limit", \
'<(tail -n $numberOfBuilds $dataFile | awk "NR % 2 == 0")' using 1:4:xtic(1) with linespoints linestyle 4 title "measured"
EOT
elif [ "$numberOfBuilds" -eq 720 ]; then
cat <<EOT >>gnuplot_script.gp
plot '<(tail -n $numberOfBuilds $dataFile | awk "NR % 7 == 0")' using 1:2 with lines linestyle 2 title "threshold", \
'<(tail -n $numberOfBuilds $dataFile | awk "NR % 7 == 0")' using 1:3 with lines linestyle 3 title "cps-limit", \
'<(tail -n $numberOfBuilds $dataFile | awk "NR % 7 == 0")' using 1:4:xtic(1) with linespoints linestyle 4 title "measured"
EOT
fi
# Run the temporary Gnuplot script
gnuplot gnuplot_script.gp
# Remove the temporary Gnuplot script
rm gnuplot_script.gp
}
# Set upper limit of the graphs to 20% bigger than largest value to have more space above the plot
findMaxPlotRange() {
dataFile="$1"
awk -F, '{
if ($2 > max) max = $2;
if ($3 > max) max = $3;
if ($4 > max) max = $4;
} END {
if (max == 0) {
max = 100;
}
print max * 1.2;
}' "$dataFile"
}
generateHtmlReport() {
local reportTitle="$1"
local outputFile="$2"
local numberOfBuilds="$3"
cat <<EOT >"$outputFile"
<!DOCTYPE html>
<html>
<head>
<title>$reportTitle</title>
</head>
<body>
<h1 style="text-align: center;">$reportTitle</h1>
<h4>Last updated for performance job build no. $latestRecordedBuild on $formattedTimestampOfLatestRecordedBuild</h4>
<table align="center">
EOT
# Loop through the tests to generate the HTML rows which consists of the plot-image
while IFS=, read -r test_case test_name units; do
dataFile="data/$test_case.csv"
# Plot the image (graph) in png format
buildPlotImage "$dataFile" "data/${test_case}_${numberOfBuilds}.png" "$units" "$numberOfBuilds"
# Output to HTML
cat <<EOF >>"$outputFile"
<tr>
<td align="center" style="padding: 10px;">
<figcaption>$test_case. $test_name ($units)</figcaption>
<img src="data/${test_case}_${numberOfBuilds}.png" width="750" height="300">
</td>
</tr>
EOF
done < test-cases.csv
# Close the HTML file
cat <<EOT >>"$outputFile"
</table>
<p>The plots are generated from the output of the Nordix Jenkins job:
<a href="https://jenkins.nordix.org/job/onap-cps-performance-test-k6/">onap-cps-performance-test-k6</a>.</p>
<p>The k6 performance tests run are described in the
<a href="https://wiki.onap.org/display/DW/CPS-391Spike%3A+Define+and+Agree+NCMP+REST+Interface#CPS391Spike:DefineandAgreeNCMPRESTInterface-Characteristics">NCMP REST Interface Characteristics</a> documentation.</p>
</body>
</html>
EOT
}
#############################################################################################################################
################################################ M A I N ####################################################################
#############################################################################################################################
# Install dependencies
sudo apt-get install -y bc gnuplot jq
# Download data from CPS performance Jenkins job
cd "$WORKSPACE"
if [ ! -d data ]; then
# If workspace is empty, pull data from all previous performance job runs
mkdir -p data
for buildNumber in $(getAllBuildNumbers); do
getAndRecordPerformanceJobResultForBuild "$buildNumber"
done
else
# Append new data from latest jobs run
lastCompletedBuildNumber=$(getLastCompletedBuildNumber)
lastRecordedBuildNumber=$(getLastRecordedBuildNumber)
# Check if last completed build number is greater than last recorded build number
if [ "$lastCompletedBuildNumber" -gt "$lastRecordedBuildNumber" ]; then
for ((i = lastRecordedBuildNumber + 1; i <= lastCompletedBuildNumber; i++)); do
# Process the new builds which hasn't been recorded yet
getAndRecordPerformanceJobResultForBuild "$i"
done
else
echo "No new builds to process."
exit
fi
fi
reportTitleDaily="daily k6 tests performance review"
outputFileDaily="k6TestsPerformanceReview.html"
generateHtmlReport "$reportTitleDaily" "$outputFileDaily" "100"
reportTitleWeekly="weekly k6 tests performance review"
outputFileWeekly="k6TestsPerformanceReviewWeekly.html"
generateHtmlReport "$reportTitleWeekly" "$outputFileWeekly" "168"
reportTitleMonthly="monthly k6 tests performance review"
outputFileMonthly="k6TestsPerformanceReviewMonthly.html"
generateHtmlReport "$reportTitleMonthly" "$outputFileMonthly" "720"