Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(performance): Expands search for serviceowners, improved tracing and logging #1439

Merged
merged 6 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/k6/common/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ export const tokenGeneratorEnv = __ENV.API_ENVIRONMENT == "yt01" ? "yt01" : "tt0
export const baseUrlGraphql = baseUrls[__ENV.API_VERSION]["graphql"][__ENV.API_ENVIRONMENT];

export const sentinelValue = "dialogporten-e2e-sentinel";
export const sentinelPerformanceValue = "dialogporten-e2e-sentinel-performance";
7 changes: 5 additions & 2 deletions tests/k6/tests/enduser/performance/enduser-search.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { enduserSearch } from '../../performancetest_common/simpleSearch.js'
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { endUsersWithTokens } from '../../performancetest_common/readTestdata.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';

export let options = {
summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'],
Expand All @@ -19,8 +20,10 @@ export let options = {
export default function() {
if (!endUsersWithTokens || endUsersWithTokens.length === 0) {
throw new Error('No end users loaded for testing');
}
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) {
}

const isSingleUserMode = (options.vus ?? 1) === 1 && (options.iterations ?? 1) === 1 && (options.duration ?? 0) === 0;
if (isSingleUserMode) {
enduserSearch(endUsersWithTokens[0]);
}
else {
Expand Down
6 changes: 4 additions & 2 deletions tests/k6/tests/graphql/performance/graphql-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* Run: k6 run tests/k6/tests/graphql/performance/graphql-search.js --vus 1 --iterations 1 -e env=yt01
*/

import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { endUsersWithTokens as endUsers } from '../../performancetest_common/readTestdata.js';
import { graphqlSearch } from "../../performancetest_common/simpleSearch.js";


/**
* The options object for configuring the performance test for GraphQL search.
*
Expand All @@ -26,7 +27,8 @@ export default function() {
if (!endUsers || endUsers.length === 0) {
throw new Error('No end users loaded for testing');
}
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) {
const isSingleUserMode = (options.vus ?? 1) === 1 && (options.iterations ?? 1) === 1 && (options.duration ?? 0) === 0;
if (isSingleUserMode) {
graphqlSearch(endUsers[0]);
}
else {
Expand Down
16 changes: 11 additions & 5 deletions tests/k6/tests/performancetest_common/createDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import dialogToInsert from "../performancetest_data/01-create-dialog.js";
* @param {Object} endUser - The end user object.
*/
export function createDialog(serviceOwner, endUser) {
var traceparent = uuidv4();
var paramsWithToken = {
headers: {
Authorization: "Bearer " + serviceOwner.token,
traceparent: uuidv4()
traceparent: traceparent
},
tags: { name: 'create dialog' }
tags: { name: 'create dialog', traceparent: traceparent, enduser: endUser.ssn }
};

describe('create dialog', () => {
Expand All @@ -35,12 +36,14 @@ export function createDialog(serviceOwner, endUser) {
* @param {Object} serviceOwner - The service owner object.
* @param {Object} endUser - The end user object.
*/
export function createAndRemoveDialog(serviceOwner, endUser) {
export function createAndRemoveDialog(serviceOwner, endUser) {
var traceparent = uuidv4();
var paramsWithToken = {
headers: {
Authorization: "Bearer " + serviceOwner.token
Authorization: "Bearer " + serviceOwner.token,
traceparent: traceparent
},
tags: { name: 'create dialog' }
tags: { name: 'create dialog', traceparent: traceparent, enduser: endUser.ssn }
dagfinno marked this conversation as resolved.
Show resolved Hide resolved
}

let dialogId = 0;
Expand All @@ -52,7 +55,10 @@ export function createAndRemoveDialog(serviceOwner, endUser) {
});

describe('remove dialog', () => {
traceparent = uuidv4();
paramsWithToken.tags.name = 'remove dialog';
paramsWithToken.tags.traceparent = traceparent;
paramsWithToken.headers.traceparent = traceparent
if (dialogId) {
let r = purgeSO('dialogs/' + dialogId, paramsWithToken);
expect(r.status, 'response status').to.equal(204);
Expand Down
40 changes: 23 additions & 17 deletions tests/k6/tests/performancetest_common/simpleSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ import { getGraphqlParty } from '../performancetest_data/graphql-search.js';
* @param {Object} paramsWithToken - The parameters with token.
* @returns {void}
*/
function retrieveDialogContent(response, paramsWithToken) {
function retrieveDialogContent(response, paramsWithToken, getFunction = getEU) {
const items = response.json().items;
if (!items?.length) return;

const dialogId = items[0].id;
if (!dialogId) return;

getContent(dialogId, paramsWithToken, 'get dialog');
getContentChain(dialogId, paramsWithToken, 'get dialog activities', 'get dialog activity', '/activities/')
getContentChain(dialogId, paramsWithToken, 'get seenlogs', 'get seenlog', '/seenlog/')
getContent(dialogId, paramsWithToken, 'get labellog', '/labellog');
getContentChain(dialogId, paramsWithToken, 'get transmissions', 'get transmission', '/transmissions/')
getContent(dialogId, paramsWithToken, 'get dialog', '', getFunction);
getContentChain(dialogId, paramsWithToken, 'get dialog activities', 'get dialog activity', '/activities/', getFunction);
getContentChain(dialogId, paramsWithToken, 'get seenlogs', 'get seenlog', '/seenlog/', getFunction);
if (getFunction == getEU) {
getContent(dialogId, paramsWithToken, 'get labellog', '/labellog', getFunction);
}
getContentChain(dialogId, paramsWithToken, 'get transmissions', 'get transmission', '/transmissions/', getFunction);
}

/**
Expand Down Expand Up @@ -61,12 +63,12 @@ export function enduserSearch(enduser) {
* @param {string} path - The path to append to the URL. Can be empty or /labellog.
* @returns {void}
*/
export function getContent(dialogId, paramsWithToken, tag, path = '') {
export function getContent(dialogId, paramsWithToken, tag, path = '', getFunction = getEU) {
const listParams = {
...paramsWithToken,
tags: { ...paramsWithToken.tags, name: tag }
};
getUrl('dialogs/' + dialogId + path, listParams);
getUrl('dialogs/' + dialogId + path, listParams, getFunction);
}

/**
Expand All @@ -78,19 +80,19 @@ export function getContent(dialogId, paramsWithToken, tag, path = '') {
* @param {string} endpoint - The endpoint to append to the URL.
* @returns {void}
*/
export function getContentChain(dialogId, paramsWithToken, tag, subtag, endpoint) {
export function getContentChain(dialogId, paramsWithToken, tag, subtag, endpoint, getFunction = getEU) {
const listParams = {
...paramsWithToken,
tags: { ...paramsWithToken.tags, name: tag }
};
let d = getUrl('dialogs/' + dialogId + endpoint, listParams);
let d = getUrl('dialogs/' + dialogId + endpoint, listParams, getFunction);
let json = d.json();
if (json.length > 0) {
const detailParams = {
...paramsWithToken,
tags: { ...paramsWithToken.tags, name: subtag }
};
getUrl('dialogs/' + dialogId + endpoint + randomItem(json).id, detailParams);
getUrl('dialogs/' + dialogId + endpoint + randomItem(json).id, detailParams, getFunction);
}
}

Expand All @@ -100,8 +102,8 @@ export function getContentChain(dialogId, paramsWithToken, tag, subtag, endpoint
* @param {Object} paramsWithToken - The parameters with token.
* @returns {Object} The response object.
*/
export function getUrl(url, paramsWithToken) {
let r = getEU(url, paramsWithToken);
export function getUrl(url, paramsWithToken, getFunction = getEU) {
let r = getFunction(url, paramsWithToken);
expectStatusFor(r).to.equal(200);
expect(r, 'response').to.have.validJsonBody();
return r;
Expand All @@ -114,12 +116,14 @@ export function getUrl(url, paramsWithToken) {
* @returns {void}
*/
export function graphqlSearch(enduser) {
let traceparent = uuidv4();
let paramsWithToken = {
headers: {
Authorization: "Bearer " + enduser.token,
traceparent: uuidv4()
traceparent: traceparent,
'User-Agent': 'dialogporten-k6-graphql-search'
},
tags: { name: 'graphql search' }
tags: { name: 'graphql search', traceparent: traceparent }
};
describe('Perform graphql dialog list', () => {
let r = postGQ(getGraphqlParty(enduser.ssn), paramsWithToken);
Expand All @@ -134,12 +138,13 @@ export function graphqlSearch(enduser) {
* @param {*} enduser
*/
export function serviceownerSearch(serviceowner, enduser, tag_name) {
let traceparent = uuidv4();
let paramsWithToken = {
headers: {
Authorization: "Bearer " + serviceowner.token,
traceparent: uuidv4()
traceparent: traceparent
},
tags: { name: tag_name }
tags: { name: tag_name, traceparent: traceparent, enduser: enduser.ssn }
}

let enduserid = encodeURIComponent(`urn:altinn:person:identifier-no:${enduser.ssn}`);
Expand All @@ -149,5 +154,6 @@ export function serviceownerSearch(serviceowner, enduser, tag_name) {
let r = getSO('dialogs' + defaultFilter, paramsWithToken);
expectStatusFor(r).to.equal(200);
expect(r, 'response').to.have.validJsonBody();
retrieveDialogContent(r, paramsWithToken, getSO);
});
}
6 changes: 5 additions & 1 deletion tests/k6/tests/performancetest_data/01-create-dialog.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {default as createDialogPayload} from "../serviceowner/testdata/01-create-dialog.js"
import { sentinelPerformanceValue } from "../../common/config.js";

const ACTIVITY_TYPE_INFORMATION = 'Information';

Expand All @@ -7,7 +8,10 @@ function cleanUp(originalPayload) {
throw new Error('Invalid payload');
}

const payload = { ...originalPayload };
const payload = {
...originalPayload,
searchTags: [...(originalPayload.searchTags || []), { "value": sentinelPerformanceValue }]
};
const { visibleFrom, ...payloadWithoutVisibleFrom } = payload;

const activities = payload.activities?.map(activity => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
org,orgno,scopes,resource
digdir,991825827,digdir:dialogporten.serviceprovider,super-simple-service
digdir,991825827,digdir:dialogporten.serviceprovider digdir:dialogporten.serviceprovider.search,super-simple-service
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Performance test for creating dialogs and searching dialogs.
* Run: k6 run tests/k6/tests/scenarios/performance/create-dialog-and-search.js -e env=yt01 -e svus=1 -e evus=1 -e duration=1m
*/
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { enduserSearch } from '../../performancetest_common/simpleSearch.js';
import { createDialog } from '../../performancetest_common/createDialog.js';
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
Expand Down
5 changes: 3 additions & 2 deletions tests/k6/tests/serviceowner/performance/create-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Performance test for creating a dialog
* Run: k6 run tests/k6/tests/serviceowner/performance/create-dialog.js --vus 1 --iterations 1
*/
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { createDialog } from '../../performancetest_common/createDialog.js';
import { serviceOwners, endUsers } from '../../performancetest_common/readTestdata.js';
Expand All @@ -19,7 +19,8 @@ export default function() {
if (!serviceOwners || serviceOwners.length === 0) {
throw new Error('No service owners loaded for testing');
}
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) {
const isSingleUserMode = (options.vus ?? 1) === 1 && (options.iterations ?? 1) === 1 && (options.duration ?? 0) === 0;
if (isSingleUserMode) {
createDialog(serviceOwners[0], endUsers[0]);
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Performance test for creating and removing a dialog
* Run: k6 run tests/k6/tests/serviceowner/performance/create-remove-dialog.js --vus 1 --iterations 1
*/
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { serviceOwners, endUsers } from "../../performancetest_common/readTestdata.js";
import { createAndRemoveDialog } from '../../performancetest_common/createDialog.js';
Expand All @@ -22,7 +22,9 @@ export default function() {
if (!serviceOwners || serviceOwners.length === 0) {
throw new Error('No service owners loaded for testing');
}
if ((options.vus === undefined || options.vus === 1) && (options.iterations === undefined || options.iterations === 1)) {

const isSingleUserMode = (options.vus ?? 1) === 1 && (options.iterations ?? 1) === 1 && (options.duration ?? 0) === 0;
if (isSingleUserMode) {
createAndRemoveDialog(serviceOwners[0], endUsers[0]);
}
else {
Expand Down
8 changes: 6 additions & 2 deletions tests/k6/tests/serviceowner/performance/purge-dialogs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
*
* Run: k6 run tests/k6/tests/serviceowner/performance/purge-dialogs.js -e env=yt01
*/
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { getSO, purgeSO } from '../../../common/request.js';
import { serviceOwners } from '../../performancetest_common/readTestdata.js';
import { expect, expectStatusFor } from "../../../common/testimports.js";
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { describe } from '../../../common/describe.js';
import { sentinelValue } from '../../../common/config.js';
import { sentinelPerformanceValue as sentinelValue } from '../../../common/config.js';

/**
* Retrieves the dialog ids to purge.
Expand All @@ -21,9 +22,12 @@ import { sentinelValue } from '../../../common/config.js';
* @returns {Array} - The dialog ids to purge.
*/
function getDialogs(serviceOwner) {
var traceparent = uuidv4();
console.log("Searching for dialogs to purge, tracevalue: " + traceparent);
var paramsWithToken = {
headers: {
Authorization: "Bearer " + serviceOwner.token
Authorization: "Bearer " + serviceOwner.token,
traceparent: traceparent
}
}
let hasNextPage = false;
Expand Down
11 changes: 9 additions & 2 deletions tests/k6/tests/serviceowner/performance/serviceowner-search.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.1.0/index.js';
import { randomItem } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
import { serviceownerSearch } from '../../performancetest_common/simpleSearch.js'
import { getDefaultThresholds } from '../../performancetest_common/getDefaultThresholds.js';
import { serviceOwners ,endUsersWithTokens } from '../../performancetest_common/readTestdata.js';
Expand All @@ -7,7 +7,14 @@ const tag_name = 'serviceowner search';

export let options = {
summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'p(99.5)', 'p(99.9)', 'count'],
thresholds: getDefaultThresholds(['http_req_duration', 'http_reqs'],[tag_name])
thresholds: getDefaultThresholds(['http_req_duration', 'http_reqs'],[tag_name,
'get dialog',
'get dialog activities',
'get dialog activity',
'get seenlogs',
'get seenlog',
'get transmissions',
'get transmission'])
};

/**
Expand Down