From b3bbad15728e30f7694041b64c461c4301bf2b30 Mon Sep 17 00:00:00 2001 From: Hongxin Date: Thu, 25 Jan 2024 17:31:22 -0600 Subject: [PATCH] Capture smartsheet exception more granularly && Add sentry service to capture exception or message (#1078) * Capture smartsheet exception more granularly && Add sentry service to capture exception or message * Update src/main/java/org/mskcc/cbio/oncokb/service/SentryService.java Co-authored-by: Calvin Lu <59149377+calvinlu3@users.noreply.github.com> --------- Co-authored-by: Calvin Lu <59149377+calvinlu3@users.noreply.github.com> --- .../cbio/oncokb/service/SentryService.java | 45 +++++++++ .../oncokb/service/SmartsheetService.java | 98 ++++++++++--------- 2 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 src/main/java/org/mskcc/cbio/oncokb/service/SentryService.java diff --git a/src/main/java/org/mskcc/cbio/oncokb/service/SentryService.java b/src/main/java/org/mskcc/cbio/oncokb/service/SentryService.java new file mode 100644 index 000000000..0393c2ec3 --- /dev/null +++ b/src/main/java/org/mskcc/cbio/oncokb/service/SentryService.java @@ -0,0 +1,45 @@ +package org.mskcc.cbio.oncokb.service; + +import io.sentry.Sentry; +import io.sentry.SentryEvent; +import io.sentry.SentryLevel; +import io.sentry.protocol.Message; +import io.sentry.protocol.User; +import org.springframework.stereotype.Service; + +@Service +public class SentryService { + + /** + * Send a message to Sentry + * + * @param sentryLevel Sentry event level. Warning, Error and more + * @param message The custom message which will be displayed in the Sentry issue + * @param user The optional user object if you want to group the issue based on the user + */ + public void throwMessage(SentryLevel sentryLevel, String message, User user) { + Sentry.setLevel(sentryLevel); + if (user != null) { + Sentry.setUser(user); + } + Sentry.captureMessage(message); + } + + /** + * Send the exception to Sentry + * + * @param sentryLevel Sentry event level. Warning, Error and more + * @param exception Any throwable exception which will be displayed in the Sentry issue + * @param message The custom message which will be displayed in the Sentry issue + */ + public void throwEvent(SentryLevel sentryLevel, Throwable exception, String message) { + SentryEvent event = new SentryEvent(); + Message sentryMessage = new Message(); + sentryMessage.setMessage(message); + event.setMessage(sentryMessage); + event.setLevel(sentryLevel); + event.setThrowable(exception); + + Sentry.captureEvent(event); + } +} diff --git a/src/main/java/org/mskcc/cbio/oncokb/service/SmartsheetService.java b/src/main/java/org/mskcc/cbio/oncokb/service/SmartsheetService.java index 7952decfd..7558d8671 100644 --- a/src/main/java/org/mskcc/cbio/oncokb/service/SmartsheetService.java +++ b/src/main/java/org/mskcc/cbio/oncokb/service/SmartsheetService.java @@ -7,6 +7,8 @@ import com.smartsheet.api.models.Row; import com.smartsheet.api.models.SearchResult; import com.smartsheet.api.models.Sheet; +import io.sentry.SentryLevel; +import io.sentry.protocol.User; import org.apache.commons.lang3.StringUtils; import org.mskcc.cbio.oncokb.config.application.ApplicationProperties; import org.mskcc.cbio.oncokb.config.application.SmartsheetProperties; @@ -34,13 +36,13 @@ public class SmartsheetService { private final int MIN_NUM_COLUMN = 8; - private final MailService mailService; private final SmartsheetProperties smartsheetProperties; + private final SentryService sentryService; private Smartsheet smartsheet; - public SmartsheetService(MailService mailService, ApplicationProperties applicationProperties) { + public SmartsheetService(ApplicationProperties applicationProperties, SentryService sentryService) { this.smartsheetProperties = applicationProperties.getSmartsheet(); - this.mailService = mailService; + this.sentryService = sentryService; if (this.smartsheetProperties != null && StringUtils.isNotEmpty(this.smartsheetProperties.getAccessToken())) { this.smartsheet = SmartsheetFactory.createDefaultClient(this.smartsheetProperties.getAccessToken()); } else { @@ -61,8 +63,9 @@ public void addUserToSheet( if (this.smartsheet != null && this.smartsheetProperties.getSheetId() != null ) { + Sheet sheet = null; try { - Sheet sheet = smartsheet.sheetResources().getSheet( + sheet = smartsheet.sheetResources().getSheet( this.smartsheetProperties.getSheetId(), null, null, @@ -72,54 +75,54 @@ public void addUserToSheet( null, null ); - if (sheet.getColumns().size() < MIN_NUM_COLUMN) { - mailService.sendEmailToDevTeam( - "ROC Smartsheet number of columns is not expected, expect no less than " + MIN_NUM_COLUMN + " columns", - "Please take a look at the sheet, it's supposed to have at least six columns", - null, - false, - false - ); - } else { - // Search user email to see whether email has been added. If the email exists, skip adding record - // Enclose double quote for exact match. This is necessary, otherwise the fuzzy search is not so accurate. - SearchResult searchResult = this.smartsheet.searchResources().search("\"" + userEmail + "\""); + } catch (SmartsheetException e) { + sentryService.throwEvent(SentryLevel.ERROR, e, "Failed to get smart sheet using smartsheet.sheetResources().getSheet"); + return; + } + if (sheet.getColumns().size() < MIN_NUM_COLUMN) { + User user = new User(); + user.setUsername(userName); + sentryService.throwMessage(SentryLevel.ERROR, "ROC Smartsheet number of columns is not expected, expect no less than " + MIN_NUM_COLUMN + " columns", user); + } else { + // Search user email to see whether email has been added. If the email exists, skip adding record + // Enclose double quote for exact match. This is necessary, otherwise the fuzzy search is not so accurate. + SearchResult searchResult = null; + try { + searchResult = this.smartsheet.searchResources().search("\"" + userEmail + "\""); if (searchResult.getTotalCount() > 0) { log.info("The user " + userEmail + " already exists in the ROC smartsheet"); return; } - - // Specify cell values for first row - List rowACells = Arrays.asList( - new Cell(this.smartsheetProperties.getColumnIds().get(0)).setValue(this.smartsheetProperties.getEditor()), - new Cell(this.smartsheetProperties.getColumnIds().get(1)).setValue(userName), - new Cell(this.smartsheetProperties.getColumnIds().get(2)).setValue(userEmail), - new Cell(this.smartsheetProperties.getColumnIds().get(3)).setValue(userCompany), - new Cell(this.smartsheetProperties.getColumnIds().get(4)).setValue(userCity), - new Cell(this.smartsheetProperties.getColumnIds().get(5)).setValue(userCountry), - new Cell(this.smartsheetProperties.getColumnIds().get(6)).setValue(licenseType), - new Cell(this.smartsheetProperties.getColumnIds().get(7)).setValue(useCase) - ); - - // Specify contents of first row - Row newRow = new Row(); - newRow.setCells(rowACells) - .setToBottom(true); - - // Add rows to sheet - List createdRows = smartsheet.sheetResources().rowResources().addRows( - this.smartsheetProperties.getSheetId(), - Collections.singletonList(newRow) - ); + } catch (SmartsheetException e) { + sentryService.throwEvent(SentryLevel.WARNING, e, "Failed to search sheet with query " + userEmail + ". But we are going to try to insert the record anyway"); } - } catch (SmartsheetException e) { - mailService.sendEmailToDevTeam( - "Critical: Operation to ROC smartsheet failed", - "Please verify the ROC smartsheet is setup properly. The error: " + e.getMessage(), - null, - false, - false + } + + // Specify cell values for first row + List rowACells = Arrays.asList( + new Cell(this.smartsheetProperties.getColumnIds().get(0)).setValue(this.smartsheetProperties.getEditor()), + new Cell(this.smartsheetProperties.getColumnIds().get(1)).setValue(userName), + new Cell(this.smartsheetProperties.getColumnIds().get(2)).setValue(userEmail), + new Cell(this.smartsheetProperties.getColumnIds().get(3)).setValue(userCompany), + new Cell(this.smartsheetProperties.getColumnIds().get(4)).setValue(userCity), + new Cell(this.smartsheetProperties.getColumnIds().get(5)).setValue(userCountry), + new Cell(this.smartsheetProperties.getColumnIds().get(6)).setValue(licenseType), + new Cell(this.smartsheetProperties.getColumnIds().get(7)).setValue(useCase) + ); + + // Specify contents of first row + Row newRow = new Row(); + newRow.setCells(rowACells) + .setToBottom(true); + + // Add rows to sheet + try { + List createdRows = smartsheet.sheetResources().rowResources().addRows( + this.smartsheetProperties.getSheetId(), + Collections.singletonList(newRow) ); + } catch (SmartsheetException e) { + sentryService.throwEvent(SentryLevel.ERROR, e, "Failed to add row to smartsheet, " + newRow); } } else { log.warn("No user record is added since smartsheet is not initiated properly"); @@ -154,9 +157,10 @@ public boolean isUsa(String country) { return Arrays.asList(usaCountryNames).stream().filter(str -> str.equalsIgnoreCase(ct)).findAny().isPresent(); } - public boolean sentToRocReview(UserDTO userDTO){ + public boolean sentToRocReview(UserDTO userDTO) { return userDTO.getAdditionalInfo() != null && Boolean.TRUE.equals(userDTO.getAdditionalInfo().getSentToRocReview()); } + public boolean shouldAddUser(UserDTO userDTO) { if (sentToRocReview(userDTO)) { return false;