CDCgov / prime-reportstream

ReportStream is a public intermediary tool for delivery of data between different parts of the healthcare ecosystem.
https://reportstream.cdc.gov
Creative Commons Zero v1.0 Universal
72 stars 40 forks source link

Improve Error Reporting for schema loading #10105

Open JFU-NAVA-PBC opened 1 year ago

JFU-NAVA-PBC commented 1 year ago

User Story

As a report stream developer, I want the error messages provide helpful info for me to know what went wrong and where the problem occurred (if possible)

Description/Use Case

Risks/Impacts/Considerations

Improve error message, no negative impact on runtime performance expected.

Dev Notes

To reproduce:

Scenarios:

At the beginning of report stream startup and also when running end 2 end tests, schema loading is performed: the schema loader basically traversal the folder hierarchies where the schemas files live, and validate them one be one, however, when there are validation errors, the error details are not showing in the final error report (exception stack)

It is desirable that more detailed (and helpful) error messages provided in the error report.

Here is a sample error report (trace) when schema loading throws exception during end2end test:

================== error output begin ========================== Running test end2end...


Output for test end2end... Starting end2end Test: send ignore.ignore-simple-report data to CSV,HL7,HL7_BATCH,HL7_NULL Running end2end synchronously -- with no query param Exception: java.lang.Exception, Error loading schema catalog: ./metadata/schemas: gov.cdc.prime.router.Metadata.loadSchemaCatalog(Metadata.kt:171) gov.cdc.prime.router.Metadata.(Metadata.kt:136) gov.cdc.prime.router.Metadata.(Metadata.kt:127) gov.cdc.prime.router.Metadata$Companion$singletonInstance$2.invoke(Metadata.kt:488) gov.cdc.prime.router.Metadata$Companion$singletonInstance$2.invoke(Metadata.kt:487) kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) gov.cdc.prime.router.Metadata$Companion.getSingletonInstance(Metadata.kt:487) gov.cdc.prime.router.Metadata$Companion.getInstance(Metadata.kt:496) gov.cdc.prime.router.cli.tests.CoolTest$Companion$metadata$2.invoke(TestReportStream.kt:835) gov.cdc.prime.router.cli.tests.CoolTest$Companion$metadata$2.invoke(TestReportStream.kt:835) kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74) gov.cdc.prime.router.cli.tests.CoolTest$Companion.getMetadata(TestReportStream.kt:835) gov.cdc.prime.router.cli.tests.End2End.forceSync(BasicTests.kt:228) gov.cdc.prime.router.cli.tests.End2End.run(BasicTests.kt:217) gov.cdc.prime.router.cli.tests.TestReportStream.runTests$runTest(TestReportStream.kt:255) gov.cdc.prime.router.cli.tests.TestReportStream.access$runTests$runTest(TestReportStream.kt:59) gov.cdc.prime.router.cli.tests.TestReportStream$runTests$1$1$1.invokeSuspend(TestReportStream.kt:274) kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284) kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85) kotlinx.coroutines.BuildersKtBuildersKt.runBlocking(Builders.kt:59) kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source) kotlinx.coroutines.BuildersKtBuildersKt.runBlocking$default(Builders.kt:38) kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source) gov.cdc.prime.router.cli.tests.TestReportStream.runTests(TestReportStream.kt:269) gov.cdc.prime.router.cli.tests.TestReportStream.run(TestReportStream.kt:226) com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:198) com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:211) com.github.ajalt.clikt.parsers.Parser.parse(Parser.kt:18) com.github.ajalt.clikt.core.CliktCommand.parse(CliktCommand.kt:400) com.github.ajalt.clikt.core.CliktCommand.parse$default(CliktCommand.kt:397) com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:415) com.github.ajalt.clikt.core.CliktCommand.main(CliktCommand.kt:440) gov.cdc.prime.router.cli.MainKt.main(main.kt:296) Tests FAILED: end2end

Task :primeCLI FAILED

================== error output end ===========================

the code section where the error thrown:

====== code begin =================== internal constructor( metadataPath: String, tableDbAccess: DatabaseLookupTableAccess? = null ) { this.tableDbAccess = tableDbAccess ?: DatabaseLookupTableAccess() val metadataDir = File(metadataPath) if (!metadataDir.isDirectory) error("Expected metadata directory") loadValueSetCatalog(metadataDir.toPath().resolve(valuesetsSubdirectory).toString()) loadDatabaseLookupTables() loadSchemaCatalog(metadataDir.toPath().resolve(schemasSubdirectory).toString()) <==== error thrown should be caught and handled (adding more details such as which schema file is being processed, what is the problem, etc. loadFileNameTemplates(metadataDir.toPath().resolve(fileNameTemplatesSubdirectory).toString()) logger.trace("Metadata initialized.") validateSchemas() } ====== code end ====================

Acceptance Criteria

  1. A more helpful error message included in error report stack.
  2. Unit tests added to cover this addition
bishoyayoub commented 1 year ago

@JFU-NAVA-PBC Please confirm that this is ready for grooming.

JFU-NAVA-PBC commented 1 year ago

@bishoyayoub yes

bishoyayoub commented 1 year ago

@JFU-NAVA-PBC Please use #4932 to use the terminology "As a [User Persona - who are we building this for?] I want to [Intent - what is this user trying to achieve?], so that [Outcome - what is the value add to the user]."