47739442a9ceeaed4c21d93c6632ce2e865beb63
[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_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_test_name_names=("Look up CM-handles by module-set-tag")
30
31 JENKINS_JOB_URL="https://jenkins.nordix.org/job/onap-cps-master-performance-test-java"
32
33 latestBuildToRecord=""
34 consoleText=""
35 latestRecordedBuild=""
36 timestampOfLatestRecordedBuild=""
37
38 # Get latest-completed build number from the jenkins job
39 # The number has not been plotted on the graphs yet
40 getLastCompletedBuildNumber() {
41   curl -s "${JENKINS_JOB_URL}/lastCompletedBuild/buildNumber"
42 }
43
44 # Get the last build number from local workspace
45 # The number has already been plotted on the graphs
46 getLastRecordedBuildNumber() {
47   cd "$WORKSPACE"
48   local file_name="Delete root node.txt"
49
50   # Check if the file exists
51   if [ -f "$file_name" ]; then
52     # Get the last line from the file
53     local last_line=$(tail -n 1 "$file_name")
54     local left_side=$(echo "$last_line" | cut -d ',' -f 1)
55     echo "$left_side"
56   else
57     echo "File '$file_name' not found in the current directory"
58   fi
59 }
60
61 # Get all builds numbers
62 getAllBuildNumbers() {
63   curl -s "${JENKINS_JOB_URL}/api/json?tree=allBuilds\[id\]" | jq -r '.allBuilds[].id' | sort -n
64 }
65
66 # Get the console text from specific build of the performance job
67 getConsoleText() {
68   buildToRead=$1
69   consoleURL="${JENKINS_JOB_URL}/${buildToRead}/consoleText"
70   consoleText=$(curl -s "$consoleURL")
71 }
72
73 # Get and record the percentage (performance job result) for each test name for a build number
74 getAndRecordPerformanceJobResultForBuild() {
75   buildNumber="$1"
76   getConsoleText "$buildNumber"
77   # Loop through each text name
78   for cps_test_name in "${cps_test_names[@]}"; do
79     getAndRecordDataResults "$consoleText" "$cps_test_name" "$cps_test_name.txt" "$buildNumber"
80   done
81   for ncmp_test_name in "${ncmp_test_name_names[@]}"; do
82     getAndRecordDataResults "$consoleText" "$ncmp_test_name" "$ncmp_test_name.txt" "$buildNumber"
83   done
84 }
85
86 # Calculate the percentage value for a specific test and append into test data file with build number
87 getAndRecordDataResults() {
88   consoleText=$1
89   patternToMatch=$2
90   dataFile=$3
91   buildNumber=$4
92   new_data=""
93   matched_line=""
94   limit_value=""
95   took_value=""
96
97   # Get and calculate percentage for the graph
98   if matched_line=$(echo "$consoleText" | grep "$patternToMatch"); then
99     limit_value=$(echo "$matched_line" | grep -o -P 'limit\s*\K\d+(\.\d+)?' | tr -cd '[:digit:].')
100     took_value=$(echo "$matched_line" | grep -o -P 'took\s*\K\d+(\.\d+)?' | tr -cd '[:digit:].')
101     percentage=$(echo "scale=2; $took_value * 100.00 / $limit_value" | bc)
102     new_data="$percentage"
103   fi
104
105   # Record result into related test data file
106   touch "$dataFile"
107   lastLine=$(tail -n 1 "$dataFile")
108   newLine="$buildNumber,$new_data"
109   if [ -z "$new_data" ]; then
110     # No data found for this build probably the build failed
111     echo "$buildNumber,0" >>"$dataFile"
112     recordLatestRecordedBuild "$buildNumber"
113   elif [ "$newLine" == "$lastLine" ]; then
114     # Data already exists
115     recordLatestRecordedBuild "$buildNumber"
116   else
117     # New data added into the file
118     echo "$buildNumber,$new_data" >>"$dataFile"
119     recordLatestRecordedBuild "$buildNumber"
120   fi
121 }
122
123 # Save the latest recorded build number with date and time
124 recordLatestRecordedBuild() {
125   latestBuildToRecord="$1"
126   timestampOfLatestRecordedBuild=$(curl -s "${JENKINS_JOB_URL}/${latestBuildToRecord}/api/json?tree=timestamp" | jq -r '.timestamp')
127   formattedTimestampOfLatestRecordedBuild=$(date -d "@$((timestampOfLatestRecordedBuild / 1000))" "+%B %e, %Y at %H:%M")
128   latestRecordedBuild=$latestBuildToRecord
129 }
130
131 # Plot the image (graph) in png format
132 buildPlotImage() {
133   dataFile="$1" # Get the input file name from the function parameter
134   chartFileName="$2"
135
136   # Create a temporary Gnuplot script
137   cat <<EOT >gnuplot_script.gp
138 set datafile separator ","
139 set terminal pngcairo size 1500,600
140 set output "${chartFileName}"
141 set xlabel "Build"
142 set ylabel "Percentage of limit %"
143 set yrange [0 < * < 80 : 120 < *]
144 set xtics rotate
145 plot '$dataFile' using (column(0)):2:xtic(sprintf("%d", column(1))) with linespoints title "measured", \
146      100 with lines linestyle 2 title "100% limit"
147 EOT
148
149   # Run the temporary Gnuplot script
150   gnuplot gnuplot_script.gp
151
152   # Remove the temporary Gnuplot script
153   rm gnuplot_script.gp
154 }
155
156 # Builds index.html file (main page)
157 buildMainPageHtmlReport() {
158 cat <<EOT >"index.html"
159 <!DOCTYPE html>
160 <html>
161 <head>
162   <title>Performance Review</title>
163 </head>
164 <body>
165     <h1 style="text-align: center;">Performance Review</h1>
166     <h4>Last updated for performance job build no. $latestRecordedBuild on $formattedTimestampOfLatestRecordedBuild</h4>
167     <p>The performance tests job runs every two hours, providing performance metrics. The following graphs update at 04:15 UTC.</p>
168     <p>Successful performance tests job build adds new data, but even if a build fails, existing data is retained.</p>
169     <p>Updates occur whenever new successful data is available.</p>
170
171     <table align="center">
172 EOT
173
174 # Loop through the test names and chart file names to generate HTML rows for CPS
175 for cps_test_name in "${cps_test_names[@]}"; do
176     cat <<EOF >>index.html
177         <tr> <!-- Row for $cps_test_name -->
178             <td align="center" style="padding: 10px;">
179                 <figcaption>"$cps_test_name (CPS)"</figcaption>
180                 <img src="$cps_test_name.png" width="750" height="300">
181             </td>
182         </tr>
183 EOF
184 done
185
186 # Loop through the test names and chart file names to generate HTML rows for NCMP
187 for ncmp_test_name in "${ncmp_test_name_names[@]}"; do
188     cat <<EOF >>index.html
189         <tr> <!-- Row for $ncmp_test_name -->
190             <td align="center" style="padding: 10px;">
191                 <figcaption>"$ncmp_test_name (NCMP)"</figcaption>
192                 <img src="$ncmp_test_name.png" width="750" height="300">
193             </td>
194         </tr>
195 EOF
196 done
197
198 # Close the HTML file
199 cat <<EOT >>index.html
200     </table>
201 </body>
202 </html>
203 EOT
204 }
205
206 # Builds sub-HTML pages
207 buildSubPageHtmlReport() {
208   chartFileName="$1"
209   reportTitle="$2"
210   outputFile="$3"
211   cat <<EOT >"$outputFile"
212     <!DOCTYPE html>
213     <html>
214     <head>
215     <title>$reportTitle</title>
216     </head>
217     <body>
218         <h1>$reportTitle</h1>
219         <h4>Last updated for performance job build no. $latestRecordedBuild on $formattedTimestampOfLatestRecordedBuild</h4>
220         <img src="$chartFileName" alt="Graph Image">
221     </body>
222     </html>
223 EOT
224 }
225
226 #############################################################################################################################
227 ################################################ M A I N ####################################################################
228 #############################################################################################################################
229
230 # Install dependencies
231 sudo apt-get install -y bc gnuplot jq
232
233 # Download data from CPS performance Jenkins job
234 cd "$WORKSPACE"
235 if [ -z "$(ls -A)" ]; then
236   # If workspace is empty, pull data from all previous performance job runs
237   for buildNumber in $(getAllBuildNumbers); do
238     getAndRecordPerformanceJobResultForBuild "$buildNumber"
239   done
240 else
241   # Append new data from latest jobs run
242   lastCompletedBuildNumber=$(getLastCompletedBuildNumber)
243   lastRecordedBuildNumber=$(getLastRecordedBuildNumber)
244   # Check if last completed build number is greater than last recorded build number
245   if [ "$lastCompletedBuildNumber" -gt "$lastRecordedBuildNumber" ]; then
246     for ((i = lastRecordedBuildNumber + 1; i <= lastCompletedBuildNumber; i++)); do
247       getAndRecordPerformanceJobResultForBuild "$i"
248     done
249   else
250     echo "No new builds to process."
251   fi
252 fi
253
254 # Plot image (graphs) files in png format
255 for cps_test_name in "${cps_test_names[@]}"; do
256   buildPlotImage "$cps_test_name.txt" "$cps_test_name.png"
257 done
258 for ncmp_test_name in "${ncmp_test_name_names[@]}"; do
259   buildPlotImage "$ncmp_test_name.txt" "$ncmp_test_name.png"
260 done
261
262 # Build the summary(index.html) page
263 buildMainPageHtmlReport
264
265 # Build individual html page reports for each test
266 for cps_test_name in "${cps_test_names[@]}"; do
267   buildSubPageHtmlReport "$cps_test_name.png" "$cps_test_name" "$cps_test_name.html"
268 done
269 for ncmp_test_name in "${ncmp_test_name_names[@]}"; do
270   buildSubPageHtmlReport "$ncmp_test_name.png" "$ncmp_test_name" "$ncmp_test_name.html"
271 done