Skip to content

Commit

Permalink
Update for the more restricted span status codes. (#1701)
Browse files Browse the repository at this point in the history
* Update for the more restricted span status codes.

* Update status codes to match the proposed proto codes
  • Loading branch information
jkwatson authored Sep 28, 2020
1 parent e7706d6 commit 287eae9
Show file tree
Hide file tree
Showing 20 changed files with 132 additions and 492 deletions.
2 changes: 1 addition & 1 deletion QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ try (Scope scope = tracer.withSpan(span)) {
// your use case
...
} catch (Throwable t) {
Status status = Status.UNKNOWN.withDescription("Change it to your error message");
Status status = Status.ERROR.withDescription("Change it to your error message");
span.setStatus(status);
} finally {
span.end(); // closing the scope does not end the span, this has to be done manually
Expand Down
310 changes: 31 additions & 279 deletions api/src/main/java/io/opentelemetry/trace/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
package io.opentelemetry.trace;

import io.opentelemetry.internal.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import javax.annotation.Nullable;
Expand All @@ -44,163 +43,18 @@ public final class Status {
* @since 0.1.0
*/
public enum CanonicalCode {
/**
* The operation completed successfully.
*
* @since 0.1.0
*/
OK(0),

/**
* The operation was cancelled (typically by the caller).
*
* @since 0.1.0
*/
CANCELLED(1),

/**
* Unknown error. An example of where this error may be returned is if a Status value received
* from another address space belongs to an error-space that is not known in this address space.
* Also errors raised by APIs that do not return enough error information may be converted to
* this error.
*
* @since 0.1.0
*/
UNKNOWN(2),

/**
* Client specified an invalid argument. Note that this differs from FAILED_PRECONDITION.
* INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the
* system (e.g., a malformed file name).
*
* @since 0.1.0
*/
INVALID_ARGUMENT(3),

/**
* Deadline expired before operation could complete. For operations that change the state of the
* system, this error may be returned even if the operation has completed successfully. For
* example, a successful response from a server could have been delayed long enough for the
* deadline to expire.
*
* @since 0.1.0
*/
DEADLINE_EXCEEDED(4),

/**
* Some requested entity (e.g., file or directory) was not found.
*
* @since 0.1.0
*/
NOT_FOUND(5),

/**
* Some entity that we attempted to create (e.g., file or directory) already exists.
*
* @since 0.1.0
*/
ALREADY_EXISTS(6),

/**
* The caller does not have permission to execute the specified operation. PERMISSION_DENIED
* must not be used for rejections caused by exhausting some resource (use RESOURCE_EXHAUSTED
* instead for those errors). PERMISSION_DENIED must not be used if the caller cannot be
* identified (use UNAUTHENTICATED instead for those errors).
*
* @since 0.1.0
*/
PERMISSION_DENIED(7),

/**
* Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system
* is out of space.
*
* @since 0.1.0
*/
RESOURCE_EXHAUSTED(8),

/**
* Operation was rejected because the system is not in a state required for the operation's
* execution. For example, directory to be deleted may be non-empty, an rmdir operation is
* applied to a non-directory, etc.
*
* <p>A litmus test that may help a service implementor in deciding between FAILED_PRECONDITION,
* ABORTED, and UNAVAILABLE: (a) Use UNAVAILABLE if the client can retry just the failing call.
* (b) Use ABORTED if the client should retry at a higher-level (e.g., restarting a
* read-modify-write sequence). (c) Use FAILED_PRECONDITION if the client should not retry until
* the system state has been explicitly fixed. E.g., if an "rmdir" fails because the directory
* is non-empty, FAILED_PRECONDITION should be returned since the client should not retry unless
* they have first fixed up the directory by deleting files from it.
*
* @since 0.1.0
*/
FAILED_PRECONDITION(9),

/**
* The operation was aborted, typically due to a concurrency issue like sequencer check
* failures, transaction aborts, etc.
*
* <p>See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE.
*
* @since 0.1.0
*/
ABORTED(10),

/**
* Operation was attempted past the valid range. E.g., seeking or reading past end of file.
*
* <p>Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system
* state changes. For example, a 32-bit file system will generate INVALID_ARGUMENT if asked to
* read at an offset that is not in the range [0,2^32-1], but it will generate OUT_OF_RANGE if
* asked to read from an offset past the current file size.
*
* <p>There is a fair bit of overlap between FAILED_PRECONDITION and OUT_OF_RANGE. We recommend
* using OUT_OF_RANGE (the more specific error) when it applies so that callers who are
* iterating through a space can easily look for an OUT_OF_RANGE error to detect when they are
* done.
*
* @since 0.1.0
* The operation has been validated by an Application developers or Operator to have completed
* successfully.
*/
OUT_OF_RANGE(11),

/**
* Operation is not implemented or not supported/enabled in this service.
*
* @since 0.1.0
*/
UNIMPLEMENTED(12),

/**
* Internal errors. Means some invariants expected by underlying system has been broken. If you
* see one of these errors, something is very broken.
*
* @since 0.1.0
*/
INTERNAL(13),

/**
* The service is currently unavailable. This is a most likely a transient condition and may be
* corrected by retrying with a backoff.
*
* <p>See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE.
*
* @since 0.1.0
*/
UNAVAILABLE(14),
OK(0),

/**
* Unrecoverable data loss or corruption.
*
* @since 0.1.0
*/
DATA_LOSS(15),
/** The default status. */
UNSET(1),

/**
* The request does not have valid authentication credentials for the operation.
*
* @since 0.1.0
*/
UNAUTHENTICATED(16);
/** The operation contains an error. */
ERROR(2);

private final int value;

Expand All @@ -225,14 +79,14 @@ public int value() {
* @since 0.1.0
*/
public Status toStatus() {
return STATUS_LIST.get(value);
return STATUSES_BY_VALUE.get(value);
}
}

// Create the canonical list of Status instances indexed by their code values.
private static final List<Status> STATUS_LIST = buildStatusList();
private static final Map<Integer, Status> STATUSES_BY_VALUE = buildStatusList();

private static List<Status> buildStatusList() {
private static Map<Integer, Status> buildStatusList() {
TreeMap<Integer, Status> canonicalizer = new TreeMap<>();
for (CanonicalCode code : CanonicalCode.values()) {
Status replaced = canonicalizer.put(code.value(), new Status(code, null));
Expand All @@ -244,133 +98,22 @@ private static List<Status> buildStatusList() {
+ code.name());
}
}
return Collections.unmodifiableList(new ArrayList<>(canonicalizer.values()));
return Collections.unmodifiableMap(canonicalizer);
}

// A pseudo-enum of Status instances mapped 1:1 with values in CanonicalCode. This simplifies
// construction patterns for derived instances of Status.
/**
* The operation completed successfully.
*
* @since 0.1.0
* The operation has been validated by an Application developers or Operator to have completed
* successfully.
*/
public static final Status OK = CanonicalCode.OK.toStatus();

/**
* The operation was cancelled (typically by the caller).
*
* @since 0.1.0
*/
public static final Status CANCELLED = CanonicalCode.CANCELLED.toStatus();

/**
* Unknown error. See {@link CanonicalCode#UNKNOWN}.
*
* @since 0.1.0
*/
public static final Status UNKNOWN = CanonicalCode.UNKNOWN.toStatus();

/**
* Client specified an invalid argument. See {@link CanonicalCode#INVALID_ARGUMENT}.
*
* @since 0.1.0
*/
public static final Status INVALID_ARGUMENT = CanonicalCode.INVALID_ARGUMENT.toStatus();

/**
* Deadline expired before operation could complete. See {@link CanonicalCode#DEADLINE_EXCEEDED}.
*
* @since 0.1.0
*/
public static final Status DEADLINE_EXCEEDED = CanonicalCode.DEADLINE_EXCEEDED.toStatus();

/**
* Some requested entity (e.g., file or directory) was not found.
*
* @since 0.1.0
*/
public static final Status NOT_FOUND = CanonicalCode.NOT_FOUND.toStatus();

/**
* Some entity that we attempted to create (e.g., file or directory) already exists.
*
* @since 0.1.0
*/
public static final Status ALREADY_EXISTS = CanonicalCode.ALREADY_EXISTS.toStatus();

/**
* The caller does not have permission to execute the specified operation. See {@link
* CanonicalCode#PERMISSION_DENIED}.
*
* @since 0.1.0
*/
public static final Status PERMISSION_DENIED = CanonicalCode.PERMISSION_DENIED.toStatus();

/**
* The request does not have valid authentication credentials for the operation.
*
* @since 0.1.0
*/
public static final Status UNAUTHENTICATED = CanonicalCode.UNAUTHENTICATED.toStatus();

/**
* Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system
* is out of space.
*
* @since 0.1.0
*/
public static final Status RESOURCE_EXHAUSTED = CanonicalCode.RESOURCE_EXHAUSTED.toStatus();

/**
* Operation was rejected because the system is not in a state required for the operation's
* execution. See {@link CanonicalCode#FAILED_PRECONDITION}.
*
* @since 0.1.0
*/
public static final Status FAILED_PRECONDITION = CanonicalCode.FAILED_PRECONDITION.toStatus();

/**
* The operation was aborted, typically due to a concurrency issue like sequencer check failures,
* transaction aborts, etc. See {@link CanonicalCode#ABORTED}.
*
* @since 0.1.0
*/
public static final Status ABORTED = CanonicalCode.ABORTED.toStatus();

/**
* Operation was attempted past the valid range. See {@link CanonicalCode#OUT_OF_RANGE}.
*
* @since 0.1.0
*/
public static final Status OUT_OF_RANGE = CanonicalCode.OUT_OF_RANGE.toStatus();
/** The default status. */
public static final Status UNSET = CanonicalCode.UNSET.toStatus();

/**
* Operation is not implemented or not supported/enabled in this service.
*
* @since 0.1.0
*/
public static final Status UNIMPLEMENTED = CanonicalCode.UNIMPLEMENTED.toStatus();

/**
* Internal errors. See {@link CanonicalCode#INTERNAL}.
*
* @since 0.1.0
*/
public static final Status INTERNAL = CanonicalCode.INTERNAL.toStatus();

/**
* The service is currently unavailable. See {@link CanonicalCode#UNAVAILABLE}.
*
* @since 0.1.0
*/
public static final Status UNAVAILABLE = CanonicalCode.UNAVAILABLE.toStatus();

/**
* Unrecoverable data loss or corruption.
*
* @since 0.1.0
*/
public static final Status DATA_LOSS = CanonicalCode.DATA_LOSS.toStatus();
/** The operation contains an error. */
public static final Status ERROR = CanonicalCode.ERROR.toStatus();

// The canonical code of this message.
private final CanonicalCode canonicalCode;
Expand Down Expand Up @@ -419,13 +162,22 @@ public String getDescription() {
}

/**
* Returns {@code true} if this {@code Status} is OK, i.e., not an error.
* Returns {@code true} if this {@code Status} is UNSET, i.e., not an error.
*
* @return {@code true} if this {@code Status} is OK.
* @since 0.1.0
* @return {@code true} if this {@code Status} is UNSET.
*/
public boolean isUnset() {
return CanonicalCode.UNSET == canonicalCode;
}

/**
* Returns {@code true} if this {@code Status} is ok, i.e., status is not set, or has been
* overridden to be ok by an operator.
*
* @return {@code true} if this {@code Status} is OK or UNSET.
*/
public boolean isOk() {
return CanonicalCode.OK == canonicalCode;
return isUnset() || CanonicalCode.OK == canonicalCode;
}

/**
Expand Down
Loading

0 comments on commit 287eae9

Please sign in to comment.