From fc4ea7b23a7c162833a07a3e139dccc34fe373c7 Mon Sep 17 00:00:00 2001 From: Benjamin Cane Date: Sat, 1 Jun 2024 13:00:19 -0700 Subject: [PATCH] Splitting to two functions and adding k6 --- .github/workflows/load.yml | 20 +- Makefile | 13 +- config/grafana/dashboards/default.json | 513 ++++++++++++++++++++----- config/prometheus.yml | 3 +- config/tarmac-basic.json | 21 + config/tarmac.json | 2 +- docker-compose.yml | 51 ++- tests/k6/script.js | 20 + tests/k6/soak.json | 25 ++ tests/k6/steady.json | 24 ++ tests/k6/stress.json | 47 +++ 11 files changed, 606 insertions(+), 133 deletions(-) create mode 100644 config/tarmac-basic.json create mode 100644 tests/k6/script.js create mode 100644 tests/k6/soak.json create mode 100644 tests/k6/steady.json create mode 100644 tests/k6/stress.json diff --git a/.github/workflows/load.yml b/.github/workflows/load.yml index 26851cf..a715a81 100644 --- a/.github/workflows/load.yml +++ b/.github/workflows/load.yml @@ -12,21 +12,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Run the Service - run: make run-background - - name: Wait for the Service to be ready - run: | - while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost/ready)" != "200" ]]; do sleep 5; done - - name: Configure Test - run: | - cat << EOF > loadtest-config.yml - url: http://localhost - payloadStr: '{"local_code":"PHX"}' - SLOs: - http/error-rate: 0 - http/latency-p99.9: 10 - EOF - - uses: iter8-tools/iter8-action@v1 - with: - chart: load-test-http - valuesFile: loadtest-config.yml + - name: Run load tests + run: make run-stress diff --git a/Makefile b/Makefile index 6e84494..6b83d47 100644 --- a/Makefile +++ b/Makefile @@ -24,16 +24,21 @@ tests: docker-compose: docker compose up -d mysql sleep 15 - docker compose up example + docker compose up data-manager lookup docker-compose-background: - docker compose up -d mysql - sleep 15 - docker compose up -d example run: build docker-compose run-nobuild: docker-compose run-background: build docker-compose-background +run-stress: + docker compose up -d mysql + sleep 15 + docker compose up data-manager lookup k6-stress --exit-code-from k6-stress +run-soak: + docker compose up -d mysql + sleep 15 + docker compose up data-manager lookup k6-soak --exit-code-from k6-soak clean: rm -rf functions/build diff --git a/config/grafana/dashboards/default.json b/config/grafana/dashboards/default.json index 6cd619e..03bcfd8 100644 --- a/config/grafana/dashboards/default.json +++ b/config/grafana/dashboards/default.json @@ -52,8 +52,8 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 27, - "gradientMode": "hue", + "fillOpacity": 25, + "gradientMode": "opacity", "hideFrom": { "legend": false, "tooltip": false, @@ -121,12 +121,12 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "sum by(path) (rate(http_server{path!=\"/metrics\"}[$__rate_interval]))", + "expr": "sum by(instance, path) (rate(http_server_count[$__rate_interval]))", "format": "time_series", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{path}}", "range": true, "refId": "A", "useBackend": false @@ -174,8 +174,9 @@ }, "id": 9, "options": { - "minVizHeight": 75, - "minVizWidth": 75, + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -184,8 +185,8 @@ "fields": "", "values": false }, - "showThresholdLabels": false, - "showThresholdMarkers": true + "textMode": "auto", + "wideLayout": true }, "pluginVersion": "10.2.2", "targets": [ @@ -194,16 +195,20 @@ "type": "prometheus", "uid": "PBFA97CFB590B2093" }, - "editorMode": "code", - "expr": "go_memstats_heap_inuse_bytes / 1024 / 1024", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(instance) (go_memstats_heap_inuse_bytes / 1024 / 1024)", + "fullMetaSearch": false, + "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}", "range": true, - "refId": "A" + "refId": "A", + "useBackend": false } ], "title": "Heap Used (in MB)", - "type": "gauge" + "type": "stat" }, { "datasource": { @@ -225,11 +230,11 @@ }, { "color": "#EAB839", - "value": 0.1 + "value": 1024 }, { "color": "red", - "value": 1 + "value": 4096 } ] } @@ -242,10 +247,11 @@ "x": 18, "y": 1 }, - "id": 8, + "id": 14, "options": { - "minVizHeight": 75, - "minVizWidth": 75, + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -254,8 +260,8 @@ "fields": "", "values": false }, - "showThresholdLabels": false, - "showThresholdMarkers": true + "textMode": "auto", + "wideLayout": true }, "pluginVersion": "10.2.2", "targets": [ @@ -264,16 +270,20 @@ "type": "prometheus", "uid": "PBFA97CFB590B2093" }, - "editorMode": "code", - "expr": "go_gc_duration_seconds{quantile=\"0.5\"}", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(process_cpu_seconds_total[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}", "range": true, - "refId": "A" + "refId": "A", + "useBackend": false } ], - "title": "Garbage Collection Duration (in sec)", - "type": "gauge" + "title": "CPU Usage", + "type": "stat" }, { "datasource": { @@ -293,7 +303,7 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 70, + "fillOpacity": 25, "gradientMode": "opacity", "hideFrom": { "legend": false, @@ -308,7 +318,7 @@ "type": "linear" }, "showPoints": "auto", - "spanNulls": false, + "spanNulls": true, "stacking": { "group": "A", "mode": "none" @@ -339,7 +349,7 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 12, "x": 0, "y": 9 @@ -348,6 +358,7 @@ "options": { "legend": { "calcs": [ + "lastNotNull", "min", "max", "mean" @@ -369,11 +380,11 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "avg by(path) (http_server{quantile=\"0.9\", path!=\"/metrics\"})", + "expr": "sum by(instance, path) (http_server{quantile=\"0.9\"})", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{path}}", "range": true, "refId": "A", "useBackend": false @@ -382,6 +393,106 @@ "title": "HTTP Response Time (in ms)", "type": "timeseries" }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(instance) (go_gc_duration_seconds{quantile=\"0.5\"})", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Garbage Collection Duration (in sec)", + "type": "timeseries" + }, { "datasource": { "type": "prometheus", @@ -391,7 +502,39 @@ "fieldConfig": { "defaults": { "color": { - "mode": "thresholds" + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } }, "mappings": [], "thresholds": { @@ -415,25 +558,23 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 5, "w": 12, "x": 12, - "y": 9 + "y": 14 }, "id": 7, "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "showThresholdLabels": false, - "showThresholdMarkers": true + "tooltip": { + "mode": "single", + "sort": "none" + } }, "pluginVersion": "10.2.2", "targets": [ @@ -448,14 +589,14 @@ "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}", "range": true, "refId": "A", "useBackend": false } ], "title": "Goroutines", - "type": "gauge" + "type": "timeseries" }, { "datasource": { @@ -475,7 +616,7 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 70, + "fillOpacity": 25, "gradientMode": "opacity", "hideFrom": { "legend": false, @@ -516,7 +657,7 @@ "h": 8, "w": 12, "x": 0, - "y": 17 + "y": 19 }, "id": 12, "options": { @@ -540,11 +681,11 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "sum by(tasks) (rate(scheduled_tasks_count[$__rate_interval]))", + "expr": "sum by(tasks, instance) (rate(scheduled_tasks_count[$__rate_interval]))", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{tasks}}", "range": true, "refId": "A", "useBackend": false @@ -561,7 +702,39 @@ "fieldConfig": { "defaults": { "color": { - "mode": "thresholds" + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } }, "mappings": [], "thresholds": { @@ -580,24 +753,20 @@ "h": 8, "w": 12, "x": 12, - "y": 17 + "y": 19 }, "id": 13, "options": { - "displayMode": "lcd", - "minVizHeight": 10, - "minVizWidth": 0, - "namePlacement": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "showUnfilled": true, - "valueMode": "color" + "tooltip": { + "mode": "single", + "sort": "none" + } }, "pluginVersion": "10.2.2", "targets": [ @@ -608,18 +777,18 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "avg by(tasks) (scheduled_tasks{quantile=\"0.9\"})", + "expr": "avg by(tasks, instance) (scheduled_tasks{quantile=\"0.9\"})", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{tasks}}", "range": true, "refId": "A", "useBackend": false } ], "title": "Scheduled Task Execution Time (in ms)", - "type": "bargauge" + "type": "timeseries" }, { "collapsed": false, @@ -627,7 +796,7 @@ "h": 1, "w": 24, "x": 0, - "y": 25 + "y": 27 }, "id": 10, "panels": [], @@ -641,6 +810,41 @@ }, "fieldConfig": { "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, "mappings": [], "thresholds": { "mode": "percentage", @@ -658,22 +862,20 @@ "h": 12, "w": 12, "x": 0, - "y": 26 + "y": 28 }, "id": 11, "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "showThresholdLabels": false, - "showThresholdMarkers": false + "tooltip": { + "mode": "single", + "sort": "none" + } }, "pluginVersion": "10.2.2", "targets": [ @@ -684,18 +886,19 @@ }, "disableTextWrap": false, "editorMode": "builder", - "expr": "sum by(route) (wasm_functions_count)", + "expr": "sum by(instance, route) (rate(wasm_functions_count[$__rate_interval]))", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "interval": "", + "legendFormat": "{{instance}}:{{route}}", "range": true, "refId": "A", "useBackend": false } ], "title": "Function Executions", - "type": "gauge" + "type": "timeseries" }, { "datasource": { @@ -716,7 +919,7 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 70, + "fillOpacity": 25, "gradientMode": "opacity", "hideFrom": { "legend": false, @@ -757,12 +960,13 @@ "h": 12, "w": 12, "x": 12, - "y": 26 + "y": 28 }, "id": 2, "options": { "legend": { "calcs": [ + "lastNotNull", "min", "max", "mean" @@ -786,17 +990,17 @@ "disableTextWrap": false, "editorMode": "builder", "exemplar": false, - "expr": "avg by(route) (wasm_functions{quantile=\"0.9\"})", + "expr": "avg by(instance, route) (wasm_functions{quantile=\"0.9\"})", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{route}}", "range": true, "refId": "A", "useBackend": false } ], - "title": "Average Function Execution Time (in ms)", + "title": "Function Execution Time (in ms)", "type": "timeseries" }, { @@ -805,7 +1009,7 @@ "h": 1, "w": 24, "x": 0, - "y": 38 + "y": 40 }, "id": 6, "panels": [], @@ -817,6 +1021,7 @@ "type": "prometheus", "uid": "PBFA97CFB590B2093" }, + "description": "", "fieldConfig": { "defaults": { "color": { @@ -830,7 +1035,105 @@ "axisPlacement": "auto", "barAlignment": 0, "drawStyle": "line", - "fillOpacity": 70, + "fillOpacity": 25, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 3, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(instance, callback) (rate(wasm_callbacks_count[$__rate_interval]))", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "interval": "", + "legendFormat": "{{instance}}:{{callback}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Callback Executions", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 25, "gradientMode": "opacity", "hideFrom": { "legend": false, @@ -859,7 +1162,7 @@ "mode": "percentage", "steps": [ { - "color": "orange", + "color": "green", "value": null } ] @@ -868,15 +1171,16 @@ "overrides": [] }, "gridPos": { - "h": 20, - "w": 24, - "x": 0, - "y": 39 + "h": 12, + "w": 12, + "x": 12, + "y": 41 }, - "id": 4, + "id": 16, "options": { "legend": { "calcs": [ + "lastNotNull", "min", "max", "mean" @@ -900,35 +1204,34 @@ "disableTextWrap": false, "editorMode": "builder", "exemplar": false, - "expr": "avg by(callback) (wasm_callbacks{quantile=\"0.9\", callback!~\"function.*\"})", + "expr": "avg by(instance, callback) (wasm_callbacks{quantile=\"0.9\"})", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, - "interval": "", - "legendFormat": "__auto", + "legendFormat": "{{instance}}:{{callback}}", "range": true, "refId": "A", "useBackend": false } ], - "title": "Function Callback Execution Time (in ms)", + "title": "Callback Execution Time (in ms)", "type": "timeseries" } ], - "refresh": "30s", + "refresh": "10s", "schemaVersion": 38, "tags": [], "templating": { "list": [] }, "time": { - "from": "now-30m", + "from": "now-5m", "to": "now" }, "timepicker": {}, "timezone": "browser", "title": "Airport Lookup Example", "uid": "f8799015-1473-42b7-87c0-625eb88ca1fa", - "version": 2, + "version": 1, "weekStart": "" } diff --git a/config/prometheus.yml b/config/prometheus.yml index 3cdbbb4..402c168 100644 --- a/config/prometheus.yml +++ b/config/prometheus.yml @@ -18,4 +18,5 @@ scrape_configs: scheme: http static_configs: - targets: - - example:8080 + - lookup:8080 + - data-manager:8080 diff --git a/config/tarmac-basic.json b/config/tarmac-basic.json new file mode 100644 index 0000000..d369faf --- /dev/null +++ b/config/tarmac-basic.json @@ -0,0 +1,21 @@ +{ + "services": { + "airport-lookup": { + "name": "airport-lookup", + "functions": { + "handler": { + "filepath": "/functions/handlers/lookup.wasm", + "pool_size": 1000 + } + }, + "routes": [ + { + "type": "http", + "path": "/", + "methods": ["POST"], + "function": "handler" + } + ] + } + } +} diff --git a/config/tarmac.json b/config/tarmac.json index b216439..b8a9155 100644 --- a/config/tarmac.json +++ b/config/tarmac.json @@ -34,7 +34,7 @@ { "type": "scheduled_task", "function": "load", - "frequency": 900 + "frequency": 300 }, { "type": "function", diff --git a/docker-compose.yml b/docker-compose.yml index e5110c8..b81c2a9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,15 +1,21 @@ version: '3.8' services: - example-basic: + lookup: + container_name: lookup image: madflojo/tarmac:unstable ports: - 80:8080 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"] + interval: 10s + timeout: 5s + retries: 3 environment: - "APP_ENABLE_TLS=false" - "APP_LISTEN_ADDR=0.0.0.0:8080" - "APP_DEBUG=false" - "APP_TRACE=false" - - "APP_WASM_FUNCTION_CONFIG=/config/tarmac.json" + - "APP_WASM_FUNCTION_CONFIG=/config/tarmac-basic.json" - "APP_ENABLE_SQL=true" - "APP_SQL_TYPE=mysql" - "APP_SQL_DSN=root:example@tcp(mysql:3306)/example" @@ -22,11 +28,18 @@ services: depends_on: - mysql - redis + - grafana - example: + data-manager: + container_name: data-manager image: madflojo/tarmac:unstable ports: - - 80:8080 + - 8080:8080 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health/ready"] + interval: 10s + timeout: 5s + retries: 3 environment: - "APP_ENABLE_TLS=false" - "APP_LISTEN_ADDR=0.0.0.0:8080" @@ -52,6 +65,11 @@ services: mysql: image: bitnami/mysql:latest restart: unless-stopped + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 3 environment: MYSQL_ROOT_PASSWORD: example MYSQL_DATABASE: example @@ -60,6 +78,11 @@ services: redis: image: bitnami/redis:latest restart: unless-stopped + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 3 environment: - ALLOW_EMPTY_PASSWORD=yes prometheus: @@ -87,6 +110,26 @@ services: - ./config/grafana/dashboards:/var/lib/grafana/dashboards depends_on: - prometheus + k6-stress: + image: grafana/k6 + container_name: k6 + volumes: + - ./tests:/tests + command: run --config /tests/k6/stress.json /tests/k6/script.js + depends_on: + - lookup + - data-manager + k6-soak: + image: grafana/k6 + container_name: k6 + volumes: + - ./tests:/tests + command: run --config /tests/k6/soak.json /tests/k6/script.js + depends_on: + - lookup + - data-manager + + volumes: prom_data: diff --git a/tests/k6/script.js b/tests/k6/script.js new file mode 100644 index 0000000..77d3954 --- /dev/null +++ b/tests/k6/script.js @@ -0,0 +1,20 @@ +import http from 'k6/http'; +import { check } from 'k6'; + +export default function () { + const url = 'http://lookup:8080/'; + const payload = JSON.stringify({ + "local_code": "PHX" + }); + + const params = { + headers: { + 'Content-Type': 'application/json', + }, + }; + + const res = http.post(url, payload, params); + check(res, { + 'status is 200': (r) => r.status === 200, + }); +} diff --git a/tests/k6/soak.json b/tests/k6/soak.json new file mode 100644 index 0000000..585f39a --- /dev/null +++ b/tests/k6/soak.json @@ -0,0 +1,25 @@ +{ + "hosts": { + "airport-lookup-example.com": "lookup", + "airport-data-manager.com": "data-manager" + }, + "stages": [ + { + "duration": "10m", + "target": 100 + }, + { + "duration": "2h", + "target": 100 + }, + { + "duration": "10m", + "target": 0 + } + ], + "thresholds": { + "http_req_duration": ["avg<100", "p(95)<200"] + }, + "noConnectionReuse": false, + "userAgent": "MyK6UserAgentString/1.0" +} diff --git a/tests/k6/steady.json b/tests/k6/steady.json new file mode 100644 index 0000000..2061ff6 --- /dev/null +++ b/tests/k6/steady.json @@ -0,0 +1,24 @@ +{ + "hosts": { + "airport-lookup-example.com": "lookup" + }, + "stages": [ + { + "duration": "10m", + "target": 5 + }, + { + "duration": "2h", + "target": 5 + }, + { + "duration": "10m", + "target": 0 + } + ], + "thresholds": { + "http_req_duration": ["avg<100", "p(95)<200"] + }, + "noConnectionReuse": false, + "userAgent": "MyK6UserAgentString/1.0" +} diff --git a/tests/k6/stress.json b/tests/k6/stress.json new file mode 100644 index 0000000..c0c52a2 --- /dev/null +++ b/tests/k6/stress.json @@ -0,0 +1,47 @@ +{ + "hosts": { + "airport-lookup-example.com": "lookup" + }, + "stages": [ + { + "duration": "1m", + "target": 10 + }, + { + "duration": "1m", + "target": 25 + }, + { + "duration": "1m", + "target": 50 + }, + { + "duration": "1m", + "target": 75 + }, + { + "duration": "1m", + "target": 100 + }, + { + "duration": "1m", + "target": 75 + }, + { + "duration": "1m", + "target": 50 + }, + { + "duration": "1m", + "target": 25 + }, + { + "duration": "1m", + "target": 0 + } + ], + "thresholds": { + "http_req_duration": ["avg<100", "p(95)<200"] + }, + "userAgent": "MyK6UserAgentString/1.0" +}