Conversation
…nning outside of docker
📝 WalkthroughWalkthroughAdds an opt-in local OpenTelemetry observability setup: new Gradle tasks to run the backend with the OTEL Java agent, a Docker Compose file defining the observability stack (tempo, otel-collector, loki, promtail, prometheus, grafana, postgres, redis), and updated docs describing two setup options and verification steps. Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer (local)
participant Gradle as Gradle Task
participant App as Backend App
participant OTEL as OTEL Collector
participant Tempo as Tempo
participant Grafana as Grafana
Dev->>Gradle: ./gradlew server-app:bootRunWithObservability
Gradle->>Gradle: ensure `copyOtelAgent` executed
Gradle->>App: set JVM arg -javaagent=buildDir/otel/opentelemetry-javaagent.jar and env vars
Dev->>OTEL: docker compose -f docker/docker-compose.local-observability-stack-dev.yaml up
App->>OTEL: send traces/metrics/logs
OTEL->>Tempo: forward traces
OTEL->>Grafana: forward metrics/logs (via Prometheus/Loki)
Grafana->>Dev: visualize traces/metrics/logs
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (beta)
No actionable comments were generated in the recent review. 🎉 Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@backend/app/build.gradle`:
- Around line 309-342: The bootRunWithObservability task currently only sets
OTEL_* environment vars in doFirst, but bootRun reads
System.getenv("OTEL_JAVAAGENT_ENABLED") at configuration time so the Java agent
never gets added; update bootRunWithObservability (and/or its doFirst block) to
explicitly append the javaagent JVM arg to bootRun.jvmArgs (e.g., add
"-javaagent:<path-to-opentelemetry-javaagent.jar>") so the agent is attached to
the JVM that runs the app, while keeping the existing environment(...) OTEL
settings; reference the bootRunWithObservability task and the bootRun.jvmArgs
property when making this change.
In `@docs/observability/README.md`:
- Around line 34-37: Update the "Method" column entry that currently reads
`./gradlew server-app:bootRun` to match the actual command used (`./gradlew
server-app:bootRunWithObservability`) in the table row where the How cell
contains `./gradlew server-app:bootRunWithObservability
--args='--spring.profiles.active=dev'`, so the Method label and the command
string are consistent.
🧹 Nitpick comments (2)
docker/docker-compose.local-observability-stack-dev.yaml (1)
79-103: Consider limiting Grafana exposure when anonymous admin is enabled.
Binding the UI to localhost reduces accidental LAN exposure while keeping the dev UX intact.🛠️ Suggested hardening
- - "3000:3000" + - "127.0.0.1:3000:3000"docs/local-observability-stack/1_Setting_Up_the_Tracing_Stack.md (1)
59-91: Drop the redundant--argsfor the dev profile.
bootRunWithObservabilityalready sets--spring.profiles.active=dev, so repeating it is unnecessary.✏️ Suggested edit
-./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev' +./gradlew server-app:bootRunWithObservability
| | Method | Use Case | How | | ||
| |--------------------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| | `./gradlew server-app:bootRun` | Local development, quick iteration | `docker compose -f docker-compose.local-observability-stack-dev.yaml up -d && ./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev'` | | ||
| | Docker (full stack) | Testing the full stack, CI, production-like | `docker compose -f docker-compose.local-observability-stack.yaml up -d` | |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n docs/observability/README.md | head -50Repository: tolgee/tolgee-platform
Length of output: 3363
Align the "Method" label with the command shown.
The Method column shows ./gradlew server-app:bootRun, but the command uses ./gradlew server-app:bootRunWithObservability. Update the Method label to match.
✏️ Suggested edit
-| `./gradlew server-app:bootRun` | Local development, quick iteration | `docker compose -f docker-compose.local-observability-stack-dev.yaml up -d && ./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev'` |
+| `./gradlew server-app:bootRunWithObservability` | Local development, quick iteration | `docker compose -f docker-compose.local-observability-stack-dev.yaml up -d && ./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev'` |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | Method | Use Case | How | | |
| |--------------------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| | |
| | `./gradlew server-app:bootRun` | Local development, quick iteration | `docker compose -f docker-compose.local-observability-stack-dev.yaml up -d && ./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev'` | | |
| | Docker (full stack) | Testing the full stack, CI, production-like | `docker compose -f docker-compose.local-observability-stack.yaml up -d` | | |
| | Method | Use Case | How | | |
| |-----------------------------------------------------|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| | |
| | `./gradlew server-app:bootRunWithObservability` | Local development, quick iteration | `docker compose -f docker-compose.local-observability-stack-dev.yaml up -d && ./gradlew server-app:bootRunWithObservability --args='--spring.profiles.active=dev'` | | |
| | Docker (full stack) | Testing the full stack, CI, production-like | `docker compose -f docker-compose.local-observability-stack.yaml up -d` | |
🤖 Prompt for AI Agents
In `@docs/observability/README.md` around lines 34 - 37, Update the "Method"
column entry that currently reads `./gradlew server-app:bootRun` to match the
actual command used (`./gradlew server-app:bootRunWithObservability`) in the
table row where the How cell contains `./gradlew
server-app:bootRunWithObservability --args='--spring.profiles.active=dev'`, so
the Method label and the command string are consistent.
gabrielshanahan
left a comment
There was a problem hiding this comment.
Just one nit, otherwise LGTM and ![]()
|
|
||
| // Copy OTEL agent to a predictable location for IntelliJ usage | ||
| // See: docs/observability/ | ||
| tasks.register('copyOtelAgent', Copy) { |
There was a problem hiding this comment.
I don't see this actually used anywhere - it should imho either be called as part of something, mentioned in the docs, or removed
There was a problem hiding this comment.
It's used by the IntelliJ IDEA runner in the other repo, though I'm not sure myself if it's required.
The previous approach set OTEL_JAVAAGENT_ENABLED via `environment` in a doFirst block, but bootRun's System.getenv() check runs at Gradle configuration time (before any task executes), so the javaagent flag was never added. Fix by adding jvmArgs directly in the doFirst block. Also clarify copyOtelAgent comment: it's a standalone helper for IntelliJ run configurations, not used by bootRun or bootRunWithObservability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rework it so it can be used as a drop in replacement for bootRun
66d2e1c to
0fdae14
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@backend/app/build.gradle`:
- Around line 301-310: The task 'copyOtelAgent' uses the deprecated buildDir;
change the destination to use the project layout API instead—replace the into
"${buildDir}/otel" usage with the layout.buildDirectory.dir("otel") (or an
equivalent DirectoryProvider) so the Copy task receives a modern
Directory/Provider; keep the rest of the task (from configurations.otelAgent,
rename, and the task name copyOtelAgent) unchanged.
🧹 Nitpick comments (1)
backend/app/build.gradle (1)
337-343: Convert environment variable names to uppercase with underscores for POSIX compliance and Spring Boot best practices.Environment variables with dots in their names are non-POSIX compliant and not portable across all systems. Spring Boot's own documentation explicitly recommends converting property names to uppercase with underscores: dots become underscores, dashes are removed, and everything is uppercased (e.g.,
spring.datasource.url→SPRING_DATASOURCE_URL). While Spring's relaxed binding may allow the current naming to work on some systems, this approach is inconsistent with the OTEL variables in the same file and deviates from Spring Boot's documented best practices.Use standard Spring Boot environment variable naming
// Database configuration (use Docker stack's PostgreSQL/Redis) - environment 'spring.datasource.url', 'jdbc:postgresql://localhost:5432/tolgee' - environment 'spring.datasource.username', 'tolgee' - environment 'spring.datasource.password', 'tolgee' - environment 'spring.redis.host', 'localhost' - environment 'spring.redis.port', '6379' - environment 'spring.redis.password', 'tolgee' - environment 'tolgee.postgres-autostart.enabled', 'false' + environment 'SPRING_DATASOURCE_URL', 'jdbc:postgresql://localhost:5432/tolgee' + environment 'SPRING_DATASOURCE_USERNAME', 'tolgee' + environment 'SPRING_DATASOURCE_PASSWORD', 'tolgee' + environment 'SPRING_REDIS_HOST', 'localhost' + environment 'SPRING_REDIS_PORT', '6379' + environment 'SPRING_REDIS_PASSWORD', 'tolgee' + environment 'TOLGEE_POSTGRES_AUTOSTART_ENABLED', 'false'
| // Copy OTEL agent JAR to a predictable location for manual IntelliJ run configuration. | ||
| // Not used by bootRun or bootRunWithObservability (they resolve the agent from Gradle's dependency cache). | ||
| // Usage: ./gradlew server-app:copyOtelAgent → build/otel/opentelemetry-javaagent.jar | ||
| // Then add -javaagent:backend/app/build/otel/opentelemetry-javaagent.jar to your IntelliJ VM options. | ||
| // See: docs/observability/ | ||
| tasks.register('copyOtelAgent', Copy) { | ||
| from configurations.otelAgent | ||
| into "${buildDir}/otel" | ||
| rename { 'opentelemetry-javaagent.jar' } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify Gradle project structure and task path
echo "=== Checking for settings.gradle files ==="
fd -t f 'settings\.gradle' --max-depth 3
echo -e "\n=== Checking settings.gradle content ==="
find . -maxdepth 3 -name 'settings.gradle*' -exec cat {} \;
echo -e "\n=== Checking backend directory structure ==="
ls -la backend/ 2>/dev/null | head -20
echo -e "\n=== Checking if server-app directory exists ==="
find . -maxdepth 3 -type d -name '*server*app*' -o -type d -name 'server-app'
echo -e "\n=== Checking for other Gradle task invocations ==="
rg 'gradlew.*copyOtelAgent|gradlew.*bootRun' --max-count 10Repository: tolgee/tolgee-platform
Length of output: 8912
🏁 Script executed:
#!/bin/bash
# Verify buildDir usage and deprecation
echo "=== Checking Gradle version and buildDir patterns ==="
grep -r "gradle\|buildDir\|layout.buildDirectory" gradle.properties settings.gradle 2>/dev/null | head -20
echo -e "\n=== Checking buildDir usage in build.gradle files ==="
rg 'buildDir|layout\.buildDirectory' backend/ --type gradle --max-count 15
echo -e "\n=== Checking environment variable naming in bootRun tasks ==="
rg 'environment.*SPRING|spring\.' backend/app/build.gradle -A 2 -B 2Repository: tolgee/tolgee-platform
Length of output: 2923
🏁 Script executed:
#!/bin/bash
# Verify the correct module naming in Gradle
echo "=== Checking gradle wrapper and build files ==="
find . -maxdepth 2 -name 'gradle.properties' -o -name 'build.gradle' | head -10 | xargs head -5
echo -e "\n=== Checking if 'app' module exists in backend ==="
test -f backend/app/build.gradle && echo "backend/app/build.gradle EXISTS" || echo "NOT FOUND"
echo -e "\n=== Checking gradle tasks available ==="
grep -E "tasks\.(register|create)" backend/app/build.gradle | grep -E 'copyOtel|bootRun' | head -5Repository: tolgee/tolgee-platform
Length of output: 561
Minor: Deprecated buildDir usage.
buildDir is deprecated in Gradle 7.1+ in favor of layout.buildDirectory. The comment and task path ./gradlew server-app:copyOtelAgent are correct as-is—the backend/app directory is mapped to the :server-app project in settings.gradle.
Suggested fix
tasks.register('copyOtelAgent', Copy) {
from configurations.otelAgent
- into "${buildDir}/otel"
+ into layout.buildDirectory.dir("otel")
rename { 'opentelemetry-javaagent.jar' }
}🤖 Prompt for AI Agents
In `@backend/app/build.gradle` around lines 301 - 310, The task 'copyOtelAgent'
uses the deprecated buildDir; change the destination to use the project layout
API instead—replace the into "${buildDir}/otel" usage with the
layout.buildDirectory.dir("otel") (or an equivalent DirectoryProvider) so the
Copy task receives a modern Directory/Provider; keep the rest of the task (from
configurations.otelAgent, rename, and the task name copyOtelAgent) unchanged.
Summary by CodeRabbit
New Features
Documentation