☕ Java Integration Guide
Learn how to instrument your Java applications with OpenTelemetry to send distributed traces to TraceKit.
Zero-Code Instrumentation!
Use the OpenTelemetry Java Agent for automatic instrumentation with ZERO code changes. Just add the agent at startup and everything is traced automatically.
Prerequisites
- • Java 8 or higher (Java 11+ recommended)
- • An active TraceKit account
- • A generated API key from the API Keys page
🔍 What Gets Traced Automatically?
With the Java Agent, these operations are traced automatically with ZERO code changes:
| Component | Setup | Auto-Traced? |
|---|---|---|
| HTTP Endpoints | Java Agent (zero code) | ✓ Yes |
| JDBC Queries | Java Agent (zero code) | ✓ Yes |
| HTTP Client Calls | Java Agent (zero code) | ✓ Yes |
| Spring Boot | Java Agent (zero code) | ✓ Yes |
| Kafka/RabbitMQ | Java Agent (zero code) | ✓ Yes |
| Custom Business Logic | Manual spans (optional) | Manual |
📦 Installation (Java Agent - Recommended)
Download the OpenTelemetry Java Agent - it provides automatic instrumentation with zero code changes:
# Download the latest OpenTelemetry Java Agent
curl -L https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar \
-o opentelemetry-javaagent.jar⚙️ Basic Setup (Java Agent)
Simply add the agent when starting your Java application:
java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=my-java-app \
-Dotel.exporter.otlp.endpoint={ appURL }/v1/traces \
-Dotel.exporter.otlp.headers=X-API-Key=your_api_key_here \
-Dotel.exporter.otlp.protocol=http/protobuf \
-jar your-application.jar
# That's it! Your app is now fully traced with zero code changes.That's it!
Your application is now fully instrumented with ZERO code changes!
🚀 Framework Integration
The Java Agent automatically instruments popular frameworks. No code changes needed!
Spring Boot
Your existing Spring Boot app works without changes:
// Your existing Spring Boot application - NO CHANGES NEEDED!
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public List<User> getUsers() {
// This endpoint is automatically traced!
return userService.findAll();
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// This endpoint is also automatically traced!
return userService.save(user);
}
}
// Just run with the Java Agent and everything is traced!Quarkus
Quarkus applications are automatically traced:
// Your existing Quarkus application - NO CHANGES NEEDED!
@Path("/api/users")
public class UserResource {
@Inject
UserService userService;
@GET
public List<User> list() {
// Automatically traced!
return userService.listAll();
}
@POST
public User create(User user) {
// Automatically traced!
return userService.save(user);
}
}⚡ Manual SDK Setup (Alternative)
If you prefer programmatic configuration instead of the Java Agent, you can use the SDK directly:
Maven Dependencies
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
<version>1.32.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
<version>1.32.0</version>
</dependency>
</dependencies>SDK Initialization
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
public class TracingConfig {
public static OpenTelemetry initializeOpenTelemetry(String serviceName) {
Resource resource = Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, serviceName
)));
OtlpHttpSpanExporter spanExporter = OtlpHttpSpanExporter.builder()
.setEndpoint("{ appURL }/v1/traces")
.addHeader("X-API-Key", System.getenv("TRACEKIT_API_KEY"))
.build();
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(spanExporter).build())
.setResource(resource)
.build();
return OpenTelemetrySdk.builder()
.setTracerProvider(tracerProvider)
.buildAndRegisterGlobal();
}
}🔧 Manual Instrumentation (Optional)
For custom business logic not automatically traced, you can manually create spans:
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
public class OrderService {
private static final Tracer tracer =
GlobalOpenTelemetry.getTracer("order-service");
public void processOrder(String orderId) {
// Start a parent span
Span span = tracer.spanBuilder("process_order")
.setAttribute("order.id", orderId)
.startSpan();
try (Scope scope = span.makeCurrent()) {
// Child spans automatically link to parent
validateOrder(orderId);
chargePayment(orderId);
span.setAttribute("order.status", "completed");
} finally {
span.end();
}
}
private void validateOrder(String orderId) {
Span span = tracer.spanBuilder("validate_order")
.setAttribute("order.id", orderId)
.startSpan();
try (Scope scope = span.makeCurrent()) {
// Validation logic here
} finally {
span.end();
}
}
}🔐 Environment Variables
Best practice: Store sensitive configuration in environment variables:
# .env or environment variables
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
OTEL_SERVICE_NAME=my-java-app
OTEL_EXPORTER_OTLP_ENDPOINT={ appURL }/v1/traces🏭 Production Configuration
Production Checklist
- • Use HTTPS/TLS for the OTLP endpoint
- • Store API keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault)
- • Set appropriate service names and versions
- • Configure resource attributes (deployment.environment, host.name, etc.)
- • Adjust sampling rates if needed for high-traffic services
- • Monitor Java Agent overhead (typically <5%)
🔧 Troubleshooting
Traces Not Appearing?
- Verify your API key is correct and not revoked
- Check the endpoint URL matches your TraceKit instance
- Ensure the Java Agent is loaded (check startup logs)
- Verify the -javaagent parameter is before -jar
- Check application logs for OpenTelemetry errors
✅ Complete Example
Here's a complete working Spring Boot example:
// Complete Spring Boot example - just run with the Java Agent!
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public List<User> getUsers() {
// Automatically traced - no code changes needed!
return userRepository.findAll();
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
// Automatically traced - no code changes needed!
return userRepository.save(user);
}
}
// Run with:
// java -javaagent:opentelemetry-javaagent.jar \
// -Dotel.service.name=spring-api \
// -Dotel.exporter.otlp.endpoint={ appURL }/v1/traces \
// -Dotel.exporter.otlp.headers=X-API-Key=$TRACEKIT_API_KEY \
// -jar target/myapp.jarYou're all set!
Your Java application is now sending traces to TraceKit. Visit the Dashboard to see your traces.
🚀 Next Steps
- • Explore your traces on the Traces page to identify performance bottlenecks
- • Optionally add custom spans for specific business logic you want to measure
- • Configure sampling for high-traffic services to reduce overhead
- • Set up alert rules to get notified when issues occur