Repository: open-telemetry/opentelemetry-java
File: api/all/src/main/java/io/opentelemetry/api/trace/TraceFlags.java (Java)

Code before:
   */
  default boolean isTraceIdRandom() {
    return false;
  }

  /**
   * Returns the lowercase hex (base16) representation of this {@link TraceFlags}.
   *
   * @return the byte representation of the {@link TraceFlags}.
   */
  String asHex();

  /**
   * Returns the byte representation of this {@link TraceFlags}.
   *
   * @return the byte representation of the {@link TraceFlags}.
   */
  byte asByte();

  /**
   * Returns an instance of {@link TraceFlags} whose value is the result of a bitwise OR between
   * this object and the SAMPLED bit. This operation does not modify this object.
   *
   * @return a new {@link TraceFlags} object representing {@code this | SAMPLED_BIT}
   */
  default TraceFlags withSampledBit() {
    byte newByte = (byte) (asByte() | ImmutableTraceFlags.SAMPLED_BIT);
    return ImmutableTraceFlags.fromByte(newByte);
  }

  /**
   * Returns an instance of {@link TraceFlags} whose value is the result of a bitwise OR between
   * this object and the RANDOM_TRACE_ID bit. This operation does not modify this object.
   *
   * @return a new {@link TraceFlags} object representing {@code this | RANDOM_TRACE_ID_BIT}
   */
  default TraceFlags withRandomTraceIdBit() {
    byte newByte = (byte) (asByte() | ImmutableTraceFlags.RANDOM_TRACE_ID_BIT);
    return ImmutableTraceFlags.fromByte(newByte);
  }
}


Review comment (bug):
Taking another look at this, I think these need to be static helpers with signatures of the form `static TraceFlags with{Param}(TraceFlags traceFlags, boolean {param}) { ...}`.

The instance levels make for nice UX, but are overridable, which I believe is never needed and would lead to bad / hard-to-debug behavior.

Code after:
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.api.trace;

import javax.annotation.concurrent.Immutable;

/**
 * A valid trace flags is a byte or 2 character lowercase hex (base16) String.
 *
 * <p>These options are propagated to all child {@link Span spans}. These determine features such as
 * whether a {@code Span} should be traced.
 */
@Immutable
public interface TraceFlags {
  /**
   * Returns the length of the lowercase hex (base16) representation of the {@link TraceFlags}.
   *
   * @return the length of the lowercase hex (base16) representation of the {@link TraceFlags}.
   */
  static int getLength() {
    return ImmutableTraceFlags.HEX_LENGTH;
  }

  /**
   * Returns the default (with all flag bits off) byte representation of the {@link TraceFlags}.
   *
   * @return the default (with all flag bits off) byte representation of the {@link TraceFlags}.
   */
  static TraceFlags getDefault() {
    return ImmutableTraceFlags.DEFAULT;
  }

  /**
   * Returns the lowercase hex (base16) representation of the {@link TraceFlags} with the sampling
   * flag bit on.
   *
   * @return the lowercase hex (base16) representation of the {@link TraceFlags} with the sampling
   *     flag bit on.
   */
  static TraceFlags getSampled() {
    return ImmutableTraceFlags.SAMPLED;
  }

  /**
   * Returns the {@link TraceFlags} converted from the given lowercase hex (base16) representation.
   *
   * <p>This may throw runtime exceptions if the input is invalid.
   *
   * @param src the buffer where the hex (base16) representation of the {@link TraceFlags} is.
   * @param srcOffset the offset int buffer.
   * @return the {@link TraceFlags} converted from the given lowercase hex (base16) representation.
   */
  static TraceFlags fromHex(CharSequence src, int srcOffset) {
    return ImmutableTraceFlags.fromHex(src, srcOffset);
  }

  /**
   * Returns the {@link TraceFlags} converted from the given byte representation.
   *
   * @param traceFlagsByte the byte representation of the {@link TraceFlags}.
   * @return the {@link TraceFlags} converted from the given byte representation.
   */
  static TraceFlags fromByte(byte traceFlagsByte) {
    return ImmutableTraceFlags.fromByte(traceFlagsByte);
  }

  /**
   * Returns {@code true} if the sampling bit is on for this {@link TraceFlags}, otherwise {@code
   * false}.
   *
   * @return {@code true} if the sampling bit is on for this {@link TraceFlags}, otherwise {@code *
   *     false}.
   */
  boolean isSampled();

  /**
   * Returns {@code true} if the TraceId accompanying this {@link TraceFlags} is known to be
   * generated by a truly random Id generator, otherwise {@code false}. Providing default
   * implementation just to maintain compatibility.
   *
   * @return {@code true} if the randomTraceId bit is on for this {@link TraceFlags}, otherwise
   *     {@code false}.
   */
  default boolean isTraceIdRandom() {
    return false;
  }

  /**
   * Returns the lowercase hex (base16) representation of this {@link TraceFlags}.
   *
   * @return the byte representation of the {@link TraceFlags}.
   */
  String asHex();

  /**
   * Returns the byte representation of this {@link TraceFlags}.
   *
   * @return the byte representation of the {@link TraceFlags}.
   */
  byte asByte();

  /** Returns an instance of {@link TraceFlagsBuilder} for {@link TraceFlags}. */
  static TraceFlagsBuilder builder() {
    return ImmutableTraceFlags.DEFAULT;
  }
}