Skip to content

Commit

Permalink
Adds performance testing framework
Browse files Browse the repository at this point in the history
  • Loading branch information
nickschuch committed Feb 27, 2024
1 parent 3722679 commit 4b0beb9
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 1 deletion.
55 changes: 55 additions & 0 deletions .github/workflows/performance-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: 📋 Performance Test

on:
pull_request:
types: [ synchronize, opened, reopened, ready_for_review ]

concurrency:
group: preview-${{ github.head_ref }}
cancel-in-progress: true

env:
K6_SCRIPTS_DIR: ./performance-testing/scripts
K6_SCENARIO: ./performance-testing/scenarios/basic.js
K6_RESULTS_DIR: ./performance-testing/results

jobs:
performance-test:
runs-on: ubuntu-latest

steps:
- name: ⬇️ Git clone the repository
uses: actions/checkout@v3

- name: 📁 Init
run: |
# Set permissions for checkout.
sudo chown -R 1000:1000 $(pwd)
# Create performance testing results directory.
sudo mkdir -p ${K6_RESULTS_DIR}
sudo chmod 777 ${K6_RESULTS_DIR}
- name: 📦 Setup
run: |
OTEL_PHP_AUTOLOAD_ENABLED=false docker compose up -d --wait
docker compose exec php-cli composer install --prefer-dist
docker compose exec php-cli ./vendor/drush/drush/drush si demo_umami -y
- name: 🧪 K6 - Execute Baseline Performance Test
run: |
bash ${K6_SCRIPTS_DIR}/k6_run.sh ${K6_SCENARIO} ${K6_RESULTS_DIR} baseline.json
- name: ⚙️ Enable OTEL
run: |
docker compose stop
docker compose up -d --wait
- name: 🧪 K6 - Execute OpenTelemetry Enabled Performance Test
run: |
bash ${K6_SCRIPTS_DIR}/k6_run.sh ${K6_SCENARIO} ${K6_RESULTS_DIR} otel.json
- name: 📋 Review Test Results
run: |
BUDGET=200
bash ${K6_SCRIPTS_DIR}/review_results.sh ${K6_RESULTS_DIR}/baseline.json ${K6_RESULTS_DIR}/otel.json ${BUDGET}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/vendor/
/performance-testing/results
.idea
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
x-otel-common:
&otel-common
OTEL_PHP_AUTOLOAD_ENABLED: true
OTEL_PHP_AUTOLOAD_ENABLED: ${OTEL_PHP_AUTOLOAD_ENABLED:-true}
OTEL_SERVICE_NAME: drupal
OTEL_TRACES_EXPORTER: otlp
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: http/protobuf
Expand Down
16 changes: 16 additions & 0 deletions performance-testing/scenarios/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import http from "k6/http"
import { check } from "k6"

export default function () {
const baseURL = `http://127.0.0.1:8080/`

let cb = (Math.random() + 1).toString(36).substring(7);
let res = http.get(http.url`${baseURL}/en/articles?cache-buster=${cb}`)
if (
!check(res, {
'ok': (res) => res.status == 200,
})
) {
fail('status code was *not* 200');
}
}
7 changes: 7 additions & 0 deletions performance-testing/scripts/k6_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

SCENARIO=$1
SUMMARY_EXPORT_DIRECTORY=$2
SUMMARY_EXPORT_FILE_NAME=$3

docker run --rm --network=host -v ${SUMMARY_EXPORT_DIRECTORY}:/results -i docker.io/grafana/k6 run - --summary-export=/results/${SUMMARY_EXPORT_FILE_NAME} --vus 2 --duration 30s < ${SCENARIO}
61 changes: 61 additions & 0 deletions performance-testing/scripts/review_results.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

#/ Usage: review_results.sh path/to/baseline.json path/to/otel.json 200
#/ Description: A script to reviewing and failing if we go over our performance budget
#/ Options:
#/ --help: Display this help message
usage() { grep '^#/' "$0" | cut -c4- ; exit 0 ; }
expr "$*" : ".*--help" > /dev/null && usage

echoerr() { printf "%s\n" "$*" >&2 ; }
info() { echoerr "[INFO] $*" ; }
warning() { echoerr "[WARNING] $*" ; }
error() { echoerr "[ERROR] $*" ; }
fatal() { echoerr "[FATAL] $*" ; exit 1 ; }

if [[ "${BASH_SOURCE[0]}" = "$0" ]]; then
BASELINE_FILE=$1
OTEL_FILE=$2
BUDGET=$3

info "Starting performance review..."

fails_baseline=$(cat ${BASELINE_FILE} | jq -r .root_group.checks.ok.fails)
fails_otel=$(cat ${OTEL_FILE} | jq -r .root_group.checks.ok.fails)

# Convert to integer.
fails_baseline=${fails_baseline%.*}
fails_otel=${fails_otel%.*}

if (( $fails_baseline > 5 )); then
fatal "Too many checks failed in the baseline performance test ($fails_baseline)"
fi

if (( $fails_otel > 5 )); then
fatal "Too many checks failed in the opentelemetry performance test ($fails_otel)"
fi

http_req_duration_baseline=$(cat ${BASELINE_FILE} | jq -r .metrics.http_req_duration.avg)
http_req_duration_otel=$(cat ${OTEL_FILE} | jq -r .metrics.http_req_duration.avg)

# Convert to integer.
http_req_duration_baseline=${http_req_duration_baseline%.*}
http_req_duration_otel=${http_req_duration_otel%.*}

info "http_req_duration = ${http_req_duration_baseline}"
info "http_req_duration with otel enabled= ${http_req_duration_otel}"

if (( $http_req_duration_baseline > $http_req_duration_otel )); then
fatal "OpenTelemetry is more performant than with it off. This cannot be! See output above for stats."
fi

http_req_duration_diff=`expr $http_req_duration_otel - $http_req_duration_baseline`

info "http_req_duration diff = ${http_req_duration_diff}"

if (( $http_req_duration_diff > $BUDGET )); then
fatal "We have failed our performance budget (${http_req_duration_diff} > ${BUDGET})"
fi
fi

0 comments on commit 4b0beb9

Please sign in to comment.