3 # Copyright 2023-2024 Nordix Foundation.
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
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
23 #############################################################################################################################
24 ################################################ F U N C T I O N S ##########################################################
25 #############################################################################################################################
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")
29 ncmp_stable_test_names=("Look up CM-handles by module-set-tag" "CpsPath Registry attributes Query")
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")
33 ncmp_unstable_test_names=("Look up CM-handle by id" "Update matching subscription" "Look up CM-handle by alternate-id")
35 JENKINS_JOB_URL="https://jenkins.nordix.org/job/onap-cps-master-performance-test-java"
37 latestBuildToRecord=""
39 latestRecordedBuild=""
40 timestampOfLatestRecordedBuild=""
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"
48 # Get the last build number from local workspace
49 # The number has already been plotted on the graphs
50 getLastRecordedBuildNumber() {
52 local file_name="Delete root node.txt"
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)
65 # Get all builds numbers
66 getAllBuildNumbers() {
67 curl -s "${JENKINS_JOB_URL}/api/json?tree=allBuilds\[id\]" | jq -r '.allBuilds[].id' | sort -n
70 # Get the console text from specific build of the performance job
73 consoleURL="${JENKINS_JOB_URL}/${buildToRead}/consoleText"
74 consoleText=$(curl -s "$consoleURL")
77 # Get and record the percentage (performance job result) for each test name for a build number
78 getAndRecordPerformanceJobResultForBuild() {
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"
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"
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"
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"
96 # Calculate the percentage value for a specific test and append into test data file with build number
97 getAndRecordDataResults() {
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"
115 # Record result into related test data file
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"
127 # New data added into the file
128 echo "$buildNumber,$new_data" >>"$dataFile"
129 recordLatestRecordedBuild "$buildNumber"
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
141 # Plot the image (graph) in png format
143 dataFile="$1" # Get the input file name from the function parameter
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}"
152 set ylabel "Percentage of limit %"
153 set yrange [0 : 120 < *]
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"
159 # Run the temporary Gnuplot script
160 gnuplot gnuplot_script.gp
162 # Remove the temporary Gnuplot script
166 # Builds category html file
167 buildCategoryHtmlReport() {
168 # use indirect expansion to get all elements of the array
169 categoryName=("${!1}")
172 cat <<EOT >"$outputFile"
176 <title>$reportTitle</title>
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">
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">
194 # Close the HTML file
195 cat <<EOT >>"$outputFile"
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>
205 #############################################################################################################################
206 ################################################ M A I N ####################################################################
207 #############################################################################################################################
209 # Install dependencies
210 sudo apt-get install -y bc gnuplot jq
212 # Download data from CPS performance Jenkins job
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"
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"
229 echo "No new builds to process."
233 # Limit the plots to last 100 builds for each test
234 for cps_stable_test_name in "${cps_stable_test_names[@]}"; do
235 tail -n 100 "$cps_stable_test_name.txt" > file.tmp && mv file.tmp "$cps_stable_test_name.txt"
237 for ncmp_stable_test_name in "${ncmp_stable_test_names[@]}"; do
238 tail -n 100 "$ncmp_stable_test_name.txt" > file.tmp && mv file.tmp "$ncmp_stable_test_name.txt"
240 for cps_unstable_test_name in "${cps_unstable_test_names[@]}"; do
241 tail -n 100 "$cps_unstable_test_name.txt" > file.tmp && mv file.tmp "$cps_unstable_test_name.txt"
243 for ncmp_unstable_test_name in "${ncmp_unstable_test_names[@]}"; do
244 tail -n 100 "$ncmp_unstable_test_name.txt" > file.tmp && mv file.tmp "$ncmp_unstable_test_name.txt"
247 # Plot image (graphs) files in png format
248 for cps_stable_test_name in "${cps_stable_test_names[@]}"; do
249 buildPlotImage "$cps_stable_test_name.txt" "$cps_stable_test_name.png"
251 for ncmp_stable_test_name in "${ncmp_stable_test_names[@]}"; do
252 buildPlotImage "$ncmp_stable_test_name.txt" "$ncmp_stable_test_name.png"
254 for cps_unstable_test_name in "${cps_unstable_test_names[@]}"; do
255 buildPlotImage "$cps_unstable_test_name.txt" "$cps_unstable_test_name.png"
257 for ncmp_unstable_test_name in "${ncmp_unstable_test_names[@]}"; do
258 buildPlotImage "$ncmp_unstable_test_name.txt" "$ncmp_unstable_test_name.png"
261 # Build the category pages
262 buildCategoryHtmlReport cps_stable_test_names[@] "cps stable tests performance review" "cpsStableTestsPerformanceReview.html"
263 buildCategoryHtmlReport ncmp_stable_test_names[@] "ncmp stable tests performance review" "ncmpStableTestsPerformanceReview.html"
264 buildCategoryHtmlReport cps_unstable_test_names[@] "cps unstable tests performance review" "cpsUnstableTestsPerformanceReview.html"
265 buildCategoryHtmlReport ncmp_unstable_test_names[@] "ncmp unstable tests performance review" "ncmpUnstableTestsPerformanceReview.html"