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

IGNITE-24150 Ability to have different prefixes for exceptions #4991

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 21 additions & 64 deletions modules/api/src/main/java/org/apache/ignite/lang/ErrorGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,49 @@

package org.apache.ignite.lang;

import static java.util.regex.Pattern.DOTALL;
import static org.apache.ignite.lang.ErrorGroups.errorGroupByCode;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jetbrains.annotations.Nullable;

/**
* This class represents a concept of error group. Error group defines a collection of errors that belong to a single semantic component.
* Each group can be identified by a name and an integer number that both must be unique across all error groups.
*/
public class ErrorGroup {
/** Additional prefix that is used in a human-readable format of ignite errors. */
public static final String ERR_PREFIX = "IGN-";

/** Error message pattern. */
private static final Pattern EXCEPTION_MESSAGE_PATTERN =
Pattern.compile("(.*)(IGN)-([A-Z]+)-(\\d+)\\s(TraceId:)([a-f0-9]{8}(?:-[a-f0-9]{4}){4}[a-f0-9]{8})(\\s?)(.*)", DOTALL);

/** Group name. */
private final String groupName;

/** Group code. */
private final short groupCode;

/** Additional prefix that is used in a human-readable format of error messages. */
private final String errorPrefix;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm a little confused by the name. Perhaps, it would be nice to change to groupNamePrefix, or vendorSpecificPrefix etc. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we honestly it's not so important and all variants reflect nature of the field but from different perspective


/** Contains error codes for this error group. */
private final Set<Short> codes = new HashSet<>();

/**
* Creates a new error group with the specified name and corresponding code.
*
* @param errorPrefix Error prefix.
* @param groupName Group name.
* @param groupCode Group code.
*/
ErrorGroup(String groupName, short groupCode) {
ErrorGroup(String errorPrefix, String groupName, short groupCode) {
this.groupName = groupName;
this.groupCode = groupCode;
this.errorPrefix = errorPrefix;
}

/**
* Returns a error prefix of this group.
*
* @return Error prefix.
*/
public String errorPrefix() {
return errorPrefix;
}

/**
Expand Down Expand Up @@ -113,74 +116,28 @@ public static short extractErrorCode(int code) {
* @return New error message with predefined prefix.
*/
public static String errorMessage(UUID traceId, int code, String message) {
return errorMessage(traceId, errorGroupByCode(code).name(), code, message);
ErrorGroup errorGroup = errorGroupByCode(code);
return errorMessage(errorGroup.errorPrefix(), traceId, errorGroup.name(), code, message);
}

/**
* Creates a new error message with predefined prefix.
*
* @param errorPrefix Prefix for the error.
* @param traceId Unique identifier of this exception.
* @param groupName Group name.
* @param code Full error code.
* @param message Original message.
* @return New error message with predefined prefix.
*/
public static String errorMessage(UUID traceId, String groupName, int code, String message) {
return ERR_PREFIX + groupName + '-' + Short.toUnsignedInt(extractErrorCode(code)) + " TraceId:" + traceId
static String errorMessage(String errorPrefix, UUID traceId, String groupName, int code, String message) {
return errorPrefix + "-" + groupName + '-' + Short.toUnsignedInt(extractErrorCode(code)) + " TraceId:" + traceId
+ ((message != null && !message.isEmpty()) ? ' ' + message : "");
}

/**
* Creates a new error message with predefined prefix.
*
* @param traceId Unique identifier of this exception.
* @param code Full error code.
* @param cause Cause.
* @return New error message with predefined prefix.
*/
public static String errorMessageFromCause(UUID traceId, int code, Throwable cause) {
return errorMessageFromCause(traceId, errorGroupByCode(code).name(), code, cause);
}

/**
* Creates a new error message with predefined prefix.
*
* @param traceId Unique identifier of this exception.
* @param groupName Group name.
* @param code Full error code.
* @param cause Cause.
* @return New error message with predefined prefix.
*/
public static String errorMessageFromCause(UUID traceId, String groupName, int code, Throwable cause) {
String c = (cause != null && cause.getMessage() != null) ? cause.getMessage() : null;

if (c != null) {
c = extractCauseMessage(c);
}

return errorMessage(traceId, groupName, code, c);
}

/**
* Returns a message extracted from the given {@code errorMessage} if this {@code errorMessage} matches
* {@link #EXCEPTION_MESSAGE_PATTERN}. If {@code errorMessage} does not match the pattern or {@code null} then returns the original
* {@code errorMessage}.
*
* @param errorMessage Message that is returned by {@link Throwable#getMessage()}
* @return Extracted message.
*/
public static @Nullable String extractCauseMessage(String errorMessage) {
if (errorMessage == null) {
return null;
}

Matcher m = EXCEPTION_MESSAGE_PATTERN.matcher(errorMessage);
return (m.matches()) ? m.group(8) : errorMessage;
}

/** {@inheritDoc} */
@Override
public String toString() {
return "ErrorGroup [name=" + name() + ", groupCode=" + groupCode() + ']';
return "ErrorGroup [errorPrefix=" + errorPrefix + ", name=" + name() + ", groupCode=" + groupCode() + ']';
}
}
58 changes: 56 additions & 2 deletions modules/api/src/main/java/org/apache/ignite/lang/ErrorGroups.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,33 @@

package org.apache.ignite.lang;

import static java.util.regex.Pattern.DOTALL;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.ignite.error.code.annotations.ErrorCodeGroup;
import org.jetbrains.annotations.Nullable;

/**
* Defines error groups and its errors.
*/
@SuppressWarnings("PublicInnerClass")
public class ErrorGroups {
/** Additional prefix that is used in a human-readable format of ignite errors. */
public static final String IGNITE_ERR_PREFIX = "IGN";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps, the following code should be updated as well

public const string ErrPrefix = "IGN-";

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

private static final String PLACEHOLDER = "${ERROR_PREFIX}";
private static final String EXCEPTION_MESSAGE_STRING_PATTERN =
"(.*)(" + PLACEHOLDER + ")-([A-Z]+)-(\\d+)\\s(TraceId:)([a-f0-9]{8}(?:-[a-f0-9]{4}){4}[a-f0-9]{8})(\\s?)(.*)";

/** Error message pattern. */
private static Pattern EXCEPTION_MESSAGE_PATTERN;

private static final HashSet<String> REGISTERED_ERROR_PREFIXES = new HashSet<>();

/** List of all registered error groups. */
private static final Map<Short, ErrorGroup> registeredGroups = new HashMap<>();

Expand All @@ -44,7 +61,7 @@ public static synchronized void initialize() {
}

/**
* Creates a new error group with the given {@code groupName} and {@code groupCode}.
* Creates a new error group with the given {@code groupName} and {@code groupCode} and default error prefix.
*
* @param groupName Group name to be created.
* @param groupCode Group code to be created.
Expand All @@ -53,6 +70,20 @@ public static synchronized void initialize() {
* the given {@code groupName} is {@code null} or empty.
*/
public static synchronized ErrorGroup registerGroup(String groupName, short groupCode) {
return registerGroup(IGNITE_ERR_PREFIX, groupName, groupCode);
}

/**
* Creates a new error group with the given {@code groupName} and {@code groupCode}.
*
* @param errorPrefix Error prefix which should be used for the created error group.
* @param groupName Group name to be created.
* @param groupCode Group code to be created.
* @return New error group.
* @throws IllegalArgumentException If the specified name or group code already registered. Also, this exception is thrown if
* the given {@code groupName} is {@code null} or empty.
*/
public static synchronized ErrorGroup registerGroup(String errorPrefix, String groupName, short groupCode) {
if (groupName == null || groupName.isEmpty()) {
throw new IllegalArgumentException("Group name is null or empty");
}
Expand All @@ -73,13 +104,36 @@ public static synchronized ErrorGroup registerGroup(String groupName, short grou
}
}

ErrorGroup newGroup = new ErrorGroup(grpName, groupCode);
if (REGISTERED_ERROR_PREFIXES.add(errorPrefix)) {
String errorPrefixes = String.join("|", REGISTERED_ERROR_PREFIXES);
String pattern = EXCEPTION_MESSAGE_STRING_PATTERN.replace(PLACEHOLDER, errorPrefixes);
EXCEPTION_MESSAGE_PATTERN = Pattern.compile(pattern, DOTALL);
korlov42 marked this conversation as resolved.
Show resolved Hide resolved
}

ErrorGroup newGroup = new ErrorGroup(errorPrefix, grpName, groupCode);

registeredGroups.put(groupCode, newGroup);

return newGroup;
}

/**
* Returns a message extracted from the given {@code errorMessage} if this {@code errorMessage} matches
* {@link #EXCEPTION_MESSAGE_PATTERN}. If {@code errorMessage} does not match the pattern or {@code null} then returns the original
* {@code errorMessage}.
*
* @param errorMessage Message that is returned by {@link Throwable#getMessage()}
* @return Extracted message.
*/
public static @Nullable String extractCauseMessage(String errorMessage) {
if (errorMessage == null) {
return null;
}

Matcher m = EXCEPTION_MESSAGE_PATTERN.matcher(errorMessage);
return (m.matches()) ? m.group(8) : errorMessage;
}

/**
* Returns group code extracted from the given full error code.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package org.apache.ignite.lang;

import static org.apache.ignite.lang.ErrorGroup.ERR_PREFIX;
import static org.apache.ignite.lang.ErrorGroup.errorMessage;
import static org.apache.ignite.lang.ErrorGroup.extractErrorCode;
import static org.apache.ignite.lang.ErrorGroups.errorGroupByCode;
Expand All @@ -34,6 +33,9 @@ public class IgniteCheckedException extends Exception implements TraceableExcept
/** Serial version UID. */
private static final long serialVersionUID = 0L;

/** Prefix for error message. */
private final String errorPrefix;

/** Name of the error group. */
private final String groupName;

Expand Down Expand Up @@ -68,7 +70,9 @@ public IgniteCheckedException(int code) {
*/
public IgniteCheckedException(UUID traceId, int code) {
this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand All @@ -93,7 +97,9 @@ public IgniteCheckedException(UUID traceId, int code, String message) {
super(message);

this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand All @@ -118,7 +124,9 @@ public IgniteCheckedException(UUID traceId, int code, @Nullable Throwable cause)
super((cause != null) ? cause.getLocalizedMessage() : null, cause);

this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand All @@ -145,7 +153,9 @@ public IgniteCheckedException(UUID traceId, int code, String message, @Nullable
super(message, cause);

this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand Down Expand Up @@ -179,7 +189,7 @@ public int code() {
* @return Full error code in a human-readable format.
*/
public String codeAsString() {
return ERR_PREFIX + groupName() + '-' + errorCode();
return errorPrefix + "-" + groupName() + '-' + errorCode();
}

/**
Expand Down Expand Up @@ -218,6 +228,6 @@ public UUID traceId() {
/** {@inheritDoc} */
@Override
public String toString() {
return getClass().getName() + ": " + errorMessage(traceId, groupName, code, getLocalizedMessage());
return getClass().getName() + ": " + errorMessage(errorPrefix, traceId, groupName, code, getLocalizedMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

package org.apache.ignite.lang;

import static org.apache.ignite.lang.ErrorGroup.ERR_PREFIX;
import static org.apache.ignite.lang.ErrorGroup.errorMessage;
import static org.apache.ignite.lang.ErrorGroup.extractErrorCode;
import static org.apache.ignite.lang.ErrorGroups.errorGroupByCode;
Expand All @@ -34,6 +33,9 @@ public class IgniteException extends RuntimeException implements TraceableExcept
/** Serial version UID. */
private static final long serialVersionUID = 0L;

/** Prefix for error message. */
private final String errorPrefix;

/** Name of the error group. */
private final String groupName;

Expand Down Expand Up @@ -73,7 +75,9 @@ public IgniteException(int code) {
*/
public IgniteException(UUID traceId, int code) {
this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand Down Expand Up @@ -130,7 +134,9 @@ public IgniteException(UUID traceId, int code, @Nullable Throwable cause) {
super((cause != null) ? cause.getLocalizedMessage() : null, cause);

this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand Down Expand Up @@ -178,7 +184,9 @@ public IgniteException(
super(message, cause, enableSuppression, writableStackTrace);

this.traceId = traceId;
this.groupName = errorGroupByCode(code).name();
ErrorGroup errorGroup = errorGroupByCode(code);
this.groupName = errorGroup.name();
this.errorPrefix = errorGroup.errorPrefix();
this.code = code;
}

Expand Down Expand Up @@ -211,7 +219,7 @@ public int code() {
* @return Full error code in a human-readable format.
*/
public String codeAsString() {
return ERR_PREFIX + groupName() + '-' + errorCode();
return errorPrefix + "-" + groupName() + '-' + errorCode();
}

/**
Expand Down Expand Up @@ -250,6 +258,6 @@ public UUID traceId() {
/** {@inheritDoc} */
@Override
public String toString() {
return getClass().getName() + ": " + errorMessage(traceId, groupName, code, getLocalizedMessage());
return getClass().getName() + ": " + errorMessage(errorPrefix, traceId, groupName, code, getLocalizedMessage());
}
}
Loading