GuicedEE Telemetry
OpenTelemetry distributed tracing for GuicedEE using Guice AOP and OTLP exporters.
Core Concept
Annotate your classes and methods with @Trace and @SpanAttribute — the framework builds an OpenTelemetrySdk at startup, binds a TraceMethodInterceptor via Guice AOP, and exports spans and logs to any OTLP-compatible backend (Tempo, Jaeger, etc.) automatically.
Required Flow
- Add
com.guicedee:guiced-telemetrydependency. - Configure telemetry:
@TelemetryOptions( serviceName = "my-service", otlpEndpoint = "http://localhost:4318", serviceVersion = "1.0.0", deploymentEnvironment = "production" ) public class MyAppConfig {}Per-signal endpoints & automatic sub-paths.
otlpEndpointis treated as a base URL — the configurator appends the correct signal sub-path (/v1/traces,/v1/logs) automatically when it is missing, sohttp://localhost:4318andhttp://localhost:4318/v1/tracesboth work.Tempo/Jaeger are traces-only. Sending OTLP logs to a traces backend yields HTTP 404 on
/v1/logs. You have two correct options:- Disable log export:
@TelemetryOptions(exportLogs = false)(no log exporter, logger provider, or OTel Log4j2 appender is registered). Ship logs to Loki out-of-band (Grafana Alloy / Promtail). - Point logs at a logs backend: set
logsEndpoint(and optionallytracesEndpoint) to send each signal to a different collector, e.g.tracesEndpoint = "http://tempo:4318/v1/traces",logsEndpoint = "http://loki:3100/otlp/v1/logs".
Standard OTel env vars are honoured too:
OTEL_EXPORTER_OTLP_ENDPOINT(base, sub-path appended),OTEL_EXPORTER_OTLP_TRACES_ENDPOINT/OTEL_EXPORTER_OTLP_LOGS_ENDPOINT(full URLs, used verbatim). - Disable log export:
- Annotate methods to trace:
@Trace("place-order") public void placeOrder(@SpanAttribute("order.id") String orderId, @SpanAttribute("order.amount") double amount) { // span is created automatically } @Trace @SpanAttribute("result") public String processPayment(String paymentId) { return "success"; // return value recorded as "result" attribute } - Configure
module-info.java:module my.app { requires com.guicedee.telemetry; opens my.app.services to com.google.guice; } - Bootstrap GuicedEE — tracing starts automatically:
IGuiceContext.registerModuleForScanning.add("my.app"); IGuiceContext.instance().inject();
Tracing Annotations
@Trace
Creates an OpenTelemetry span around a method invocation.
- Custom name:
@Trace("fetch-users") - Default name:
ClassName.methodName - Class-level: traces all methods in the class
@SpanAttribute
Records method parameters or return values as span attributes.
- Supported types:
String,Boolean,Long,Double,Integer,Float - Complex objects serialized to JSON via Jackson
Uni support
When a @Trace method returns a Mutiny Uni, the span remains open until the Uni completes or fails.
Span propagation
Parent spans are propagated through GuicedEE's CallScoper. Nested @Trace methods create child spans automatically.
Configuration
@TelemetryOptions annotation
| Attribute | Purpose |
|---|---|
| enabled | Enable/disable tracing |
| serviceName | OpenTelemetry service name |
| otlpEndpoint | OTLP HTTP base endpoint (signal sub-path appended automatically) |
| tracesEndpoint | Optional full URL for spans (used verbatim); derives from base when blank |
| logsEndpoint | Optional full URL for logs (used verbatim); point at a logs backend, not Tempo |
| exportLogs | Set false for traces-only backends (Tempo) to skip OTLP log export entirely |
| serviceVersion | Service version resource attribute |
| deploymentEnvironment | Deployment environment attribute |
| useInMemoryExporters | In-memory exporters for unit testing |
| configureLogs | Enable Log4j2 OpenTelemetry appender |
| maxBatchSize | Batch span processor max batch size |
Environment variable overrides
Every @TelemetryOptions attribute can be overridden via system properties or environment variables.
Startup Flow
IGuiceContext.instance().inject()
└─ TelemetryPreStartup (scans for @TelemetryOptions)
└─ OpenTelemetrySDKConfigurator.initialize()
├─ Build Resource (service.name, version, environment, host)
├─ Create OTLP HTTP exporters (spans + logs)
├─ Build SdkTracerProvider + SdkLoggerProvider
├─ Set GlobalOpenTelemetry
└─ Register shutdown hook
└─ TraceModule (binds TraceMethodInterceptor for @Trace)
Testing
Use in-memory exporters for unit tests:
@TelemetryOptions(useInMemoryExporters = true)
public class TestConfig {}
Access InMemorySpanExporter and InMemoryLogRecordExporter to assert on captured spans.
Non-Negotiable Constraints
- Module must
requires com.guicedee.telemetry;. - Traced classes must be in packages opened to
com.google.guice. - Guice AOP requires non-final, non-private methods for interception.
- The telemetry module is registered automatically — no
providesneeded. - A JVM shutdown hook flushes pending spans automatically.