Skip to content

Commit

Permalink
Redesign Assessment HTML report to have a single subsection having al…
Browse files Browse the repository at this point in the history
…l issues(all categories) (#2184)

* Design: For each issue there is summary which is expandable to show more details
Summary - Category, Type, Object /SQL Preview , Impact
Expandable Details - Object Type, Object Name, Category Description, Sql Statement, Description

Users can also sort the issues based on summary/type/impact.

* Added description to each of the defined issues(ddl and dml)
  • Loading branch information
sanyamsinghal authored Jan 16, 2025
1 parent 8b91860 commit 2a705b2
Show file tree
Hide file tree
Showing 8 changed files with 551 additions and 489 deletions.
31 changes: 14 additions & 17 deletions yb-voyager/cmd/analyzeSchema.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,17 @@ const (

// Reports one case in JSON
func reportCase(filePath string, reason string, ghIssue string, suggestion string, objType string, objName string, sqlStmt string, category string, docsLink string, impact string) {
var issue utils.AnalyzeSchemaIssue
issue.FilePath = filePath
issue.Reason = reason
issue.GH = ghIssue
issue.Suggestion = suggestion
issue.ObjectType = objType
issue.ObjectName = objName
issue.SqlStatement = sqlStmt
issue.IssueType = category // IssueType field of analyze schema should be renamed to Category
issue.Impact = lo.Ternary(impact != "", impact, constants.IMPACT_LEVEL_1)
if sourceDBType == POSTGRESQL {
issue.DocsLink = docsLink
issue := utils.AnalyzeSchemaIssue{
IssueType: category, // TODO: to be replaced with Category as a field
Reason: reason,
Impact: lo.Ternary(impact != "", impact, constants.IMPACT_LEVEL_1),
ObjectType: objType,
ObjectName: objName,
SqlStatement: sqlStmt,
FilePath: filePath,
Suggestion: suggestion,
GH: ghIssue,
DocsLink: docsLink,
}

schemaAnalysisReport.Issues = append(schemaAnalysisReport.Issues, issue)
Expand Down Expand Up @@ -663,10 +662,8 @@ func convertIssueInstanceToAnalyzeIssue(issueInstance queryissue.QueryIssue, fil
// 2. Keep it in issue.Details and write logic in UI layer to construct display name.
*/
displayObjectName := issueInstance.ObjectName

constraintName, ok := issueInstance.Details[queryissue.CONSTRAINT_NAME]
if slices.Contains(constraintIssues, issueInstance.Type) && ok {
//In case of constraint issues we add constraint name to the object name as well
if constraintName, ok := issueInstance.Details[queryissue.CONSTRAINT_NAME]; slices.Contains(constraintIssues, issueInstance.Type) && ok {
//In case of constraint issues we add constraint name to the object name to achieve the uniqueness
displayObjectName = fmt.Sprintf("%s, constraint: (%s)", issueInstance.ObjectName, constraintName)
}

Expand All @@ -676,8 +673,8 @@ func convertIssueInstanceToAnalyzeIssue(issueInstance queryissue.QueryIssue, fil
IssueType: issueType,
ObjectType: issueInstance.ObjectType,
ObjectName: displayObjectName,
Reason: issueInstance.Name,
Type: issueInstance.Type,
Reason: issueInstance.Name,
Impact: issueInstance.Impact,
SqlStatement: issueInstance.SqlStatement,
DocsLink: issueInstance.DocsLink,
Expand Down
5 changes: 3 additions & 2 deletions yb-voyager/cmd/assessMigrationCommand.go
Original file line number Diff line number Diff line change
Expand Up @@ -1011,13 +1011,12 @@ func getUnsupportedFeaturesFromSchemaAnalysisReport(featureName string, issueRea
return UnsupportedFeature{featureName, objects, displayDDLInHTML, link, description, minVersionsFixedIn}
}

// Q: do we no need of displayDDLInHTML in this approach? DDL can always be there for issues in the table if present.
func convertAnalyzeSchemaIssueToAssessmentIssue(analyzeSchemaIssue utils.AnalyzeSchemaIssue, issueDescription string, minVersionsFixedIn map[string]*ybversion.YBVersion) AssessmentIssue {
return AssessmentIssue{
Category: analyzeSchemaIssue.IssueType,
CategoryDescription: GetCategoryDescription(analyzeSchemaIssue.IssueType),
Type: analyzeSchemaIssue.Type,
Name: analyzeSchemaIssue.Reason, // in convertIssueInstanceToAnalyzeIssue() we assign IssueType to Reason field
Name: analyzeSchemaIssue.Reason, // in convertIssueInstanceToAnalyzeIssue() we assign Issue.Name to AnalyzeSchemaIssue.Reason field
Description: issueDescription, // TODO: verify
Impact: analyzeSchemaIssue.Impact,
ObjectType: analyzeSchemaIssue.ObjectType,
Expand Down Expand Up @@ -1653,6 +1652,8 @@ func generateAssessmentReportHtml(reportDir string) error {
"groupByObjectName": groupByObjectName,
"totalUniqueObjectNamesOfAllTypes": totalUniqueObjectNamesOfAllTypes,
"getSupportedVersionString": getSupportedVersionString,
"snakeCaseToTitleCase": utils.SnakeCaseToTitleCase,
"getSqlPreview": utils.GetSqlStmtToPrint,
}
tmpl := template.Must(template.New("report").Funcs(funcMap).Parse(string(bytesTemplate)))

Expand Down
4 changes: 2 additions & 2 deletions yb-voyager/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -1073,12 +1073,12 @@ type AssessmentReport struct {

// Fields apart from Category, CategoryDescription, TypeName and Impact will be populated only if/when available
type AssessmentIssue struct {
Category string // expected values: feature, query_constrcuts, migration_caveats, plpgsql_objects, datatytpe
Category string // expected values: unsupported_features, unsupported_query_constructs, migration_caveats, unsupported_plpgsql_objects, unsupported_datatype
CategoryDescription string
Type string // Ex: GIN_INDEXES, SECURITY_INVOKER_VIEWS, STORED_GENERATED_COLUMNS
Name string // Ex: "Stored generated columns are not supported."
Description string
Impact string // Level-1, Level-2, Level-3 (default: Level-1 ??)
Impact string // Level-1, Level-2, Level-3 (no default: need to be assigned for each issue)
ObjectType string // For datatype category, ObjectType will be datatype (for eg "geometry")
ObjectName string
SqlStatement string
Expand Down
18 changes: 9 additions & 9 deletions yb-voyager/cmd/migration_complexity.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ const explainTemplateHTML = `
<thead>
<tr>
<th>Category</th>
<th>Level-1</th>
<th>Level-2</th>
<th>Level-3</th>
<th>Level 1</th>
<th>Level 2</th>
<th>Level 3</th>
<th>Total</th>
</tr>
</thead>
Expand All @@ -248,9 +248,9 @@ const explainTemplateHTML = `
<p>
<strong>Impact Levels:</strong></br>
Level-1: Resolutions are available with minimal effort.<br/>
Level-2: Resolutions are available requiring moderate effort.<br/>
Level-3: Resolutions may not be available or are complex.
Level 1: Resolutions are available with minimal effort.<br/>
Level 2: Resolutions are available requiring moderate effort.<br/>
Level 3: Resolutions may not be available or are complex.
</p>
`

Expand Down Expand Up @@ -301,11 +301,11 @@ func buildMigrationComplexityExplanation(sourceDBType string, assessmentReport A
func buildRationale(finalComplexity string, l1Count int, l2Count int, l3Count int) string {
switch finalComplexity {
case constants.MIGRATION_COMPLEXITY_HIGH:
return fmt.Sprintf("Found %d Level-2 issue(s) and %d Level-3 issue(s), resulting in HIGH migration complexity", l2Count, l3Count)
return fmt.Sprintf("Found %d Level 2 issue(s) and %d Level 3 issue(s), resulting in HIGH migration complexity", l2Count, l3Count)
case constants.MIGRATION_COMPLEXITY_MEDIUM:
return fmt.Sprintf("Found %d Level-1 issue(s), %d Level-2 issue(s) and %d Level-3 issue(s), resulting in MEDIUM migration complexity", l1Count, l2Count, l3Count)
return fmt.Sprintf("Found %d Level 1 issue(s), %d Level 2 issue(s) and %d Level 3 issue(s), resulting in MEDIUM migration complexity", l1Count, l2Count, l3Count)
case constants.MIGRATION_COMPLEXITY_LOW:
return fmt.Sprintf("Found %d Level-1 issue(s) and %d Level-2 issue(s), resulting in LOW migration complexity", l1Count, l2Count)
return fmt.Sprintf("Found %d Level 1 issue(s) and %d Level 2 issue(s), resulting in LOW migration complexity", l1Count, l2Count)
}
return ""
}
Expand Down
Loading

0 comments on commit 2a705b2

Please sign in to comment.