open-feature / open-feature/java-sdk

EventDetails.fromProviderEventDetails drops errorCode, so API-level handlers never see it

Đang mở Phù hợp với người mới
#2,014 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Java
Star
128
Fork
61
Merge trung bình
5 giờ 57 phút
Pull request đã merge (30 ngày)
26

Mô tả

### Summary

`EventDetails.fromProviderEventDetails(...)` does not copy `errorCode`, so a handler
registered at API level — `OpenFeatureAPI.onProviderError(Consumer)` —
always sees `details.getErrorCode() == null`, even when the provider explicitly emitted
one.

`message`, `flagsChanged`, `providerName` and `eventMetadata` all arrive intact. Only
`errorCode` is lost, and it is lost silently: `EventDetails` extends
`ProviderEventDetails`, so `getErrorCode()` compiles and returns `null` rather than
failing to compile.

### Environment

- `dev.openfeature:sdk` **1.22.0**

### Steps to reproduce

Emit an error event carrying an explicit code from any `EventProvider` (here a probe
extending `InMemoryProvider`, which is already an `EventProvider`):

```java
probe.emitProviderError(ProviderEventDetails.builder()
.errorCode(ErrorCode.PROVIDER_NOT_READY)
.message("connect refused")
.build());
```

Log it from an API-level handler:

```java
OpenFeatureAPI.getInstance().onProviderError(details ->
log.error("event=PROVIDER_ERROR provider={} message={} error_code={}",
details.getProviderName(), details.getMessage(), details.getErrorCode()));
```

Observed:

```
event=PROVIDER_ERROR provider=InMemoryProvider message=connect refused error_code=null
```

`message` arrives, which rules out "the event never got delivered".

### Root cause

`EventDetails.fromProviderEventDetails(...)` is the only path from a provider-emitted
`ProviderEventDetails` to the `EventDetails` handed to API-level handlers, and its
builder chain simply does not mention `errorCode` (`EventDetails.java` on `main`):

```java
static EventDetails fromProviderEventDetails(
ProviderEventDetails providerEventDetails, String providerName, String domain) {
return builder()
.domain(domain)
.providerName(providerName)
.flagsChanged(providerEventDetails.getFlagsChanged())
.eventMetadata(providerEventDetails.getEventMetadata())
.message(providerEventDetails.getMessage())
.build();
}
```

`ProviderEventDetails` has four fields; three of them are copied. Decompiling 1.22.0
shows the same five-field builder chain, so the observed behaviour and the source agree,
and the two lines of evidence are independent of each other.

### Why it cannot be worked around

- API-level handlers receive `EventDetails`; the original `ProviderEventDetails` is not
reachable from there.
- There is no public way to observe a provider's events directly —
`EventProvider.setEventProviderListener` and `EventProvider.attach` are both
package-private.
- Recovering the code by parsing `message` is not viable: that text is entirely up to
each provider.

So until this is fixed, an application consuming provider events in Java has no error
code available at all.

### Note: the Go SDK does not drop it

`openfeature.EventDetails` in the Go SDK carries `ErrorCode` directly, so the
equivalent handler there does receive it. This is an SDK-level divergence between the
two implementations rather than a difference in how applications are written.

### Suggested fix

Add the missing line to the builder chain:

```java
.errorCode(providerEventDetails.getErrorCode())
```

One line, and I checked the two things that would have made it bigger than that.

**`errorCode` is the only field affected.** `ProviderEventDetails` declares exactly four
fields — `flagsChanged`, `message`, `eventMetadata`, `errorCode` — and the builder chain
transfers the first three. There is no second omission, so this is a missing line rather
than a conversion that needs realigning.

**Populating it does not make SDK-generated events ambiguous.** The events the SDK raises
itself build a `ProviderEventDetails` carrying no error code
(`OpenFeatureAPI.java:307` and `:320`), so their `getErrorCode()` stays `null` exactly as
it is today. The only thing that changes is that a code a provider explicitly set now
survives the conversion.

### Still present on `main`

Confirmed by reading the source at `5bf9f56`, not only the 1.22.0 bytecode:
`EventDetails.fromProviderEventDetails` still has no `.errorCode(...)` in its builder
chain, and all three call sites (`OpenFeatureAPI.java:531`, `:535`, `:543`) go through it.

Happy to open a PR.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Hướng nghiên cứu

Bắt đầu trong EventDetails.java tại fromProviderEventDetails và kiểm tra ba vị trí gọi trong OpenFeatureAPI.java. Tái hiện lỗi của provider bằng InMemoryProvider và xác minh rằng một ErrorCode tường minh đến được handler cấp API; hoàn tất có nghĩa là code được giữ nguyên, trong khi các event không có code này vẫn expose null.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
java
Lĩnh vực
api
Loại issue
Lỗi
Độ khó
1/5
Thời gian dự kiến
Dưới một giờ
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
88/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.