Merge "Create jenkins pipeline for k6 performance tests"
[infra/cicd.git] / jjb / onap / cps / prepare-performance-tests-data.sh
1 #!/bin/bash
2 #
3 # Copyright 2023-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
18 set -o errexit  # Exit on most errors
19 set -o nounset  # Disallow expansion of unset variables
20 set -o pipefail # Use last non-zero exit code in a pipeline
21 #set -o xtrace   # Trace logging - disabled to avoid producing gigabytes of logs
22
23 #############################################################################################################################
24 ################################################ F U N C T I O N S ##########################################################
25 #############################################################################################################################
26
27 cps_stable_test_names=("Delete data nodes for anchor" "Delete one large node" "Batch delete 100 lists elements" "Batch delete 100 containers" "Query across anchors top element" "Delete root node" "Query across anchors ancestors" "Query across anchors leaf condition + an" "Read datatrees using openroadm root" "Read datatrees using openroadm top eleme" "Query 1 anchor leaf condition + ancestor" "Query 1 anchor top element" "Creating 33,000 books" "Replace list of 0 with 100" "Query ancestors with all descendants" "Replace 0 nodes with 100" "Writing 6400 books" "Read datatrees with all descendants" "Query 1 anchor ancestors" "Writing 400 devices" "Writing 3200 books" "Saving list of 100 devices" "Saving list of 50 devices" "Saving list of 400 devices" "Query with all descendants" "Writing 100 devices" "Writing 50 devices" "Writing 200 devices" "Read datatrees for multiple xpaths" "Saving list of 200 devices")
28
29 ncmp_stable_test_names=("Look up CM-handles by module-set-tag" "CpsPath Registry attributes Query")
30
31 cps_unstable_test_names=("Batch delete 100 non-existing"  "Batch delete 100 whole lists"  "Query with direct descendants"  "Delete 100 whole lists"  "Query 1 anchor non-existing data"  "Read datatrees with no descendants"  "Read non-existing xpaths"  "Query with no descendants"  "Update leaves for 100 data nodes"  "Query ancestors with no descendants"  "Replace 100 with new leaf values"  "Query ancestors with direct descendants"  "Replace list of 100 with new leaf values"  "Replace list of 100 using same data"  "Deleting test data"  "Replace list of 100 nodes with 1"  "Read datatrees using openroadm whole lis"  "Replace 100 using same data"  "Read datatrees with direct descendants"  "Replace 100 nodes with 0"  "Replace list with 50 existing and 50 new"  "Delete 100 lists elements"  "Replace 50 existing and 50 new"  "Writing 800 books"  "Delete 100 containers"  "Replace list with 100 new nodes"  "Replace 100 with 100 new nodes"  "Writing 1600 books"  "Saving list of 200 devices"  "Read datatrees for multiple xpaths")
32
33 ncmp_unstable_test_names=("Look up CM-handle by id" "Update matching subscription" "Look up CM-handle by alternate-id")
34
35 JENKINS_JOB_URL="https://jenkins.nordix.org/job/onap-cps-master-performance-test-java"
36
37 latestBuildToRecord=""
38 consoleText=""
39 latestRecordedBuild=""
40 timestampOfLatestRecordedBuild=""
41
42 # Get latest-completed build number from the jenkins job
43 # The number has not been plotted on the graphs yet
44 getLastCompletedBuildNumber() {
45   curl -s "${JENKINS_JOB_URL}/lastCompletedBuild/buildNumber"
46 }
47
48 # Get the last build number from local workspace
49 # The number has already been plotted on the graphs
50 getLastRecordedBuildNumber() {
51   cd "$WORKSPACE"
52   local file_name="Delete root node.txt"
53
54   # Check if the file exists
55   if [ -f "$file_name" ]; then
56     # Get the last line from the file
57     local last_line=$(tail -n 1 "$file_name")
58     local left_side=$(echo "$last_line" | cut -d ',' -f 1)
59     echo "$left_side"
60   else
61     echo "0"
62   fi
63 }
64
65 # Get all builds numbers
66 getAllBuildNumbers() {
67   curl -s "${JENKINS_JOB_URL}/api/json?tree=allBuilds\[id\]" | jq -r '.allBuilds[].id' | sort -n
68 }
69
70 # Get the console text from specific build of the performance job
71 getConsoleText() {
72   buildToRead=$1
73   consoleURL="${JENKINS_JOB_URL}/${buildToRead}/consoleText"
74   consoleText=$(curl -s "$consoleURL")
75 }
76
77 # Get and record the percentage (performance job result) for each test name for a build number
78 getAndRecordPerformanceJobResultForBuild() {
79   buildNumber="$1"
80   getConsoleText "$buildNumber"
81   # Loop through each text name
82   for cps_stable_test_name in "${cps_stable_test_names[@]}"; do
83     getAndRecordDataResults "$consoleText" "$cps_stable_test_name" "$cps_stable_test_name.txt" "$buildNumber"
84   done
85   for ncmp_stable_test_name in "${ncmp_stable_test_names[@]}"; do
86     getAndRecordDataResults "$consoleText" "$ncmp_stable_test_name" "$ncmp_stable_test_name.txt" "$buildNumber"
87   done
88   for cps_unstable_test_name in "${cps_unstable_test_names[@]}"; do
89     getAndRecordDataResults "$consoleText" "$cps_unstable_test_name" "$cps_unstable_test_name.txt" "$buildNumber"
90   done
91   for ncmp_unstable_test_name in "${ncmp_unstable_test_names[@]}"; do
92     getAndRecordDataResults "$consoleText" "$ncmp_unstable_test_name" "$ncmp_unstable_test_name.txt" "$buildNumber"
93   done
94 }
95
96 # Calculate the percentage value for a specific test and append into test data file with build number
97 getAndRecordDataResults() {
98   consoleText=$1
99   patternToMatch=$2
100   dataFile=$3
101   buildNumber=$4
102   new_data=""
103   matched_line=""
104   limit_value=""
105   took_value=""
106
107   # Get and calculate percentage for the graph
108   if matched_line=$(echo "$consoleText" | grep "$patternToMatch"); then
109     limit_value=$(echo "$matched_line" | grep -o -P 'limit\s*\K\d+(\.\d+)?' | tr -cd '[:digit:].')
110     took_value=$(echo "$matched_line" | grep -o -P 'took\s*\K\d+(\.\d+)?' | tr -cd '[:digit:].')
111     percentage=$(echo "scale=2; $took_value * 100.00 / $limit_value" | bc)
112     new_data="$percentage"
113   fi
114
115   # Record result into related test data file
116   touch "$dataFile"
117   lastLine=$(tail -n 1 "$dataFile")
118   newLine="$buildNumber,$new_data"
119   if [ -z "$new_data" ]; then
120     # No data found for this build probably the build failed
121     echo "$buildNumber,0" >>"$dataFile"
122     recordLatestRecordedBuild "$buildNumber"
123   elif [ "$newLine" == "$lastLine" ]; then
124     # Data already exists
125     recordLatestRecordedBuild "$buildNumber"
126   else
127     # New data added into the file
128     echo "$buildNumber,$new_data" >>"$dataFile"
129     recordLatestRecordedBuild "$buildNumber"
130   fi
131 }
132
133 # Save the latest recorded build number with date and time
134 recordLatestRecordedBuild() {
135   latestBuildToRecord="$1"
136   timestampOfLatestRecordedBuild=$(curl -s "${JENKINS_JOB_URL}/${latestBuildToRecord}/api/json?tree=timestamp" | jq -r '.timestamp')
137   formattedTimestampOfLatestRecordedBuild=$(date -d "@$((timestampOfLatestRecordedBuild / 1000))" "+%B %e, %Y at %H:%M")
138   latestRecordedBuild=$latestBuildToRecord
139 }
140
141 # Plot the image (graph) in png format
142 buildPlotImage() {
143   dataFile="$1" # Get the input file name from the function parameter
144   chartFileName="$2"
145
146   # Create a temporary Gnuplot script
147   cat <<EOT >gnuplot_script.gp
148 set datafile separator ","
149 set terminal pngcairo size 1500,600
150 set output "${chartFileName}"
151 set xlabel "Build"
152 set ylabel "Percentage of limit %"
153 set yrange [0 < * < 80 : 120 < *]
154 set xtics rotate
155 plot '$dataFile' using (column(0)):2:xtic(sprintf("%d", column(1))) with linespoints title "measured", \
156      100 with lines linestyle 2 title "100% limit"
157 EOT
158
159   # Run the temporary Gnuplot script
160   gnuplot gnuplot_script.gp
161
162   # Remove the temporary Gnuplot script
163   rm gnuplot_script.gp
164 }
165
166 # Builds category html file
167 buildCategoryHtmlReport() {
168   # use indirect expansion to get all elements of the array
169   categoryName=("${!1}")
170   reportTitle="$2"
171   outputFile="$3"
172   cat <<EOT >"$outputFile"
173     <!DOCTYPE html>
174     <html>
175     <head>
176     <title>$reportTitle</title>
177     </head>
178     <body>
179       <h1 style="text-align: center;">$reportTitle</h1>
180       <h4>Last updated for performance job build no. $latestRecordedBuild on $formattedTimestampOfLatestRecordedBuild</h4>
181       <table align="center">
182 EOT
183 # Loop through the test names to generate HTML rows
184 for test_name_in_category in "${categoryName[@]}"; do
185     cat <<EOF >>"$outputFile"
186         <tr> <!-- Row for $test_name_in_category -->
187             <td align="center" style="padding: 10px;">
188                 <figcaption>"$test_name_in_category"</figcaption>
189                 <img src="$test_name_in_category.png" width="750" height="300">
190             </td>
191         </tr>
192 EOF
193 done
194 # Close the HTML file
195 cat <<EOT >>"$outputFile"
196       </table>
197         <p>The performance tests job runs every two (even) hours, providing performance metrics. The following graphs being updated every two (odd) hours.</p>
198         <p>Successful performance tests job build adds new data, but even if a build fails, existing data is retained.</p>
199         <p>Updates occur whenever new successful data is available.</p>
200     </body>
201   </html>
202 EOT
203 }
204
205 #############################################################################################################################
206 ################################################ M A I N ####################################################################
207 #############################################################################################################################
208
209 # Install dependencies
210 sudo apt-get install -y bc gnuplot jq
211
212 # Download data from CPS performance Jenkins job
213 cd "$WORKSPACE"
214 if [ -z "$(ls -A)" ]; then
215   # If workspace is empty, pull data from all previous performance job runs
216   for buildNumber in $(getAllBuildNumbers); do
217     getAndRecordPerformanceJobResultForBuild "$buildNumber"
218   done
219 else
220   # Append new data from latest jobs run
221   lastCompletedBuildNumber=$(getLastCompletedBuildNumber)
222   lastRecordedBuildNumber=$(getLastRecordedBuildNumber)
223   # Check if last completed build number is greater than last recorded build number
224   if [ "$lastCompletedBuildNumber" -gt "$lastRecordedBuildNumber" ]; then
225     for ((i = lastRecordedBuildNumber + 1; i <= lastCompletedBuildNumber; i++)); do
226       getAndRecordPerformanceJobResultForBuild "$i"
227     done
228   else
229     echo "No new builds to process."
230   fi
231 fi
232
233 # Plot image (graphs) files in png format
234 for cps_stable_test_name in "${cps_stable_test_names[@]}"; do
235   buildPlotImage "$cps_stable_test_name.txt" "$cps_stable_test_name.png"
236 done
237 for ncmp_stable_test_name in "${ncmp_stable_test_names[@]}"; do
238   buildPlotImage "$ncmp_stable_test_name.txt" "$ncmp_stable_test_name.png"
239 done
240 for cps_unstable_test_name in "${cps_unstable_test_names[@]}"; do
241   buildPlotImage "$cps_unstable_test_name.txt" "$cps_unstable_test_name.png"
242 done
243 for ncmp_unstable_test_name in "${ncmp_unstable_test_names[@]}"; do
244   buildPlotImage "$ncmp_unstable_test_name.txt" "$ncmp_unstable_test_name.png"
245 done
246
247 # Build the category pages
248 buildCategoryHtmlReport cps_stable_test_names[@] "cps stable tests performance review" "cpsStableTestsPerformanceReview.html"
249 buildCategoryHtmlReport ncmp_stable_test_names[@] "ncmp stable tests performance review" "ncmpStableTestsPerformanceReview.html"
250 buildCategoryHtmlReport cps_unstable_test_names[@] "cps unstable tests performance review" "cpsUnstableTestsPerformanceReview.html"
251 buildCategoryHtmlReport ncmp_unstable_test_names[@] "ncmp unstable tests performance review" "ncmpUnstableTestsPerformanceReview.html"