#!/bin/bash # # Copyright (c) 2023 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 # Helper routines for generating JSON formatted results. declare -a json_result_array declare -a json_array_array JSON_TX_ONELINE="${JSON_TX_ONELINE:-}" JSON_URL="${JSON_URL:-}" # Generate a timestamp in nanoseconds since 1st Jan 1970 function timestamp_ns() { local t local s local n local ns t="$(date +%-s:%-N)" s=$(echo $t | awk -F ':' '{print $1}') n=$(echo $t | awk -F ':' '{print $2}') ns=$(echo "$s * 1000000000 + $n" | bc) echo $ns } # Generate a timestamp in milliseconds since 1st Jan 1970 function timestamp_ms() { echo $(($(date +%s%N)/1000000)) } # Initialise the json subsystem function metrics_json_init() { # collect kata-env data common_init # Clear out any previous results json_result_array=() despaced_name="$(echo ${TEST_NAME} | sed 's/[ \/]/-/g')" json_filename="${RESULT_DIR}/${despaced_name}.json" # get_kata_memory_and_vcpus() function measures the memory and the number of vcpus # from a kata container, and saves these values ​​in the variables: # 'MEASURED_CONTAINER_NUM_VCPUS' and 'MEASURED_CONTAINER_TOTAL_MEM' get_kata_memory_and_vcpus local json="$(cat << EOF "@timestamp" : $(timestamp_ms) EOF )" if [ "${CTR_RUNTIME}" == "io.containerd.kata.v2" ]; then metrics_json_add_fragment "$json" local json="$(cat << EOF "env" : { "RuntimeVersion": "${RUNTIME_VERSION}", "RuntimeCommit": "${RUNTIME_COMMIT}", "RuntimeConfig": "${RUNTIME_CONFIG_PATH}", "Hypervisor": "${HYPERVISOR_PATH}", "HypervisorVersion": "${HYPERVISOR_VERSION}", "Shim": "${SHIM_PATH}", "ShimVersion": "${SHIM_VERSION}", "machinename": "$(uname -n)", "SharedFs": "${SHARED_FS}", "ReqMemKB": "${REQ_MEMORY}", "ReqNumVcpus": "${REQ_NUM_VCPUS}", "MeasuredTotalMem": "${MEASURED_CONTAINER_TOTAL_MEM}", "MeasuredNumVcpus": "${MEASURED_CONTAINER_NUM_VCPUS}" } EOF )" fi metrics_json_add_fragment "$json" local json="$(cat << EOF "date" : { "ns": $(timestamp_ns), "Date": "$(date -u +"%Y-%m-%dT%T.%3N")" } EOF )" metrics_json_add_fragment "$json" local json="$(cat << EOF "test" : { "runtime": "${CTR_RUNTIME}", "testname": "${TEST_NAME}" } EOF )" if [ "$CTR_RUNTIME" == "io.containerd.kata.v2" ]; then metrics_json_add_fragment "$json" # Now add a runtime specific environment section if we can local iskata=$(is_a_kata_runtime "${RUNTIME}") if [ "$iskata" == "1" ]; then local rpath="$(command -v kata-runtime)" local json="$(cat << EOF "kata-env" : $($rpath kata-env --json) EOF )" fi fi if [ "${CTR_RUNTIME}" == "io.containerd.runc.v2" ]; then metrics_json_add_fragment "$json" local output=$(runc -v) local runcversion=$(grep version <<< "$output" | sed 's/runc version //') local runccommit=$(grep commit <<< "$output" | sed 's/commit: //') local json="$(cat << EOF "runc-env" : { "Version": { "Semver": "${runcversion}", "Commit": "${runccommit}" } } EOF )" fi metrics_json_end_of_system } # Save out the final JSON file function metrics_json_save() { if [ ! -d "${RESULT_DIR}" ];then mkdir -p "${RESULT_DIR}" fi local maxelem=$(( ${#json_result_array[@]} - 1 )) local json="$(cat << EOF { $(for index in $(seq 0 $maxelem); do # After the standard system data, we then place all the test generated # data into its own unique named subsection. if (( index == system_index )); then echo "\"${despaced_name}\" : {" fi if (( index != maxelem )); then echo "${json_result_array[$index]}," else echo "${json_result_array[$index]}" fi done) } } EOF )" echo "${json}" | jq . > "${json_filename}" # If we have a JSON URL or host/socket pair set up, post the results there as well. # Optionally compress into a single line. if [[ $JSON_TX_ONELINE ]]; then json="$(sed 's/[\n\t]//g' <<< ${json})" fi if [[ $JSON_HOST ]]; then echo "socat'ing results to [$JSON_HOST:$JSON_SOCKET]" socat -u - TCP:${JSON_HOST}:${JSON_SOCKET} <<< ${json} fi if [[ $JSON_URL ]]; then echo "curl'ing results to [$JSON_URL]" curl -XPOST -H"Content-Type: application/json" "$JSON_URL" -d "@-" <<< ${json} fi } function metrics_json_end_of_system() { system_index=$(( ${#json_result_array[@]})) } # Add a top level (complete) JSON fragment to the data function metrics_json_add_fragment() { local data=$1 # Place on end of array json_result_array[${#json_result_array[@]}]="$data" } # Prepare to collect up array elements function metrics_json_start_array() { json_array_array=() } # Add a (complete) element to the current array function metrics_json_add_array_element() { local data=$1 # Place on end of array json_array_array[${#json_array_array[@]}]="$data" } # Add a fragment to the current array element function metrics_json_add_array_fragment() { local data=$1 # Place on end of array json_array_fragments[${#json_array_fragments[@]}]="$data" } # Turn the currently registered array fragments into an array element function metrics_json_close_array_element() { local maxelem=$(( ${#json_array_fragments[@]} - 1 )) local json="$(cat << EOF { $(for index in $(seq 0 $maxelem); do if (( index != maxelem )); then echo "${json_array_fragments[$index]}," else echo "${json_array_fragments[$index]}" fi done) } EOF )" # And save that to the top level metrics_json_add_array_element "$json" # Reset the array fragment array ready for a new one json_array_fragments=() } # Close the current array function metrics_json_end_array() { local name=$1 local maxelem=$(( ${#json_array_array[@]} - 1 )) local json="$(cat << EOF "$name": [ $(for index in $(seq 0 $maxelem); do if (( index != maxelem )); then echo "${json_array_array[$index]}," else echo "${json_array_array[$index]}" fi done) ] EOF )" # And save that to the top level metrics_json_add_fragment "$json" }