blob: ef2883ae8fb09066b945949dc1a4637ba4e73104 [file] [log] [blame]
Jeremy Ronquillob4076492018-05-11 13:04:16 -07001# Copyright 2017 Open Networking Foundation (ONF)
2#
3# Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
4# the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
5# or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
6#
7# TestON is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 2 of the License, or
10# (at your option) any later version.
11#
12# TestON is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with TestON. If not, see <http://www.gnu.org/licenses/>.
19#
20# Example script:
21# Rscript trendCHO event.csv failure.csv error.csv master 60 /path/to/save/directory/
22
23
24# **********************************************************
25# STEP 1: Data management.
26# **********************************************************
27
28print( "**********************************************************" )
29print( "STEP 1: Data management." )
30print( "**********************************************************" )
31
32# Command line arguments are read. Args include the database credentials, test name, branch name, and the directory to output files.
33print( "Reading commmand-line args." )
34args <- commandArgs( trailingOnly=TRUE )
35
36event_input_file <- 1
37failure_input_file <- 2
38error_input_file <- 3
39branch_name <- 4
40time_quantum <- 5
41save_directory <- 6
42
43# ----------------
44# Import Libraries
45# ----------------
46
47print( "Importing libraries." )
48library( ggplot2 )
49library( reshape2 )
50library( RPostgreSQL )
51source( "dependencies/saveGraph.R" )
52source( "dependencies/fundamentalGraphData.R" )
53
54# -------------------
55# Check CLI Arguments
56# -------------------
57
58print( "Verifying CLI args." )
59
60if ( length( args ) != save_directory ){
61 print( "Usage: Rscript trendCHO.R <events-input-file> <failures-input-file> <errors-input-file> <time_quantum> <branch-name> <directory-to-save-graph>" )
62 quit( status = 1 )
63}
64
65# ----------------------
66# Read From File: Events
67# ----------------------
68
69print( "Reading from file for 'events' input." )
70
71event_fileData <- read.delim2( args[ event_input_file ],
72 header = TRUE,
73 sep = ",",
74 dec = "." )
75print( "Event File Data:" )
76print( event_fileData )
77
78# ------------------------
79# Read From File: Failures
80# ------------------------
81
82print( "Reading from file for 'failure' input." )
83
84failure_fileData <- read.delim2( args[ failure_input_file ],
85 header = TRUE,
86 sep = ",",
87 dec = "." )
88print( "Failure File Data:" )
89print( failure_fileData )
90
91# ----------------------
92# Read From File: Errors
93# ----------------------
94
95print( "Reading from file for 'errors' input." )
96
97error_fileData <- read.delim2( args[ error_input_file ],
98 header = TRUE,
99 sep = ",",
100 dec = "." )
101print( "Error File Data:" )
102print( error_fileData )
103
104# -------------------------------
105# Create Title and Graph Filename
106# -------------------------------
107
108print( "Creating titles of graphs." )
109
110failedChecksTitle <- paste( "Failed Checks - ",
111 args[ branch_name ],
112 "\n(frequency per ",
113 args[ time_quantum ],
114 " mins)",
115 sep="" )
116
117eventsTitle <- paste( "Network, Application, and ONOS Events - ",
118 args[ branch_name ],
119 "\n(frequency per ",
120 args[ time_quantum ],
121 " mins)",
122 sep="" )
123
124errorsTitle <- paste( "Warnings, Errors, and Exceptions from Logs - ",
125 args[ branch_name ],
126 "\n(frequency per ",
127 args[ time_quantum ],
128 " mins)",
129 sep="" )
130
131print( "Creating graph filenames." )
132
133failedChecksFilename <- paste( args[ save_directory ],
134 "CHO_Failure-Check_",
135 args[ branch_name ],
136 "_graph.jpg",
137 sep="" )
138
139eventsFilename <- paste( args[ save_directory ],
140 "CHO_Events_",
141 args[ branch_name ],
142 "_graph.jpg",
143 sep="" )
144
145errorsFilename <- paste( args[ save_directory ],
146 "CHO_Errors_",
147 args[ branch_name ],
148 "_graph.jpg",
149 sep="" )
150
151# **********************************************************
152# STEP 2: Organize data.
153# **********************************************************
154
155print( "**********************************************************" )
156print( "STEP 2: Organize Data." )
157print( "**********************************************************" )
158
159# -------------------------------------------------------
160# Verifying all required columns are present.
161# -------------------------------------------------------
162
163# ------------------
164# Verifying 'Events'
165# ------------------
166
167print( "Verifying all required columns are present for 'events'." )
168
169requiredColumns <- c( "Link.Down",
170 "Link.Up",
171 "Device.Down",
172 "Device.Up",
173 "Add.Host.Intent",
174 "Delete.Host.Intent",
175 "Add.Point.Intent",
176 "Delete.Point.Intent",
177 "ONOS.Down",
178 "ONOS.Up" )
179
180tryCatch( eventsCombined <- c( event_fileData[ requiredColumns] ),
181 error = function( e ) {
182 print( "[ERROR] One or more expected columns are missing from 'events'. Please check that the data and file are valid, then try again." )
183 print( "Required columns: " )
184 print( requiredColumns )
185 print( "Actual columns: " )
186 print( names( event_fileData ) )
187 print( "Error dump:" )
188 print( e )
189 quit( status = 1 )
190 }
191 )
192
193# --------------------
194# Verifying 'Failures'
195# --------------------
196
197print( "Verifying all required columns are present for 'failures'." )
198
199requiredColumns <- c( "Intent.Check.Failure",
200 "Flow.Check.Failure",
201 "Traffic.Check.Failure",
202 "Topo.Check.Failure",
203 "ONOS.Check.Failure" )
204
205tryCatch( failureCombined <- c( failure_fileData[ requiredColumns] ),
206 error = function( e ) {
207 print( "[ERROR] One or more expected columns are missing from 'failures'. Please check that the data and file are valid, then try again." )
208 print( "Required columns: " )
209 print( requiredColumns )
210 print( "Actual columns: " )
211 print( names( failure_fileData ) )
212 print( "Error dump:" )
213 print( e )
214 quit( status = 1 )
215 }
216 )
217
218# ------------------
219# Verifying 'Errors'
220# ------------------
221
222print( "Verifying all required columns are present for 'errors'." )
223
224requiredColumns <- c( "Test.Warnings",
225 "ONOS.Warnings",
226 "ONOS.Errors",
227 "Exceptions" )
228
229tryCatch( errorCombined <- c( error_fileData[ requiredColumns] ),
230 error = function( e ) {
231 print( "[ERROR] One or more expected columns are missing from 'errors'. Please check that the data and file are valid, then try again." )
232 print( "Required columns: " )
233 print( requiredColumns )
234 print( "Actual columns: " )
235 print( names( error_fileData ) )
236 print( "Error dump:" )
237 print( e )
238 quit( status = 1 )
239 }
240 )
241
242# -------------------------------
243# Create Events Data Frame
244# -------------------------------
245
246# -------------------
247# 'Events' Data Frame
248# -------------------
249
250print( "Constructing data frame for 'events'." )
251
252events_dataFrame <- melt( eventsCombined )
253
254# Rename column names in events_dataFrame
255colnames( events_dataFrame ) <- c( "Events",
256 "Type" )
257
258# Format data frame so that the data is in the same order as it appeared in the file.
259events_dataFrame$Type <- as.character( events_dataFrame$Type )
260events_dataFrame$Type <- factor( events_dataFrame$Type, levels = unique( events_dataFrame$Type ) )
261
262events_dataFrame$timeStamps <- rev( gsub('^(.{11})(.*)$', '\\1\n\\2', event_fileData$Time ) )
263
264# Adding a temporary reversed iterative list to the events_dataFrame so that there are no gaps in-between build numbers.
265events_dataFrame$iterative <- rev( seq( 1, nrow( event_fileData ), by = 1 ) )
266
267# Omit any data that doesn't exist
268events_dataFrame <- na.omit( events_dataFrame )
269
270print( "'Events' Data Frame Results:" )
271print( events_dataFrame )
272
273# ---------------------
274# 'Failures' Data Frame
275# ---------------------
276
277print( "Constructing data frame for 'failures'." )
278
279failures_dataFrame <- melt( failureCombined )
280
281# Rename column names in failures_dataFrame
282colnames( failures_dataFrame ) <- c( "Failures",
283 "Type" )
284
285# Format data frame so that the data is in the same order as it appeared in the file.
286failures_dataFrame$Type <- as.character( failures_dataFrame$Type )
287failures_dataFrame$Type <- factor( failures_dataFrame$Type, levels = unique( failures_dataFrame$Type ) )
288
289failures_dataFrame$timeStamps <- rev( gsub('^(.{11})(.*)$', '\\1\n\\2', failure_fileData$Time ) )
290
291# Adding a temporary reversed iterative list to the failures_dataFrame so that there are no gaps in-between build numbers.
292failures_dataFrame$iterative <- rev( seq( 1, nrow( failure_fileData ), by = 1 ) )
293
294# Omit any data that doesn't exist
295failures_dataFrame <- na.omit( failures_dataFrame )
296
297print( "'Failures' Data Frame Results:" )
298print( failures_dataFrame )
299
300# -------------------
301# 'Errors' Data Frame
302# -------------------
303
304print( "Constructing data frame for 'errors'." )
305
306errors_dataFrame <- melt( errorCombined )
307
308# Rename column names in errors_dataFrame
309colnames( errors_dataFrame ) <- c( "Errors",
310 "Type" )
311
312# Format data frame so that the data is in the same order as it appeared in the file.
313errors_dataFrame$Type <- as.character( errors_dataFrame$Type )
314errors_dataFrame$Type <- factor( errors_dataFrame$Type, levels = unique( errors_dataFrame$Type ) )
315
316errors_dataFrame$timeStamps <- gsub('^(.{11})(.*)$', '\\1\n\\2', error_fileData$Time )
317
318# Adding a temporary reversed iterative list to the errors_dataFrame so that there are no gaps in-between build numbers.
319errors_dataFrame$iterative <- seq( 1, nrow( error_fileData ), by = 1 )
320
321# Omit any data that doesn't exist
322errors_dataFrame <- na.omit( errors_dataFrame )
323
324print( "'Errors' Data Frame Results:" )
325print( errors_dataFrame )
326
327# **********************************************************
328# STEP 3: Generate graphs.
329# **********************************************************
330
331print( "**********************************************************" )
332print( "STEP 3: Generate Graph." )
333print( "**********************************************************" )
334
335# -------------------
336# Main Plot Generated
337# -------------------
338
339print( "Creating main plots." )
340
341eventsPlot <- ggplot( data = events_dataFrame, aes( x = iterative,
342 y = Events,
343 color = Type ) )
344
345failuresPlot <- ggplot( data = failures_dataFrame, aes( x = iterative,
346 y = Failures,
347 color = Type ) )
348
349errorsPlot <- ggplot( data = errors_dataFrame, aes( x = iterative,
350 y = Errors,
351 color = Type ) )
352
353# ------------------------------
354# Fundamental Variables Assigned
355# ------------------------------
356
357print( "Generating fundamental graph data used in all 3 graphs." )
358
359defaultTextSize()
360
361yAxisTicksExponents <- seq( -1, floor( max( c( max( events_dataFrame$Events ), max( failures_dataFrame$Failures ), max( errors_dataFrame$Errors ) ) ) ^ 0.1 ) + 1, by=1 )
362yAxisTicks <- 10 ^ yAxisTicksExponents
363yAxisTicksLabels <- floor( yAxisTicks )
364
365yScaleConfig <- scale_y_log10( breaks = yAxisTicks,
366 labels = yAxisTicksLabels )
367xLabel <- xlab( "Time" )
368
369print( "Generating line graph." )
370
371lineGraphFormat <- geom_line( size = 1.1 )
372pointFormat <- geom_point( size = 3 )
373
374graphTheme <- graphTheme() + theme( axis.text.x = element_text( angle = 90, hjust = 1, size = 14 ),
375 axis.text.y = element_text( size = 17 ) )
376
377# -------------------
378# 'Events' Graph Data
379# -------------------
380
381print( "Generating 'events' graph data." )
382
383yLabel <- ylab( "Events" )
384
385xScaleConfig <- scale_x_continuous( breaks = events_dataFrame$iterative,
386 label = events_dataFrame$timeStamps )
387
388lineColorsAndLabels <- scale_color_manual( values=c( webColor( "light_blue" ),
389 webColor( "red" ),
390 webColor( "purple" ),
391 webColor( "yellow" ),
392 webColor( "orange" ),
393 webColor( "blue" ),
394 webColor( "magenta" ),
395 webColor( "green" ),
396 webColor( "brown" ),
397 webColor( "black" )
398 ),
399 labels = c( "Link Down",
400 "Link Up",
401 "Device Down",
402 "Device Up",
403 "Add Host Intent",
404 "Delete Host Intent",
405 "Add Point Intent",
406 "Delete Point Intent",
407 "ONOS Down",
408 "ONOS Up" )
409 )
410
411title <- labs( title = eventsTitle, subtitle = lastUpdatedLabel() )
412
413result <- eventsPlot +
414 xScaleConfig +
415 yScaleConfig +
416 xLabel +
417 yLabel +
418 graphTheme +
419 title +
420 lineGraphFormat +
421 lineColorsAndLabels +
422 pointFormat
423
424# -----------------------
425# Exporting Graph to File
426# -----------------------
427
428saveGraph( eventsFilename ) # from saveGraph.R
429
430# ---------------------
431# 'Failures' Graph Data
432# ---------------------
433
434print( "Generating 'failures' graph data." )
435
436yLabel <- ylab( "Failures" )
437
438xScaleConfig <- scale_x_continuous( breaks = failures_dataFrame$iterative,
439 label = failures_dataFrame$timeStamps )
440
441lineColorsAndLabels <- scale_color_manual( values=c( webColor( "red" ),
442 webColor( "yellow" ),
443 webColor( "green" ),
444 webColor( "blue" ),
445 webColor( "magenta" )
446 ),
447 labels = c( "Intent Check Failure",
448 "Flow Check Failure",
449 "Traffic Check Failure",
450 "Topo Check Failure",
451 "ONOS Check Failure" )
452 )
453
454title <- labs( title = failedChecksTitle, subtitle = lastUpdatedLabel() )
455
456result <- failuresPlot +
457 xScaleConfig +
458 yScaleConfig +
459 xLabel +
460 yLabel +
461 graphTheme +
462 title +
463 lineGraphFormat +
464 lineColorsAndLabels + wrapLegend(byrow=FALSE) +
465 pointFormat
466
467
468# -----------------------
469# Exporting Graph to File
470# -----------------------
471
472saveGraph( failedChecksFilename ) # from saveGraph.R
473
474# ---------------------
475# 'Errors' Graph Data
476# ---------------------
477
478print( "Generating 'errors' graph data." )
479
480yLabel <- ylab( "Errors" )
481
482xScaleConfig <- scale_x_continuous( breaks = errors_dataFrame$iterative,
483 label = errors_dataFrame$timeStamps )
484
485lineColorsAndLabels <- scale_color_manual( values=c( webColor( "magenta" ),
486 webColor( "yellow" ),
487 webColor( "orange" ),
488 webColor( "red" )
489 ),
490 labels = c( "Test Warnings",
491 "ONOS Warnings",
492 "ONOS Errors",
493 "Exceptions" )
494 )
495
496title <- labs( title = errorsTitle, subtitle = lastUpdatedLabel() )
497
498result <- errorsPlot +
499 xScaleConfig +
500 yScaleConfig +
501 xLabel +
502 yLabel +
503 graphTheme +
504 title +
505 lineGraphFormat +
506 lineColorsAndLabels +
507 pointFormat
508
509# -----------------------
510# Exporting Graph to File
511# -----------------------
512
513saveGraph( errorsFilename ) # from saveGraph.R