blob: 06a8eda5bd4d230eb2aeb2952eee77708cd7fe0e [file] [log] [blame]
halil.cakal25ff8e82024-05-31 11:18:54 +01001#!/bin/bash
2#
3# Copyright 2024 Nordix Foundation.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18set -o errexit # Exit on most errors
19set -o nounset # Disallow expansion of unset variables
20set -o pipefail # Use last non-zero exit code in a pipeline
danielhanrahan913c6ea2024-06-28 18:14:14 +010021set -o xtrace # Trace logging
halil.cakal25ff8e82024-05-31 11:18:54 +010022
23#############################################################################################################################
24################################################ F U N C T I O N S ##########################################################
25#############################################################################################################################
26
halil.cakal25ff8e82024-05-31 11:18:54 +010027JENKINS_JOB_URL="https://jenkins.nordix.org/job/onap-cps-performance-test-k6"
28
halil.cakal25ff8e82024-05-31 11:18:54 +010029latestRecordedBuild=""
danielhanrahan913c6ea2024-06-28 18:14:14 +010030formattedTimestampOfLatestRecordedBuild=""
halil.cakal25ff8e82024-05-31 11:18:54 +010031
32# Get last completed build number
33# The number has not been plotted on the graphs yet
34getLastCompletedBuildNumber() {
35 curl -s "${JENKINS_JOB_URL}/lastCompletedBuild/buildNumber"
36}
37
38# Get the last recorded build number from local workspace of the jenkins
39# The number has already been plotted on the graphs
40getLastRecordedBuildNumber() {
danielhanrahan913c6ea2024-06-28 18:14:14 +010041 local file_name="data/1.csv"
halil.cakal25ff8e82024-05-31 11:18:54 +010042 if [ -f "$file_name" ]; then
danielhanrahan913c6ea2024-06-28 18:14:14 +010043 tail -n 1 "$file_name" | cut -d, -f1
halil.cakal25ff8e82024-05-31 11:18:54 +010044 else
danielhanrahan913c6ea2024-06-28 18:14:14 +010045 echo 0
halil.cakal25ff8e82024-05-31 11:18:54 +010046 fi
47}
48
49# Get all builds numbers
50getAllBuildNumbers() {
51 curl -s "${JENKINS_JOB_URL}/api/json?tree=allBuilds\[id\]" | jq -r '.allBuilds[].id' | sort -n
52}
53
danielhanrahan913c6ea2024-06-28 18:14:14 +010054# Extract CSV results from the console text of k6 performance job
55getSummaryCsv() {
halil.cakal25ff8e82024-05-31 11:18:54 +010056 buildToRead=$1
57 consoleURL="${JENKINS_JOB_URL}/${buildToRead}/consoleText"
danielhanrahan913c6ea2024-06-28 18:14:14 +010058 # Extract summary CSV from Jenkins console output
59 curl -s "$consoleURL" | sed -n '/-- BEGIN CSV REPORT/, /-- END CSV REPORT/p' | grep "^[1-9].*,.*,.*,.*,.*$" || true
halil.cakal25ff8e82024-05-31 11:18:54 +010060}
61
62# Get and record the latest k6-job-results with the build number for all tests
63getAndRecordPerformanceJobResultForBuild() {
64 buildNumber="$1"
danielhanrahan913c6ea2024-06-28 18:14:14 +010065 getSummaryCsv "$buildNumber" > summary.csv
66 if [ -s summary.csv ]; then
67 # Store the test cases, names, and units
68 cut -d, -f1,2,3 summary.csv > test-cases.csv
69 # Process each row in the CSV, storing the limit and actual value for this build
70 while IFS=, read -r test_case test_name units limit actual; do
71 echo "$buildNumber,$limit,$actual" >> "data/$test_case.csv"
72 done < summary.csv
halil.cakal25ff8e82024-05-31 11:18:54 +010073 else
danielhanrahan913c6ea2024-06-28 18:14:14 +010074 # No CSV data for this build, so record zeroes for this build in each existing data file
75 for dataFile in data/*.csv; do
76 echo "$buildNumber,0,0" >> "$dataFile"
77 done
halil.cakal25ff8e82024-05-31 11:18:54 +010078 fi
danielhanrahan913c6ea2024-06-28 18:14:14 +010079 recordLatestRecordedBuild "$buildNumber"
halil.cakal25ff8e82024-05-31 11:18:54 +010080}
81
82# Format the date and time of the latest build
83recordLatestRecordedBuild() {
danielhanrahan913c6ea2024-06-28 18:14:14 +010084 local latestBuildToRecord="$1"
85 local timestampOfLatestRecordedBuild
halil.cakal25ff8e82024-05-31 11:18:54 +010086 timestampOfLatestRecordedBuild=$(curl -s "${JENKINS_JOB_URL}/${latestBuildToRecord}/api/json?tree=timestamp" | jq -r '.timestamp')
87 formattedTimestampOfLatestRecordedBuild=$(date -d "@$((timestampOfLatestRecordedBuild / 1000))" "+%B %e, %Y at %H:%M")
88 latestRecordedBuild=$latestBuildToRecord
89}
90
91# Plot the image (graph) in png format
92buildPlotImage() {
93 dataFile="$1"
94 chartFileName="$2"
danielhanrahan913c6ea2024-06-28 18:14:14 +010095 units="$3"
halil.cakal25ff8e82024-05-31 11:18:54 +010096
danielhanrahanea512782024-08-01 11:14:13 +010097 y_max=$(findMaxPlotRange "$dataFile")
halil.cakal25ff8e82024-05-31 11:18:54 +010098
99 # Create a temporary Gnuplot script
100 cat <<EOT >gnuplot_script.gp
101set datafile separator ","
102set terminal pngcairo size 1500,600
103set output "${chartFileName}"
104set xlabel "Build"
danielhanrahan913c6ea2024-06-28 18:14:14 +0100105set ylabel "${units}"
danielhanrahanea512782024-08-01 11:14:13 +0100106set yrange [0 : ${y_max} < *]
halil.cakal7ae89342024-06-14 17:28:29 +0100107set xtics rotate
danielhanrahan913c6ea2024-06-28 18:14:14 +0100108plot '$dataFile' using 1:3:xtic(sprintf("%d", column(1))) with linespoints title "measured", \
109 '$dataFile' using 1:2 with lines linestyle 2 title "limit"
halil.cakal25ff8e82024-05-31 11:18:54 +0100110EOT
111
112 # Run the temporary Gnuplot script
113 gnuplot gnuplot_script.gp
114
115 # Remove the temporary Gnuplot script
116 rm gnuplot_script.gp
117}
118
danielhanrahanea512782024-08-01 11:14:13 +0100119# Set upper limit of the graphs to 20% bigger than largest value to have more space above the plot
120findMaxPlotRange() {
121 dataFile="$1"
122 awk -F, '{
123 if ($2 > max) max = $2;
124 if ($3 > max) max = $3;
125 } END {
126 print max * 1.2;
127 }' "$dataFile"
128}
halil.cakal25ff8e82024-05-31 11:18:54 +0100129#############################################################################################################################
130################################################ M A I N ####################################################################
131#############################################################################################################################
132
133# Install dependencies
134sudo apt-get install -y bc gnuplot jq
135
136# Download data from CPS performance Jenkins job
137cd "$WORKSPACE"
danielhanrahan913c6ea2024-06-28 18:14:14 +0100138if [ ! -d data ]; then
halil.cakal25ff8e82024-05-31 11:18:54 +0100139 # If workspace is empty, pull data from all previous performance job runs
danielhanrahan913c6ea2024-06-28 18:14:14 +0100140 mkdir -p data
halil.cakal25ff8e82024-05-31 11:18:54 +0100141 for buildNumber in $(getAllBuildNumbers); do
142 getAndRecordPerformanceJobResultForBuild "$buildNumber"
143 done
144else
145 # Append new data from latest jobs run
146 lastCompletedBuildNumber=$(getLastCompletedBuildNumber)
147 lastRecordedBuildNumber=$(getLastRecordedBuildNumber)
148 # Check if last completed build number is greater than last recorded build number
149 if [ "$lastCompletedBuildNumber" -gt "$lastRecordedBuildNumber" ]; then
150 for ((i = lastRecordedBuildNumber + 1; i <= lastCompletedBuildNumber; i++)); do
151 # Process the new builds which hasn't been recorded yet
152 getAndRecordPerformanceJobResultForBuild "$i"
153 done
154 else
155 echo "No new builds to process."
danielhanrahan913c6ea2024-06-28 18:14:14 +0100156 exit
halil.cakal25ff8e82024-05-31 11:18:54 +0100157 fi
158fi
159
danielhanrahan913c6ea2024-06-28 18:14:14 +0100160reportTitle="k6 tests performance review"
161outputFile="k6TestsPerformanceReview.html"
162cat <<EOT >"$outputFile"
163 <!DOCTYPE html>
164 <html>
165 <head>
166 <title>$reportTitle</title>
167 </head>
168 <body>
169 <h1 style="text-align: center;">$reportTitle</h1>
170 <h4>Last updated for performance job build no. $latestRecordedBuild on $formattedTimestampOfLatestRecordedBuild</h4>
171 <table align="center">
172EOT
halil.cakal25ff8e82024-05-31 11:18:54 +0100173
danielhanrahan913c6ea2024-06-28 18:14:14 +0100174# Loop through the tests to generate the HTML rows which consists of the plot-image
175while IFS=, read -r test_case test_name units; do
176 dataFile="data/$test_case.csv"
177 # Limit the plots to last 100 builds for each test
178 tail -n 100 "$dataFile" > file.tmp && mv file.tmp "$dataFile"
179 # Plot image files in png format
180 buildPlotImage "$dataFile" "data/$test_case.png" "$units"
181 # Output to HTML
182 cat <<EOF >>"$outputFile"
183 <tr>
184 <td align="center" style="padding: 10px;">
185 <figcaption>$test_case. $test_name ($units)</figcaption>
186 <img src="data/$test_case.png" width="750" height="300">
187 </td>
188 </tr>
189EOF
190done < test-cases.csv
halil.cakal25ff8e82024-05-31 11:18:54 +0100191
danielhanrahan913c6ea2024-06-28 18:14:14 +0100192# Close the HTML file
193cat <<EOT >>"$outputFile"
194 </table>
195 <p>The plots are generated from the output of the Nordix Jenkins job:
196 <a href="https://jenkins.nordix.org/job/onap-cps-performance-test-k6/">onap-cps-performance-test-k6</a>.</p>
197 <p>The k6 performance tests run are described in the
198 <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>
199 </body>
200 </html>
201EOT