Java
The OpenTelemetry Java agent with WizeLens defaults. N+1 queries, slow queries, SQL parameters, request bodies, and logs, with no code change.
Start with the agent
Java apps send to WizeLens through the OpenTelemetry Java agent. It traces Spring, servlets, JDBC, Hibernate, HTTP clients, Kafka, and more, with no code change.
curl -LO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
OTEL_SERVICE_NAME=orders-api \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5960 \
java -javaagent:opentelemetry-javaagent.jar -jar app.jar
That is enough for traces, logs (Logback, Log4j, and java.util.logging), and the insights: N+1 queries, N+1 HTTP
calls, slow queries, and database waits. The agent replaces SQL values with ?, so WizeLens cannot tell whether two
queries had the same values. It does not call them duplicates; the extension below brings them back.
Add the WizeLens extension
The extension is one jar that the agent loads. It sets the WizeLens defaults, keeps every trace with an error or a slow span when you sample, and turns on SQL parameters.
curl -L -o wizelens.jar https://repo1.maven.org/maven2/com/wizelens/wizelens/0.1.0-alpha.1/wizelens-0.1.0-alpha.1.jar
WIZELENS_HUB=http://localhost:5960 \
java -javaagent:opentelemetry-javaagent.jar -Dotel.javaagent.extensions=wizelens.jar \
-Dotel.service.name=orders-api -jar app.jar
What it sets (anything you set yourself with -D or OTEL_* wins):
| Setting | Value |
|---|---|
otel.exporter.otlp.endpoint |
WIZELENS_HUB, else http://localhost:5960 |
otel.exporter.otlp.headers |
Authorization=Bearer <WIZELENS_HUB_TOKEN> |
otel.traces.sampler |
parentbased_always_on: WizeLens samples at the end of the trace instead |
otel.instrumentation.jdbc.experimental.capture-query-parameters |
true (off with WIZELENS_CAPTURE_SQL_PARAMETERS=false) |
otel.instrumentation.http.server.capture-request-headers |
Common headers; authorization and cookie arrive redacted |
| Logback and Log4j attributes | MDC and code attributes on each log line |
| Resource | wizelens.project from WIZELENS_PROJECT |
Request and response bodies
Agents do not keep bodies. Add the library to your app and register its servlet filter:
<dependency>
<groupId>com.wizelens</groupId>
<artifactId>wizelens</artifactId>
<version>0.1.0-alpha.1</version>
</dependency>
@Bean
FilterRegistrationBean<WizeLensBodyFilter> wizelensBodies() {
return new FilterRegistrationBean<>(new WizeLensBodyFilter());
}
Then set WIZELENS_CAPTURE_BODY=true. The filter keeps text and JSON bodies, up to 16 KB each, on the request's server
span. JSON keys that look like secrets (password, token, ...) are redacted. The bodies show on the request's Headers
and Response tabs.
Settings
| Variable | Default | What it does |
|---|---|---|
WIZELENS_HUB |
http://localhost:5960 |
Hub or cloud address |
WIZELENS_HUB_TOKEN |
none | Hub token or cloud ingest key |
WIZELENS_PROJECT |
none | Project on a shared hub |
WIZELENS_SAMPLE_RATE |
1 |
Share of traces kept. See Sampling |
WIZELENS_KEEP_SLOW_MS |
1000 |
Keep traces with a span this slow at any rate (off for none) |
WIZELENS_KEEP_ERRORS |
true |
Keep traces with an error at any rate |
WIZELENS_CAPTURE_BODY |
false |
Request and response bodies |
WIZELENS_CAPTURE_SQL_PARAMETERS |
true |
SQL parameters |
WIZELENS_REDACT_KEYS |
none | More key fragments to redact, comma-separated |
WIZELENS_ENABLED |
true |
false turns the agent's SDK off |
Each also works as a system property: -Dwizelens.sample.rate=0.1.
A runnable sample
samples/java-spring is a Spring Boot service
with an H2 database. GET /orders shows N+1 queries, a duplicate query, and N+1 HTTP calls to the Python sample;
GET /report shows a slow query and a database wait; GET /fail shows an error with its log line.
mvn -f java install && mvn -f samples/java-spring package
WIZELENS_CAPTURE_BODY=true java -javaagent:opentelemetry-javaagent.jar \
-Dotel.javaagent.extensions=java/target/wizelens-0.1.0-alpha.1.jar \
-jar samples/java-spring/target/orders-java-0.0.0.jar
Run the Python and Go samples too, and one GET /orders crosses all three services.