Repository: open-telemetry/opentelemetry-java
File: sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkSpan.java (Java)

Code before:
      this.status = StatusData.create(statusCode, description);
    }
    return this;
  }

  @Override
  public ReadWriteSpan recordException(Throwable exception) {
    recordException(exception, Attributes.empty());
    return this;
  }

  @Override
  public ReadWriteSpan recordException(Throwable exception, Attributes additionalAttributes) {
    if (exception == null) {
      return this;
    }
    if (additionalAttributes == null) {
      additionalAttributes = Attributes.empty();
    }

    int maxAttributeLength = spanLimits.getMaxAttributeValueLength();
    AttributesMap attributes =
        AttributesMap.create(
            spanLimits.getMaxNumberOfAttributes(), spanLimits.getMaxAttributeValueLength());

    AttributeUtil.addExceptionAttributes(
        exceptionAttributeResolver, maxAttributeLength, exception, attributes::put);

    additionalAttributes.forEach(attributes::put);

    addTimedEvent(
        ExceptionEventData.create(
            clock.now(), exception, attributes, attributes.getTotalAddedValues()));
    return this;
  }

  @Override
  public ReadWriteSpan updateName(String name) {
    if (name == null) {
      return this;
    }
    synchronized (lock) {
      if (!isModifiableByCurrentThread()) {
        logger.log(Level.FINE, "Calling updateName() on an ended Span.");
        return this;
      }
      this.name = name;
    }
    return this;
  }


Review comment (suggestion):
So the exception attributes are still resolved eagerly and the raw exception is also appended to the event?   I guess that's fine.  If someone wanted to they could have the resolver not render the `exception.stacktrace` attribute and have a processor add one on later.

Code after:
      this.status = StatusData.create(statusCode, description);
    }
    return this;
  }

  @Override
  public ReadWriteSpan recordException(Throwable exception) {
    recordException(exception, Attributes.empty());
    return this;
  }

  @Override
  public ReadWriteSpan recordException(Throwable exception, Attributes additionalAttributes) {
    if (exception == null) {
      return this;
    }
    if (additionalAttributes == null) {
      additionalAttributes = Attributes.empty();
    }

    int maxAttributeLength = spanLimits.getMaxAttributeValueLength();
    AttributesMap attributes =
        AttributesMap.create(
            spanLimits.getMaxNumberOfAttributes(), spanLimits.getMaxAttributeValueLength());

    exceptionAttributeResolver.setExceptionAttributes(
        attributes::putIfCapacity, exception, maxAttributeLength);

    additionalAttributes.forEach(attributes::put);

    addTimedEvent(
        ExceptionEventData.create(
            clock.now(), exception, attributes, attributes.getTotalAddedValues()));
    return this;
  }

  @Override
  public ReadWriteSpan updateName(String name) {
    if (name == null) {
      return this;
    }
    synchronized (lock) {
      if (!isModifiableByCurrentThread()) {
        logger.log(Level.FINE, "Calling updateName() on an ended Span.");
        return this;
      }
      this.name = name;
    }
    return this;
  }