|
1 | 1 | #!/usr/bin/env bash |
2 | | - |
3 | | -set +e # Disable exit on error |
| 2 | +# |
| 3 | +# CI entry point for the chaos harness. Thin wrapper around |
| 4 | +# utils/run-chaos-harness.sh — this file only supplies the CI-specific |
| 5 | +# caching paths (so repeated scheduled runs on the same runner reuse the |
| 6 | +# downloaded JDK/agent jar) and the fixed hs_err.log location the pipeline's |
| 7 | +# `artifacts:` block expects at the repo root. All the actual build/run logic |
| 8 | +# lives in the standalone script, which is also runnable by hand. |
4 | 9 |
|
5 | 10 | HERE="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" |
6 | 11 | ROOT="$( cd "${HERE}/../.." >/dev/null 2>&1 && pwd )" |
7 | 12 |
|
8 | | -RUNTIME=${1} |
9 | | -CONFIG=${2:-profiler+tracer} |
10 | | -ALLOCATOR=${3:-gmalloc} |
11 | | - |
12 | | -echo "Chaos run: runtime=${RUNTIME}s config=${CONFIG} allocator=${ALLOCATOR}" |
13 | | - |
14 | | -CHAOS_JDK="${CHAOS_JDK:-21.0.3-tem}" |
15 | | -# CHAOS_JDK uses sdkman notation (<version>-<dist>); extract major for Adoptium API. |
16 | | -JDK_MAJOR="${CHAOS_JDK%%.*}" |
17 | | -JDK_ARCH=$(uname -m | sed 's/x86_64/x64/') |
18 | | -JDK_INSTALL_DIR="/opt/jdk-${CHAOS_JDK}" |
19 | | - |
20 | | -if [ ! -x "${JDK_INSTALL_DIR}/bin/java" ]; then |
21 | | - TMP=$(mktemp -d) |
22 | | - DL_URL="https://api.adoptium.net/v3/binary/latest/${JDK_MAJOR}/ga/linux/${JDK_ARCH}/jdk/hotspot/normal/eclipse" |
23 | | - echo "Downloading JDK ${CHAOS_JDK} (major ${JDK_MAJOR}) from Adoptium..." |
24 | | - if ! curl -fsSL --max-time 300 "${DL_URL}" -o "${TMP}/jdk.tar.gz"; then |
25 | | - echo "FAIL:JDK ${CHAOS_JDK} download failed" >&2 |
26 | | - rm -rf "${TMP}" |
27 | | - exit 1 |
28 | | - fi |
29 | | - mkdir -p "${JDK_INSTALL_DIR}" |
30 | | - tar -xzf "${TMP}/jdk.tar.gz" -C "${JDK_INSTALL_DIR}" --strip-components=1 |
31 | | - rm -rf "${TMP}" |
32 | | -fi |
33 | | - |
34 | | -if [ ! -x "${JDK_INSTALL_DIR}/bin/java" ]; then |
35 | | - echo "FAIL:JDK ${CHAOS_JDK} not available after install" >&2 |
36 | | - exit 1 |
37 | | -fi |
38 | | -export JAVA_HOME="${JDK_INSTALL_DIR}" |
39 | | -export PATH="${JAVA_HOME}/bin:${PATH}" |
40 | | -ACTIVE_JDK=$(java -version 2>&1 | head -1) |
41 | | -# Check major version only — patch may differ from the Adoptium latest GA. |
42 | | -if ! echo "${ACTIVE_JDK}" | grep -qE "\"${JDK_MAJOR}\."; then |
43 | | - echo "FAIL:wrong JDK active (expected major ${JDK_MAJOR}, got: ${ACTIVE_JDK})" >&2 |
44 | | - exit 1 |
45 | | -fi |
46 | | - |
47 | | -# Resolve ddprof.jar: prefer local build artifact, fall back to Maven snapshot. |
48 | | -# Running mvn from /tmp avoids the empty pom.xml at the repo root. |
49 | | -DDPROF_JAR_LOCAL=$(ls "${ROOT}/ddprof-lib/build/libs/ddprof-"*.jar 2>/dev/null | head -1) |
50 | | -if [ -n "${DDPROF_JAR_LOCAL}" ] && [ -f "${DDPROF_JAR_LOCAL}" ]; then |
51 | | - DDPROF_JAR="${DDPROF_JAR_LOCAL}" |
52 | | - echo "Using local ddprof jar: ${DDPROF_JAR}" |
53 | | -else |
54 | | - if [ -z "${CURRENT_VERSION:-}" ]; then |
55 | | - echo "FAIL:CURRENT_VERSION is empty and no local jar found (get-versions dotenv missing)" >&2 |
56 | | - exit 1 |
57 | | - fi |
58 | | - echo "Local ddprof jar not found — downloading ${CURRENT_VERSION} from Maven snapshots" |
59 | | - (cd /tmp && mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:get \ |
60 | | - -DrepoUrl=https://central.sonatype.com/repository/maven-snapshots/ \ |
61 | | - -Dartifact=com.datadoghq:ddprof:${CURRENT_VERSION}) |
62 | | - DDPROF_JAR="/root/.m2/repository/com/datadoghq/ddprof/${CURRENT_VERSION}/ddprof-${CURRENT_VERSION}.jar" |
63 | | -fi |
64 | | - |
65 | | -if [ ! -f "${DDPROF_JAR}" ]; then |
66 | | - echo "FAIL:ddprof jar unavailable" >&2 |
67 | | - exit 1 |
68 | | -fi |
69 | | - |
70 | | -mkdir -p /var/lib/datadog |
71 | | -wget -q --timeout=120 --tries=3 -O /var/lib/datadog/dd-java-agent.jar 'https://dtdg.co/latest-java-tracer' |
72 | | - |
73 | | -# chaos.jar is produced once per pipeline by the chaos:build job (stresstest |
74 | | -# stage) and pulled here as an artifact. Fall back to an inline build if the |
75 | | -# artifact is absent (e.g. local repro outside CI). |
76 | | -CHAOS_JAR="${ROOT}/ddprof-stresstest/build/libs/chaos.jar" |
77 | | -if [ ! -f "${CHAOS_JAR}" ]; then |
78 | | - echo "chaos.jar artifact not present — building inline" |
79 | | - ( cd "${ROOT}" && ./gradlew :ddprof-stresstest:chaosJar -q ) |
80 | | -fi |
81 | | - |
82 | | -if [ ! -f "${CHAOS_JAR}" ]; then |
83 | | - echo "FAIL:chaos.jar unavailable" >&2 |
84 | | - exit 1 |
85 | | -fi |
86 | | - |
87 | | -# Patch dd-java-agent.jar with the locally built ddprof contents so the agent's |
88 | | -# (relocated) profiler classes match the version under test. |
89 | | -DD_AGENT_JAR=/var/lib/datadog/dd-java-agent.jar \ |
90 | | -DDPROF_JAR=${DDPROF_JAR} \ |
91 | | -OUTPUT_JAR=/var/lib/datadog/dd-java-agent-patched.jar \ |
92 | | -"${ROOT}/utils/patch-dd-java-agent.sh" |
93 | | - |
94 | | -if [ ! -f /var/lib/datadog/dd-java-agent-patched.jar ]; then |
95 | | - echo "FAIL:dd-java-agent patching failed" >&2 |
96 | | - exit 1 |
97 | | -fi |
98 | | - |
99 | | -PATCHED_AGENT=/var/lib/datadog/dd-java-agent-patched.jar |
100 | | - |
101 | | -case $CONFIG in |
102 | | - profiler) |
103 | | - echo "Running with profiler only" |
104 | | - ENABLEMENT="-Ddd.profiling.enabled=true -Ddd.trace.enabled=false" |
105 | | - # @Trace is a no-op without the tracer, so trace-context is excluded here. |
106 | | - ANTAGONISTS="thread-churn,alloc-storm,vthread-churn,classloader-churn,bounded-pool,context-hop,consumer-group,hidden-class-churn,direct-memory,weakref-wave,dump-storm" |
107 | | - ;; |
108 | | - profiler+tracer) |
109 | | - echo "Running with profiler and tracer" |
110 | | - ENABLEMENT="-Ddd.profiling.enabled=true -Ddd.trace.enabled=true" |
111 | | - ANTAGONISTS="thread-churn,alloc-storm,vthread-churn,classloader-churn,trace-context,bounded-pool,context-hop,consumer-group,hidden-class-churn,direct-memory,weakref-wave,dump-storm" |
112 | | - ;; |
113 | | - *) |
114 | | - echo "Unknown configuration: $CONFIG" |
115 | | - exit 1 |
116 | | - ;; |
117 | | -esac |
118 | | - |
119 | | -case $ALLOCATOR in |
120 | | - gmalloc) |
121 | | - echo "Running with gmalloc" |
122 | | - ;; |
123 | | - tcmalloc) |
124 | | - echo "Running with tcmalloc" |
125 | | - export LD_PRELOAD=$(find /usr/lib/ -name 'libtcmalloc_minimal.so.4') |
126 | | - # thread-churn/dump-storm antagonists cycle many short-lived threads; |
127 | | - # tcmalloc's defaults are slow to return their per-thread caches to the |
128 | | - # OS, which was inflating container RSS past the OOM limit on aarch64. |
129 | | - export TCMALLOC_RELEASE_RATE=10 |
130 | | - export TCMALLOC_AGGRESSIVE_DECOMMIT=1 |
131 | | - ;; |
132 | | - jemalloc) |
133 | | - echo "Running with jemalloc" |
134 | | - export LD_PRELOAD=$(find /usr/lib/ -name 'libjemalloc.so') |
135 | | - ;; |
136 | | - *) |
137 | | - echo "Unknown allocator: $ALLOCATOR" |
138 | | - echo "Valid values are: gmalloc, tcmalloc, jemalloc" |
139 | | - exit 1 |
140 | | - ;; |
141 | | -esac |
142 | | - |
143 | | -echo "LD_PRELOAD=$LD_PRELOAD" |
144 | | - |
145 | | -timeout "$((RUNTIME + 300))" \ |
146 | | -java -javaagent:${PATCHED_AGENT} \ |
147 | | - ${ENABLEMENT} \ |
148 | | - -Ddd.profiling.upload.period=10 \ |
149 | | - -Ddd.profiling.start-force-first=true \ |
150 | | - -Ddd.profiling.ddprof.liveheap.enabled=true \ |
151 | | - -Ddd.profiling.ddprof.alloc.enabled=true \ |
152 | | - -Ddd.profiling.ddprof.wall.enabled=true \ |
153 | | - -Ddd.profiling.ddprof.nativemem.enabled=true \ |
154 | | - -Ddd.env=java-profiler-stability \ |
155 | | - -Ddd.service=java-profiler-chaos \ |
156 | | - -Xmx2g -Xms2g \ |
157 | | - -XX:MaxMetaspaceSize=384m \ |
158 | | - -XX:ErrorFile=${HERE}/../../hs_err.log \ |
159 | | - -XX:OnError="${HERE}/../../dd_crash_uploader.sh %p" \ |
160 | | - -jar ${CHAOS_JAR} \ |
161 | | - --duration ${RUNTIME}s \ |
162 | | - --antagonists ${ANTAGONISTS} |
163 | | - |
164 | | -RC=$? |
165 | | -echo "RC=$RC" |
| 13 | +export CHAOS_JDK_DIR="${CHAOS_JDK_DIR:-/opt/jdk-${CHAOS_JDK}}" |
| 14 | +export CHAOS_WORK_DIR="${CHAOS_WORK_DIR:-/var/lib/datadog}" |
| 15 | +export CHAOS_ERROR_FILE="${ROOT}/hs_err.log" |
166 | 16 |
|
167 | | -if [ $RC -ne 0 ]; then |
168 | | - CRASH_MSG="Chaos harness crashed (RC=${RC})" |
169 | | - HS_ERR="${HERE}/../../hs_err.log" |
170 | | - if [ -f "${HS_ERR}" ]; then |
171 | | - SIG=$(grep -m1 '^siginfo:' "${HS_ERR}" 2>/dev/null | tr -d '\n' | cut -c1-120) |
172 | | - FRAME=$(grep -m1 'libjavaProfiler\|AsyncProfiler' "${HS_ERR}" 2>/dev/null | sed 's/^[[:space:]]*//' | tr -d '\n' | cut -c1-120) |
173 | | - [ -n "${SIG}" ] && CRASH_MSG="${CRASH_MSG};${SIG}" |
174 | | - [ -n "${FRAME}" ] && CRASH_MSG="${CRASH_MSG};${FRAME}" |
175 | | - fi |
176 | | - echo "FAIL:${CRASH_MSG}" >&2 |
177 | | - exit 1 |
178 | | -fi |
| 17 | +exec "${ROOT}/utils/run-chaos-harness.sh" "$@" |
0 commit comments