Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SentryJobErrorReportingClient: set event platform from parsed stacktrace #16906

Merged
merged 11 commits into from
Sep 26, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,51 @@
@SuppressWarnings("PMD.AvoidLiteralsInIfCondition")
public class SentryExceptionHelper {

private static final Logger LOGGER = LoggerFactory.getLogger(SentryExceptionHelper.class);
public record SentryParsedException(SentryExceptionPlatform platform, List<SentryException> exceptions) {}

public static final String ERROR_MAP_MESSAGE_KEY = "errorMessage";
public static final String ERROR_MAP_TYPE_KEY = "errorType";
private static final Logger LOGGER = LoggerFactory.getLogger(SentryExceptionHelper.class);

public enum ERROR_MAP_KEYS {
ERROR_MAP_MESSAGE_KEY,
ERROR_MAP_TYPE_KEY
}

/**
* Specifies the platform for a thrown exception. Values must be supported by Sentry as specified in
* https://develop.sentry.dev/sdk/event-payloads/#required-attributes. Currently, only java, python
* and dbt (other) exceptions are supported.
*/
public enum SentryExceptionPlatform {

JAVA("java"),
PYTHON("python"),
OTHER("other");

private final String value;

SentryExceptionPlatform(final String value) {
this.value = value;
}

public String getValue() {
return value;
}

@Override
public String toString() {
return String.valueOf(value);
}

}

/**
* Processes a raw stacktrace string into structured SentryExceptions
* <p>
* Currently, Java and Python stacktraces are supported. If an unsupported stacktrace format is
* encountered, an empty optional will be returned, in which case we can fall back to alternate
* grouping.
*/
public Optional<List<SentryException>> buildSentryExceptions(final String stacktrace) {
public Optional<SentryParsedException> buildSentryExceptions(final String stacktrace) {
return Exceptions.swallowWithDefault(() -> {
if (stacktrace.startsWith("Traceback (most recent call last):")) {
return buildPythonSentryExceptions(stacktrace);
Expand All @@ -56,7 +83,7 @@ public Optional<List<SentryException>> buildSentryExceptions(final String stackt
}, Optional.empty());
}

private static Optional<List<SentryException>> buildPythonSentryExceptions(final String stacktrace) {
private static Optional<SentryParsedException> buildPythonSentryExceptions(final String stacktrace) {
final List<SentryException> sentryExceptions = new ArrayList<>();

// separate chained exceptions
Expand Down Expand Up @@ -115,10 +142,10 @@ private static Optional<List<SentryException>> buildPythonSentryExceptions(final
if (sentryExceptions.isEmpty())
return Optional.empty();

return Optional.of(sentryExceptions);
return Optional.of(new SentryParsedException(SentryExceptionPlatform.PYTHON, sentryExceptions));
}

private static Optional<List<SentryException>> buildJavaSentryExceptions(final String stacktrace) {
private static Optional<SentryParsedException> buildJavaSentryExceptions(final String stacktrace) {
final List<SentryException> sentryExceptions = new ArrayList<>();

// separate chained exceptions
Expand Down Expand Up @@ -182,10 +209,10 @@ private static Optional<List<SentryException>> buildJavaSentryExceptions(final S
if (sentryExceptions.isEmpty())
return Optional.empty();

return Optional.of(sentryExceptions);
return Optional.of(new SentryParsedException(SentryExceptionPlatform.JAVA, sentryExceptions));
}

private static Optional<List<SentryException>> buildNormalizationDbtSentryExceptions(final String stacktrace) {
private static Optional<SentryParsedException> buildNormalizationDbtSentryExceptions(final String stacktrace) {
final List<SentryException> sentryExceptions = new ArrayList<>();

final Map<ERROR_MAP_KEYS, String> usefulErrorMap = getUsefulErrorMessageAndTypeFromDbtError(stacktrace);
Expand All @@ -202,7 +229,7 @@ private static Optional<List<SentryException>> buildNormalizationDbtSentryExcept
if (sentryExceptions.isEmpty())
return Optional.empty();

return Optional.of(sentryExceptions);
return Optional.of(new SentryParsedException(SentryExceptionPlatform.OTHER, sentryExceptions));
}

public static Map<ERROR_MAP_KEYS, String> getUsefulErrorMessageAndTypeFromDbtError(final String stacktrace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.airbyte.config.FailureReason;
import io.airbyte.config.Metadata;
import io.airbyte.config.StandardWorkspace;
import io.airbyte.persistence.job.errorreporter.SentryExceptionHelper.SentryParsedException;
import io.sentry.Hub;
import io.sentry.IHub;
import io.sentry.NoOpHub;
Expand All @@ -24,6 +25,7 @@
public class SentryJobErrorReportingClient implements JobErrorReportingClient {

static final String STACKTRACE_PARSE_ERROR_TAG_KEY = "stacktrace_parse_error";
static final String STACKTRACE_PLATFORM_TAG_KEY = "stacktrace_platform";
private final IHub sentryHub;
private final SentryExceptionHelper exceptionHelper;

Expand Down Expand Up @@ -98,9 +100,13 @@ public void reportJobFailureReason(@Nullable final StandardWorkspace workspace,
// attach failure reason stack trace
final String failureStackTrace = failureReason.getStacktrace();
if (failureStackTrace != null && !failureStackTrace.isBlank()) {
final Optional<List<SentryException>> parsedExceptions = exceptionHelper.buildSentryExceptions(failureStackTrace);
if (parsedExceptions.isPresent()) {
event.setExceptions(parsedExceptions.get());
final Optional<SentryParsedException> optParsedException = exceptionHelper.buildSentryExceptions(failureStackTrace);
if (optParsedException.isPresent()) {
final SentryParsedException parsedException = optParsedException.get();
final String platform = parsedException.platform().getValue();
event.setPlatform(platform);
event.setTag(STACKTRACE_PLATFORM_TAG_KEY, platform);
event.setExceptions(parsedException.exceptions());
} else {
event.setTag(STACKTRACE_PARSE_ERROR_TAG_KEY, "1");

Expand Down
Loading