Skip to content

feat(insight): add HttpExporter - #702

Draft
wangyb-A wants to merge 2 commits into
mainfrom
workflow-insight-http-exporter
Draft

feat(insight): add HttpExporter#702
wangyb-A wants to merge 2 commits into
mainfrom
workflow-insight-http-exporter

Conversation

@wangyb-A

Copy link
Copy Markdown
Contributor

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Issue Link, if available

Related: #679

Description

This adds HttpExporter to the Workflow Insight plugin. It sends one insight record to an HTTP endpoint as one request. It mirrors the JS HttpExporter so the two SDKs behave the same.

What it does:

  • Sends the record with POST or PUT. POST is the default.
  • Sets Content-Type: application/json. A caller may pass their own headers, including their own Content-Type. The caller's value wins. Header names are matched without caring about upper or lower case, so a lowercase content-type replaces the default instead of adding a second one. The endpoint receives exactly one Content-Type header.
  • Waits at most timeoutMs for the endpoint. The default is 10000 ms. A non-2xx reply throws.
  • Shapes the body with operationsFormat: ARRAY (the default) writes the operations array, BY_NAME writes the operationsByName map, BOTH writes both. render() builds the shape and export() sends it, sharing one path.

How it talks HTTP:

  • It uses the JDK's own java.net.http.HttpClient. This adds no new dependency. The client sits behind a small package-visible HttpSender seam so tests can inject a fake, the same way S3Exporter and CloudWatchLogsExporter allow a .client(...).
  • It never copies the server's response body into a log. A failure throws with the numeric status and a derived reason label only. This is on purpose: an arbitrary response body could carry sensitive server content.

No change to the SDK core or the Workflow Insight plugin wiring.

Demo/Screenshots

N/A. This is a backend Java change with no user-visible UI, so there is nothing to screenshot.

Checklist

  • I have filled out every section of the PR template
  • I have thoroughly tested this change

Testing

Unit Tests

Yes. HttpExporterTest (17 tests) covers, with a mock sender: default POST + Content-Type + array body + 10s timeout; PUT with a merged Authorization header; non-2xx throws; BY_NAME map; BOTH array + map; a configured timeout is applied; the caller's Content-Type overrides the default case-insensitively with no duplicate; and builder rejects a missing url, a non-http scheme, a non-absolute url, and a non-positive timeout.

Integration Tests

Transport-level tests run the real default JDK sender end to end against an in-process com.sun.net.httpserver.HttpServer: a POST returns 200 and the handler asserts method, Content-Type, and body; a 500 throws; a PUT with a custom Authorization header is received; the wire carries exactly one Content-Type when the caller overrides its casing; a connection to a dead loopback port throws IllegalStateException; and an interrupted export throws while restoring the thread's interrupt flag.

Examples

N/A. No new example is needed for a new exporter class; the plugin README's HttpExporter section documents customer usage.

Alex Wang added 2 commits September 9, 2026 23:39
Port the JS workflow-insight HttpExporter to Java: POST/PUT each
record to any HTTP(S) endpoint or webhook as application/json.

- Builder config mirrors the JS contract: url (required, validated
  absolute http/https), method (POST default / PUT), custom headers,
  timeoutMs (default 10000), operationsFormat (ARRAY/BY_NAME/BOTH),
  optional maxRecordSizeBytes (no default).
- Transport uses the JDK's own java.net.http.HttpClient, so no new
  dependency is added. An injectable HttpSender seam (default
  JdkHttpSender) makes the exporter mockable; render()/export() share
  one shaping path per the InsightExporter size-limiter contract.
- Non-2xx responses throw and are contained by the plugin's existing
  per-exporter isolation, so a bad endpoint never disrupts execution.
- Deterministic unit tests cover the mock seam and a real in-process
  com.sun.net.httpserver server; README documents the exporter.

No changes to sdk core or the WorkflowInsight plugin wiring.
Merge request headers case-insensitively so a caller-supplied
Content-Type of any casing overrides the default application/json
and yields exactly one header with no duplicate on the wire.

Add default JDK-sender transport-failure coverage: a connection
refusal (reserved-then-released loopback port, bounded timeout)
and thread interruption, both proving IllegalStateException; the
interruption test also asserts the interrupt flag is preserved.

Align HttpExporter Javadoc and README wording: Content-Type is a
default a caller may override. No response-body logging added.
@wangyb-A

Copy link
Copy Markdown
Contributor Author

Intent: Add an HttpExporter to the Workflow Insight plugin that POSTs/PUTs one insight record as JSON to a generic HTTP endpoint, mirroring the JS SDK's HttpExporter, using only the JDK HttpClient (no new dependency).
Not a goal: No retry/backoff, no response-body logging, no SDK-core or Workflow Insight wiring changes, and no promotion of a toBothWireMap() to core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant