blob: 19e0d5d5c0d998ed84793b8f23afc0b07cb30a4b [file]
#!/bin/bash
################################################################################
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
#
# Sample JVM and system memory while integration tests run.
#
# Usage:
# ./itests/sample-it-memory.sh start [--target-dir itests/target] [--interval 30]
# ./itests/sample-it-memory.sh stop [--target-dir itests/target]
# ./itests/sample-it-memory.sh sample-once [--target-dir itests/target]
# ./itests/sample-it-memory.sh summarize [--target-dir itests/target]
# ./itests/sample-it-memory.sh operator-note [--target-dir itests/target] [--print-only]
# ./itests/sample-it-memory.sh verify [--target-dir itests/target]
# Started automatically by ./build.sh --integration-tests (disable with --no-memory-sampler).
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/it-run.sh disable=SC1091
source "$SCRIPT_DIR/lib/it-run.sh"
# shellcheck source=lib/it-run-memory.sh disable=SC1091
source "$SCRIPT_DIR/lib/it-run-memory.sh"
TARGET_DIR="$SCRIPT_DIR/target"
INTERVAL=30
SEARCH_PORT=""
PRINT_ONLY=false
COMMAND=""
usage() {
cat <<EOF
Usage: $0 <command> [options]
Commands:
start Run the sampler in the background until "stop" is called
stop Stop the background sampler and write memory-summary.txt
sample-once Print one TSV sample line to stdout
summarize Build memory-summary.txt from memory-samples.tsv
operator-note Write it-run-operator-note.txt from trace + test + memory data
verify Cross-platform sanity checks (macOS + Linux)
Options:
--target-dir DIR IT target directory (default: itests/target)
--interval SEC Sample interval in seconds for start (default: 30)
--port PORT Search engine HTTP port override
--print-only With operator-note: print to stdout instead of writing file
-h, --help Show this help
EOF
exit 1
}
parse_args() {
COMMAND="${1:-}"
shift || true
while [ $# -gt 0 ]; do
case "$1" in
--target-dir)
shift
TARGET_DIR="${1:-}"
;;
--interval)
shift
INTERVAL="${1:-30}"
;;
--port)
shift
SEARCH_PORT="${1:-}"
;;
--print-only)
PRINT_ONLY=true
;;
-h | --help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
shift
done
if [ -z "$COMMAND" ]; then
usage
fi
mkdir -p "$TARGET_DIR"
if [ -n "$SEARCH_PORT" ]; then
IT_SEARCH_PORT="$SEARCH_PORT"
export IT_SEARCH_PORT
fi
}
sampler_paths() {
SAMPLES_FILE="$TARGET_DIR/$IT_MEMORY_SAMPLES"
SUMMARY_FILE="$TARGET_DIR/$IT_MEMORY_SUMMARY"
PID_FILE="$TARGET_DIR/$IT_MEMORY_SAMPLER_PID"
STOP_FILE="$TARGET_DIR/$IT_MEMORY_SAMPLER_STOP"
LOG_FILE="$TARGET_DIR/$IT_MEMORY_SAMPLER_LOG"
}
sampler_loop() {
local interval="$1"
sampler_paths
it_memory_write_samples_header "$SAMPLES_FILE"
while [ ! -f "$STOP_FILE" ]; do
it_memory_sample_once "$TARGET_DIR" >> "$SAMPLES_FILE" || true
sleep "$interval"
done
}
cmd_start() {
sampler_paths
if [ -f "$PID_FILE" ]; then
existing_pid="$(cat "$PID_FILE" 2>/dev/null || true)"
if [ -n "$existing_pid" ] && kill -0 "$existing_pid" 2>/dev/null; then
echo "Memory sampler already running (pid $existing_pid)" >&2
exit 0
fi
rm -f "$PID_FILE"
fi
rm -f "$STOP_FILE"
it_memory_clear_sampler_cache "$TARGET_DIR"
it_memory_write_samples_header "$SAMPLES_FILE"
echo "# started $(date -u +%Y-%m-%dT%H:%M:%SZ) interval=${INTERVAL}s target=$TARGET_DIR" >> "$LOG_FILE"
(
sampler_loop "$INTERVAL"
) >> "$LOG_FILE" 2>&1 &
echo $! > "$PID_FILE"
echo "Memory sampler started (pid $(cat "$PID_FILE"), interval ${INTERVAL}s)"
echo "Samples: $SAMPLES_FILE"
}
cmd_stop() {
sampler_paths
if [ ! -f "$PID_FILE" ]; then
echo "Memory sampler is not running" >&2
cmd_summarize || true
return 0
fi
pid="$(cat "$PID_FILE" 2>/dev/null || true)"
touch "$STOP_FILE"
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
kill -TERM "$pid" 2>/dev/null || true
wait "$pid" 2>/dev/null || true
fi
rm -f "$PID_FILE" "$STOP_FILE"
echo "# stopped $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$LOG_FILE"
cmd_summarize || true
echo "Memory sampler stopped"
}
cmd_sample_once() {
sampler_paths
it_memory_write_samples_header "$SAMPLES_FILE"
it_memory_sample_once "$TARGET_DIR"
}
cmd_summarize() {
sampler_paths
if it_memory_summarize_samples "$SAMPLES_FILE" "$SUMMARY_FILE"; then
echo "Wrote $SUMMARY_FILE"
return 0
fi
echo "No memory samples to summarize in $SAMPLES_FILE" >&2
return 1
}
cmd_operator_note() {
if [ "$PRINT_ONLY" = true ]; then
it_generate_operator_note "$TARGET_DIR" "$SCRIPT_DIR"
return 0
fi
if it_write_operator_note_file "$TARGET_DIR" "$SCRIPT_DIR"; then
echo "Wrote $TARGET_DIR/$IT_OPERATOR_NOTE_FILE"
return 0
fi
echo "Could not generate operator note (missing $IT_RUN_TRACE in $TARGET_DIR)" >&2
return 1
}
cmd_verify() {
it_memory_verify "$TARGET_DIR" "$SCRIPT_DIR"
}
main() {
parse_args "$@"
case "$COMMAND" in
start) cmd_start ;;
stop) cmd_stop ;;
sample-once) cmd_sample_once ;;
summarize) cmd_summarize ;;
operator-note) cmd_operator_note ;;
verify) cmd_verify ;;
*)
echo "Unknown command: $COMMAND" >&2
usage
;;
esac
}
main "$@"