|
| 1 | +# OpenTelemetry Java Instrumentation |
| 2 | + |
| 3 | +OpenTelemetry Java Instrumentation is a Java agent that provides automatic instrumentation for a wide variety of libraries and frameworks. It dynamically injects bytecode to capture telemetry data without requiring code changes. |
| 4 | + |
| 5 | +Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. |
| 6 | + |
| 7 | +## Working Effectively |
| 8 | +- Bootstrap, build, and test the repository: |
| 9 | + - Use Java 21 for building (required, see `.java-version`) |
| 10 | + - Configuration phase: Takes 60-90 seconds due to ~500+ modules (normal). NEVER CANCEL. |
| 11 | + - `./gradlew assemble` -- builds the complete Java agent. NEVER CANCEL. Build takes 20-45 minutes. Set timeout to 60+ minutes. |
| 12 | + - `./gradlew check javadoc sourcesJar -x spotlessCheck -PskipTests=true` -- builds with checks but skips tests for faster iteration |
| 13 | + - The Java agent artifact will be at: `javaagent/build/libs/opentelemetry-javaagent-<version>.jar` |
| 14 | +- For faster local development, add `removeJarVersionNumbers=true` to `~/.gradle/gradle.properties` to keep consistent jar names |
| 15 | +- Run tests: |
| 16 | + - `./gradlew test` -- runs all tests. NEVER CANCEL. Takes 60-120 minutes across multiple Java versions. Set timeout to 180+ minutes. |
| 17 | + - `./gradlew :instrumentation:test` -- runs instrumentation tests only |
| 18 | + - `./gradlew :smoke-tests:test` -- runs smoke tests (separate from main test suite) |
| 19 | + - `./gradlew test -PtestJavaVersion=<version>` -- test on specific Java version (8, 11, 17, 21, 23, 24, 25-ea) |
| 20 | + - `./gradlew test -PtestLatestDeps=true` -- test against latest dependency versions |
| 21 | + - `./gradlew test -Ddev=true -x spotlessCheck -x checkstyleMain` -- ignore warnings during development |
| 22 | +- Code quality: |
| 23 | + - `./gradlew spotlessCheck` -- NEVER CANCEL. Takes 10-20 minutes with ~500 modules. Set timeout to 30+ minutes. |
| 24 | + - `./gradlew spotlessApply` -- auto-fix formatting issues |
| 25 | + - `./gradlew generateLicenseReport --no-build-cache` -- update license information |
| 26 | + |
| 27 | +## Validation |
| 28 | +- ALWAYS run `./gradlew spotlessCheck` before committing or the CI (.github/workflows/build-common.yml) will fail |
| 29 | +- Build validation scenario: After successful build, verify the Java agent jar exists at `javaagent/build/libs/opentelemetry-javaagent-*.jar` |
| 30 | +- Test validation scenarios: |
| 31 | + - Run specific instrumentation tests: `./gradlew :instrumentation:<INSTRUMENTATION_NAME>:test --tests <TEST_CLASS>` |
| 32 | + - Always test with `./gradlew test -Ddev=true -x spotlessCheck -x checkstyleMain` to ignore warnings during development |
| 33 | +- Use build scans for debugging failures - check `build-scan.txt` after failed builds |
| 34 | +- ALWAYS manually test instrumentation changes by running the affected instrumentation's test suite |
| 35 | + |
| 36 | +## Common tasks |
| 37 | +The following are critical commands and patterns for working with this repository: |
| 38 | + |
| 39 | +### Required Environment Setup |
| 40 | +- Java 21 is REQUIRED for building (see `.java-version`) |
| 41 | +- Gradle 9.1.0 (provided via wrapper `./gradlew`) |
| 42 | +- Docker is required for some tests (smoke tests, instrumentation tests using testcontainers) |
| 43 | +- Node 16 for Vaadin tests (if working on Vaadin instrumentation) |
| 44 | + |
| 45 | +### Repository Structure |
| 46 | +Key directories: |
| 47 | +- `instrumentation/` - Contains all instrumentation modules (~500+ modules for different libraries) |
| 48 | +- `javaagent/` - Core Java agent implementation |
| 49 | +- `docs/` - Documentation including supported libraries list |
| 50 | +- `smoke-tests/` - End-to-end integration tests |
| 51 | +- `examples/` - Example extensions and distributions |
| 52 | +- `gradle-plugins/` - Custom Gradle plugins used by the build |
| 53 | +- `.github/workflows/` - CI/CD pipeline definitions |
| 54 | +- `settings.gradle.kts` - Contains ~649 lines with all module definitions |
| 55 | + |
| 56 | +### Working with Instrumentations |
| 57 | +- Each instrumentation is in `instrumentation/<library-name>/` |
| 58 | +- Structure: `<library>/<version>/<javaagent|library>/` (e.g., `instrumentation/spring/spring-boot-autoconfigure/`) |
| 59 | +- Test structure: Each instrumentation has separate test modules |
| 60 | +- Documentation generator: `./gradlew :instrumentation-docs:runAnalysis` updates `docs/instrumentation-list.yaml` |
| 61 | +- Telemetry collection: `./instrumentation-docs/collect.sh` runs tests to generate telemetry metadata |
| 62 | + |
| 63 | +### Build Performance Tips |
| 64 | +- Configuration phase takes 60-90 seconds due to large number of modules (~500+) - this is NORMAL |
| 65 | +- Gradle daemon startup adds 10-20 seconds on first run |
| 66 | +- Use `--no-parallel` for problematic builds |
| 67 | +- Use `--continue` to run all tests even if some fail |
| 68 | +- Build cache is enabled by default (`--build-cache`) for faster rebuilds |
| 69 | +- Use `./gradlew build --scan` for detailed build analysis (may fail due to network restrictions) |
| 70 | +- IntelliJ users: Use module unloading to reduce resource consumption with 500+ modules |
| 71 | + |
| 72 | +### Testing Patterns |
| 73 | +- Tests use multiple JVM versions: 8, 11, 17, 21, 23, 24, 25-ea |
| 74 | +- Tests run on both HotSpot and OpenJ9 VMs |
| 75 | +- Matrix testing: 4 test partitions × multiple Java versions × 2 VMs |
| 76 | +- Some tests require x86_64 architecture (use colima on ARM: `./instrumentation-docs/collect.sh`) |
| 77 | + |
| 78 | +### Common Issues and Solutions |
| 79 | +- Network connectivity issues: Some builds may fail if external repositories are unreachable |
| 80 | +- OutOfMemoryError: Increase Gradle daemon heap size: `org.gradle.jvmargs=-Xmx3g` in `gradle.properties` |
| 81 | +- ARM compatibility: Some instrumentation tests need x86_64, use colima for containerized testing |
| 82 | +- IDE setup: IntelliJ users should unload unused modules to reduce resource consumption |
| 83 | + |
| 84 | +### CI/CD Integration |
| 85 | +- Main workflow: `.github/workflows/build.yml` |
| 86 | +- Common checks: `.github/workflows/build-common.yml` (spotless, license, build, test matrix) |
| 87 | +- Tests run in 4 partitions for parallelization |
| 88 | +- Smoke tests run separately for different application servers (jetty, tomcat, wildfly, etc.) |
| 89 | + |
| 90 | +### Key Files to Check After Changes |
| 91 | +- Always run `./gradlew spotlessCheck` before committing or the CI will fail |
| 92 | +- Always regenerate documentation if adding/modifying instrumentations: `./gradlew :instrumentation-docs:runAnalysis` |
| 93 | +- Check license compliance: `./gradlew generateLicenseReport --no-build-cache` |
| 94 | +- Verify instrumentation list: `docs/instrumentation-list.yaml` |
| 95 | +- Update supported libraries docs: `docs/supported-libraries.md` |
| 96 | +- Run muzzle checks for specific instrumentation: `./gradlew :instrumentation:<module>:javaagent:muzzle` |
| 97 | + |
| 98 | +## Instrumentation Development Workflow |
| 99 | +1. Create/modify instrumentation in `instrumentation/<library>/<version>/<type>/` |
| 100 | +2. Add metadata in `metadata.yaml` if needed (see `instrumentation-docs/readme.md`) |
| 101 | +3. Write/update tests following existing patterns (see `docs/contributing/writing-instrumentation.md`) |
| 102 | +4. Run specific tests: `./gradlew :instrumentation:<library>:<version>:<type>:test` |
| 103 | +5. Run muzzle check: `./gradlew :instrumentation:<library>:<version>:javaagent:muzzle` |
| 104 | +6. Update documentation: `./gradlew :instrumentation-docs:runAnalysis` |
| 105 | +7. Validate with broader test suite: `./gradlew test -PtestJavaVersion=21` (faster than full matrix) |
| 106 | +8. Run formatting: `./gradlew spotlessApply` |
| 107 | +9. Final check: `./gradlew spotlessCheck` |
| 108 | + |
| 109 | +### Available Gradle Help Commands |
| 110 | +- `./gradlew help --task <task>` -- get detailed info about any task |
| 111 | +- `./gradlew tasks` -- list all available tasks (takes 2-3 minutes) |
| 112 | +- `./gradlew tasks --group Muzzle` -- list muzzle-specific tasks |
| 113 | +- `./gradlew projects` -- list all project modules (~500+) |
| 114 | + |
| 115 | +## Critical Build Time Warnings |
| 116 | +- **NEVER CANCEL** builds or tests - they legitimately take 20-180 minutes |
| 117 | +- Configuration phase: 1-2 minutes (normal due to 500+ modules in settings.gradle.kts) |
| 118 | +- Full build (`./gradlew assemble`): 20-45 minutes |
| 119 | +- Test suite (`./gradlew test`): 60-120 minutes (matrix of Java versions × VMs × test partitions) |
| 120 | +- Code formatting (`./gradlew spotlessCheck`): 10-20 minutes |
| 121 | +- Always set timeouts to 2x expected time to account for CI variability |
| 122 | +- Network issues may cause build failures due to unreachable external repositories |
| 123 | + |
| 124 | +## Environment Variables for Testing |
| 125 | +- `TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE` - Docker socket location |
| 126 | +- `TESTCONTAINERS_HOST_OVERRIDE` - Container-to-container communication host |
| 127 | +- `USE_LINUX_CONTAINERS=1` - Force Linux containers on Windows |
| 128 | +- Set `-Ddev=true` for development to ignore warnings in tests |
0 commit comments