https://github.com/roebi/qf-fx-gui-lib-telemetry
OpenTelemetry instrumentation library for QFTest FX GUI Library performance measurement
https://github.com/roebi/qf-fx-gui-lib-telemetry
fx java telemetry
Last synced: about 2 months ago
JSON representation
OpenTelemetry instrumentation library for QFTest FX GUI Library performance measurement
- Host: GitHub
- URL: https://github.com/roebi/qf-fx-gui-lib-telemetry
- Owner: roebi
- License: mit
- Created: 2026-05-11T13:20:20.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-23T07:42:31.000Z (about 2 months ago)
- Last Synced: 2026-05-23T09:30:53.528Z (about 2 months ago)
- Topics: fx, java, telemetry
- Language: Java
- Homepage: https://central.sonatype.com/artifact/io.github.roebi/qf-fx-gui-lib-telemetry
- Size: 429 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# qf-fx-gui-lib-telemetry
OpenTelemetry instrumentation library for QFTest FX GUI Library performance measurement.
## Architecture
```Architecture
QFTest Server JVM (one per test run)
ServerTelemetry.init() -> ServerSpans.*
<-- agent protocol (black box) -->
Client JVM 1..N (one per SUT instance)
ClientTelemetry.init(clientId) -> ClientSpans.*
```
## The 5 Measurement Points
| # | Span name | JVM | Class |
| --- | --- | --- | --- |
| 1 | `resolver.lookup` | Server | `ServerSpans.resolverLookup()` |
| 2 | `agent.command.roundtrip` | Server | `ServerSpans.agentRoundTrip()` |
| 3 | `fx.queue.wait` | Client | `ClientSpans.startQueueWait()` |
| 4 | `fx.event.dispatch` | Client | `ClientSpans.fxEventDispatch()` |
| 5 | `fx.verification.wait` | Client | `ClientSpans.verificationWait()` |
Cross-JVM correlation is done via the `qf.step.id` attribute (not W3C trace propagation,
which cannot cross the QFTest agent protocol boundary).
## Prerequisites
- Java 21+
- Jaeger running locally (see below)
## Build
```bash
./gradlew build
./gradlew test
```
## Run Jaeger locally
```bash
podman run --rm -d \
--name jaeger \
-p 16686:16686 \
-p 4318:4318 \
jaegertracing/all-in-one:latest
```
Open [http://localhost:16686](http://localhost:16686) after the test run.
Note: this library uses OTLP/HTTP (port 4318), not gRPC (port 4317),
to keep the dependency tree simple.
## Usage - Server JVM
Call once during suite initialisation (resolver registration hook):
```java
// default endpoint: http://localhost:4318/v1/traces
ServerTelemetry.init();
// or custom endpoint:
ServerTelemetry.init("http://my-otel-collector:4318/v1/traces");
```
Instrument resolver lookup:
```java
try (ActiveSpan s = ServerSpans.resolverLookup(clientId, componentId, stepId)) {
return resolverRegistry.resolve(componentId);
} catch (Exception e) {
// s.recordException(e) is called automatically if you rethrow
throw e;
}
```
Instrument agent round-trip:
```java
try (ActiveSpan s = ServerSpans.agentRoundTrip(clientId, "click")) {
return agentChannel.sendAndAwaitAck(clientId, command);
}
```
Shutdown in suite teardown:
```java
ServerTelemetry.shutdown();
```
## Usage - Client JVM
Call once in your client-side init hook:
```java
ClientTelemetry.init(qftestClientId); // e.g. "MyApp_1"
```
Instrument Platform.runLater() queue wait + FX event dispatch:
```java
QueueWaitMark mark = ClientSpans.startQueueWait(componentId, stepId);
Platform.runLater(() -> {
mark.arrived(); // records fx.queue.wait_ms, ends that span
try (ActiveSpan s = ClientSpans.fxEventDispatch(componentId, stepId, eventType)) {
node.fireEvent(event);
}
});
```
Instrument verification / polling wait:
```java
try (VerificationSpan vs = ClientSpans.verificationWait(componentId, stepId)) {
while (!stateCondition.isMet()) {
vs.incrementPollCount();
Thread.sleep(pollIntervalMs);
}
}
// fx.verification.polls is recorded automatically on close
```
Shutdown when client is stopped:
```java
ClientTelemetry.shutdown();
```
## Interpreting Results in Jaeger
Search by tag `qf.step.id=` to correlate server and client spans for the same test step.
| Finding | Likely cause | Fix |
| --- | --- | --- |
| `resolver.lookup` slow | Linear scan of resolver list | HashMap by component type |
| `agent.command.roundtrip` slow | Serialization or IPC latency | Batch commands |
| `fx.queue.wait_ms` high | FAT overloaded | Reduce `runLater` frequency |
| `fx.event.dispatch` slow | Heavy scene graph traversal | Cache Node references |
| `fx.verification.polls` high | Poll interval too short | Adaptive backoff |
## Adding to Your Project
After building, the jar is at `build/libs/qf-fx-gui-lib-telemetry-1.0.0.jar`.
Add to your GUI Library's build:
```kotlin
// build.gradle.kts
dependencies {
implementation(files("libs/qf-fx-gui-lib-telemetry-1.0.0.jar"))
// OTel SDK + exporter (transitive via the lib, or declare explicitly)
}
```
## publish.yml Dependency audit gradlew dependencyCheckAnalyze
This product uses the NVD API but is not endorsed or certified by the NVD.