-
Notifications
You must be signed in to change notification settings - Fork 344
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15774 from cdapio/CDAP-21099
[CDAP-21099] Implement ErrorClassification API for program runs
- Loading branch information
Showing
13 changed files
with
650 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
204 changes: 204 additions & 0 deletions
204
cdap-proto/src/main/java/io/cdap/cdap/proto/ErrorClassificationResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
/* | ||
* Copyright © 2024 Cask Data, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package io.cdap.cdap.proto; | ||
|
||
/** | ||
* Represents the response for classifying error logs. | ||
*/ | ||
public class ErrorClassificationResponse { | ||
private final String stageName; | ||
private final String errorCategory; | ||
private final String errorReason; | ||
private final String errorMessage; | ||
private final String errorType; | ||
private final String dependency; | ||
private final String errorCodeType; | ||
private final String errorCode; | ||
private final String supportedDocumentationUrl; | ||
|
||
private ErrorClassificationResponse(String stageName, String errorCategory, String errorReason, | ||
String errorMessage, String errorType, String dependency, String errorCodeType, | ||
String errorCode, String supportedDocumentationUrl) { | ||
this.stageName = stageName; | ||
this.errorCategory = errorCategory; | ||
this.errorReason = errorReason; | ||
this.errorMessage = errorMessage; | ||
this.errorType = errorType; | ||
this.dependency = dependency; | ||
this.errorCodeType = errorCodeType; | ||
this.errorCode = errorCode; | ||
this.supportedDocumentationUrl = supportedDocumentationUrl; | ||
} | ||
|
||
/** | ||
* Gets the stage name for ErrorClassificationResponse. | ||
*/ | ||
public String getStageName() { | ||
return stageName; | ||
} | ||
|
||
/** | ||
* Gets the error category for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorCategory() { | ||
return errorCategory; | ||
} | ||
|
||
/** | ||
* Gets the error reason for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorReason() { | ||
return errorReason; | ||
} | ||
|
||
/** | ||
* Gets the error message for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorMessage() { | ||
return errorMessage; | ||
} | ||
|
||
/** | ||
* Gets the error type for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorType() { | ||
return errorType; | ||
} | ||
|
||
/** | ||
* Gets the dependency flag for ErrorClassificationResponse. | ||
*/ | ||
public String getDependency() { | ||
return dependency; | ||
} | ||
|
||
/** | ||
* Gets the error code type for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorCodeType() { | ||
return errorCodeType; | ||
} | ||
|
||
/** | ||
* Gets the error code for ErrorClassificationResponse. | ||
*/ | ||
public String getErrorCode() { | ||
return errorCode; | ||
} | ||
|
||
/** | ||
* Gets the supported documentation URL for ErrorClassificationResponse. | ||
*/ | ||
public String getSupportedDocumentationUrl() { | ||
return supportedDocumentationUrl; | ||
} | ||
|
||
/** | ||
* Builder for {@link ErrorClassificationResponse}. | ||
*/ | ||
public static class Builder { | ||
private String stageName; | ||
private String errorCategory; | ||
private String errorReason; | ||
private String errorMessage; | ||
private String errorType; | ||
private String dependency; | ||
private String errorCodeType; | ||
private String errorCode; | ||
private String supportedDocumentationUrl; | ||
|
||
/** | ||
* Sets the stage name for ErrorClassificationResponse. | ||
*/ | ||
public Builder setStageName(String stageName) { | ||
this.stageName = stageName; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error category for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorCategory(String errorCategory) { | ||
this.errorCategory = errorCategory; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error reason for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorReason(String errorReason) { | ||
this.errorReason = errorReason; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error message for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorMessage(String errorMessage) { | ||
this.errorMessage = errorMessage; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error type for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorType(String errorType) { | ||
this.errorType = errorType; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the dependency flag for ErrorClassificationResponse. | ||
*/ | ||
public Builder setDependency(String dependency) { | ||
this.dependency = dependency; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error code type for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorCodeType(String errorCodeType) { | ||
this.errorCodeType = errorCodeType; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the error code for ErrorClassificationResponse. | ||
*/ | ||
public Builder setErrorCode(String errorCode) { | ||
this.errorCode = errorCode; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the supported documentation URL for ErrorClassificationResponse. | ||
*/ | ||
public Builder setSupportedDocumentationUrl(String supportedDocumentationUrl) { | ||
this.supportedDocumentationUrl = supportedDocumentationUrl; | ||
return this; | ||
} | ||
|
||
/** | ||
* Builds and returns a new instance of ErrorClassificationResponse. | ||
*/ | ||
public ErrorClassificationResponse build() { | ||
return new ErrorClassificationResponse(stageName, errorCategory, errorReason, errorMessage, | ||
errorType, dependency, errorCodeType, errorCode, supportedDocumentationUrl); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
cdap-watchdog/src/main/java/io/cdap/cdap/logging/ErrorLogsClassifier.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright © 2024 Cask Data, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package io.cdap.cdap.logging; | ||
|
||
import ch.qos.logback.classic.spi.ILoggingEvent; | ||
import ch.qos.logback.classic.spi.IThrowableProxy; | ||
import com.google.gson.Gson; | ||
import io.cdap.cdap.api.dataset.lib.CloseableIterator; | ||
import io.cdap.cdap.api.exception.ProgramFailureException; | ||
import io.cdap.cdap.common.conf.Constants.Logging; | ||
import io.cdap.cdap.logging.read.LogEvent; | ||
import io.cdap.cdap.proto.ErrorClassificationResponse; | ||
import io.cdap.http.HttpResponder; | ||
import io.netty.handler.codec.http.HttpResponseStatus; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import org.elasticsearch.common.Strings; | ||
|
||
/** | ||
* Classifies error logs and returns {@link ErrorClassificationResponse}. | ||
* TODO - | ||
* - Add rule based classification. | ||
* - Handle cases when stage name is not present in the mdc. | ||
*/ | ||
public class ErrorLogsClassifier { | ||
private static final Gson GSON = new Gson(); | ||
|
||
/** | ||
* Classifies error logs and returns {@link ErrorClassificationResponse}. | ||
* | ||
* @param logIter Logs Iterator that can be closed. | ||
* @param responder The HttpResponder. | ||
*/ | ||
public void classify(CloseableIterator<LogEvent> logIter, HttpResponder responder) { | ||
Map<String, ErrorClassificationResponse> responseMap = new HashMap<>(); | ||
while(logIter.hasNext()) { | ||
ILoggingEvent logEvent = logIter.next().getLoggingEvent(); | ||
Map<String, String> mdc = logEvent.getMDCPropertyMap(); | ||
if (!mdc.containsKey(Logging.TAG_FAILED_STAGE)) { | ||
continue; | ||
} | ||
String stageName = mdc.get(Logging.TAG_FAILED_STAGE); | ||
String errorMessage = null; | ||
if (responseMap.containsKey(stageName)) { | ||
continue; | ||
} | ||
IThrowableProxy throwableProxy = logEvent.getThrowableProxy(); | ||
while (throwableProxy != null) { | ||
if (ProgramFailureException.class.getName().equals(throwableProxy.getClassName())) { | ||
errorMessage = throwableProxy.getMessage(); | ||
} | ||
throwableProxy = throwableProxy.getCause(); | ||
} | ||
if (!Strings.isNullOrEmpty(errorMessage)) { | ||
ErrorClassificationResponse classificationResponse = | ||
new ErrorClassificationResponse.Builder() | ||
.setStageName(stageName) | ||
.setErrorCategory(String.format("%s-'%s'",mdc.get(Logging.TAG_ERROR_CATEGORY), | ||
stageName)) | ||
.setErrorReason(mdc.get(Logging.TAG_ERROR_REASON)) | ||
.setErrorMessage(errorMessage) | ||
.setErrorType(mdc.get(Logging.TAG_ERROR_TYPE)) | ||
.setDependency(mdc.get(Logging.TAG_DEPENDENCY)) | ||
.setErrorCodeType(mdc.get(Logging.TAG_ERROR_CODE_TYPE)) | ||
.setErrorCode(mdc.get(Logging.TAG_ERROR_CODE)) | ||
.setSupportedDocumentationUrl(mdc.get(Logging.TAG_SUPPORTED_DOC_URL)) | ||
.build(); | ||
responseMap.put(stageName, classificationResponse); | ||
} | ||
} | ||
responder.sendJson(HttpResponseStatus.OK, GSON.toJson(responseMap.values())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.