Skip to content

Commit

Permalink
Merge pull request #1302 from visualize-admin/perf/graphql-performanc…
Browse files Browse the repository at this point in the history
…e-testing-2

perf: GraphQL performance tests continuation
  • Loading branch information
bprusinowski authored Dec 14, 2023
2 parents 50afe2c + edad59a commit 893a691
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 36 deletions.
45 changes: 38 additions & 7 deletions .github/workflows/performance-tests.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
name: Performance tests
name: GraphQL performance tests

on: workflow_dispatch

jobs:
compile:
name: Compile site assets
run_tests:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Check out the repo
- name: Check out
uses: actions/checkout@v2
- name: Run the build process with Docker
- name: Run k6 and upload results to Prometheus
uses: addnab/docker-run-action@v3
with:
image: grafana/k6:latest
options: -rm -e K6_PROMETHEUS_RW_USERNAME=${{ secrets.K6_PROMETHEUS_RW_USERNAME }} -e K6_PROMETHEUS_RW_PASSWORD=${{ secrets.K6_PROMETHEUS_RW_PASSWORD }} -e K6_PROMETHEUS_RW_SERVER_URL=${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
run: k6 run -o experimental-prometheus-rw --tag testid=StateAccounts_Office/4/ --env ENV=test --env CUBE=StateAccounts_Office/4/ - <k6/performance-tests/graphql/metadata.js && k6 run -o experimental-prometheus-rw --tag testid=StateAccounts_Office/4/ --env ENV=int --env CUBE=StateAccounts_Office/4/ - <k6/performance-tests/graphql/metadata.js && k6 run -o experimental-prometheus-rw --tag testid=StateAccounts_Office/4/ --env ENV=prod --env CUBE=StateAccounts_Office/4/ - <k6/performance-tests/graphql/metadata.js
options: |
-v ${{ github.workspace }}:/root
-e K6_PROMETHEUS_RW_USERNAME=${{ secrets.K6_PROMETHEUS_RW_USERNAME }}
-e K6_PROMETHEUS_RW_PASSWORD=${{ secrets.K6_PROMETHEUS_RW_PASSWORD }}
-e K6_PROMETHEUS_RW_SERVER_URL=${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
run: |
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=test --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=test --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=test --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=test --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=int --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=int --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=int --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=int --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=prod --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeComponents --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeComponents.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=prod --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubeMetadata --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubeMetadata.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9 --env CUBE_LABEL=Photovoltaikanlagen/9 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=prod --env CUBE_IRI=https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2 --env CUBE_LABEL=NFI/2023-2 - </root/k6/performance-tests/graphql/DataCubePreview.js &&
k6 run -o experimental-prometheus-rw --tag testid=DataCubePreview --env ENV=prod --env CUBE_IRI=https://energy.ld.admin.ch/elcom/electricityprice --env CUBE_LABEL=Elcom - </root/k6/performance-tests/graphql/DataCubePreview.js
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,18 @@ Playwright is run on every successful deployment of a branch. Screenshots are ma
A special [test page](http://localhost:3000/en/__test) shows all the charts that are screenshotted.
Those charts configurations are kept in the repository.
## GraphQL performance tests
The project uses a combination of [k6](https://k6.io) and [Grafana](https://grafana.com) with [Prometheus](https://k6.io/docs/results-output/real-time/prometheus-remote-write/) for GraphQL performance testing.
### Automation
To ensure constant monitoring of the performance of selected GraphQL queries, the performance tests are run [once an hour](https://github.com/visualize-admin/visualization-tool/blob/main/.github/workflows/performance-tests.yml) against each environment of the application. The results are then sent to the governmental Grafana dashboards.
### How to add or modify the tests
To add or modify the performance tests, go to the [k6/performance-tests](https://github.com/visualize-admin/visualization-tool/tree/main/k6/performance-tests) folder. The GitHub Action is generated by running the `yarn run github:codegen` command; be sure to run it after modifying the [generate-github-action.js](`https://github.com/visualize-admin/visualization-tool/blob/main/k6/performance-tests/generate-github-action.js`) file.

## Load tests

The project uses [k6](https://k6.io) for load testing.
Expand Down
58 changes: 40 additions & 18 deletions k6/performance-tests/generate-github-action.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,59 @@
const fs = require("fs");

const envs = ["test", "int", "prod"];
const queries = ["metadata"];
const cubes = ["StateAccounts_Office/4/"];
const queries = ["DataCubeComponents", "DataCubeMetadata", "DataCubePreview"];
const cubes = [
{
iri: "https://energy.ld.admin.ch/sfoe/bfe_ogd84_einmalverguetung_fuer_photovoltaikanlagen/9",
label: "Photovoltaikanlagen/9",
},
{
iri: "https://environment.ld.admin.ch/foen/nfi/nfi_C-96/cube/2023-2",
label: "NFI/2023-2",
},
{
iri: "https://energy.ld.admin.ch/elcom/electricityprice",
label: "Elcom",
},
];
const commands = envs
.flatMap((e) =>
queries.flatMap((q) => cubes.map((c) => getRunCommand(e, q, c)))
)
.join(" &&\n ");

const generate = () => {
const file = `name: Performance tests
const file = `name: GraphQL performance tests
on: workflow_dispatch
on:
workflow_dispatch:
schedule:
- cron: 37 * * * *"
jobs:
compile:
name: Compile site assets
run_tests:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Check out the repo
- name: Check out
uses: actions/checkout@v2
- name: Run the build process with Docker
- name: Run k6 and upload results to Prometheus
uses: addnab/docker-run-action@v3
with:
image: grafana/k6:latest
options: -rm -e K6_PROMETHEUS_RW_USERNAME=\${{ secrets.K6_PROMETHEUS_RW_USERNAME }} -e K6_PROMETHEUS_RW_PASSWORD=\${{ secrets.K6_PROMETHEUS_RW_PASSWORD }} -e K6_PROMETHEUS_RW_SERVER_URL=\${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
run: ${envs
.map((env) => {
return queries.map((query) => {
return cubes.map((cube) => {
return `k6 run -o experimental-prometheus-rw --tag testid=${cube} --env ENV=${env} --env CUBE=${cube} - <k6/performance-tests/graphql/${query}.js`;
});
});
})
.join(" && ")}`;
options: |
-v \${{ github.workspace }}:/root
-e K6_PROMETHEUS_RW_USERNAME=\${{ secrets.K6_PROMETHEUS_RW_USERNAME }}
-e K6_PROMETHEUS_RW_PASSWORD=\${{ secrets.K6_PROMETHEUS_RW_PASSWORD }}
-e K6_PROMETHEUS_RW_SERVER_URL=\${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
run: |
${commands}`;

fs.writeFileSync("./.github/workflows/performance-tests.yml", file);
};

generate();

function getRunCommand(env, query, cube) {
return `k6 run -o experimental-prometheus-rw --tag testid=${query} --env ENV=${env} --env CUBE_IRI=${cube.iri} --env CUBE_LABEL=${cube.label} - </root/k6/performance-tests/graphql/${query}.js`;
}
50 changes: 50 additions & 0 deletions k6/performance-tests/graphql/DataCubeComponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import exec from "k6/execution";
import http from "k6/http";

const query = `query DataCubeComponents(
$sourceType: String!
$sourceUrl: String!
$locale: String!
$cubeFilter: DataCubeComponentFilter!
) {
dataCubeComponents(
sourceType: $sourceType
sourceUrl: $sourceUrl
locale: $locale
cubeFilter: $cubeFilter
)
}`;

const env = __ENV.ENV;
const cubeIri = __ENV.CUBE_IRI;
const cubeLabel = __ENV.CUBE_LABEL;

const variables = {
locale: "en",
sourceType: "sparql",
sourceUrl: "https://lindas.admin.ch/query",
cubeFilter: {
iri: cubeIri,
},
};

/** @type {import("k6/options").Options} */
export const options = {
iterations: 1,
};

const headers = {
"Content-Type": "application/json",
"x-visualize-cache-control": "no-cache",
};

export default function Components() {
exec.vu.metrics.tags.env = env;
exec.vu.metrics.tags.cube = cubeLabel;

http.post(
`https://${env === "prod" ? "" : `${env}.`}visualize.admin.ch/api/graphql`,
JSON.stringify({ query, variables }),
{ headers }
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,36 @@ const query = `query DataCubeMetadata(
)
}`;

const env = __ENV.ENV;
const cubeIri = __ENV.CUBE_IRI;
const cubeLabel = __ENV.CUBE_LABEL;

const variables = {
locale: "en",
sourceType: "sparql",
sourceUrl: "https://lindas.admin.ch/query",
cubeFilter: {
iri: "https://culture.ld.admin.ch/sfa/StateAccounts_Office/4/",
iri: cubeIri,
},
};

const env = __ENV.ENV;
const cube = __ENV.CUBE;

/** @type {import("k6/options").Options} */
export const options = {
iterations: 1,
};

const headers = {
"Content-Type": "application/json",
"x-visualize-cache-control": "no-cache",
};

export default function Components() {
exec.vu.metrics.tags.env = env;
exec.vu.metrics.tags.cube = cube;
exec.vu.metrics.tags.cube = cubeLabel;

http.post(
`https://${env === "prod" ? "" : `${env}.`}visualize.admin.ch/api/graphql`,
JSON.stringify({ query, variables }),
{
headers: {
"Content-Type": "application/json",
"x-visualize-cache-control": "no-cache",
},
}
{ headers }
);
}
67 changes: 67 additions & 0 deletions k6/performance-tests/graphql/DataCubePreview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import exec from "k6/execution";
import http from "k6/http";

const query = `query DataCubePreview(
$iri: String!
$sourceType: String!
$sourceUrl: String!
$locale: String!
$latest: Boolean
$disableValuesLoad: Boolean = true
) {
dataCubeByIri(
iri: $iri
sourceType: $sourceType
sourceUrl: $sourceUrl
locale: $locale
latest: $latest
disableValuesLoad: $disableValuesLoad
) {
iri
title
description
publicationStatus
observations(
sourceType: $sourceType
sourceUrl: $sourceUrl
preview: true
limit: 10
) {
data
sparqlEditorUrl
}
}
}`;

const env = __ENV.ENV;
const cubeIri = __ENV.CUBE_IRI;
const cubeLabel = __ENV.CUBE_LABEL;

const variables = {
iri: cubeIri,
sourceType: "sparql",
sourceUrl: "https://lindas.admin.ch/query",
locale: "en",
latest: false,
};

/** @type {import("k6/options").Options} */
export const options = {
iterations: 1,
};

const headers = {
"Content-Type": "application/json",
"x-visualize-cache-control": "no-cache",
};

export default function Components() {
exec.vu.metrics.tags.env = env;
exec.vu.metrics.tags.cube = cubeLabel;

http.post(
`https://${env === "prod" ? "" : `${env}.`}visualize.admin.ch/api/graphql`,
JSON.stringify({ query, variables }),
{ headers }
);
}

1 comment on commit 893a691

@vercel
Copy link

@vercel vercel bot commented on 893a691 Dec 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization-tool – ./

visualization-tool-git-main-ixt1.vercel.app
visualization-tool-alpha.vercel.app
visualization-tool-ixt1.vercel.app

Please sign in to comment.