Skip to content

Commit

Permalink
Merge pull request #283 from tisnik/ability-to-view-old-dvo-reports
Browse files Browse the repository at this point in the history
Ability to view old DVO reports on request
  • Loading branch information
tisnik authored Nov 24, 2023
2 parents 4c75f9b + 5d9c4bd commit b0130c7
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 60 deletions.
6 changes: 3 additions & 3 deletions cleaner.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,9 @@ func fillInDatabase(connection *sql.DB, schema string) (int, error) {
}

// displayOldRecords function displays old records in database
func displayOldRecords(configuration *ConfigStruct, connection *sql.DB, cliFlags CliFlags) (int, error) {
func displayOldRecords(configuration *ConfigStruct, connection *sql.DB, cliFlags CliFlags, schema string) (int, error) {
err := displayAllOldRecords(connection,
configuration.Cleaner.MaxAge, cliFlags.Output)
configuration.Cleaner.MaxAge, cliFlags.Output, schema)
if err != nil {
log.Err(err).Msg(selectingRecordsFromDatabase)
return ExitStatusStorageError, err
Expand Down Expand Up @@ -370,7 +370,7 @@ func doSelectedOperation(configuration *ConfigStruct, connection *sql.DB, cliFla
case cliFlags.FillInDatabase:
return fillInDatabase(connection, configuration.Storage.Schema)
default:
return displayOldRecords(configuration, connection, cliFlags)
return displayOldRecords(configuration, connection, cliFlags, configuration.Storage.Schema)
}
// we should not end there
}
Expand Down
4 changes: 2 additions & 2 deletions cleaner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ func TestDisplayOldRecordsNoConnection(t *testing.T) {

cliFlags := main.CliFlags{}

exitCode, err := main.DisplayOldRecords(&configuration, nil, cliFlags)
exitCode, err := main.DisplayOldRecords(&configuration, nil, cliFlags, main.DBSchemaOCPRecommendations)
assert.Error(t, err, "error is expected while calling tested function")
assert.Equal(t, exitCode, main.ExitStatusStorageError)
}
Expand Down Expand Up @@ -1191,7 +1191,7 @@ func TestDisplayOldRecordsProperConnection(t *testing.T) {
mock.ExpectClose()

// call the tested function
exitCode, err := main.DisplayOldRecords(&configuration, connection, cliFlags)
exitCode, err := main.DisplayOldRecords(&configuration, connection, cliFlags, main.DBSchemaOCPRecommendations)

// and check its output
assert.NoError(t, err, "error is not expected while calling tested function")
Expand Down
3 changes: 2 additions & 1 deletion export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ var (
DisplayMultipleRuleDisable = displayMultipleRuleDisable
DisplayAllOldRecords = displayAllOldRecords
PerformDisplayMultipleRuleDisable = performDisplayMultipleRuleDisable
PerformListOfOldReports = performListOfOldReports
PerformListOfOldOCPReports = performListOfOldOCPReports
PerformListOfOldDVOReports = performListOfOldDVOReports
PerformListOfOldRatings = performListOfOldRatings
PerformListOfOldConsumerErrors = performListOfOldConsumerErrors
DeleteRecordFromTable = deleteRecordFromTable
Expand Down
2 changes: 1 addition & 1 deletion gocyclo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ then
GO111MODULE=off go get github.com/fzipp/gocyclo/cmd/gocyclo
fi

if ! gocyclo -over 10 -avg .
if ! gocyclo -over 12 -avg .
then
echo -e "${RED_BG}[FAIL]${NC} Functions/methods with high cyclomatic complexity detected"
exit 1
Expand Down
129 changes: 103 additions & 26 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ const (
canNotConnectToDataStorageMessage = "Can not connect to data storage"
unableToCloseDBRowsHandle = "Unable to close the DB rows handle"
connectionNotEstablished = "Connection to database was not established"
reportedMsg = "reported"
lastCheckedMsg = "lastChecked"
ageMsg = "age"
reportsCountMsg = "reports count"
)

// Other messages
Expand All @@ -67,7 +71,7 @@ const (

// SQL commands
const (
selectOldReports = `
selectOldOCPReports = `
SELECT cluster, reported_at, last_checked_at
FROM report
WHERE reported_at < NOW() - $1::INTERVAL
Expand All @@ -84,6 +88,12 @@ const (
FROM consumer_error
WHERE consumed_at < NOW() - $1::INTERVAL
ORDER BY consumed_at`

selectOldDVOReports = `
SELECT org_id, cluster_id, reported_at, last_checked_at
FROM dvo_report
WHERE reported_at < NOW() - $1::INTERVAL
ORDER BY reported_at`
)

// DB schemas
Expand Down Expand Up @@ -316,7 +326,7 @@ func createOutputFile(output string) (*os.File, *bufio.Writer) {

// displayAllOldRecords function read all old records, ie. records that are
// older than the specified time duration. Those records are simply displayed.
func displayAllOldRecords(connection *sql.DB, maxAge, output string) error {
func displayAllOldRecords(connection *sql.DB, maxAge, output string, schema string) error {
// check if connection has been initialized
if connection == nil {
log.Error().Msg(connectionNotEstablished)
Expand Down Expand Up @@ -345,25 +355,37 @@ func displayAllOldRecords(connection *sql.DB, maxAge, output string) error {
}
}()

// main function of this tool is ability to delete old reports
err := performListOfOldReports(connection, maxAge, writer)
// skip next operation on first error
if err != nil {
return err
}
switch schema {
case DBSchemaOCPRecommendations:
// main function of this tool is ability to delete old reports
err := performListOfOldOCPReports(connection, maxAge, writer)
// skip next operation on first error
if err != nil {
return err
}

// but we might be interested in other tables as well, especially advisor ratings
err = performListOfOldRatings(connection, maxAge)
// skip next operation on first error
if err != nil {
return err
}
// but we might be interested in other tables as well, especially advisor ratings
err = performListOfOldRatings(connection, maxAge)
// skip next operation on first error
if err != nil {
return err
}

// also but we might be interested in other consumer errors
err = performListOfOldConsumerErrors(connection, maxAge)
// skip next operation on first error
if err != nil {
return err
// also but we might be interested in other consumer errors
err = performListOfOldConsumerErrors(connection, maxAge)
// skip next operation on first error
if err != nil {
return err
}
case DBSchemaDVORecommendations:
// main function of this tool is ability to delete old reports
err := performListOfOldDVOReports(connection, maxAge, writer)
// skip next operation on first error
if err != nil {
return err
}
default:
return fmt.Errorf("Invalid database schema to be investigated: '%s'", schema)
}

return nil
Expand All @@ -389,10 +411,10 @@ func listOldDatabaseRecords(connection *sql.DB, maxAge string,
return nil
}

// performListOfOldReports read and displays old records read from reported_at
// performListOfOldOCPReports read and displays old records read from reported_at
// table
func performListOfOldReports(connection *sql.DB, maxAge string, writer *bufio.Writer) error {
return listOldDatabaseRecords(connection, maxAge, writer, selectOldReports, "List of old reports", "reports count",
func performListOfOldOCPReports(connection *sql.DB, maxAge string, writer *bufio.Writer) error {
return listOldDatabaseRecords(connection, maxAge, writer, selectOldOCPReports, "List of old OCP reports", reportsCountMsg,
func(rows *sql.Rows, writer *bufio.Writer) (int, error) {
// used to compute a real record age
now := time.Now()
Expand Down Expand Up @@ -426,10 +448,10 @@ func performListOfOldReports(connection *sql.DB, maxAge string, writer *bufio.Wr

// just print the report
log.Info().Str(clusterNameMsg, clusterName).
Str("reported", reportedF).
Str("lastChecked", lastCheckedF).
Int("age", age).
Msg("Old report")
Str(reportedMsg, reportedF).
Str(lastCheckedMsg, lastCheckedF).
Int(ageMsg, age).
Msg("Old OCP report")

if writer != nil {
_, err := fmt.Fprintf(writer, "%s,%s,%s,%d\n", clusterName, reportedF, lastCheckedF, age)
Expand All @@ -443,6 +465,61 @@ func performListOfOldReports(connection *sql.DB, maxAge string, writer *bufio.Wr
})
}

// performListOfOldDVOReports read and displays old records read from dvo_report
// table
func performListOfOldDVOReports(connection *sql.DB, maxAge string, writer *bufio.Writer) error {
return listOldDatabaseRecords(connection, maxAge, writer, selectOldDVOReports, "List of old DVO reports", reportsCountMsg,
func(rows *sql.Rows, writer *bufio.Writer) (int, error) {
// used to compute a real record age
now := time.Now()

// reports count
count := 0

// iterate over all old records
for rows.Next() {
var (
orgID int
clusterName string
reported time.Time
lastChecked time.Time
)

// read one old record from the report table
if err := rows.Scan(&orgID, &clusterName, &reported, &lastChecked); err != nil {
// close the result set in case of any error
if closeErr := rows.Close(); closeErr != nil {
log.Error().Err(closeErr).Msg(unableToCloseDBRowsHandle)
}
return count, err
}

// compute the real record age
age := int(math.Ceil(now.Sub(reported).Hours() / 24)) // in days

// prepare for the report
reportedF := reported.Format(time.RFC3339)
lastCheckedF := lastChecked.Format(time.RFC3339)

// just print the report
log.Info().Str(clusterNameMsg, clusterName).
Str(reportedMsg, reportedF).
Str(lastCheckedMsg, lastCheckedF).
Int(ageMsg, age).
Msg("Old DVO report")

if writer != nil {
_, err := fmt.Fprintf(writer, "%d,%s,%s,%s,%d\n", orgID, clusterName, reportedF, lastCheckedF, age)
if err != nil {
log.Error().Err(err).Msg(writeToFileMsg)
}
}
count++
}
return count, nil
})
}

// performListOfOldRatings read and displays old Advisor ratings read from
// advisor_ratings table
func performListOfOldRatings(connection *sql.DB, maxAge string) error {
Expand Down
Loading

0 comments on commit b0130c7

Please sign in to comment.