diff --git a/.devops/performance-test-pipelines.yml b/.devops/performance-test-pipelines.yml new file mode 100644 index 00000000..b8975e18 --- /dev/null +++ b/.devops/performance-test-pipelines.yml @@ -0,0 +1,83 @@ +# azure-pipelines.yml +trigger: none + +parameters: + - name: "ENVIRONMENT" + displayName: "Environment" + type: string + values: + - "dev" + - "uat" + default: "uat" + - name: "TEST_TYPE" + displayName: "Test type" + type: string + values: + - "constant" + - "load" + - "spike" + - "stress" + default: "constant" + - name: "SCRIPT" + displayName: "Script name" + type: string + values: + - receipt_generator + - name: "DB_NAME" + displayName: "DB name" + type: string + values: + - pagopa_receipt_pdf_generatork6 + - name: "PROCESS_TIME" + displayName: "Process time" + type: number + default: 5 + +variables: + ${{ if eq(parameters['ENVIRONMENT'], 'dev') }}: + receiptCosmosSubscriptionKey: "$(DEV_RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY)" + receiptQueueAccountName: "pagopadweureceiptsfnsa" + receiptQueueName: "pagopa-d-weu-receipts-queue-receipt-waiting-4-gen" + azureSubscription: "$(TF_DEV_AZURE_SERVICE_CONNECTION)" + poolImage: "pagopa-dev-loadtest-linux" + ${{ if eq(parameters['ENVIRONMENT'], 'uat') }}: + receiptCosmosSubscriptionKey: "$(UAT_RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY)" + receiptQueueAccountName: "pagopauweureceiptsfnsa" + receiptQueueName: "pagopa-u-weu-receipts-queue-receipt-waiting-4-gen" + azureSubscription: "$(TF_UAT_AZURE_SERVICE_CONNECTION)" + poolImage: "pagopa-uat-loadtest-linux" + +pool: + name: $(poolImage) + +steps: + - script: | + cd ./performance-test/src + docker pull grafana/k6 + displayName: Pull k6 image + - script: | + apt-get update + apt-get install azure-cli + az version + displayName: Install Azure CLI + - task: AzureCLI@2 + displayName: Login Azure + inputs: + azureSubscription: "$(azureSubscription)" + scriptType: bash + scriptLocation: inlineScript + inlineScript: | + end="$(date -d '+1 day' +'%Y-%m-%d')" + export SAS_TOKEN="$(az storage queue generate-sas \ + -n ${{ variables.receiptQueueName }} \ + --account-name ${{ variables.receiptQueueAccountName }} \ + --permissions apru \ + --expiry $end)" + echo "##vso[task.setvariable variable=SAS_TOKEN]$SAS_TOKEN" + - script: | + cd ./performance-test + sh ./run_performance_test.sh ${{ parameters.ENVIRONMENT }} ${{ parameters.TEST_TYPE }} ${{ parameters.SCRIPT }} ${{ parameters.DB_NAME }} $(SAS_TOKEN) $RECEIPT_COSMOS_SUBSCRIPTION_KEY $PROCESS_TIME + displayName: Run k6 ${{ parameters.SCRIPT }} on ${{ parameters.ENVIRONMENT }} + env: + RECEIPT_COSMOS_SUBSCRIPTION_KEY: ${{ variables.receiptCosmosSubscriptionKey }} + PROCESS_TIME: ${{ parameters.PROCESS_TIME }} diff --git a/performance-test/README.md b/performance-test/README.md new file mode 100644 index 00000000..1a7c0583 --- /dev/null +++ b/performance-test/README.md @@ -0,0 +1,14 @@ +# K6 tests + +This is a set of [k6](https://k6.io) tests. + +To invoke k6 tests use `run_performance_test.sh` script. + + +## How to run 🚀 + +Use this command to launch the tests: + +``` shell +sh run_performance_test.sh +``` diff --git a/performance-test/docker-compose.yaml b/performance-test/docker-compose.yaml new file mode 100644 index 00000000..3528a8f2 --- /dev/null +++ b/performance-test/docker-compose.yaml @@ -0,0 +1,29 @@ +version: '3.3' +services: + k6: + image: grafana/k6 + container_name: k6 + volumes: + - '${PWD}/src:/scripts' + environment: + - RECEIPT_QUEUE_SUBSCRIPTION_KEY=${receipts_queue_key} + - RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY=${receipts_cosmos_key} + - PROCESS_TIME=${process_time} + - VARS=${env}.environment.json + - TEST_TYPE=/scripts/test-types/${type}.json + - K6_OUT=influxdb=http://nginx:8086/${db_name} + command: run /scripts/${script}.js + depends_on: + - nginx + + nginx: + image: nginx + container_name: nginx + volumes: + - '${PWD}/nginx/nginx.conf:/etc/nginx/nginx.conf' + environment: + - ENVIRONMENT=${env} + ports: + - "8086:8086" + - "80:80" + diff --git a/performance-test/nginx/nginx.conf b/performance-test/nginx/nginx.conf new file mode 100644 index 00000000..a9cc127d --- /dev/null +++ b/performance-test/nginx/nginx.conf @@ -0,0 +1,16 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 8086; + location / { + proxy_pass https://api.uat.platform.pagopa.it/shared/influxdb/v1/; + proxy_http_version 1.1; + proxy_set_header Host api.uat.platform.pagopa.it; + proxy_pass_request_headers on; + } + } +} + diff --git a/performance-test/run_performance_test.sh b/performance-test/run_performance_test.sh new file mode 100644 index 00000000..dc969407 --- /dev/null +++ b/performance-test/run_performance_test.sh @@ -0,0 +1,39 @@ +# sh run_performance_test.sh + +ENVIRONMENT=$1 +TYPE=$2 +SCRIPT=$3 +DB_NAME=$4 +RECEIPT_QUEUE_SUBSCRIPTION_KEY=$5 +RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY=$6 +PROCESS_TIME=$7 + +if [ -z "$ENVIRONMENT" ] +then + echo "No env specified: sh run_performance_test.sh " + exit 1 +fi + +if [ -z "$TYPE" ] +then + echo "No test type specified: sh run_performance_test.sh " + exit 1 +fi +if [ -z "$SCRIPT" ] +then + echo "No script name specified: sh run_performance_test.sh " + exit 1 +fi + +export env=${ENVIRONMENT} +export type=${TYPE} +export script=${SCRIPT} +export db_name=${DB_NAME} +export receipts_queue_key=${RECEIPT_QUEUE_SUBSCRIPTION_KEY} +export receipts_cosmos_key=${RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY} +export process_time=${PROCESS_TIME} + +stack_name=$(cd .. && basename "$PWD") +docker compose -p "${stack_name}-k6" up -d --remove-orphans --force-recreate --build +docker logs -f k6 +docker stop nginx diff --git a/performance-test/src/README.md b/performance-test/src/README.md new file mode 100644 index 00000000..68b2fa77 --- /dev/null +++ b/performance-test/src/README.md @@ -0,0 +1,49 @@ +# K6 tests for _ReceiptsToDatastore_ project + +[k6](https://k6.io/) is a load testing tool. 👀 See [here](https://k6.io/docs/get-started/installation/) to install it. + +- [01. Receipt datastore function](#01-receipt-datastore-function) + +This is a set of [k6](https://k6.io) tests related to the _Biz Events to Datastore_ initiative. + +To invoke k6 test passing parameter use -e (or --env) flag: + +``` +-e MY_VARIABLE=MY_VALUE +``` + +## 01. Receipt datastore function + +Test the receipt datastore function: + +``` +k6 run --env VARS=local.environment.json --env TEST_TYPE=./test-types/load.json --env RECEIPT_QUEUE_SUBSCRIPTION_KEY= --env RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY= receipt_generator.js +``` + +where the mean of the environment variables is: + +```json + "environment": [ + { + "env": "local", + "receiptCosmosDBURI": "", + "receiptDatabaseID":"", + "receiptContainerID":"", + "receiptQueueAccountName": "", + "receiptQueueName": "", + "processTime":"" + } + ] +``` + +`receiptCosmosDBURI`: CosmosDB url to access Receipts CosmosDB REST API + +`receiptDatabaseID`: database name to access Receipts Cosmos DB REST API + +`receiptContainerID`: collection name to access Receipts Cosmos DB REST API + +`receiptQueueAccountName`: storage account name to access Receipts Queue + +`receiptQueueName`: queue name for the Receipts, + +`processTime`: boundary time taken by azure function to fetch the payment event and save it in the datastore \ No newline at end of file diff --git a/performance-test/src/dev.environment.json b/performance-test/src/dev.environment.json new file mode 100644 index 00000000..0ed9eba3 --- /dev/null +++ b/performance-test/src/dev.environment.json @@ -0,0 +1,12 @@ +{ + "environment": [ + { + "env": "dev", + "receiptCosmosDBURI": "https://pagopa-d-weu-receipts-ds-cosmos-account.documents.azure.com:443/", + "receiptDatabaseID":"db", + "receiptContainerID":"receipts", + "receiptQueueAccountName": "pagopadweureceiptsfnsa", + "receiptQueueName": "pagopa-d-weu-receipts-queue-receipt-waiting-4-gen" + } + ] +} diff --git a/performance-test/src/local.environment.json b/performance-test/src/local.environment.json new file mode 100644 index 00000000..45874f4c --- /dev/null +++ b/performance-test/src/local.environment.json @@ -0,0 +1,12 @@ +{ + "environment": [ + { + "env": "local", + "receiptCosmosDBURI": "https://pagopa-d-weu-receipts-ds-cosmos-account.documents.azure.com:443/", + "receiptDatabaseID":"db", + "receiptContainerID":"receipts", + "receiptQueueAccountName": "pagopadweureceiptsfnsa", + "receiptQueueName": "pagopa-d-weu-receipts-queue-receipt-waiting-4-gen" + } + ] +} diff --git a/performance-test/src/modules/common.js b/performance-test/src/modules/common.js new file mode 100644 index 00000000..b6ab1d4c --- /dev/null +++ b/performance-test/src/modules/common.js @@ -0,0 +1,114 @@ + +export function randomString(length, charset) { + let res = ''; + while (length--) res += charset[(Math.random() * charset.length) | 0]; + return res; +} + +export function createEvent(id) { + const idPA = randomString(11, "0123456789"); + const idPSP = randomString(11, "0123456789"); + let json_event = { + "id": id, + "version": "2", + "complete": "false", + "receiptId": "0095ff2bafec4bc0a719c9bf003aee4a", + "missingInfo": [ + "idPaymentManager", + "psp.pspPartitaIVA", + "paymentInfo.primaryCiIncurredFee", + "paymentInfo.idBundle", + "paymentInfo.idCiBundle", + "paymentInfo.metadata" + ], + "debtorPosition": { + "modelType": "2", + "noticeNumber": randomString(18, "0123456789"), + "iuv": randomString(17, "0123456789") + }, + "creditor": { + "idPA": idPA, + "idBrokerPA": idPA, + "idStation": `${idPA}_08`, + "companyName": "PA test_company" + }, + "psp": { + "idPsp": idPSP, + "idBrokerPsp": idPSP, + "idChannel": `${idPSP}_08`, + "psp": "test_PSP" + }, + "debtor": { + "fullName": "John Doe", + "entityUniqueIdentifierType": "F", + "entityUniqueIdentifierValue": "GENERATOR_PERF_TEST", + "streetName": "street", + "civicNumber": "12", + "postalCode": "89020", + "city": "city", + "stateProvinceRegion": "MI", + "country": "IT", + "eMail": "john.doe@test.it" + }, + "payer": { + "fullName": "John Doe", + "entityUniqueIdentifierType": "F", + "entityUniqueIdentifierValue": "GENERATOR_PERF_TEST", + "streetName": "street", + "civicNumber": "12", + "postalCode": "89020", + "city": "city", + "stateProvinceRegion": "MI", + "country": "IT", + "eMail": "john.doe@test.it" + }, + "paymentInfo": { + "paymentDateTime": "2022-12-13T01:52:02.926587", + "applicationDate": "2021-10-01", + "transferDate": "2021-10-02", + "dueDate": "2021-07-31", + "paymentToken": "0095ff2bafec4bc0a719c9bf003aee4a", + "amount": "70.0", + "fee": "2.0", + "totalNotice": "1", + "paymentMethod": "creditCard", + "touchpoint": "app", + "remittanceInformation": "TARI 2021", + "description": "TARI 2021" + }, + "transferList": [ + { + "fiscalCodePA": idPA, + "companyName": "PA test_company", + "amount": "2.00", + "transferCategory": "paTest", + "remittanceInformation": "/RFB/00202200000217527/5.00/TXT/" + }, + { + "fiscalCodePA": randomString(11, "0123456789"), + "companyName": "PA test_company", + "amount": "8.00", + "transferCategory": "paTest", + "remittanceInformation": "/RFB/00202200000217527/5.00/TXT/" + } + ], + "eventStatus": "DONE", + "eventRetryEnrichmentCount": 0 + } + return json_event; +} + +export function createReceipt(id) { + let receipt = + { + "eventId": id, + "eventData": { + "payerFiscalCode": "GENERATOR_PERF_TEST", + "debtorFiscalCode": "GENERATOR_PERF_TEST" + }, + "status": "INSERTED", + "numRetry": 0, + "id": id + } + return receipt +} diff --git a/performance-test/src/modules/datastore_client.js b/performance-test/src/modules/datastore_client.js new file mode 100644 index 00000000..95191d83 --- /dev/null +++ b/performance-test/src/modules/datastore_client.js @@ -0,0 +1,126 @@ +import http from 'k6/http'; +import crypto from 'k6/crypto'; +import encoding from 'k6/encoding'; + +const authorizationType = "master" +const authorizationVersion = "1.0"; +const cosmosDBApiVersion = "2018-12-31"; + +export function getDocumentById(cosmosDbURI, databaseId, containerId, authorizationSignature, id) { + const path = `dbs/${databaseId}/colls/${containerId}/docs`; + const resourceLink = `dbs/${databaseId}/colls/${containerId}`; + const resourceType = "docs"; + const date = new Date().toUTCString(); + const verb = 'post'; + const authorizationToken = getCosmosDBAuthorizationToken(verb,authorizationType,authorizationVersion,authorizationSignature,resourceType,resourceLink,date); + + let partitionKeyArray = []; + let headers = getCosmosDBAPIHeaders(authorizationToken, date, partitionKeyArray, 'application/query+json', "true"); + + const query = { + "query": "SELECT * FROM c where c.id=@id", + "parameters": [ + { + "name":"@id", + "value": id + } + ] + }; + + const body = JSON.stringify(query); + + let resp = http.post(cosmosDbURI+path, body, {headers}); + + return resp; +} + + +export function getDocumentByEventId(cosmosDbURI, databaseId, containerId, authorizationSignature, id) { + const path = `dbs/${databaseId}/colls/${containerId}/docs`; + const resourceLink = `dbs/${databaseId}/colls/${containerId}`; + const resourceType = "docs"; + const date = new Date().toUTCString(); + const verb = 'post'; + const authorizationToken = getCosmosDBAuthorizationToken(verb,authorizationType,authorizationVersion,authorizationSignature,resourceType,resourceLink,date); + + let partitionKeyArray = []; + let headers = getCosmosDBAPIHeaders(authorizationToken, date, partitionKeyArray, 'application/query+json', "true"); + + const query = { + "query": "SELECT * FROM c WHERE c.eventId = @id", + "parameters": [ + { + "name":"@id", + "value": id + } + ] + }; + + const body = JSON.stringify(query); + + return http.post(cosmosDbURI+path, body, {headers, responseType: "text"}); +} + + +export function createDocument(cosmosDbURI, databaseId, containerId, authorizationSignature, document, pk) { + let path = `dbs/${databaseId}/colls/${containerId}/docs`; + let resourceLink = `dbs/${databaseId}/colls/${containerId}`; + // resource type (colls, docs...) + let resourceType = "docs" + let date = new Date().toUTCString(); + // request method (a.k.a. verb) to build text for authorization token + let verb = 'post'; + let authorizationToken = getCosmosDBAuthorizationToken(verb,authorizationType,authorizationVersion,authorizationSignature,resourceType,resourceLink,date); + + let partitionKeyArray = "[\""+pk+"\"]"; + let headers = getCosmosDBAPIHeaders(authorizationToken, date, partitionKeyArray, 'application/json'); + + const body = JSON.stringify(document); + + let resp = http.post(cosmosDbURI+path, body, {headers}); + + return resp; +} + +export function deleteDocument(cosmosDbURI, databaseId, containerId, authorizationSignature, id) { + const path = `dbs/${databaseId}/colls/${containerId}/docs/${id}`; + const resourceLink = path; + const resourceType = "docs" + const date = new Date().toUTCString(); + const verb = 'delete'; + const partitionKeyArray = "[\""+id+"\"]"; + + let authorizationToken = getCosmosDBAuthorizationToken(verb,authorizationType,authorizationVersion,authorizationSignature,resourceType,resourceLink,date); + let headers = getCosmosDBAPIHeaders(authorizationToken, date, partitionKeyArray, 'application/json'); + + let resp = http.del(cosmosDbURI+path, null, {headers}); + + return resp; +} + +function getCosmosDBAPIHeaders(authorizationToken, date, partitionKeyArray, contentType, isQuery){ + + return {'Accept': 'application/json', + 'Content-Type': contentType, + 'Authorization': authorizationToken, + 'x-ms-version': cosmosDBApiVersion, + 'x-ms-date': date, + 'x-ms-documentdb-isquery': isQuery ? isQuery : "false", + 'x-ms-query-enable-crosspartition': 'true', + 'x-ms-documentdb-partitionkey': partitionKeyArray + }; +} + + +function getCosmosDBAuthorizationToken(verb, autorizationType, autorizationVersion, authorizationSignature, resourceType, resourceLink, dateUtc) { + // Decode authorization signature + let key = encoding.b64decode(authorizationSignature); + let text = (verb || "").toLowerCase() + "\n" + + (resourceType || "").toLowerCase() + "\n" + + (resourceLink || "") + "\n" + + dateUtc.toLowerCase() + "\n\n"; + let hmacSha256 = crypto.createHMAC("sha256", key); + hmacSha256.update(text); + // Build autorization token, encode it and return + return encodeURIComponent("type=" + autorizationType + "&ver=" + autorizationVersion + "&sig=" + hmacSha256.digest("base64")); +} diff --git a/performance-test/src/modules/queue_client.js b/performance-test/src/modules/queue_client.js new file mode 100644 index 00000000..9ef6cb95 --- /dev/null +++ b/performance-test/src/modules/queue_client.js @@ -0,0 +1,12 @@ +import { b64encode } from 'k6/encoding'; +import http from 'k6/http'; + +export function sendMessageToQueue(message, url, accountKey){ + let headers = { + 'x-ms-date': new Date().toUTCString() + }; + + let body = `${b64encode(message)}`; + + return http.post(`${url}?${accountKey}`, body, { headers }); +} \ No newline at end of file diff --git a/performance-test/src/receipt_generator.js b/performance-test/src/receipt_generator.js new file mode 100644 index 00000000..47c0553e --- /dev/null +++ b/performance-test/src/receipt_generator.js @@ -0,0 +1,115 @@ +import { sleep, check } from 'k6'; +import { SharedArray } from 'k6/data'; + +import { randomString, createEvent, createReceipt } from './modules/common.js' +import { createDocument, deleteDocument, getDocumentByEventId } from "./modules/datastore_client.js"; +import {sendMessageToQueue} from "./modules/queue_client.js"; + +export let options = JSON.parse(open(__ENV.TEST_TYPE)); + +// read configuration +// note: SharedArray can currently only be constructed inside init code +// according to https://k6.io/docs/javascript-api/k6-data/sharedarray +const varsArray = new SharedArray('vars', function () { + return JSON.parse(open(`./${__ENV.VARS}`)).environment; +}); +// workaround to use shared array (only array should be used) +const vars = varsArray[0]; +//COSMOS +const receiptCosmosDBURI = `${vars.receiptCosmosDBURI}`; +const receiptDatabaseID = `${vars.receiptDatabaseID}`; +const receiptContainerID = `${vars.receiptContainerID}`; +const receiptCosmosDBPrimaryKey = `${__ENV.RECEIPT_COSMOS_DB_SUBSCRIPTION_KEY}`; +//QUEUE +const receiptQueueAccountName = `${vars.receiptQueueAccountName}`; +const receiptQueueName = `${vars.receiptQueueName}`; +const receiptQueueURI = `https://${receiptQueueAccountName}.queue.core.windows.net/${receiptQueueName}/messages`; +const receiptQueuePrimaryKey = `${__ENV.RECEIPT_QUEUE_SUBSCRIPTION_KEY}`; +// boundary time (s) to process event: activate trigger, process function, upload event to datastore +const processTime = `${__ENV.PROCESS_TIME >= 0 ? __ENV.PROCESS_TIME : 3}`; + +export function setup() { + // 2. setup code (once) + // The setup code runs, setting up the test environment (optional) and generating data + // used to reuse code for the same VU + + // todo + + // precondition is moved to default fn because in this stage + // __VU is always 0 and cannot be used to create env properly +} + +// teardown the test data +export function teardown(data) { + // todo +} + +function postcondition(eventId) { + // verify that published event have been stored properly in the datastore + let tag = { datastoreMethod: "GetDocumentByEventId" }; + let r = getDocumentByEventId(receiptCosmosDBURI, receiptDatabaseID, receiptContainerID, receiptCosmosDBPrimaryKey, eventId); + + console.log("GetDocumentByEventId call, Status " + r.status); + + let { _count, Documents } = r.json(); + + let receipt = Documents[0]; + + console.log("Receipt status " + receipt.status); + + check(r, { + "Assert published receipt is in the datastore and with status GENERATED or beyond": (_r) => _count === 1 && ( + receipt.status !== "INSERTED" && + receipt.status !== "FAILED" && + receipt.status !== "NOT_QUEUE_SENT" && + receipt.status !== "RETRY" + ) && + receipt.mdAttach + && + receipt.mdAttach.url + , + }, tag); + + if (_count) { + let receiptId = receipt.id; + + deleteDocument(receiptCosmosDBURI, receiptDatabaseID, receiptContainerID, receiptCosmosDBPrimaryKey, receiptId); + } +} + +export default function () { + // publish receipt + let tag = { datastoreMethod: "SaveReceipt" }; + const id = randomString(15, "abcdefghijklmnopqrstuvwxyz0123456789"); + + let receipt = createReceipt(id); + + let responseReceipt = createDocument(receiptCosmosDBURI, receiptDatabaseID, receiptContainerID, receiptCosmosDBPrimaryKey, receipt, id); + + console.log("PublishReceipt call, Status " + responseReceipt.status); + + check(responseReceipt, { + 'PublishReceipt status is 201': (_response) => responseReceipt.status === 201, + }, tag); + + //if the receipt is saved + if (responseReceipt.status === 201) { + //send event to queue + tag = { storageMethod: "SendMessageToQueue" }; + + let eventMessage = JSON.stringify(createEvent(id)); + let responseQueue = sendMessageToQueue(eventMessage, receiptQueueURI, receiptQueuePrimaryKey); + + console.log("SendMessageToQueue call, Status " + responseQueue.status); + + check(eventMessage, { + 'SendMessageToQueue status is 201': (_response) => responseQueue.status === 201, + }, tag); + + //if the message is sent to queue wait and check if it was correctly processed + if (responseQueue.status === 201) { + sleep(processTime); + postcondition(id); + } + } +} diff --git a/performance-test/src/test-types/constant.json b/performance-test/src/test-types/constant.json new file mode 100644 index 00000000..156206b7 --- /dev/null +++ b/performance-test/src/test-types/constant.json @@ -0,0 +1,50 @@ +{ + "discardResponseBodies": true, + "summaryTrendStats": [ + "avg", + "min", + "med", + "max", + "p(95)", + "p(99)", + "p(99.99)", + "count" + ], + "scenarios": { + "contacts": { + "executor": "constant-arrival-rate", + "duration": "3m", + "rate": 50, + "timeUnit": "1s", + "preAllocatedVUs": 20, + "maxVUs": 50 + } + }, + "thresholds": { + "http_req_failed": [ + "rate<0.1" + ], + "http_req_duration": [ + "p(99)<2000" + ], + "http_req_duration{group:::setup}": [ + "max>=0" + ], + "http_req_duration{scenario:contacts}": [ + "max>=0" + ], + "iteration_duration{scenario:contacts}": [ + "max>=0" + ], + "iteration_duration{group:::setup}": [ + "max>=0" + ], + "iterations{group:::setup}": [ + "rate>=0" + ], + "iterations{scenario:contacts}": [ + "rate>=0" + ] + }, + "setupTimeout": "60m" + } \ No newline at end of file diff --git a/performance-test/src/test-types/load.json b/performance-test/src/test-types/load.json new file mode 100644 index 00000000..1525a1a5 --- /dev/null +++ b/performance-test/src/test-types/load.json @@ -0,0 +1,34 @@ +{ + "summaryTrendStats": [ + "avg", + "min", + "med", + "max", + "p(95)", + "p(99)", + "p(99.99)", + "count" + ], + "stages": [ + { + "duration": "1m", + "target": 20 + }, + { + "duration": "2m", + "target": 20 + }, + { + "duration": "2m", + "target": 0 + } + ], + "thresholds": { + "http_req_failed": [ + "rate<0.001" + ], + "http_req_duration": [ + "p(99)<1500" + ] + } +} diff --git a/performance-test/src/test-types/spike.json b/performance-test/src/test-types/spike.json new file mode 100644 index 00000000..efbf1d4b --- /dev/null +++ b/performance-test/src/test-types/spike.json @@ -0,0 +1,38 @@ +{ + "summaryTrendStats": [ + "avg", + "min", + "med", + "max", + "p(95)", + "p(99)", + "p(99.99)", + "count" + ], + "stages": [ + { + "duration": "10s", + "target": 1 + }, + { + "duration": "20s", + "target": 5 + }, + { + "duration": "10s", + "target": 1 + }, + { + "duration": "10s", + "target": 0 + } + ], + "thresholds": { + "http_req_failed": [ + "rate<0.001" + ], + "http_req_duration": [ + "p(99)<100" + ] + } +} diff --git a/performance-test/src/test-types/stress.json b/performance-test/src/test-types/stress.json new file mode 100644 index 00000000..f9cf5d5a --- /dev/null +++ b/performance-test/src/test-types/stress.json @@ -0,0 +1,61 @@ +{ + "summaryTrendStats": [ + "avg", + "min", + "med", + "max", + "p(95)", + "p(99)", + "p(99.99)", + "count" + ], + "stages": [ + { + "duration": "2m", + "target": 100 + }, + { + "duration": "5m", + "target": 100 + }, + { + "duration": "2m", + "target": 200 + }, + { + "duration": "5m", + "target": 200 + }, + { + "duration": "2m", + "target": 300 + }, + { + "duration": "5m", + "target": 300 + }, + { + "duration": "2m", + "target": 400 + }, + { + "duration": "5m", + "target": 400 + }, + { + "duration": "10m", + "target": 0 + } + ], + "thresholds": { + "http_req_failed": [ + "rate<0.001" + ], + "http_req_duration": [ + "p(99)<5000" + ], + "http_req_duration{bizEventMethod:GetOrganizationReceipt}": [ + "p(95)<1500" + ] + } +} diff --git a/performance-test/src/uat.environment.json b/performance-test/src/uat.environment.json new file mode 100644 index 00000000..ee2adabd --- /dev/null +++ b/performance-test/src/uat.environment.json @@ -0,0 +1,12 @@ +{ + "environment": [ + { + "env": "uat", + "receiptCosmosDBURI": "https://pagopa-u-weu-receipts-ds-cosmos-account.documents.azure.com:443/", + "receiptDatabaseID":"db", + "receiptContainerID":"receipts", + "receiptQueueAccountName": "pagopauweureceiptsfnsa", + "receiptQueueName": "pagopa-u-weu-receipts-queue-receipt-waiting-4-gen" + } + ] +} diff --git a/src/main/java/it/gov/pagopa/receipt/pdf/generator/entity/event/DebtorPosition.java b/src/main/java/it/gov/pagopa/receipt/pdf/generator/entity/event/DebtorPosition.java index c53bbf4d..80540a78 100644 --- a/src/main/java/it/gov/pagopa/receipt/pdf/generator/entity/event/DebtorPosition.java +++ b/src/main/java/it/gov/pagopa/receipt/pdf/generator/entity/event/DebtorPosition.java @@ -1,5 +1,6 @@ package it.gov.pagopa.receipt.pdf.generator.entity.event; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.*; @Getter @@ -7,8 +8,10 @@ @NoArgsConstructor @AllArgsConstructor @Builder +@JsonIgnoreProperties(ignoreUnknown = true) public class DebtorPosition { private String modelType; private String noticeNumber; private String iuv; + private String iur; }