Full Code of artilleryio/artillery for AI

main 5ccaa8bb39c5 cached
770 files
27.7 MB
2.7M tokens
849 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (10,936K chars total). Download the full file to get everything.
Repository: artilleryio/artillery
Branch: main
Commit: 5ccaa8bb39c5
Files: 770
Total size: 27.7 MB

Directory structure:
gitextract_y554pkx1/

├── .artilleryrc
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── create-release-pr.yml
│       ├── docker-ecs-worker-image.yml
│       ├── docker-publish-artillery.yml
│       ├── examples.yml
│       ├── npm-publish-all-packages-canary.yml
│       ├── npm-publish-all-packages.yml
│       ├── npm-publish-artillery-engine-posthog.yml
│       ├── npm-publish-artillery-plugin-memory-inspector.yml
│       ├── npm-publish-artillery-types.yml
│       ├── npm-publish-specific-package.yml
│       ├── run-aws-tests-on-pr.yml
│       ├── run-distributed-tests.yml
│       ├── run-tests-windows.yml
│       ├── run-tests.yml
│       ├── s3-publish-cf-templates.yml
│       └── scripts/
│           ├── get-all-packages-by-name.js
│           ├── get-tests-in-package-location.js
│           ├── npm-command-retry.sh
│           └── replace-package-versions.js
├── .gitignore
├── .npmignore
├── .npmrc
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE-BSL.txt
├── LICENSE.txt
├── README.md
├── SECURITY.md
├── biome.json
├── commitlint.config.js
├── examples/
│   ├── README.md
│   ├── artillery-engine-example/
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── example.yaml
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── index.js
│   ├── artillery-plugin-hello-world/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test.yml
│   ├── automated-checks/
│   │   ├── README.md
│   │   └── load-test-with-automated-checks.yml
│   ├── browser-load-testing-playwright/
│   │   ├── README.md
│   │   ├── browser-load-test.ts
│   │   ├── browser-load-test.yml
│   │   ├── browser-smoke-test.ts
│   │   ├── browser-smoke-test.yml
│   │   ├── browser-test-with-steps.yml
│   │   ├── flows.js
│   │   └── pages.csv
│   ├── browser-playwright-reuse-authentication/
│   │   ├── README.md
│   │   ├── flow.js
│   │   ├── package.json
│   │   ├── scenario.yml
│   │   └── storage.json
│   ├── browser-playwright-reuse-typescript/
│   │   ├── README.md
│   │   ├── e2e/
│   │   │   ├── .gitignore
│   │   │   ├── helpers/
│   │   │   │   └── index.ts
│   │   │   ├── playwright.config.ts
│   │   │   └── tests/
│   │   │       └── get-issues.spec.ts
│   │   ├── package.json
│   │   └── performance/
│   │       ├── processor.ts
│   │       └── search-for-ts-doc.yml
│   ├── cicd/
│   │   ├── README.md
│   │   ├── aws-codebuild/
│   │   │   ├── README.md
│   │   │   ├── buildspec.yml
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── azure-devops/
│   │   │   ├── README.md
│   │   │   ├── azure-pipelines.yml
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── circleci/
│   │   │   ├── .circleci/
│   │   │   │   └── config.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── github-actions/
│   │   │   ├── .github/
│   │   │   │   └── workflows/
│   │   │   │       └── load-test.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── gitlab-ci-cd/
│   │   │   ├── .gitlab-ci.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   └── jenkins/
│   │       ├── Jenkinsfile
│   │       ├── README.md
│   │       └── tests/
│   │           └── performance/
│   │               └── socket-io.yml
│   ├── functional-testing-with-expect-plugin/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── functional-load-tests.yml
│   │   └── package.json
│   ├── generating-vu-tokens/
│   │   ├── README.md
│   │   ├── auth-with-token.yml
│   │   └── helpers.js
│   ├── graphql-api-server/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── graphql.yaml
│   │   ├── package.json
│   │   └── prisma/
│   │       ├── migrations/
│   │       │   ├── 20211005051218_init/
│   │       │   │   └── migration.sql
│   │       │   └── migration_lock.toml
│   │       └── schema.prisma
│   ├── http-file-uploads/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── file-uploads.yml
│   │   ├── package.json
│   │   └── uploads/
│   │       └── .keep
│   ├── http-metrics-by-endpoint/
│   │   └── endpoint-metrics.yml
│   ├── http-set-custom-header/
│   │   ├── README.md
│   │   ├── helpers.js
│   │   └── set-header.yml
│   ├── http-socketio-server/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── data/
│   │   │   └── movies.json
│   │   ├── http-socket.yml
│   │   ├── http.js
│   │   ├── package.json
│   │   └── socketio.js
│   ├── k8s-testing-with-kubectl-artillery/
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── Dockerfile
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── data/
│   │   │   └── movies.json
│   │   ├── hack/
│   │   │   └── kind/
│   │   │       └── kind-with-registry.sh
│   │   ├── http.js
│   │   ├── k8s-deploy.yaml
│   │   └── package.json
│   ├── multiple-scenario-specs/
│   │   ├── README.md
│   │   ├── common-config.yml
│   │   └── scenarios/
│   │       ├── armadillo.yml
│   │       ├── dino.yml
│   │       └── pony.yml
│   ├── prometheus-grafana-dashboards/
│   │   ├── README.md
│   │   ├── dashboard-http-metrics-1652971310916.json
│   │   └── dashboard-vusers-metrics-1652971366368.json
│   ├── refresh-auth-token/
│   │   ├── README.md
│   │   ├── refresh.mjs
│   │   └── refresh.yml
│   ├── rpc-twirp-with-custom-function/
│   │   ├── README.md
│   │   ├── test/
│   │   │   ├── processor.mjs
│   │   │   └── scenario.yml
│   │   └── twirp/
│   │       ├── package.json
│   │       ├── protos/
│   │       │   ├── haberdasher.pb.js
│   │       │   └── haberdasher.proto
│   │       └── server/
│   │           ├── haberdasher/
│   │           │   └── index.js
│   │           └── index.js
│   ├── scenario-weights/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── package.json
│   │   └── scenario-weights.yml
│   ├── script-overrides/
│   │   ├── README.md
│   │   └── test.yaml
│   ├── soap-with-custom-function/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── processor.js
│   │   ├── server/
│   │   │   ├── MyService.wsdl
│   │   │   ├── app.js
│   │   │   └── package.json
│   │   └── soap.yml
│   ├── socket-io/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── package.json
│   │   ├── public/
│   │   │   └── index.html
│   │   └── socket-io.yml
│   ├── starter-kit/
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── processors/
│   │   │   ├── _baseProcessor.js
│   │   │   ├── sample_task_01.js
│   │   │   └── sample_task_02.js
│   │   ├── reports/
│   │   │   └── .gitkeep
│   │   └── scenarios/
│   │       ├── sample_task_01.yaml
│   │       ├── sample_task_02.yaml
│   │       └── sample_task_03.yaml
│   ├── table-driven-functional-tests/
│   │   ├── README.md
│   │   ├── functional-test.yml
│   │   ├── package.json
│   │   └── request-response.csv
│   ├── tracetest/
│   │   └── README.md
│   ├── track-custom-metrics/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── custom-metrics.yml
│   │   ├── metrics.js
│   │   └── package.json
│   ├── using-cookies/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── cookies.yml
│   │   └── package.json
│   ├── using-data-from-csv/
│   │   ├── csv/
│   │   │   └── urls.csv
│   │   └── website-test.yml
│   ├── using-data-from-redis/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── processor.js
│   │   ├── scenario.yml
│   │   └── scripts/
│   │       └── seed-redis-with-users.js
│   └── websockets/
│       ├── .gitignore
│       ├── README.md
│       ├── app.js
│       ├── my-functions.js
│       ├── package.json
│       └── test.yml
├── package.json
├── packages/
│   ├── artillery/
│   │   ├── Dockerfile
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── bin/
│   │   │   ├── run
│   │   │   └── run.cmd
│   │   ├── console-reporter.js
│   │   ├── doc/
│   │   │   └── CLA.md
│   │   ├── lib/
│   │   │   ├── artillery-global.js
│   │   │   ├── cli/
│   │   │   │   ├── banner.js
│   │   │   │   ├── common-flags.js
│   │   │   │   └── hooks/
│   │   │   │       └── version.js
│   │   │   ├── cmds/
│   │   │   │   ├── dino.js
│   │   │   │   ├── quick.js
│   │   │   │   ├── report.js
│   │   │   │   ├── run-aci.js
│   │   │   │   ├── run-fargate.js
│   │   │   │   ├── run-lambda.js
│   │   │   │   └── run.js
│   │   │   ├── console-capture.js
│   │   │   ├── console-reporter.js
│   │   │   ├── create-bom/
│   │   │   │   ├── built-in-plugins.js
│   │   │   │   └── create-bom.js
│   │   │   ├── dispatcher.js
│   │   │   ├── dist.js
│   │   │   ├── index.js
│   │   │   ├── launch-platform.js
│   │   │   ├── load-plugins.js
│   │   │   ├── platform/
│   │   │   │   ├── aws/
│   │   │   │   │   ├── aws-cloudwatch.js
│   │   │   │   │   ├── aws-create-sqs-queue.js
│   │   │   │   │   ├── aws-ensure-s3-bucket-exists.js
│   │   │   │   │   ├── aws-get-account-id.js
│   │   │   │   │   ├── aws-get-bucket-region.js
│   │   │   │   │   ├── aws-get-credentials.js
│   │   │   │   │   ├── aws-get-default-region.js
│   │   │   │   │   ├── aws-whoami.js
│   │   │   │   │   ├── constants.js
│   │   │   │   │   └── iam-cf-templates/
│   │   │   │   │       ├── aws-iam-fargate-cf-template.yml
│   │   │   │   │       ├── aws-iam-lambda-cf-template.yml
│   │   │   │   │       ├── gh-oidc-fargate.yml
│   │   │   │   │       └── gh-oidc-lambda.yml
│   │   │   │   ├── aws-ecs/
│   │   │   │   │   ├── ecs.js
│   │   │   │   │   ├── legacy/
│   │   │   │   │   │   ├── aws-util.js
│   │   │   │   │   │   ├── bom.js
│   │   │   │   │   │   ├── constants.js
│   │   │   │   │   │   ├── create-s3-client.js
│   │   │   │   │   │   ├── create-test.js
│   │   │   │   │   │   ├── errors.js
│   │   │   │   │   │   ├── find-public-subnets.js
│   │   │   │   │   │   ├── plugins/
│   │   │   │   │   │   │   ├── artillery-plugin-inspect-script/
│   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   └── artillery-plugin-sqs-reporter/
│   │   │   │   │   │   │       ├── azure-aqs.js
│   │   │   │   │   │   │       └── index.js
│   │   │   │   │   │   ├── plugins.js
│   │   │   │   │   │   ├── run-cluster.js
│   │   │   │   │   │   ├── sqs-reporter.js
│   │   │   │   │   │   ├── tags.js
│   │   │   │   │   │   ├── test-run-status.js
│   │   │   │   │   │   ├── time.js
│   │   │   │   │   │   └── util.js
│   │   │   │   │   └── worker/
│   │   │   │   │       ├── Dockerfile
│   │   │   │   │       ├── helpers.sh
│   │   │   │   │       └── loadgen-worker
│   │   │   │   ├── aws-lambda/
│   │   │   │   │   ├── dependencies.js
│   │   │   │   │   ├── index.js
│   │   │   │   │   ├── lambda-handler/
│   │   │   │   │   │   ├── a9-handler-dependencies.js
│   │   │   │   │   │   ├── a9-handler-helpers.js
│   │   │   │   │   │   ├── a9-handler-index.js
│   │   │   │   │   │   └── package.json
│   │   │   │   │   └── prices.js
│   │   │   │   ├── az/
│   │   │   │   │   ├── aci.js
│   │   │   │   │   ├── aqs-queue-consumer.js
│   │   │   │   │   └── regions.js
│   │   │   │   ├── cloud/
│   │   │   │   │   ├── api.js
│   │   │   │   │   ├── cloud.js
│   │   │   │   │   └── http-client.js
│   │   │   │   ├── local/
│   │   │   │   │   ├── artillery-worker-local.js
│   │   │   │   │   ├── index.js
│   │   │   │   │   └── worker.js
│   │   │   │   └── worker-states.js
│   │   │   ├── queue-consumer/
│   │   │   │   └── index.js
│   │   │   ├── stash.js
│   │   │   ├── telemetry.js
│   │   │   ├── util/
│   │   │   │   ├── await-on-ee.js
│   │   │   │   ├── generate-id.js
│   │   │   │   ├── parse-tag-string.js
│   │   │   │   ├── prepare-test-execution-plan.js
│   │   │   │   ├── sleep.js
│   │   │   │   └── validate-script.js
│   │   │   ├── util.js
│   │   │   └── utils-config.js
│   │   ├── man/
│   │   │   ├── artillery.1
│   │   │   └── artillery.1.md
│   │   ├── package.json
│   │   ├── test/
│   │   │   ├── cli/
│   │   │   │   ├── async-hooks-esm.test.js
│   │   │   │   ├── command-report.test.js
│   │   │   │   ├── command-run.test.js
│   │   │   │   ├── custom-plugin.test.js
│   │   │   │   ├── errors-and-warnings.test.js
│   │   │   │   ├── run-smoke.test.js
│   │   │   │   ├── run-typescript.test.js
│   │   │   │   ├── suggested-exit-codes.test.js
│   │   │   │   ├── unknown-engine.test.js
│   │   │   │   └── variables-from-external-files.test.js
│   │   │   ├── cloud-e2e/
│   │   │   │   ├── fargate/
│   │   │   │   │   ├── bom.test.js
│   │   │   │   │   ├── cloud-api-key.test.js
│   │   │   │   │   ├── cw-adot.test.js
│   │   │   │   │   ├── dd-adot.test.js
│   │   │   │   │   ├── ensure-plugin.test.js
│   │   │   │   │   ├── expect-plugin.test.js
│   │   │   │   │   ├── fixtures/
│   │   │   │   │   │   ├── adot/
│   │   │   │   │   │   │   ├── adot-cloudwatch.yml
│   │   │   │   │   │   │   ├── adot-dd-pass.yml
│   │   │   │   │   │   │   ├── flow.js
│   │   │   │   │   │   │   └── helpers.js
│   │   │   │   │   │   ├── cli-exit-conditions/
│   │   │   │   │   │   │   ├── with-expect-ensure.yml
│   │   │   │   │   │   │   └── with-expect.yml
│   │   │   │   │   │   ├── cli-kitchen-sink/
│   │   │   │   │   │   │   ├── kitchen-sink-env
│   │   │   │   │   │   │   └── kitchen-sink.yml
│   │   │   │   │   │   ├── cloud-api-key-load/
│   │   │   │   │   │   │   └── scenario.yml
│   │   │   │   │   │   ├── heartbeat/
│   │   │   │   │   │   │   └── heartbeat.yml
│   │   │   │   │   │   ├── large-output/
│   │   │   │   │   │   │   ├── lots-of-output.yml
│   │   │   │   │   │   │   └── processor.js
│   │   │   │   │   │   ├── memory-hog/
│   │   │   │   │   │   │   ├── memory-hog.yml
│   │   │   │   │   │   │   └── processor.js
│   │   │   │   │   │   ├── mixed-hierarchy/
│   │   │   │   │   │   │   ├── code/
│   │   │   │   │   │   │   │   ├── functions.js
│   │   │   │   │   │   │   │   ├── lib/
│   │   │   │   │   │   │   │   │   └── signer.js
│   │   │   │   │   │   │   │   ├── meow.js
│   │   │   │   │   │   │   │   └── set-url.js
│   │   │   │   │   │   │   ├── config/
│   │   │   │   │   │   │   │   ├── config-no-file-uploads.yml
│   │   │   │   │   │   │   │   └── config.yml
│   │   │   │   │   │   │   ├── data/
│   │   │   │   │   │   │   │   └── variables.csv
│   │   │   │   │   │   │   ├── package.json
│   │   │   │   │   │   │   └── scenarios/
│   │   │   │   │   │   │       ├── mixed-hierarchy-dino.yml
│   │   │   │   │   │   │       └── mixed-hierarchy-pony.yml
│   │   │   │   │   │   ├── simple-bom/
│   │   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   │   ├── deps/
│   │   │   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   │   │   ├── data/
│   │   │   │   │   │   │   │   │   ├── lists.json
│   │   │   │   │   │   │   │   │   ├── names-local.csv
│   │   │   │   │   │   │   │   │   ├── names-prod.csv
│   │   │   │   │   │   │   │   │   ├── names-test.csv
│   │   │   │   │   │   │   │   │   └── user-data.csv
│   │   │   │   │   │   │   │   ├── dummy-util.js
│   │   │   │   │   │   │   │   ├── functions.js
│   │   │   │   │   │   │   │   ├── local-mod-dir/
│   │   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   │   └── not-included.json
│   │   │   │   │   │   │   └── simple-bom.yml
│   │   │   │   │   │   ├── ts-external-pkg/
│   │   │   │   │   │   │   ├── package.json
│   │   │   │   │   │   │   ├── processor.ts
│   │   │   │   │   │   │   └── with-external-foreign-pkg.yml
│   │   │   │   │   │   └── uses-ensure/
│   │   │   │   │   │       └── with-ensure.yaml
│   │   │   │   │   ├── heartbeat.test.js
│   │   │   │   │   ├── memory.test.js
│   │   │   │   │   ├── misc.test.js
│   │   │   │   │   └── processors.test.js
│   │   │   │   └── lambda/
│   │   │   │       ├── fixtures/
│   │   │   │       │   ├── dotenv/
│   │   │   │       │   │   ├── .env-test
│   │   │   │       │   │   ├── dotenv-test.yml
│   │   │   │       │   │   └── processor.js
│   │   │   │       │   ├── quick-loop-with-csv/
│   │   │   │       │   │   ├── blitz.yml
│   │   │   │       │   │   ├── config.yml
│   │   │   │       │   │   ├── helpers.js
│   │   │   │       │   │   └── test.csv
│   │   │   │       │   └── ts-external-pkg/
│   │   │   │       │       ├── package.json
│   │   │   │       │       ├── processor.ts
│   │   │   │       │       └── with-external-foreign-pkg.yml
│   │   │   │       ├── lambda-bom.test.js
│   │   │   │       ├── lambda-dotenv.test.js
│   │   │   │       ├── lambda-ensure.test.js
│   │   │   │       ├── lambda-expect.test.js
│   │   │   │       └── lambda-smoke.test.js
│   │   │   ├── data/
│   │   │   │   ├── calc-test-data-1.csv
│   │   │   │   ├── calc-test-data-2.csv
│   │   │   │   ├── geometric.json
│   │   │   │   ├── multi-period-local-report.json
│   │   │   │   ├── response-times-histograms.json
│   │   │   │   └── ssms-buckets.json
│   │   │   ├── helpers/
│   │   │   │   ├── expectations.js
│   │   │   │   ├── index.js
│   │   │   │   └── sleep.js
│   │   │   ├── index.js
│   │   │   ├── integration/
│   │   │   │   └── core/
│   │   │   │       ├── fixtures/
│   │   │   │       │   ├── http-file-upload-processor.js
│   │   │   │       │   └── http-file-upload.yml
│   │   │   │       └── http-file-upload.test.js
│   │   │   ├── lib/
│   │   │   │   ├── index.js
│   │   │   │   ├── run.sh
│   │   │   │   ├── test_util.js
│   │   │   │   └── validate-script.test.js
│   │   │   ├── plugins/
│   │   │   │   ├── artillery-plugin-dummy-csv-logger/
│   │   │   │   │   └── index.js
│   │   │   │   └── artillery-plugin-httphooks/
│   │   │   │       ├── index.js
│   │   │   │       └── package.json
│   │   │   ├── publish-metrics/
│   │   │   │   ├── fixtures/
│   │   │   │   │   ├── flow.js
│   │   │   │   │   ├── helpers.js
│   │   │   │   │   ├── http-trace.yml
│   │   │   │   │   └── playwright-trace.yml
│   │   │   │   └── tracing/
│   │   │   │       ├── http-trace-assertions.js
│   │   │   │       ├── http-trace.test.js
│   │   │   │       ├── playwright-trace-assertions.js
│   │   │   │       └── playwright-trace.test.js
│   │   │   ├── runner.sh
│   │   │   ├── scripts/
│   │   │   │   ├── environments.yaml
│   │   │   │   ├── environments2.json
│   │   │   │   ├── gh_215_add_token.json
│   │   │   │   ├── hello.json
│   │   │   │   ├── hello_config.json
│   │   │   │   ├── hello_plugin.json
│   │   │   │   ├── hello_with_xpath.json
│   │   │   │   ├── http/
│   │   │   │   │   ├── async_function.json
│   │   │   │   │   ├── error_code_function.json
│   │   │   │   │   ├── error_message_function.json
│   │   │   │   │   ├── processors.js
│   │   │   │   │   ├── simple_function.json
│   │   │   │   │   └── undefined_function.json
│   │   │   │   ├── local-urls.csv
│   │   │   │   ├── multiple_payloads.json
│   │   │   │   ├── pets.csv
│   │   │   │   ├── pets.txt
│   │   │   │   ├── processor.js
│   │   │   │   ├── ramp-regression-1682.json
│   │   │   │   ├── ramp.json
│   │   │   │   ├── report.json
│   │   │   │   ├── scenario-async-esm-hooks/
│   │   │   │   │   ├── helpers.mjs
│   │   │   │   │   └── test.yml
│   │   │   │   ├── scenario-cli-variables/
│   │   │   │   │   ├── processor.js
│   │   │   │   │   ├── scenario-with-other-nested-config.yml
│   │   │   │   │   └── scenario-with-variables.yml
│   │   │   │   ├── scenario-config-different-folder/
│   │   │   │   │   ├── __processor__/
│   │   │   │   │   │   └── index.js
│   │   │   │   │   ├── config/
│   │   │   │   │   │   ├── config-processor-backward-compatibility.yml
│   │   │   │   │   │   └── config.yml
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-named/
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-payload-with-envs/
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── artillery-config.yml
│   │   │   │   │   ├── data/
│   │   │   │   │   │   └── my-data.csv
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-with-custom-plugin/
│   │   │   │   │   ├── custom-plugin.yml
│   │   │   │   │   └── processor.js
│   │   │   │   ├── scenario-with-parallel/
│   │   │   │   │   ├── processor.js
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenarios-typescript/
│   │   │   │   │   ├── error.yml
│   │   │   │   │   ├── lodash.yml
│   │   │   │   │   └── processor.ts
│   │   │   │   ├── single_payload.json
│   │   │   │   ├── single_payload_object.json
│   │   │   │   ├── single_payload_options.json
│   │   │   │   ├── test-calc-server.yml
│   │   │   │   ├── test-suggest-exit-code.js
│   │   │   │   ├── test-suggest-exit-code.yml
│   │   │   │   ├── unknown_engine.json
│   │   │   │   ├── urls.csv
│   │   │   │   ├── wildcard_processor.js
│   │   │   │   ├── wildcard_socketio.json
│   │   │   │   ├── with-dotenv/
│   │   │   │   │   ├── my-vars
│   │   │   │   │   └── with-dotenv.yml
│   │   │   │   └── with-process-env/
│   │   │   │       ├── processor.js
│   │   │   │       ├── with-env.yml
│   │   │   │       └── with-processEnvironment.yml
│   │   │   ├── targets/
│   │   │   │   ├── calc-server.js
│   │   │   │   ├── gh_215_target.js
│   │   │   │   ├── http-file-upload-server.js
│   │   │   │   └── targetServer.js
│   │   │   ├── tinyproxy.conf
│   │   │   └── unit/
│   │   │       ├── before_after_hooks.test.js
│   │   │       ├── create-bom.test.js
│   │   │       ├── dist.test.js
│   │   │       ├── fargate-bom.test.js
│   │   │       ├── processor.js
│   │   │       ├── ssms-basic.test.js
│   │   │       ├── ssms-buckets.test.js
│   │   │       ├── ssms-multi-process.test.js
│   │   │       └── ssms-worker.js
│   │   ├── types.d.ts
│   │   └── util.js
│   ├── artillery-engine-playwright/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fargate.aws.js
│   │       ├── fixtures/
│   │       │   ├── processor.js
│   │       │   ├── processor.ts
│   │       │   ├── pw-acceptance-ts.yml
│   │       │   ├── pw-acceptance.yml
│   │       │   └── pw-url-normalization.yml
│   │       └── index.test.js
│   ├── artillery-engine-posthog/
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── examples/
│   │   │   ├── example.yml
│   │   │   ├── example_js_logic.yml
│   │   │   └── logic.js
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── index.js
│   ├── artillery-plugin-apdex/
│   │   ├── LICENSE
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── processor.js
│   │       │   └── scenario.yml
│   │       └── index.spec.js
│   ├── artillery-plugin-ensure/
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── test/
│   │   │   ├── fixtures/
│   │   │   │   ├── processor.js
│   │   │   │   ├── scenario-custom-metrics.yml
│   │   │   │   └── scenario.yml
│   │   │   ├── index.spec.js
│   │   │   └── utils.unit.js
│   │   └── utils.js
│   ├── artillery-plugin-expect/
│   │   ├── .circleci/
│   │   │   └── config.yml
│   │   ├── .gitignore
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── expectations.js
│   │   │   └── formatters.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── cdn-test.yml
│   │       ├── index.js
│   │       ├── lib/
│   │       │   └── formatters.js
│   │       ├── mock-pets-server.yaml
│   │       ├── parallel.yml
│   │       ├── pets-fail-test.yaml
│   │       ├── pets-test.yaml
│   │       ├── run.sh
│   │       └── urls.csv
│   ├── artillery-plugin-fake-data/
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   └── package.json
│   ├── artillery-plugin-memory-inspector/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── myProcessor.js
│   │       │   └── scenario.yml
│   │       ├── index.spec.js
│   │       ├── server/
│   │       │   └── server.js
│   │       └── util.js
│   ├── artillery-plugin-metrics-by-endpoint/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── scenario-parallel.yml
│   │       │   ├── scenario-templated-url.yml
│   │       │   └── scenario.yml
│   │       ├── index.spec.js
│   │       └── index.unit.js
│   ├── artillery-plugin-publish-metrics/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── cloudwatch.js
│   │   │   ├── datadog.js
│   │   │   ├── dynatrace/
│   │   │   │   └── index.js
│   │   │   ├── mixpanel.js
│   │   │   ├── newrelic/
│   │   │   │   ├── README.md
│   │   │   │   └── index.js
│   │   │   ├── open-telemetry/
│   │   │   │   ├── exporters.js
│   │   │   │   ├── file-span-exporter.js
│   │   │   │   ├── index.js
│   │   │   │   ├── metrics.js
│   │   │   │   ├── outlier-detection-processor.js
│   │   │   │   ├── tracing/
│   │   │   │   │   ├── base.js
│   │   │   │   │   ├── http.js
│   │   │   │   │   └── playwright.js
│   │   │   │   └── translators/
│   │   │   │       ├── vendor-adot.js
│   │   │   │       └── vendor-otel.js
│   │   │   ├── prometheus.js
│   │   │   ├── splunk/
│   │   │   │   ├── README.md
│   │   │   │   └── index.js
│   │   │   └── util.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── config-agent.yaml
│   │       ├── config-api.yaml
│   │       ├── config-dynatrace.yaml
│   │       ├── config-honeycomb.yaml
│   │       ├── config-influxdb-statsd.yaml
│   │       ├── config-mixpanel.yaml
│   │       ├── config-newrelic-api.yaml
│   │       ├── config-prometheus.yaml
│   │       ├── config-splunk.yaml
│   │       ├── config-statsd.yaml
│   │       ├── index.js
│   │       ├── scenario.yaml
│   │       └── unit/
│   │           ├── adot-translators.js
│   │           └── tracing.js
│   ├── artillery-plugin-slack/
│   │   ├── LICENSE.txt
│   │   ├── index.js
│   │   └── package.json
│   ├── commons/
│   │   ├── engine_util.js
│   │   ├── index.js
│   │   ├── jitter.js
│   │   └── package.json
│   ├── core/
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── engine_http.js
│   │   │   ├── engine_socketio.js
│   │   │   ├── engine_ws.js
│   │   │   ├── is-idle-phase.js
│   │   │   ├── phases.js
│   │   │   ├── readers.js
│   │   │   ├── runner.js
│   │   │   ├── ssms.js
│   │   │   └── weighted-pick.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── acceptance/
│   │       │   ├── arrivals.test.js
│   │       │   ├── basic-auth.test.js
│   │       │   ├── capture-ws.test.js
│   │       │   ├── capture.test.js
│   │       │   ├── conditional-requests.test.js
│   │       │   ├── config-variables.test.js
│   │       │   ├── cookies-http.test.js
│   │       │   ├── cookies-socketio.test.js
│   │       │   ├── headers.test.js
│   │       │   ├── loop.test.js
│   │       │   ├── misc/
│   │       │   │   ├── helper.js
│   │       │   │   ├── http.test.js
│   │       │   │   ├── large-payload.test.js
│   │       │   │   ├── multiple-phases.test.js
│   │       │   │   ├── socketio-with-args.test.js
│   │       │   │   ├── socketio-with-http.test.js
│   │       │   │   ├── socketio.test.js
│   │       │   │   ├── ws-proxy.test.js
│   │       │   │   └── ws.test.js
│   │       │   ├── multiple-payloads.test.js
│   │       │   ├── multiple-runners.test.js
│   │       │   ├── parallel.test.js
│   │       │   ├── probability.test.js
│   │       │   ├── think-time.test.js
│   │       │   ├── tls.test.js
│   │       │   ├── ws/
│   │       │   │   ├── scripts/
│   │       │   │   │   ├── subprotocols.json
│   │       │   │   │   └── ws-tls.json
│   │       │   │   ├── ws-subprotocols.test.js
│   │       │   │   └── ws-tls.test.js
│   │       │   └── ws-engine.test.js
│   │       ├── plugins/
│   │       │   ├── normal_plugin/
│   │       │   │   ├── index.js
│   │       │   │   └── package.json
│   │       │   └── packaged_plugin/
│   │       │       ├── index.js
│   │       │       └── package.json
│   │       ├── quarantine/
│   │       │   ├── concurrent-requests.test.js
│   │       │   ├── test_config_plugin_package.js
│   │       │   ├── test_engine_http.js
│   │       │   └── test_environments.js
│   │       ├── scripts/
│   │       │   ├── after_test.json
│   │       │   ├── all_features.json
│   │       │   ├── arrival_phases.json
│   │       │   ├── arrival_phases_time_format.json
│   │       │   ├── artillery_plugin.json
│   │       │   ├── before_test.json
│   │       │   ├── captures-regexp.json
│   │       │   ├── concurrent_requests_arrival_count.json
│   │       │   ├── concurrent_requests_arrival_rate.json
│   │       │   ├── concurrent_requests_multiple_phases.json
│   │       │   ├── concurrent_requests_ramp_to.json
│   │       │   ├── config_variables.json
│   │       │   ├── cookies.json
│   │       │   ├── cookies_malformed_response.json
│   │       │   ├── cookies_socketio.json
│   │       │   ├── data/
│   │       │   │   ├── pets.csv
│   │       │   │   └── urls.csv
│   │       │   ├── defaults_cookies.json
│   │       │   ├── express_socketio.json
│   │       │   ├── generators_http.json
│   │       │   ├── hello.json
│   │       │   ├── hello_basic_auth.json
│   │       │   ├── hello_environments.json
│   │       │   ├── hello_socketio.json
│   │       │   ├── hello_socketio_with_args.json
│   │       │   ├── hello_ws.json
│   │       │   ├── iftrue.json
│   │       │   ├── large_payload.json
│   │       │   ├── loop.json
│   │       │   ├── loop_infinite.json
│   │       │   ├── loop_nested_range.json
│   │       │   ├── loop_range.json
│   │       │   ├── multiple_payloads.json
│   │       │   ├── multiple_phases.json
│   │       │   ├── namespaces_socketio.json
│   │       │   ├── no_defaults_cookies.json
│   │       │   ├── parallel.json
│   │       │   ├── plugin_packaged_inner.json
│   │       │   ├── plugin_packaged_inner_override_outter.json
│   │       │   ├── plugin_packaged_outer.json
│   │       │   ├── plugin_statsd.json
│   │       │   ├── probability.json
│   │       │   ├── single_payload.json
│   │       │   ├── thinks_http.json
│   │       │   ├── tls-lax.json
│   │       │   ├── tls-strict.json
│   │       │   └── ws_proxy.json
│   │       ├── targets/
│   │       │   ├── certs/
│   │       │   │   ├── private-key.pem
│   │       │   │   └── public-cert.pem
│   │       │   ├── express_socketio.js
│   │       │   ├── simple.js
│   │       │   ├── simple_socketio.js
│   │       │   ├── simple_tls.js
│   │       │   ├── simple_ws.js
│   │       │   ├── socketio_args.js
│   │       │   ├── ws_proxy.js
│   │       │   └── ws_tls.js
│   │       └── unit/
│   │           ├── context_functions.test.js
│   │           ├── engine_http.test.js
│   │           ├── engine_socketio.test.js
│   │           ├── engine_ws.test.js
│   │           ├── interpolation.test.js
│   │           ├── large-json-payload-669kb.json
│   │           ├── large-json-payload-7.2mb.json
│   │           ├── phases.test.js
│   │           ├── readers.test.js
│   │           ├── templates.test.js
│   │           └── util.test.js
│   ├── skytrace/
│   │   ├── .editorconfig
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── asciiart-flow.yml
│   │   ├── bin/
│   │   │   ├── dev
│   │   │   ├── dev.cmd
│   │   │   ├── run
│   │   │   └── run.cmd
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── commands/
│   │   │   │   ├── ping.ts
│   │   │   │   └── run.ts
│   │   │   ├── index.ts
│   │   │   └── telemetry.ts
│   │   └── tsconfig.json
│   └── types/
│       ├── .gitignore
│       ├── LICENSE
│       ├── definitions.ts
│       ├── generate-schema.js
│       ├── package.json
│       ├── plugins/
│       │   └── expect.ts
│       ├── schema/
│       │   ├── config/
│       │   │   └── phases.js
│       │   ├── config.js
│       │   ├── engines/
│       │   │   ├── common.js
│       │   │   ├── http.js
│       │   │   ├── playwright.js
│       │   │   ├── socketio.js
│       │   │   └── websocket.js
│       │   ├── index.js
│       │   ├── joi.helpers.js
│       │   ├── plugins/
│       │   │   ├── apdex.js
│       │   │   ├── ensure.js
│       │   │   ├── expect.js
│       │   │   ├── fake-data.js
│       │   │   ├── metrics-by-endpoint.js
│       │   │   ├── publish-metrics.js
│       │   │   └── slack.js
│       │   └── scenario.js
│       ├── test/
│       │   ├── config.phases.test.ts
│       │   ├── engine.arbitrary.test.ts
│       │   ├── engine.http.test.ts
│       │   ├── engine.socketio.test.ts
│       │   ├── engine.websocket.test.ts
│       │   ├── examples.test.ts
│       │   ├── helpers.ts
│       │   ├── plugin.expect.test.ts
│       │   ├── simple.test.ts
│       │   └── tsconfig.json
│       ├── tsconfig.json
│       └── tsconfig.schema.json
├── socket.yml
└── turbo.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .artilleryrc
================================================
{
  "logFilenameFormat": "[artillery_report_]YMMDD_HHmmSS[.json]"
}


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating it.
-->

Version info: <!-- artillery -v output -->
```
<version>
```

Running this command: 
```
<command>
```

I expected to see this happen:

*explanation*

Instead, this happened:

*explanation*

Files being used:
```
<relevant yaml/js/csv go here>
```


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    exclude-paths:
      - "examples/**"


================================================
FILE: .github/pull_request_template.md
================================================
## Description

<!-- PR description goes here.

Why the change is needed, and any details to help code reviewers.

-->

## Pre-merge checklist

**This is for use by the Artillery team. Please leave this in if you're contributing to Artillery.**

- [ ] Does this require an update to the docs?
- [ ] Does this require a changelog entry?


================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
  push:
    branches: [ master ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ master ]
  schedule:
    - cron: '18 19 * * 3'

jobs:
  analyze:
    name: Analyze
    runs-on: blacksmith-4vcpu-ubuntu-2404
    permissions:
      actions: read
      contents: read
      security-events: write

    strategy:
      fail-fast: false
      matrix:
        language: [ 'javascript' ]
        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
        # Learn more about CodeQL language support at https://git.io/codeql-language-support

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    # Initializes the CodeQL tools for scanning.
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v1
      with:
        languages: ${{ matrix.language }}
        # If you wish to specify custom queries, you can do so here or in a config file.
        # By default, queries listed here will override any specified in a config file.
        # Prefix the list here with "+" to use these queries and those in the config file.
        # queries: ./path/to/local/query, your-org/your-repo/queries@main

    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
    # If this step fails, then you should remove it and run the build manually (see below)
    - name: Autobuild
      uses: github/codeql-action/autobuild@v1

    # ℹ️ Command-line programs to run using the OS shell.
    # 📚 https://git.io/JvXDl

    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
    #    and modify them (or add more) to build your code if your project
    #    uses a compiled language

    #- run: |
    #   make bootstrap
    #   make release

    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v1


================================================
FILE: .github/workflows/create-release-pr.yml
================================================
name: Create Release PR

on:
  workflow_dispatch:

permissions:
  contents: write
  pull-requests: write

jobs:
  create_release_pr:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    env:
      # these are the packages we auto release (e.g. standalone pkgs like artillery/skytrace/types, and included dependencies like plugins)
      # some non-included dependencies are not released automatically (e.g. posthog, memory-inspector)
      # this list should be kept in sync with npm-publish-all-packages.yml
      PACKAGES_TO_RELEASE: "\
        artillery-engine-playwright,\
        artillery-plugin-apdex,\
        artillery-plugin-ensure,\
        artillery-plugin-expect,\
        artillery-plugin-fake-data,\
        artillery-plugin-metrics-by-endpoint,\
        artillery-plugin-publish-metrics,\
        artillery-plugin-slack,\
        commons,\
        core,\
        artillery"
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Replace package folder name with actual name from package.json
        run: |
          for package in $(echo $PACKAGES_TO_RELEASE | tr "," "\n"); do
            PACKAGE_NAME=$(node -e "console.log(require('./packages/$package/package.json').name)")
            PACKAGES_TO_RELEASE=${PACKAGES_TO_RELEASE/$package/$PACKAGE_NAME}
            echo "PACKAGES_TO_RELEASE=$PACKAGES_TO_RELEASE" >> "$GITHUB_ENV"
          done

      # all packages receive minor version bump, except for artillery which receives a patch version bump as convention
      - name: Update package versions
        run: |
          for package in $(echo ${{ env.PACKAGES_TO_RELEASE }} | tr "," "\n"); do
            if [ "$package" = "artillery" ]; then
              npm version patch --workspace $package
            else
              npm version minor --workspace $package
            fi
          done

      - name: Get new Artillery version
        run: |
          ARTILLERY_VERSION=$(node -e "console.log(require('./packages/artillery/package.json').version)")
          echo "ARTILLERY_VERSION=$ARTILLERY_VERSION" >> "$GITHUB_ENV"

      - name: Create branch
        run: |
          export BRANCH_NAME=release/artillery-v${{ env.ARTILLERY_VERSION }}-$(date '+%Y-%m-%d-%H-%M-%S')
          echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
          git checkout -b $BRANCH_NAME
          git push --set-upstream origin $BRANCH_NAME

      - name: Install dependencies
        run: npm ci

      - name: Add changes to commit
        run: git add .

      - name: Commit changes
        run: |
          git config --global user.name "${{ github.actor }}"
          git config --global user.email "${{ github.actor }}@users.noreply.github.com"
          RELEASE_COMMIT_MSG="ci: release v${{ env.ARTILLERY_VERSION }} artillery" >> "$GITHUB_ENV"
          git commit -m "ci: release v${{ env.ARTILLERY_VERSION }} artillery"
          git push

      - name: create pull request
        run: gh pr create -B main -H ${{ env.BRANCH_NAME }} --body 'Release v${{ env.ARTILLERY_VERSION }}. Created by Github action' --fill
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

================================================
FILE: .github/workflows/docker-ecs-worker-image.yml
================================================
name: Build & publish ECS/Fargate worker image to ECR

on:
  workflow_dispatch:
    inputs:
      SHOULD_BUILD_ARM64:
        description: 'Whether to build the ARM64 image.'
        type: boolean
        default: false
  workflow_call:
    inputs:
      COMMIT_SHA:
        description: 'Branch ref to checkout. Needed for pull_request_target to be able to pull correct ref.'
        type: string
        required: true
      USE_COMMIT_SHA_IN_VERSION:
        description: 'Whether to use the commit sha in building the pkg version of the image.'
        type: boolean
      SHOULD_BUILD_ARM64:
        description: 'Whether to build the ARM64 image.'
        type: boolean
        default: false
    secrets:
      ECR_WORKER_IMAGE_PUSH_ROLE_ARN:
        description: 'ARN of the IAM role to assume to push the image to ECR.'
        required: true

permissions:
  id-token: write
  contents: read

jobs:
  build_docker_image_amd64:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    env:
      # Set by the caller workflow, defaults to github.sha when not passed (e.g. workflow_dispatch against a branch)
      WORKER_VERSION: ${{ inputs.COMMIT_SHA || github.sha }}
    strategy:
      matrix:
        registry: [ public, private ]

    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ env.WORKER_VERSION }}
          fetch-depth: 0
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      
      - name: Replace package version
        if: ${{ inputs.USE_COMMIT_SHA_IN_VERSION || false }}
        run: node .github/workflows/scripts/replace-package-versions.js
        env:
          COMMIT_SHA: ${{ env.WORKER_VERSION }}
          REPLACE_MAIN_VERSION_ONLY: true # we don't need to replace dependencies, as docker image builds using workspaces
    
      - name: Get Artillery version
        # we only want to tag with an actual version from pkg.json outside of PRs and manual dispatches
        # NOTE: can't check for refs/head/main because of pull_request_target used in some workflows
        if: github.event.pull_request == null && github.event_name != 'workflow_dispatch'
        run: |
            echo "WORKER_VERSION=$(node -e 'console.log(require("./packages/artillery/package.json").version)')" >> $GITHUB_ENV

      - name: Show git ref
        run: |
          echo GITHUB REF ${{ github.ref }}
          echo GITHUB PR HEAD SHA ${{ github.event.pull_request.head.sha }}
          echo GITHUB SHA ${{ github.sha }}
          echo WORKER_VERSION ENV ${{ env.WORKER_VERSION }}
      
      - name: Configure AWS Credentials (Public ECR)
        if: matrix.registry == 'public'
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: us-east-1
          audience: sts.amazonaws.com
          role-to-assume: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}
          role-session-name: OIDCSession
          mask-aws-account-id: true
    
      - name: Login to Amazon (Public ECR)
        if: matrix.registry == 'public'
        id: login-ecr-public
        uses: aws-actions/amazon-ecr-login@v1
        with:
          registry-type: public
      
      - name: Build the Docker image (Public ECR)
        if: matrix.registry == 'public'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-x86_64
        run: |
          docker build . --platform linux/amd64 --build-arg="WORKER_VERSION=${{ env.WORKER_VERSION }}" --tag public.ecr.aws/d8a4z9o5/artillery-worker:${{ env.DOCKER_TAG }} -f ./packages/artillery/lib/platform/aws-ecs/worker/Dockerfile
      
      - name: Push Docker image (Public ECR)
        if: matrix.registry == 'public'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-x86_64
        run: |
          docker push public.ecr.aws/d8a4z9o5/artillery-worker:${{ env.DOCKER_TAG }}

      - name: Configure AWS Credentials (Private ECR)
        if: matrix.registry == 'private'
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: eu-west-1
          audience: sts.amazonaws.com
          role-to-assume: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}
          role-session-name: OIDCSession
          mask-aws-account-id: true
  
      - name: Login to Amazon (Private ECR)
        if: matrix.registry == 'private'
        id: login-ecr-private
        uses: aws-actions/amazon-ecr-login@v1
    
      - name: Build the Docker image (Private ECR)
        if: matrix.registry == 'private'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-x86_64
        run: |
          docker build . --platform linux/amd64 --build-arg="WORKER_VERSION=${{ env.WORKER_VERSION }}" --tag 248481025674.dkr.ecr.eu-west-1.amazonaws.com/artillery-worker:${{ env.DOCKER_TAG }} -f ./packages/artillery/lib/platform/aws-ecs/worker/Dockerfile

      - name: Push Docker image (Private ECR)
        if: matrix.registry == 'private'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-x86_64
        run: |
          docker push 248481025674.dkr.ecr.eu-west-1.amazonaws.com/artillery-worker:${{ env.DOCKER_TAG }}
        
  build_docker_image_arm64:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    if: ${{ inputs.SHOULD_BUILD_ARM64 }}
    env:
      # Set by the caller workflow, defaults to github.sha when not passed (e.g. workflow_dispatch against a branch)
      WORKER_VERSION: ${{ inputs.COMMIT_SHA || github.sha }}
    strategy:
      matrix:
        registry: [ public, private ]

    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ env.WORKER_VERSION }}
          fetch-depth: 0
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      
      - name: Replace package version
        if: ${{ inputs.USE_COMMIT_SHA_IN_VERSION || false }}
        run: node .github/workflows/scripts/replace-package-versions.js
        env:
          COMMIT_SHA: ${{ env.WORKER_VERSION }}
          REPLACE_MAIN_VERSION_ONLY: true # we don't need to replace dependencies, as docker image builds using workspaces

      - name: Get Artillery version
        # we only want to tag with an actual version from pkg.json outside of PRs and manual dispatches
        # NOTE: can't check for refs/head/main because of pull_request_target used in some workflows
        if: github.event.pull_request == null && github.event_name != 'workflow_dispatch'
        run: |
            echo "WORKER_VERSION=$(node -e 'console.log(require("./packages/artillery/package.json").version)')" >> $GITHUB_ENV

      - name: Show git ref
        run: |
          echo GITHUB REF ${{ github.ref }}
          echo GITHUB PR HEAD SHA ${{ github.event.pull_request.head.sha }}
          echo GITHUB SHA ${{ github.sha }}
          echo WORKER_VERSION ENV ${{ env.WORKER_VERSION }}
      
      - name: Configure AWS Credentials (Public ECR)
        if: matrix.registry == 'public'
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: us-east-1
          audience: sts.amazonaws.com
          role-to-assume: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}
          role-session-name: OIDCSession
          mask-aws-account-id: true

      - name: Login to Amazon (Public ECR)
        if: matrix.registry == 'public'
        id: login-ecr-public
        uses: aws-actions/amazon-ecr-login@v1
        with:
          registry-type: public
      
      - name: Build the Docker image (Public ECR)
        if: matrix.registry == 'public'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-arm64
        run: |
          docker build . --platform linux/arm64 --build-arg="WORKER_VERSION=${{ env.WORKER_VERSION }}" --tag public.ecr.aws/d8a4z9o5/artillery-worker:${{ env.DOCKER_TAG }} -f ./packages/artillery/lib/platform/aws-ecs/worker/Dockerfile
      
      - name: Push Docker image (Public ECR)
        if: matrix.registry == 'public'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-arm64
        run: |
          docker push public.ecr.aws/d8a4z9o5/artillery-worker:${{ env.DOCKER_TAG }}

      - name: Configure AWS Credentials (Private ECR)
        if: matrix.registry == 'private'
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: eu-west-1
          audience: sts.amazonaws.com
          role-to-assume: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}
          role-session-name: OIDCSession
          mask-aws-account-id: true

      - name: Login to Amazon (Private ECR)
        if: matrix.registry == 'private'
        id: login-ecr-private
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build the Docker image (Private ECR)
        if: matrix.registry == 'private'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-arm64
        run: |
          docker build . --platform linux/arm64 --build-arg="WORKER_VERSION=${{ env.WORKER_VERSION }}" --tag 248481025674.dkr.ecr.eu-west-1.amazonaws.com/artillery-worker:${{ env.DOCKER_TAG }} -f ./packages/artillery/lib/platform/aws-ecs/worker/Dockerfile

      - name: Push Docker image (Private ECR)
        if: matrix.registry == 'private'
        env: 
          DOCKER_TAG: ${{ env.WORKER_VERSION }}-arm64
        run: |
          docker push 248481025674.dkr.ecr.eu-west-1.amazonaws.com/artillery-worker:${{ env.DOCKER_TAG }}
        
      

================================================
FILE: .github/workflows/docker-publish-artillery.yml
================================================
name: Publish Docker image for Artillery

on:
  workflow_dispatch:
    # this will override the latest image, so only trigger when you want to publish a new version
    inputs:
      COMMIT_SHA:
        description: 'Commit SHA'
        required: true
        type: string
  workflow_call:
    inputs:
      COMMIT_SHA:
        description: 'Commit SHA'
        required: true
        type: string
    secrets:
      DOCKER_USERNAME:
        description: 'Docker Hub username'
        required: true
      DOCKER_PASSWORD:
        description: 'Docker Hub password'
        required: true

jobs:
  push_to_registry:
    name: Push Docker image to Docker Hub
    runs-on: blacksmith-4vcpu-ubuntu-2404
    steps:
      - name: Check out the repo
        uses: actions/checkout@v3
        with:
          ref: ${{ inputs.COMMIT_SHA || null }}
          fetch-depth: 0

      - name: Get Artillery version
        run: |
          echo "ARTILLERY_VERSION=$(node -e 'console.log(require("./packages/artillery/package.json").version)')" >> $GITHUB_ENV

      - name: Log in to Docker Hub
        uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
        with:
          images: artilleryio/artillery
          tags: |
            type=semver,pattern={{version}},value=${{env.ARTILLERY_VERSION}}
            type=raw,value=latest

      - name: Build and push Docker image
        uses: useblacksmith/build-push-action@v2
        with:
          context: ./packages/artillery
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}


================================================
FILE: .github/workflows/examples.yml
================================================
name: Examples

on:
  push:
    branches: [main]
  pull_request:
  workflow_dispatch:

env:
  ARTILLERY_BINARY_PATH: ${{ github.workspace }}/packages/artillery/bin/run
  CLI_TAGS: repo:${{ github.repository }},actor:${{ github.actor }},type:smoke,ci:true
  CLI_NOTE: Running&nbsp;from&nbsp;the&nbsp;Official&nbsp;Artillery&nbsp;Github&nbsp;Action!&nbsp;😀

jobs:
  browser-load-test:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    timeout-minutes: 10
    env:
      CWD: ./examples/browser-load-testing-playwright
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: "22.x"

      - name: Install dependencies
        run: npm install

      # Uses the version from packages/artillery-engine-playwright
      - name: Install Playwright Browsers
        run: npm exec --workspace artillery-engine-playwright -- playwright install chromium --with-deps

      - name: Run test
        run: |
          $ARTILLERY_BINARY_PATH run browser-load-test.ts --record --tags ${{ env.CLI_TAGS }},group:browser-load-test --note "${{ env.CLI_NOTE }}"
        working-directory: ${{ env.CWD }}
        env:
          ARTILLERY_BINARY_PATH: ${{ env.ARTILLERY_BINARY_PATH }}
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}

  http-metrics-by-endpoint:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    timeout-minutes: 10
    env:
      CWD: ./examples/http-metrics-by-endpoint
    defaults:
      run:
        working-directory: ${{ env.CWD }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install
        run: npm ci

      - name: Test
        uses: artilleryio/action-cli@v1
        with:
          command: run ./endpoint-metrics.yml --record --tags ${{ env.CLI_TAGS }},group:http-metrics-by-endpoint --note ${{ env.CLI_NOTE }}
          working-directory: ${{ env.CWD }}
        env:
          ARTILLERY_BINARY_PATH: ${{ env.ARTILLERY_BINARY_PATH }}
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}

  multiple-scenarios-spec:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    timeout-minutes: 10
    env:
      CWD: ./examples/multiple-scenario-specs
    defaults:
      run:
        working-directory: ${{ env.CWD }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install
        run: npm ci

      - name: Run armadillo scenario
        uses: artilleryio/action-cli@v1
        with:
          command: run --config ./common-config.yml ./scenarios/armadillo.yml --record --tags ${{ env.CLI_TAGS }},group:multiple-scenario-specs --note ${{ env.CLI_NOTE }}
          working-directory: ${{ env.CWD }}
        env:
          ARTILLERY_BINARY_PATH: ${{ env.ARTILLERY_BINARY_PATH }}
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}

      - name: Run dino scenario
        uses: artilleryio/action-cli@v1
        with:
          command: run --config ./common-config.yml ./scenarios/dino.yml --record --tags ${{ env.CLI_TAGS }},group:multiple-scenario-specs --note ${{ env.CLI_NOTE }}
          working-directory: ${{ env.CWD }}
        env:
          ARTILLERY_BINARY_PATH: ${{ env.ARTILLERY_BINARY_PATH }}
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}

  using-data-from-csv:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    timeout-minutes: 15
    env:
      CWD: ./examples/using-data-from-csv
    defaults:
      run:
        working-directory: ${{ env.CWD }}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install
        run: npm ci

      - name: Test
        uses: artilleryio/action-cli@v1
        with:
          command: run ./website-test.yml --record --tags ${{ env.CLI_TAGS }},group:using-data-from-csv --note ${{ env.CLI_NOTE }}
          working-directory: ${{ env.CWD }}
        env:
          ARTILLERY_BINARY_PATH: ${{ env.ARTILLERY_BINARY_PATH }}
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}


================================================
FILE: .github/workflows/npm-publish-all-packages-canary.yml
================================================
name: Publish packages to NPM (canary)
on:
  push:
    branches:
      - main
    paths:
      - 'packages/artillery/**'
      - 'packages/artillery-engine-playwright/**'
      - 'packages/artillery-engine-posthog/**'
      - 'packages/artillery-plugin-apdex/**'
      - 'packages/artillery-plugin-ensure/**'
      - 'packages/artillery-plugin-expect/**'
      - 'packages/artillery-plugin-metrics-by-endpoint/**'
      - 'packages/artillery-plugin-publish-metrics/**'
      - 'packages/artillery-plugin-fake-data/**'
      - 'packages/artillery-plugin-slack/**'
      - 'packages/commons/**'
      - 'packages/core/**'
      - 'packages/skytrace/**'
      - 'packages/artillery-plugin-memory-inspector/**'
      
jobs:
  publish-fargate-worker-image:
    if: "!contains( github.event.head_commit.message, 'ci: release v')"
    uses: ./.github/workflows/docker-ecs-worker-image.yml
    permissions:
      contents: read
      id-token: write
    with:
      COMMIT_SHA: ${{ github.sha }}
      USE_COMMIT_SHA_IN_VERSION: true
      SHOULD_BUILD_ARM64: false
    secrets:
      ECR_WORKER_IMAGE_PUSH_ROLE_ARN: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}

  build:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    if: "!contains( github.event.head_commit.message, 'ci: release v')"
    needs: publish-fargate-worker-image
    permissions:
      contents: read
      packages: write
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
    outputs:
      ARTILLERY_VERSION: ${{ steps.get-artillery-version.outputs.ARTILLERY_VERSION }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: node .github/workflows/scripts/replace-package-versions.js
        env:
          COMMIT_SHA: ${{ github.sha }}
      # It must be published in this specific order to account for order of dependencies (e.g. artillery depends on commons, core, etc), in case failures happen in publishing.
      - run: npm -w @artilleryio/int-commons publish --tag canary
      - run: npm -w @artilleryio/int-core publish --tag canary
      - run: npm -w artillery-plugin-expect publish --tag canary
      - run: npm -w artillery-plugin-publish-metrics publish --tag canary
      - run: npm -w artillery-plugin-metrics-by-endpoint publish --tag canary
      - run: npm -w artillery-plugin-ensure publish --tag canary
      - run: npm -w artillery-plugin-apdex publish --tag canary
      - run: npm -w artillery-engine-posthog publish --tag canary
      - run: npm -w artillery-engine-playwright publish --tag canary
      - run: npm -w artillery-plugin-fake-data publish --tag canary
      - run: npm -w artillery-plugin-slack publish --tag canary
      - run: npm -w artillery publish --tag canary
      - id: get-artillery-version
        run: |
          ARTILLERY_VERSION=$(node -e "console.log(require('./packages/artillery/package.json').version)")
          echo "ARTILLERY_VERSION=$ARTILLERY_VERSION" >> $GITHUB_OUTPUT
      # Skytrace is a Typescript Package and needs to install -> build -> publish
      - run: npm install -w skytrace --ignore-scripts
      - run: npm run build -w skytrace
      - run: npm -w skytrace publish --tag canary
      - run: npm -w artillery-plugin-memory-inspector publish --tag canary

  run-distributed-tests:
    uses: ./.github/workflows/run-distributed-tests.yml
    needs: build
    with:
      ARTILLERY_VERSION_OVERRIDE: ${{ needs.build.outputs.ARTILLERY_VERSION }}
      HAS_ARM64_BUILD: false
    permissions:
      contents: read
      id-token: write
    secrets:
      ARTILLERY_CLOUD_ENDPOINT_TEST: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
      ARTILLERY_CLOUD_API_KEY_TEST: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
      DD_TESTS_API_KEY: ${{ secrets.DD_TESTS_API_KEY }}
      DD_TESTS_APP_KEY: ${{ secrets.DD_TESTS_APP_KEY }}
      AWS_TEST_EXECUTION_ROLE_ARN_TEST5: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}

  publish-cloudformation-templates-canary-to-s3:
    uses: ./.github/workflows/s3-publish-cf-templates.yml
    needs: run-distributed-tests
    with:
      canary: true
    permissions:
      contents: read
      id-token: write
    secrets:
      AWS_ASSET_UPLOAD_ROLE_ARN: ${{ secrets.AWS_ASSET_UPLOAD_ROLE_ARN }}


================================================
FILE: .github/workflows/npm-publish-all-packages.yml
================================================
name: Publish packages to NPM
on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      #If there are changes to package.json and ci:release v is in commit msg, it's a release
      - 'packages/artillery/package.json'
      
jobs:
  publish-fargate-worker-image:
    if: >
      github.event_name == 'workflow_dispatch' ||
      contains(github.event.head_commit.message, 'ci: release v')
    uses: ./.github/workflows/docker-ecs-worker-image.yml
    permissions:
      contents: read
      id-token: write
    with:
      COMMIT_SHA: ${{ github.sha }}
      SHOULD_BUILD_ARM64: true
    secrets:
      ECR_WORKER_IMAGE_PUSH_ROLE_ARN: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}

  publish-packages-to-npm:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    if: >
      github.event_name == 'workflow_dispatch' ||
      contains(github.event.head_commit.message, 'ci: release v')
    needs: publish-fargate-worker-image
    permissions:
      contents: read
      packages: write
    outputs:
      ARTILLERY_VERSION: ${{ steps.get-artillery-version.outputs.ARTILLERY_VERSION }}
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      # this list should be kept in sync with create-release-pr.yml
      PACKAGES_TO_RELEASE: "\
        artillery-engine-playwright,\
        artillery-plugin-apdex,\
        artillery-plugin-ensure,\
        artillery-plugin-expect,\
        artillery-plugin-fake-data,\
        artillery-plugin-slack,\
        artillery-plugin-metrics-by-endpoint,\
        artillery-plugin-publish-metrics,\
        commons,\
        core,\
        artillery"
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: node .github/workflows/scripts/replace-package-versions.js
      # It must be published in this specific order to account for order of dependencies (e.g. artillery depends on commons, core, etc), in case failures happen in publishing.
      - run: npm -w @artilleryio/int-commons publish
      - run: npm -w @artilleryio/int-core publish
      - run: npm -w artillery-plugin-expect publish
      - run: npm -w artillery-plugin-publish-metrics publish
      - run: npm -w artillery-plugin-metrics-by-endpoint publish
      - run: npm -w artillery-plugin-ensure publish
      - run: npm -w artillery-plugin-apdex publish
      - run: npm -w artillery-engine-playwright publish
      - run: npm -w artillery-plugin-fake-data publish
      - run: npm -w artillery-plugin-slack publish
      - run: npm -w artillery publish
      - id: get-artillery-version
        run: |
          ARTILLERY_VERSION=$(node -e "console.log(require('./packages/artillery/package.json').version)")
          echo "ARTILLERY_VERSION=$ARTILLERY_VERSION" >> $GITHUB_OUTPUT
      # # Skytrace is a Typescript Package and needs to install -> build -> publish
      # - run: npm install -w skytrace --ignore-scripts
      # - run: npm run build -w skytrace
      # - run: npm -w skytrace publish

  publish-official-docker-image:
    uses: ./.github/workflows/docker-publish-artillery.yml
    if: >
      github.event_name == 'workflow_dispatch' ||
      contains(github.event.head_commit.message, 'ci: release v')
    needs: publish-packages-to-npm
    with:
      COMMIT_SHA: ${{ github.sha }}
    secrets:
      DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}

  run-distributed-tests:
    uses: ./.github/workflows/run-distributed-tests.yml
    needs: publish-packages-to-npm
    with:
      ARTILLERY_VERSION_OVERRIDE: ${{ needs.publish-packages-to-npm.outputs.ARTILLERY_VERSION }}
      HAS_ARM64_BUILD: true
    permissions:
      contents: read
      id-token: write
    secrets:
      ARTILLERY_CLOUD_ENDPOINT_TEST: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
      ARTILLERY_CLOUD_API_KEY_TEST: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
      DD_TESTS_API_KEY: ${{ secrets.DD_TESTS_API_KEY }}
      DD_TESTS_APP_KEY: ${{ secrets.DD_TESTS_APP_KEY }}
      AWS_TEST_EXECUTION_ROLE_ARN_TEST5: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}
  
  publish-cloudformation-templates-to-s3:
    uses: ./.github/workflows/s3-publish-cf-templates.yml
    needs: run-distributed-tests
    with:
      canary: true
    permissions:
      contents: read
      id-token: write
    secrets:
      AWS_ASSET_UPLOAD_ROLE_ARN: ${{ secrets.AWS_ASSET_UPLOAD_ROLE_ARN }}


================================================
FILE: .github/workflows/npm-publish-artillery-engine-posthog.yml
================================================
name: Publish artillery-engine-posthog to npm
on:
  push:
    branches:
      - main
    paths:
      - packages/artillery-engine-posthog/package.json
jobs:
  build:
    if: "contains(github.event.head_commit.message, 'ci: release v')"
    runs-on: blacksmith-4vcpu-ubuntu-2404
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: npm -w artillery-engine-posthog publish --tag latest
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/npm-publish-artillery-plugin-memory-inspector.yml
================================================
name: Publish artillery-plugin-memory-inspector to npm
on:
  push:
    branches:
      - main
    paths:
      - packages/artillery-plugin-memory-inspector/package.json
jobs:
  build:
    if: "contains(github.event.head_commit.message, 'ci: release v')"
    runs-on: blacksmith-4vcpu-ubuntu-2404
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: npm -w artillery-plugin-memory-inspector publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/npm-publish-artillery-types.yml
================================================
name: Publish @artilleryio/types to npm
on:
  push:
    branches:
      - main
    paths:
      - packages/types/package.json
jobs:
  build:
    if: "contains(github.event.head_commit.message, 'ci: release v')"
    runs-on: blacksmith-4vcpu-ubuntu-2404
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: node .github/workflows/scripts/replace-package-versions.js
      - run: npm ci
      - run: npm -w '@artilleryio/types' publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/npm-publish-specific-package.yml
================================================
name: Publish specific package to NPM
on:
  workflow_dispatch:
    inputs:
      CHANNEL:
        description: 'Channel to publish to. Can be "latest" or "canary".'
        type: choice
        options:
          - 'latest'
          - 'canary'
        default: 'canary'
      PACKAGE_FOLDER_NAME:
        description: 'Name of the package to publish (folder package).'
        required: true
      
jobs:
  publish-fargate-worker-image:
    uses: ./.github/workflows/docker-ecs-worker-image.yml
    if: ${{ inputs.PACKAGE_FOLDER_NAME == 'artillery' }}
    permissions:
      contents: read
      id-token: write
    with:
      COMMIT_SHA: ${{ github.sha }}
      SHOULD_BUILD_ARM64: true
    secrets:
      ECR_WORKER_IMAGE_PUSH_ROLE_ARN: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}

  publish-packages-to-npm:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    needs: publish-fargate-worker-image
    permissions:
      contents: read
      packages: write
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22.x'
          registry-url: 'https://registry.npmjs.org'
          scope: '@artilleryio'
      - run: node .github/workflows/scripts/replace-package-versions.js
        if: ${{ inputs.CHANNEL == 'latest'}}
      - run: node .github/workflows/scripts/replace-package-versions.js
        env:
          COMMIT_SHA: ${{ github.sha }}
        if: ${{ inputs.CHANNEL == 'canary'}}

      - name: Get corresponding package name from package.json
        run: |
            PACKAGE_NAME=$(node -e "console.log(require('./packages/${{ inputs.PACKAGE_FOLDER_NAME }}/package.json').name)")
            echo "PACKAGE_NAME=$PACKAGE_NAME" >> "$GITHUB_ENV"
      
      - run: npm install -w skytrace --ignore-scripts && npm run build -w skytrace
        if: ${{ inputs.PACKAGE_FOLDER_NAME == 'skytrace'}}
        
      - run: npm -w ${{ env.PACKAGE_NAME }} publish --tag ${{ inputs.CHANNEL }}

  publish-official-docker-image:
    uses: ./.github/workflows/docker-publish-artillery.yml
    if: ${{ inputs.PACKAGE_FOLDER_NAME == 'artillery'}}
    needs: publish-packages-to-npm
    with:
      COMMIT_SHA: ${{ github.sha }}
    secrets:
      DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}

================================================
FILE: .github/workflows/run-aws-tests-on-pr.yml
================================================
name: Run AWS tests (on PR)

on:
  pull_request_target:
    branches: [main]
    #opened, reopened and synchronize will cause the workflow to fail on forks due to permissions
    #once labeled, that will then be overridden by the is-collaborator job
    types: [opened, labeled, synchronize, reopened]

jobs:
  is-collaborator:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    steps:
      - name: Get User Permission
        id: checkAccess
        uses: actions-cool/check-user-permission@cd622002ff25c2311d2e7fb82107c0d24be83f9b
        with:
          require: write
          username: ${{ github.actor }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Check User Permission
        if: steps.checkAccess.outputs.require-result == 'false'
        run: |
          echo "${{ github.actor }} does not have permissions on this repo."
          echo "Current permission level is ${{ steps.checkAccess.outputs.user-permission }}"
          exit 1

  publish-branch-image:
    if: contains( github.event.pull_request.labels.*.name, 'run-aws-tests' )
    needs: is-collaborator
    uses: ./.github/workflows/docker-ecs-worker-image.yml
    permissions:
      contents: read
      id-token: write
    secrets:
      ECR_WORKER_IMAGE_PUSH_ROLE_ARN: ${{ secrets.ECR_WORKER_IMAGE_PUSH_ROLE_ARN }}
    with:
      COMMIT_SHA: ${{ github.event.pull_request.head.sha || null }} # this should only be run with this ref if is-collaborator has been run and passed

  run-distributed-tests:
    needs: publish-branch-image
    uses: ./.github/workflows/run-distributed-tests.yml
    with:
      COMMIT_SHA: ${{ github.event.pull_request.head.sha || null }}
    permissions:
      contents: read
      id-token: write
    secrets:
      ARTILLERY_CLOUD_ENDPOINT_TEST: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
      ARTILLERY_CLOUD_API_KEY_TEST: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
      DD_TESTS_API_KEY: ${{ secrets.DD_TESTS_API_KEY }}
      DD_TESTS_APP_KEY: ${{ secrets.DD_TESTS_APP_KEY }}
      AWS_TEST_EXECUTION_ROLE_ARN_TEST5: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}

================================================
FILE: .github/workflows/run-distributed-tests.yml
================================================
name: Run distributed tests

on:
  workflow_call:
    inputs:
      COMMIT_SHA:
        type: string
      ARTILLERY_VERSION_OVERRIDE:
        type: string
      HAS_ARM64_BUILD:
        type: boolean
        default: false
    secrets:
      ARTILLERY_CLOUD_ENDPOINT_TEST: 
        required: true
        description: 'The endpoint for the Artillery Cloud API'
      ARTILLERY_CLOUD_API_KEY_TEST:
        required: true
        description: 'The api key for the Artillery Cloud API'
      DD_TESTS_API_KEY:
        required: true
        description: 'The api key for the Datadog API'
      DD_TESTS_APP_KEY:
        required: true
        description: 'The app key for the Datadog API'
      AWS_TEST_EXECUTION_ROLE_ARN_TEST5:
        required: true
        description: 'The role to assume for the AWS tests'

permissions:
  contents: read
  id-token: write

jobs:
  generate-test-matrix:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    outputs:
      matrix: ${{ steps.generate-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ inputs.COMMIT_SHA || null }}
      - name: Use Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 22.x
      - id: generate-matrix
        run: |
          RESULT=$(node .github/workflows/scripts/get-tests-in-package-location.js)
          echo $RESULT
          echo "matrix=$RESULT" >> $GITHUB_OUTPUT

  run-tests:
    needs: generate-test-matrix
    timeout-minutes: 20
    runs-on: blacksmith-4vcpu-ubuntu-2404
    strategy:
      fail-fast: false
      matrix:
        testName: ${{fromJson(needs.generate-test-matrix.outputs.matrix).names}}
    permissions:
      contents: read
      id-token: write
    env:
      ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
      ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
      DD_TESTS_API_KEY: ${{ secrets.DD_TESTS_API_KEY }}
      DD_TESTS_APP_KEY: ${{ secrets.DD_TESTS_APP_KEY }}
      GITHUB_REPO: ${{ github.repository }}
      GITHUB_ACTOR: ${{ github.actor }}
      HAS_ARM64_BUILD: ${{ inputs.HAS_ARM64_BUILD }}
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ inputs.COMMIT_SHA || null }} # in a PR we make a collaborator check, otherwise this would override pull_request_target
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        env:
          SHOW_STACK_TRACE: true
        with:
          aws-region: eu-west-1
          role-to-assume: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}
          role-session-name: OIDCSession
          mask-aws-account-id: true
      - name: Use Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 22.x
      - run: .github/workflows/scripts/npm-command-retry.sh install
      - run: npm run build
      - name: Install Specific Artillery Version if needed
        if: ${{ inputs.ARTILLERY_VERSION_OVERRIDE || false }}
        run: mkdir __artillery__ && cd __artillery__ && npm init -y && ../.github/workflows/scripts/npm-command-retry.sh install artillery@${{ inputs.ARTILLERY_VERSION_OVERRIDE }}
      - name: Set A9_PATH
        if: ${{ inputs.ARTILLERY_VERSION_OVERRIDE || false }}
        run: echo "A9_PATH=${{ github.workspace }}/__artillery__/node_modules/.bin/artillery" >> $GITHUB_ENV
      - name: Set ECR Image Version if needed
        if: ${{ inputs.COMMIT_SHA }}
        run: |
          echo "ECR_IMAGE_VERSION=${{ inputs.COMMIT_SHA }}" >> $GITHUB_ENV
          echo "LAMBDA_IMAGE_VERSION=${{ inputs.COMMIT_SHA }}" >> $GITHUB_ENV
      # runs the single test file from `package` workspace in the `file`, as defined in the matrix output
      - run: npm run test:aws:ci --workspace ${{fromJson(needs.generate-test-matrix.outputs.matrix).namesToFiles[matrix.testName].packageName }} -- --files ${{ fromJson(needs.generate-test-matrix.outputs.matrix).namesToFiles[matrix.testName].file }}
        env:
          FORCE_COLOR: 1
  
  run-tests-windows:
    needs: generate-test-matrix
    timeout-minutes: 20
    runs-on: blacksmith-4vcpu-ubuntu-2404
    continue-on-error: true
    permissions:
      contents: read
      id-token: write
    env:
      ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
      ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
      DD_TESTS_API_KEY: ${{ secrets.DD_TESTS_API_KEY }}
      DD_TESTS_APP_KEY: ${{ secrets.DD_TESTS_APP_KEY }}
      GITHUB_REPO: ${{ github.repository }}
      GITHUB_ACTOR: ${{ github.actor }}
      HAS_ARM64_BUILD: ${{ inputs.HAS_ARM64_BUILD }}
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ inputs.COMMIT_SHA || null }} # in a PR we make a collaborator check, otherwise this would override pull_request_target
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        env:
          SHOW_STACK_TRACE: true
        with:
          aws-region: eu-west-1
          role-to-assume: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}
          role-session-name: OIDCSession
          mask-aws-account-id: true
      - name: Use Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 22.x
      - run: .github/workflows/scripts/npm-command-retry.sh install
      - run: npm run build
      - name: Install Specific Artillery Version if needed
        if: ${{ inputs.ARTILLERY_VERSION_OVERRIDE || false }}
        run: mkdir __artillery__ && cd __artillery__ && npm init -y && ../.github/workflows/scripts/npm-command-retry.sh install artillery@${{ inputs.ARTILLERY_VERSION_OVERRIDE }}
      - name: Set A9_PATH
        if: ${{ inputs.ARTILLERY_VERSION_OVERRIDE || false }}
        run: echo "A9_PATH=${{ github.workspace }}/__artillery__/node_modules/.bin/artillery" >> $GITHUB_ENV
      - name: Set ECR Image Version if needed
        if: ${{ inputs.COMMIT_SHA }}
        run: |
          echo "ECR_IMAGE_VERSION=${{ inputs.COMMIT_SHA }}" >> $GITHUB_ENV
          echo "LAMBDA_IMAGE_VERSION=${{ inputs.COMMIT_SHA }}" >> $GITHUB_ENV
      - run: npm run test:aws:windows --workspace artillery
        env:
          FORCE_COLOR: 1

================================================
FILE: .github/workflows/run-tests-windows.yml
================================================
name: Run Windows tests

on:
  workflow_dispatch:
    inputs:
      ECR_IMAGE_VERSION:
        description: 'ECR image version'

jobs:
  test:
    timeout-minutes: 60
    runs-on: windows-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js 22.x
        uses: actions/setup-node@v3
        with:
          node-version: 22.x
      - run: npm install
      - run: npm run build
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        env:
          SHOW_STACK_TRACE: true
        with:
          aws-region: eu-west-1
          role-to-assume: ${{ secrets.AWS_TEST_EXECUTION_ROLE_ARN_TEST5 }}
          role-session-name: OIDCSession
          mask-aws-account-id: true
      - name: Run local windows tests
        run: npm run test:windows --workspace artillery
        env:
          FORCE_COLOR: 1
      - name: Run AWS windows tests
        run: npm run test:aws:windows --workspace artillery
        env:
          FORCE_COLOR: 1
          ARTILLERY_CLOUD_ENDPOINT: ${{ secrets.ARTILLERY_CLOUD_ENDPOINT_TEST }}
          ARTILLERY_CLOUD_API_KEY: ${{ secrets.ARTILLERY_CLOUD_API_KEY_TEST }}
          GITHUB_REPO: ${{ github.repository }}
          GITHUB_ACTOR: ${{ github.actor }}
          ECR_IMAGE_VERSION: ${{ inputs.ECR_IMAGE_VERSION || github.sha}}
      - name: Notify about failures
        if: failure() && github.ref == 'refs/heads/main'
        uses: 8398a7/action-slack@v3.15.1
        with:
          status: ${{ job.status }}
          fields: repo,message,commit,author,eventName,job,took,pullRequest
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

================================================
FILE: .github/workflows/run-tests.yml
================================================
name: Run tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:

jobs:
  generate-matrix-with-packages:
    runs-on: blacksmith-4vcpu-ubuntu-2404
    outputs:
      matrix: ${{ steps.generate-matrix.outputs.matrix }}
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 22.x
      - id: generate-matrix
        run: |
          RESULT=$(node .github/workflows/scripts/get-all-packages-by-name.js)
          echo "matrix=$RESULT" >> $GITHUB_OUTPUT
  test:
    timeout-minutes: 30
    runs-on: blacksmith-4vcpu-ubuntu-2404
    needs: generate-matrix-with-packages
    permissions:
      contents: read
    strategy:
      matrix:
        node-version: [22.x, 24.x]
        package: ${{fromJson(needs.generate-matrix-with-packages.outputs.matrix)}}
      fail-fast: false
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm install
      - run: npm run build
      - name: Install Playwright Browsers
        if: matrix.package == 'artillery-engine-playwright'
        run: npm exec --workspace artillery-engine-playwright -- playwright install chromium --with-deps
      - run: npm run test --workspace ${{ matrix.package }}
        env:
          FORCE_COLOR: 1
      - name: Notify about failures
        if: failure() && github.ref == 'refs/heads/main'
        uses: 8398a7/action-slack@v3.15.1
        with:
          status: ${{ job.status }}
          fields: repo,message,commit,author,eventName,job,took,pullRequest
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

  test-windows:
    timeout-minutes: 60
    runs-on: windows-latest
    needs: generate-matrix-with-packages
    continue-on-error: true
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js 22.x
        uses: actions/setup-node@v3
        with:
          node-version: 22.x
      - run: npm install
      - run: npm run build
      - name: Run windows tests and capture exit code
        continue-on-error: true
        run: |
          npm run test:windows --workspace artillery
          echo "HAS_PASSED=$?" >> $env:GITHUB_ENV
        env:
          FORCE_COLOR: 1
      - name: Notify about failures
        if: env.HAS_PASSED == 'False'
        uses: 8398a7/action-slack@v3.15.1
        with:
          status: failure
          fields: repo,message,commit,author,eventName,job,took,pullRequest
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}


================================================
FILE: .github/workflows/s3-publish-cf-templates.yml
================================================
name: Publish CloudFormation templates to AWS S3

on:
  workflow_call:
    inputs:
      canary:
        type: boolean
        default: false
        description: 'Whether to deploy the canary versions of the templates'
    secrets:
      AWS_ASSET_UPLOAD_ROLE_ARN:
        description: 'ARN of the IAM role to assume to upload assets to S3'
        required: true

  workflow_dispatch:
    inputs:
      canary:
        type: boolean
        default: false
        description: 'Whether to deploy the canary versions of the templates'

env:
  CF_LAMBDA_TEMPLATE: ${{ inputs.canary && 'aws-iam-lambda-cf-template-canary.yml' || 'aws-iam-lambda-cf-template.yml' }}
  CF_FARGATE_TEMPLATE: ${{ inputs.canary && 'aws-iam-fargate-cf-template-canary.yml' || 'aws-iam-fargate-cf-template.yml' }}
  GH_OIDC_LAMBDA_TEMPLATE: ${{ inputs.canary && 'gh-oidc-lambda-canary.yml' || 'gh-oidc-lambda.yml' }}
  GH_OIDC_FARGATE_TEMPLATE: ${{ inputs.canary && 'gh-oidc-fargate-canary.yml' || 'gh-oidc-fargate.yml' }}
jobs:
  put-cloudformation-templates:
    runs-on: blacksmith-4vcpu-ubuntu-2404

    permissions:
      id-token: write
      contents: read
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        env:
          SHOW_STACK_TRACE: true
        with:
          aws-region: us-east-1
          role-to-assume: ${{ secrets.AWS_ASSET_UPLOAD_ROLE_ARN }}
          role-session-name: OIDCSession
          mask-aws-account-id: true

      - name: Update IAM CloudFormation templates
        run: |
          aws s3 cp --acl public-read ./packages/artillery/lib/platform/aws/iam-cf-templates/aws-iam-fargate-cf-template.yml s3://artilleryio-cf-templates/${{ env.CF_FARGATE_TEMPLATE }}
          aws s3 cp --acl public-read ./packages/artillery/lib/platform/aws/iam-cf-templates/aws-iam-lambda-cf-template.yml s3://artilleryio-cf-templates/${{ env.CF_LAMBDA_TEMPLATE }}
          aws s3 cp --acl public-read ./packages/artillery/lib/platform/aws/iam-cf-templates/gh-oidc-lambda.yml s3://artilleryio-cf-templates/${{ env.GH_OIDC_LAMBDA_TEMPLATE }}
          aws s3 cp --acl public-read ./packages/artillery/lib/platform/aws/iam-cf-templates/gh-oidc-fargate.yml s3://artilleryio-cf-templates/${{ env.GH_OIDC_FARGATE_TEMPLATE }}

================================================
FILE: .github/workflows/scripts/get-all-packages-by-name.js
================================================
const fs = require('node:fs');

const packageNames = [];
fs.readdirSync('packages').forEach((pkg) => {
  if (fs.statSync(`packages/${pkg}`).isDirectory()) {
    const pkgJson = fs.readFileSync(`packages/${pkg}/package.json`, 'utf8');
    packageNames.push(JSON.parse(pkgJson).name);
  }
});

console.log(JSON.stringify(packageNames));


================================================
FILE: .github/workflows/scripts/get-tests-in-package-location.js
================================================
const fs = require('node:fs');
const path = require('node:path');

/**
 * This script is used to discover all the tests in different test directories that match a specific suffix
 * and generate a JSON file that can be used to run the tests in parallel leveraging Github Actions
 */

const testLocations = [
  {
    location: 'test/cloud-e2e/fargate',
    packageName: 'artillery',
    suffix: '.test.js'
  },
  {
    location: 'test/cloud-e2e/lambda',
    packageName: 'artillery',
    suffix: '.test.js'
  },
  {
    location: 'test',
    packageName: 'artillery-engine-playwright',
    suffix: '.aws.js'
  }
];

const tests = {
  names: [],
  namesToFiles: {}
};

const addTest = (fileName, baseLocation, packageName, suffix) => {
  if (!fileName.endsWith(suffix)) {
    return;
  }
  const testName = fileName.replace(suffix, '');
  const jobName = `${packageName}/${testName}`;
  tests.names.push(jobName);
  tests.namesToFiles[jobName] = {
    file: `${baseLocation}/${fileName}`,
    packageName: packageName
  };
};

// Recursively scan a directory to find files, and add tests to the tests object
function scanDirectory(location, baseLocation, packageName, suffix) {
  fs.readdirSync(location).forEach((file) => {
    const absolute = path.join(location, file);
    if (fs.statSync(absolute).isDirectory()) {
      scanDirectory(absolute, baseLocation, packageName, suffix);
    } else {
      addTest(file, baseLocation, packageName, suffix);
    }
  });
}

// Scan all the test locations
for (const { packageName, location, suffix } of testLocations) {
  const fullLocation = `packages/${packageName}/${location}`;
  scanDirectory(fullLocation, location, packageName, suffix);
}

// Output the tests object as a JSON string to be used by Github Actions
console.log(JSON.stringify(tests));


================================================
FILE: .github/workflows/scripts/npm-command-retry.sh
================================================
#!/bin/bash

# This is necessary because npm commands can fail intermittently due to network issues
# The script retries an npm command up to 5 times with a 2-second delay between each attempt
run_npm_command() {
  local max_retries=5
  local retry_count=0
  local sleep_time=2
  local command="$@"

  while [ $retry_count -lt $max_retries ]; do
    $command && break

    retry_count=$((retry_count + 1))
    echo "Command attempt $retry_count failed. Retrying in $sleep_time seconds..."
    sleep $sleep_time
  done

  if [ $retry_count -eq $max_retries ]; then
    echo "Command failed after $max_retries attempts."
    exit 1
  else
    echo "Command succeeded."
  fi
}

if [ $# -eq 0 ]; then
  echo "No npm command provided."
  exit 1
else
  command="npm $@"
fi

run_npm_command "$command"

================================================
FILE: .github/workflows/scripts/replace-package-versions.js
================================================
const fs = require('node:fs');
const path = require('node:path');

const packagesDir = '../../../packages';
const commitSha = process.env.COMMIT_SHA;

const getNewVersion = (version) => {
  if (!commitSha || commitSha === 'null') {
    return version;
  }

  const shortSha = commitSha.slice(0, 7);
  return `${version}-${shortSha}`;
};

const versionMapping = {};

/**
 * This script iterates through every folder in ./packages and replaces their package.version with VERSION-COMMIT_SHA.
 * It then replaces the versions of all dependencies that are in this repo with the new VERSION-COMMIT_SHA of the corresponding package.
 * It is only used by the npm-publish-all-packages-canary.yml script, for the purposes of releasing a canary version of every package scoped to the latest commit to main.
 */
const updatePackageVersions = () => {
  const packageFolders = fs
    .readdirSync(path.join(__dirname, packagesDir), { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name);

  packageFolders.forEach((folder) => {
    const packageJsonRelativePath = `${packagesDir}/${folder}/package.json`;
    const packageJsonFullPath = path.join(__dirname, packageJsonRelativePath);

    if (!fs.existsSync(packageJsonFullPath)) {
      throw new Error(
        `Path ${packageJsonRelativePath} does not exist! Please ensure that it is a package!`
      );
    }

    const packageData = fs.readFileSync(packageJsonFullPath);
    const packageJson = JSON.parse(packageData);

    packageJson.version = getNewVersion(packageJson.version);

    versionMapping[packageJson.name] = {
      content: packageJson,
      path: packageJsonFullPath
    };
  });

  for (const pkg of Object.values(versionMapping)) {
    if (!process.env.REPLACE_MAIN_VERSION_ONLY) {
      updateDependencies(pkg);
    }
    saveUpdatedPackage(pkg);
  }
};

const updateDependencies = (pkg) => {
  const {
    content: { dependencies }
  } = pkg;

  for (const packageNameToReplace of Object.keys(versionMapping)) {
    if (dependencies?.[packageNameToReplace]) {
      //replace the dependency we care about in this package with its corrected canary version
      dependencies[packageNameToReplace] =
        versionMapping[packageNameToReplace].content.version;

      console.log(
        `Updated dependency ${packageNameToReplace} in ${pkg.content.name} to ${dependencies[packageNameToReplace]}`
      );
    }
  }
};

const saveUpdatedPackage = (pkg) => {
  fs.writeFileSync(pkg.path, JSON.stringify(pkg.content, null, 2));
};

updatePackageVersions();


================================================
FILE: .gitignore
================================================
.idea
*.iml
npm-debug.log
dump.rdb
node_modules
components
build
.tap
results.xml
config.json
.DS_Store
*/.DS_Store
*/*/.DS_Store
._*
*/._*
*/*/._*
coverage.*
lib-cov
*scratch*
artillery_report*
coverage/*
.vagrant/
.vscode
.turbo
build/**
dist/**
.next/**

================================================
FILE: .npmignore
================================================
test/
.idea
*.iml
npm-debug.log
dump.rdb
node_modules
components
build
results.tap
results.xml
config.json
.DS_Store
*/.DS_Store
*/*/.DS_Store
._*
*/._*
*/*/._*
coverage.*
lib-cov
*scratch*
coverage/*
node_modules
examples
packages/


================================================
FILE: .npmrc
================================================
ignore-scripts=true


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
team@artillery.io.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CONTRIBUTING.md
================================================
# Artillery.io Contributors Guide

## Need to get in touch?

All project discussions should happen in the [issue tracker](https://github.com/artilleryio/artillery/issues) or via [Discussions](https://github.com/artilleryio/artillery/discussions).

If you are a first-time contributor and want some help getting started, feel free to get in touch over email:

* Hassy Veldstra - [h@artillery.io](mailto:h@artillery.io?subject=Artillery Contribution Help)

## Guide for Contributions

* We use the usual Fork+Pull model (more info here: [https://help.github.com/articles/using-pull-requests/](https://help.github.com/articles/using-pull-requests/)]
* Pull requests that modify or add behavior should have tests, whether it's a new feature or a bug fix. If you're unsure how to structure a test, we can help.
* We love PRs that fix bugs.
* Do not add a new feature without discussing it via [Discussions](https://github.com/artilleryio/artillery/discussions) first. We've had to decline feature suggestions submitted via PRs in the past because they duplicate existing functionality, have limited utility to the wider user base, or carry too much maintenance burden. We don't want you to spend your time on something that we will not accept.
* One logical change per commit please. We'll ask you to rebase PRs containing commits that change several unrelated things.
* The smaller a PR is the better. Smaller PRs are much easier to review and provide feedback on. Always lean towards smaller PRs.
* Before you write more than a few lines of code, please make sure:

    * If it's a new feature proposal - that it has been discussed and accepted
    * Let others know that you are working on the issue
    
* Commit messages should follow this style (we use the [commitlint conventional](https://github.com/marionebl/commitlint/tree/master/%40commitlint/config-conventional) config):
  ```
  feat: A brief one-liner < 50 chars, use the imperative mood

  Followed by further explanation if needed, this should be wrapped at
  around 72 characters. Most commits should reference an existing
  issue, such as #101 above.
  ```

  Some reading on good commit messages: [http://chris.beams.io/posts/git-commit/](http://chris.beams.io/posts/git-commit/)
* Once your first PR has been merged, please add yourself to `package.json` for the relevant module and open another PR.

## Licensing

By sending a patch you certify that you have the rights to and agree for your contribution to be distributed under the terms of [MPL2](https://www.mozilla.org/en-US/MPL/2.0/).

You will also need to sign a CLA before your first PR is merged. A GitHub bot will guide you through that after a new PR is opened.


================================================
FILE: LICENSE-BSL.txt
================================================
Business Source License
=======================

License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
“Business Source License” is a trademark of MariaDB Corporation Ab.

Parameters

Licensor:             Artillery Software Inc
Licensed Works:       Azure-related code in Artillery. The Licensed Work is
                      (c) 2024 Artillery Software Inc
Additional Use Grant: You may make use of the Licensed Work strictly for
                      evaluation and/or non-production use only. Your use
                      does not include offering the Licensed Work to third
                      parties on a hosted or embedded basis.
Change Date:          Four years from the date the Licensed Work is published
Change License:       MPL 2.0

For information about commercial licensing arrangements for the Licensed Work,
please contact sales@artillery.io.

Notice

Business Source License 1.1

Terms

The Licensor hereby grants you the right to copy, modify, create derivative
works, redistribute, and make non-production use of the Licensed Work. The
Licensor may make an Additional Use Grant, above, permitting limited production use.

Effective on the Change Date, or the fourth anniversary of the first publicly
available distribution of a specific version of the Licensed Work under this
License, whichever comes first, the Licensor hereby grants you rights under
the terms of the Change License, and the rights granted in the paragraph
above terminate.

If your use of the Licensed Work does not comply with the requirements
currently in effect as described in this License, you must purchase a
commercial license from the Licensor, its affiliated entities, or authorized
resellers, or you must refrain from using the Licensed Work.

All copies of the original and modified Licensed Work, and derivative works
of the Licensed Work, are subject to this License. This License applies
separately for each version of the Licensed Work and the Change Date may vary
for each version of the Licensed Work released by Licensor.

You must conspicuously display this License on each original or modified copy
of the Licensed Work. If you receive the Licensed Work in original or
modified form from a third party, the terms and conditions set forth in this
License apply to your use of that work.

Any use of the Licensed Work in violation of this License will automatically
terminate your rights under this License for the current and all other
versions of the Licensed Work.

This License does not grant you any right in any trademark or logo of
Licensor or its affiliates (provided that you may use a trademark or logo of
Licensor as expressly required by this License).

TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
TITLE.

================================================
FILE: LICENSE.txt
================================================
Mozilla Public License, version 2.0

1. Definitions

1.1. “Contributor”

     means each individual or legal entity that creates, contributes to the
     creation of, or owns Covered Software.

1.2. “Contributor Version”

     means the combination of the Contributions of others (if any) used by a
     Contributor and that particular Contributor’s Contribution.

1.3. “Contribution”

     means Covered Software of a particular Contributor.

1.4. “Covered Software”

     means Source Code Form to which the initial Contributor has attached the
     notice in Exhibit A, the Executable Form of such Source Code Form, and
     Modifications of such Source Code Form, in each case including portions
     thereof.

1.5. “Incompatible With Secondary Licenses”
     means

     a. that the initial Contributor has attached the notice described in
        Exhibit B to the Covered Software; or

     b. that the Covered Software was made available under the terms of version
        1.1 or earlier of the License, but not also under the terms of a
        Secondary License.

1.6. “Executable Form”

     means any form of the work other than Source Code Form.

1.7. “Larger Work”

     means a work that combines Covered Software with other material, in a separate
     file or files, that is not Covered Software.

1.8. “License”

     means this document.

1.9. “Licensable”

     means having the right to grant, to the maximum extent possible, whether at the
     time of the initial grant or subsequently, any and all of the rights conveyed by
     this License.

1.10. “Modifications”

     means any of the following:

     a. any file in Source Code Form that results from an addition to, deletion
        from, or modification of the contents of Covered Software; or

     b. any new file in Source Code Form that contains any Covered Software.

1.11. “Patent Claims” of a Contributor

      means any patent claim(s), including without limitation, method, process,
      and apparatus claims, in any patent Licensable by such Contributor that
      would be infringed, but for the grant of the License, by the making,
      using, selling, offering for sale, having made, import, or transfer of
      either its Contributions or its Contributor Version.

1.12. “Secondary License”

      means either the GNU General Public License, Version 2.0, the GNU Lesser
      General Public License, Version 2.1, the GNU Affero General Public
      License, Version 3.0, or any later versions of those licenses.

1.13. “Source Code Form”

      means the form of the work preferred for making modifications.

1.14. “You” (or “Your”)

      means an individual or a legal entity exercising rights under this
      License. For legal entities, “You” includes any entity that controls, is
      controlled by, or is under common control with You. For purposes of this
      definition, “control” means (a) the power, direct or indirect, to cause
      the direction or management of such entity, whether by contract or
      otherwise, or (b) ownership of more than fifty percent (50%) of the
      outstanding shares or beneficial ownership of such entity.


2. License Grants and Conditions

2.1. Grants

     Each Contributor hereby grants You a world-wide, royalty-free,
     non-exclusive license:

     a. under intellectual property rights (other than patent or trademark)
        Licensable by such Contributor to use, reproduce, make available,
        modify, display, perform, distribute, and otherwise exploit its
        Contributions, either on an unmodified basis, with Modifications, or as
        part of a Larger Work; and

     b. under Patent Claims of such Contributor to make, use, sell, offer for
        sale, have made, import, and otherwise transfer either its Contributions
        or its Contributor Version.

2.2. Effective Date

     The licenses granted in Section 2.1 with respect to any Contribution become
     effective for each Contribution on the date the Contributor first distributes
     such Contribution.

2.3. Limitations on Grant Scope

     The licenses granted in this Section 2 are the only rights granted under this
     License. No additional rights or licenses will be implied from the distribution
     or licensing of Covered Software under this License. Notwithstanding Section
     2.1(b) above, no patent license is granted by a Contributor:

     a. for any code that a Contributor has removed from Covered Software; or

     b. for infringements caused by: (i) Your and any other third party’s
        modifications of Covered Software, or (ii) the combination of its
        Contributions with other software (except as part of its Contributor
        Version); or

     c. under Patent Claims infringed by Covered Software in the absence of its
        Contributions.

     This License does not grant any rights in the trademarks, service marks, or
     logos of any Contributor (except as may be necessary to comply with the
     notice requirements in Section 3.4).

2.4. Subsequent Licenses

     No Contributor makes additional grants as a result of Your choice to
     distribute the Covered Software under a subsequent version of this License
     (see Section 10.2) or under the terms of a Secondary License (if permitted
     under the terms of Section 3.3).

2.5. Representation

     Each Contributor represents that the Contributor believes its Contributions
     are its original creation(s) or it has sufficient rights to grant the
     rights to its Contributions conveyed by this License.

2.6. Fair Use

     This License is not intended to limit any rights You have under applicable
     copyright doctrines of fair use, fair dealing, or other equivalents.

2.7. Conditions

     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
     Section 2.1.


3. Responsibilities

3.1. Distribution of Source Form

     All distribution of Covered Software in Source Code Form, including any
     Modifications that You create or to which You contribute, must be under the
     terms of this License. You must inform recipients that the Source Code Form
     of the Covered Software is governed by the terms of this License, and how
     they can obtain a copy of this License. You may not attempt to alter or
     restrict the recipients’ rights in the Source Code Form.

3.2. Distribution of Executable Form

     If You distribute Covered Software in Executable Form then:

     a. such Covered Software must also be made available in Source Code Form,
        as described in Section 3.1, and You must inform recipients of the
        Executable Form how they can obtain a copy of such Source Code Form by
        reasonable means in a timely manner, at a charge no more than the cost
        of distribution to the recipient; and

     b. You may distribute such Executable Form under the terms of this License,
        or sublicense it under different terms, provided that the license for
        the Executable Form does not attempt to limit or alter the recipients’
        rights in the Source Code Form under this License.

3.3. Distribution of a Larger Work

     You may create and distribute a Larger Work under terms of Your choice,
     provided that You also comply with the requirements of this License for the
     Covered Software. If the Larger Work is a combination of Covered Software
     with a work governed by one or more Secondary Licenses, and the Covered
     Software is not Incompatible With Secondary Licenses, this License permits
     You to additionally distribute such Covered Software under the terms of
     such Secondary License(s), so that the recipient of the Larger Work may, at
     their option, further distribute the Covered Software under the terms of
     either this License or such Secondary License(s).

3.4. Notices

     You may not remove or alter the substance of any license notices (including
     copyright notices, patent notices, disclaimers of warranty, or limitations
     of liability) contained within the Source Code Form of the Covered
     Software, except that You may alter any license notices to the extent
     required to remedy known factual inaccuracies.

3.5. Application of Additional Terms

     You may choose to offer, and to charge a fee for, warranty, support,
     indemnity or liability obligations to one or more recipients of Covered
     Software. However, You may do so only on Your own behalf, and not on behalf
     of any Contributor. You must make it absolutely clear that any such
     warranty, support, indemnity, or liability obligation is offered by You
     alone, and You hereby agree to indemnify every Contributor for any
     liability incurred by such Contributor as a result of warranty, support,
     indemnity or liability terms You offer. You may include additional
     disclaimers of warranty and limitations of liability specific to any
     jurisdiction.

4. Inability to Comply Due to Statute or Regulation

   If it is impossible for You to comply with any of the terms of this License
   with respect to some or all of the Covered Software due to statute, judicial
   order, or regulation then You must: (a) comply with the terms of this License
   to the maximum extent possible; and (b) describe the limitations and the code
   they affect. Such description must be placed in a text file included with all
   distributions of the Covered Software under this License. Except to the
   extent prohibited by statute or regulation, such description must be
   sufficiently detailed for a recipient of ordinary skill to be able to
   understand it.

5. Termination

5.1. The rights granted under this License will terminate automatically if You
     fail to comply with any of its terms. However, if You become compliant,
     then the rights granted under this License from a particular Contributor
     are reinstated (a) provisionally, unless and until such Contributor
     explicitly and finally terminates Your grants, and (b) on an ongoing basis,
     if such Contributor fails to notify You of the non-compliance by some
     reasonable means prior to 60 days after You have come back into compliance.
     Moreover, Your grants from a particular Contributor are reinstated on an
     ongoing basis if such Contributor notifies You of the non-compliance by
     some reasonable means, this is the first time You have received notice of
     non-compliance with this License from such Contributor, and You become
     compliant prior to 30 days after Your receipt of the notice.

5.2. If You initiate litigation against any entity by asserting a patent
     infringement claim (excluding declaratory judgment actions, counter-claims,
     and cross-claims) alleging that a Contributor Version directly or
     indirectly infringes any patent, then the rights granted to You by any and
     all Contributors for the Covered Software under Section 2.1 of this License
     shall terminate.

5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
     license agreements (excluding distributors and resellers) which have been
     validly granted by You or Your distributors under this License prior to
     termination shall survive termination.

6. Disclaimer of Warranty

   Covered Software is provided under this License on an “as is” basis, without
   warranty of any kind, either expressed, implied, or statutory, including,
   without limitation, warranties that the Covered Software is free of defects,
   merchantable, fit for a particular purpose or non-infringing. The entire
   risk as to the quality and performance of the Covered Software is with You.
   Should any Covered Software prove defective in any respect, You (not any
   Contributor) assume the cost of any necessary servicing, repair, or
   correction. This disclaimer of warranty constitutes an essential part of this
   License. No use of  any Covered Software is authorized under this License
   except under this disclaimer.

7. Limitation of Liability

   Under no circumstances and under no legal theory, whether tort (including
   negligence), contract, or otherwise, shall any Contributor, or anyone who
   distributes Covered Software as permitted above, be liable to You for any
   direct, indirect, special, incidental, or consequential damages of any
   character including, without limitation, damages for lost profits, loss of
   goodwill, work stoppage, computer failure or malfunction, or any and all
   other commercial damages or losses, even if such party shall have been
   informed of the possibility of such damages. This limitation of liability
   shall not apply to liability for death or personal injury resulting from such
   party’s negligence to the extent applicable law prohibits such limitation.
   Some jurisdictions do not allow the exclusion or limitation of incidental or
   consequential damages, so this exclusion and limitation may not apply to You.

8. Litigation

   Any litigation relating to this License may be brought only in the courts of
   a jurisdiction where the defendant maintains its principal place of business
   and such litigation shall be governed by laws of that jurisdiction, without
   reference to its conflict-of-law provisions. Nothing in this Section shall
   prevent a party’s ability to bring cross-claims or counter-claims.

9. Miscellaneous

   This License represents the complete agreement concerning the subject matter
   hereof. If any provision of this License is held to be unenforceable, such
   provision shall be reformed only to the extent necessary to make it
   enforceable. Any law or regulation which provides that the language of a
   contract shall be construed against the drafter shall not be used to construe
   this License against a Contributor.


10. Versions of the License

10.1. New Versions

      Mozilla Foundation is the license steward. Except as provided in Section
      10.3, no one other than the license steward has the right to modify or
      publish new versions of this License. Each version will be given a
      distinguishing version number.

10.2. Effect of New Versions

      You may distribute the Covered Software under the terms of the version of
      the License under which You originally received the Covered Software, or
      under the terms of any subsequent version published by the license
      steward.

10.3. Modified Versions

      If you create software not governed by this License, and you want to
      create a new license for such software, you may create and use a modified
      version of this License if you rename the license and remove any
      references to the name of the license steward (except to note that such
      modified license differs from this License).

10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
      If You choose to distribute Source Code Form that is Incompatible With
      Secondary Licenses under the terms of this version of the License, the
      notice described in Exhibit B of this License must be attached.

Exhibit A - Source Code Form License Notice

      This Source Code Form is subject to the
      terms of the Mozilla Public License, v.
      2.0. If a copy of the MPL was not
      distributed with this file, You can
      obtain one at
      http://mozilla.org/MPL/2.0/.

If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.

You may add additional accurate notices of copyright ownership.

Exhibit B - “Incompatible With Secondary Licenses” Notice

      This Source Code Form is “Incompatible
      With Secondary Licenses”, as defined by
      the Mozilla Public License, v. 2.0.


================================================
FILE: README.md
================================================
<div align="center">
  <a href="./packages/artillery#readme"><img src="./packages/artillery/artillery-logo.svg" width="80"></a>
  <h1>Artillery</h1>
<p align="center">
  <a href="https://www.artillery.io/docs">Docs</a> | <a href="https://github.com/artilleryio/artillery/discussions">Discussions</a> | <a href="https://twitter.com/artilleryio">@artilleryio</a>
</p>

<p align="center">
  <img alt="npm" src="https://img.shields.io/npm/dm/artillery?style=flat-square">
</p>


<a href="https://www.artillery.io/">
  <img
    src="https://www.artillery.io/api/og?title=Full-stack%20reliability%20%26%20performance&description=Scalable%20API%20and%20Playwright%20load%20testing"
  />
</a>

</div>

## Features

- **Test at cloud scale.** Cloud-native distributed load testing at scale, **out-of-the box and for free**.
  - Scale out your load tests on top of AWS Lambda or AWS Fargate. No DevOps needed, zero infrastructure to set up or manage.
- **Test with Playwright**. Load test with real headless browsers.
- **Batteries-included.** 20+ integrations for monitoring, observability, and CICD.
- **Test anything**. HTTP, WebSocket, Socket.io, gRPC, Kinesis, and more.
- **Powerful workload modeling**. Emulate complex user behavior with request chains, multiple steps, transactions, and more.
- **Extensible & hackable**. Artillery has a plugin API to allow extending and customization.

## License

* Most of the code in this repository is licensed under the terms of the [MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.
* Some Azure-specific modules are licensed under the terms of the [BSL license](https://mariadb.com/bsl-faq-adopting/). See [LICENSE-BSL.txt](./LICENSE-BSL.txt) for details. You may use Artillery on Azure for evaluation and proof-of-concept purposes, but commercial and/or production usage requires a commercial license.


→ [Learn more](./packages/artillery#readme)

<!--

----

<div align="center">
  <img src="./packages/skytrace/skytrace-logo.svg" width="80">
  <h1>Skytrace<br />fast & simple end-to-end testing</h1>
</div>

**Skytrace makes it easy to write, run and reuse e2e tests.**

* Write flows fast with editor autocomplete and auto-reload mode
* Set assertions and expectations on responses
* Run locally, in CI/CD, or in production
* Batteries-included with 20+ integrations for CICD, monitoring, and observability
* Reuse flows for load testing with Artillery

→ [Learn more](./packages/skytrace#readme)

⚠️ Skytrace is an alpha project ⚠️

----

<img src="https://149753425.v2.pressablecdn.com/wp-content/uploads/2009/06/osi_symbol_100X100_0.png" width="36" align="left" />

**Artillery** and **Skytrace** are open-source software distributed under the terms of the [MPLv2](https://www.mozilla.org/en-US/MPL/2.0/) license.

-->


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

The following versions of Artillery are currently being supported with security updates:

| Version | Supported          |
| ------- | ------------------ |
| 2.x.x   | :white_check_mark: |
| 1.7.x   | :x:                |
| < 1.7   | :x:                |

## Reporting a Vulnerability

Please see the latest version of our security policy at

https://www.artillery.io/security-policy


================================================
FILE: biome.json
================================================
{
  "$schema": "https://biomejs.dev/schemas/2.3.3/schema.json",
  "formatter": {
    "enabled": false
  },
  "linter": {
    "enabled": true,
    "rules": {
      "suspicious": {
        "noThenProperty": "off",
        "noExplicitAny": "off"
      }
    }
  },
  "files": {
    "includes": [
      "**",
      "!**/packages/types",
      "!**/packages/artillery-engine-playwright/test/**/*.ts",
      "!**/examples/browser-playwright-reuse-typescript/**/*.ts",
      "!**/node_modules",
      "!**/dist",
      "!**/build"
    ]
  }
}


================================================
FILE: commitlint.config.js
================================================
const config = require('@commitlint/config-conventional');

const types = config.rules['type-enum'][2].concat(['dep']);

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', types]
  }
};


================================================
FILE: examples/README.md
================================================
<p align="center">
<img width="1012" alt="artillery-examples" src="https://user-images.githubusercontent.com/1490/139437758-7093853a-2f19-40fd-b827-29d3584cf438.png">
</p>

# Artillery Examples

This repo contains examples of how to use various features in Artillery. Every example is self-contained and can be run as-is without external dependencies (other than those in `package.json`).

## Test scripts

### Core features

- [using-data-from-csv](./using-data-from-csv) - using data from an external CSV file in vuser scenarios
- [scenario-weights](./scenario-weights) - set weights to change how often Artillery runs a scenario
- [script-overrides](./script-overrides) - override parts of the script such as load phases dynamically at runtime
- [multiple-scenario-specs](./multiple-scenario-specs) - organizing your Artillery test codebase into separate scenario files
- [automated-checks](./automated-checks) - setting up automated checks with `ensure` and `apdex` plugins

### How-tos

- [refresh-auth-token](./refresh-auth-token/) - how to refresh an auth token used by a VU as the test is running

### End-to-end examples

- [socket-io](./socket-io) - testing a Socket.io service
- [websockets](./websockets) - testing a WebSocket service
- [graphql-api-server](./graphql-api-server) - testing a GraphQL API server
- [browser-load-testing-playwright](./browser-load-testing-playwright) - load testing with real browsers
- [functional testing](./functional-testing-with-expect-plugin) - use `artillery-plugin-expect` to run both load and functional tests
- [CSV-driven functional testing](./table-driven-functional-tests) - define functional tests with a CSV file

### HTTP-specific examples

- [http-set-custom-header](./http-set-custom-header) - set an HTTP header in a `beforeRequest` hook
- [using-cookies](./using-cookies) - using cookies with HTTP services
- [file-uploads](./file-uploads) - HTTP file uploads with Artillery Pro

### Plugins and extensions

- [track-custom-metrics](./track-custom-metrics) - track custom metrics (counters and histograms)
- [artillery-plugin-hello-world](./artillery-plugin-hello-world) - a "hello world" plugin

## Running Artillery in CI/CD

- [cicd examples](./cicd) - using Artillery with Github Actions, Gitlab CI, Azure DevOps, CircleCI and more

## Starter kits

- [starter-kit](./starter-kit) - @cfryerdev's Artillery starter kit - an example of how a few different bits fit together

## Testing on Kubernetes

- [k8s-testing-with-kubectl-artillery-](./k8s-testing-with-kubectl-artillery)

# Contributing

Would you like to share an example showing how to use a feature in Artillery with the community? Send us a PR 💜

# License

All code in this repo is licensed under the terms of the [MPL2 license](https://www.mozilla.org/en-US/MPL/2.0/FAQ/).


================================================
FILE: examples/artillery-engine-example/.gitignore
================================================
.idea
*.iml
npm-debug.log
dump.rdb
node_modules
components
build
results.tap
results.xml
config.json
.DS_Store
*/.DS_Store
*/*/.DS_Store
._*
*/._*
*/*/._*
coverage.*
lib-cov
*scratch*
artillery_report*
coverage/*
.vagrant/
.vscode

================================================
FILE: examples/artillery-engine-example/LICENSE
================================================
Mozilla Public License Version 2.0
==================================

1. Definitions
--------------

1.1. "Contributor"
    means each individual or legal entity that creates, contributes to
    the creation of, or owns Covered Software.

1.2. "Contributor Version"
    means the combination of the Contributions of others (if any) used
    by a Contributor and that particular Contributor's Contribution.

1.3. "Contribution"
    means Covered Software of a particular Contributor.

1.4. "Covered Software"
    means Source Code Form to which the initial Contributor has attached
    the notice in Exhibit A, the Executable Form of such Source Code
    Form, and Modifications of such Source Code Form, in each case
    including portions thereof.

1.5. "Incompatible With Secondary Licenses"
    means

    (a) that the initial Contributor has attached the notice described
        in Exhibit B to the Covered Software; or

    (b) that the Covered Software was made available under the terms of
        version 1.1 or earlier of the License, but not also under the
        terms of a Secondary License.

1.6. "Executable Form"
    means any form of the work other than Source Code Form.

1.7. "Larger Work"
    means a work that combines Covered Software with other material, in
    a separate file or files, that is not Covered Software.

1.8. "License"
    means this document.

1.9. "Licensable"
    means having the right to grant, to the maximum extent possible,
    whether at the time of the initial grant or subsequently, any and
    all of the rights conveyed by this License.

1.10. "Modifications"
    means any of the following:

    (a) any file in Source Code Form that results from an addition to,
        deletion from, or modification of the contents of Covered
        Software; or

    (b) any new file in Source Code Form that contains any Covered
        Software.

1.11. "Patent Claims" of a Contributor
    means any patent claim(s), including without limitation, method,
    process, and apparatus claims, in any patent Licensable by such
    Contributor that would be infringed, but for the grant of the
    License, by the making, using, selling, offering for sale, having
    made, import, or transfer of either its Contributions or its
    Contributor Version.

1.12. "Secondary License"
    means either the GNU General Public License, Version 2.0, the GNU
    Lesser General Public License, Version 2.1, the GNU Affero General
    Public License, Version 3.0, or any later versions of those
    licenses.

1.13. "Source Code Form"
    means the form of the work preferred for making modifications.

1.14. "You" (or "Your")
    means an individual or a legal entity exercising rights under this
    License. For legal entities, "You" includes any entity that
    controls, is controlled by, or is under common control with You. For
    purposes of this definition, "control" means (a) the power, direct
    or indirect, to cause the direction or management of such entity,
    whether by contract or otherwise, or (b) ownership of more than
    fifty percent (50%) of the outstanding shares or beneficial
    ownership of such entity.

2. License Grants and Conditions
--------------------------------

2.1. Grants

Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:

(a) under intellectual property rights (other than patent or trademark)
    Licensable by such Contributor to use, reproduce, make available,
    modify, display, perform, distribute, and otherwise exploit its
    Contributions, either on an unmodified basis, with Modifications, or
    as part of a Larger Work; and

(b) under Patent Claims of such Contributor to make, use, sell, offer
    for sale, have made, import, and otherwise transfer either its
    Contributions or its Contributor Version.

2.2. Effective Date

The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.

2.3. Limitations on Grant Scope

The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:

(a) for any code that a Contributor has removed from Covered Software;
    or

(b) for infringements caused by: (i) Your and any other third party's
    modifications of Covered Software, or (ii) the combination of its
    Contributions with other software (except as part of its Contributor
    Version); or

(c) under Patent Claims infringed by Covered Software in the absence of
    its Contributions.

This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).

2.4. Subsequent Licenses

No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).

2.5. Representation

Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.

2.6. Fair Use

This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.

2.7. Conditions

Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.

3. Responsibilities
-------------------

3.1. Distribution of Source Form

All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.

3.2. Distribution of Executable Form

If You distribute Covered Software in Executable Form then:

(a) such Covered Software must also be made available in Source Code
    Form, as described in Section 3.1, and You must inform recipients of
    the Executable Form how they can obtain a copy of such Source Code
    Form by reasonable means in a timely manner, at a charge no more
    than the cost of distribution to the recipient; and

(b) You may distribute such Executable Form under the terms of this
    License, or sublicense it under different terms, provided that the
    license for the Executable Form does not attempt to limit or alter
    the recipients' rights in the Source Code Form under this License.

3.3. Distribution of a Larger Work

You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).

3.4. Notices

You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.

3.5. Application of Additional Terms

You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.

4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------

If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.

5. Termination
--------------

5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.

5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.

5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.

************************************************************************
*                                                                      *
*  6. Disclaimer of Warranty                                           *
*  -------------------------                                           *
*                                                                      *
*  Covered Software is provided under this License on an "as is"       *
*  basis, without warranty of any kind, either expressed, implied, or  *
*  statutory, including, without limitation, warranties that the       *
*  Covered Software is free of defects, merchantable, fit for a        *
*  particular purpose or non-infringing. The entire risk as to the     *
*  quality and performance of the Covered Software is with You.        *
*  Should any Covered Software prove defective in any respect, You     *
*  (not any Contributor) assume the cost of any necessary servicing,   *
*  repair, or correction. This disclaimer of warranty constitutes an   *
*  essential part of this License. No use of any Covered Software is   *
*  authorized under this License except under this disclaimer.         *
*                                                                      *
************************************************************************

************************************************************************
*                                                                      *
*  7. Limitation of Liability                                          *
*  --------------------------                                          *
*                                                                      *
*  Under no circumstances and under no legal theory, whether tort      *
*  (including negligence), contract, or otherwise, shall any           *
*  Contributor, or anyone who distributes Covered Software as          *
*  permitted above, be liable to You for any direct, indirect,         *
*  special, incidental, or consequential damages of any character      *
*  including, without limitation, damages for lost profits, loss of    *
*  goodwill, work stoppage, computer failure or malfunction, or any    *
*  and all other commercial damages or losses, even if such party      *
*  shall have been informed of the possibility of such damages. This   *
*  limitation of liability shall not apply to liability for death or   *
*  personal injury resulting from such party's negligence to the       *
*  extent applicable law prohibits such limitation. Some               *
*  jurisdictions do not allow the exclusion or limitation of           *
*  incidental or consequential damages, so this exclusion and          *
*  limitation may not apply to You.                                    *
*                                                                      *
************************************************************************

8. Litigation
-------------

Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.

9. Miscellaneous
----------------

This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.

10. Versions of the License
---------------------------

10.1. New Versions

Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.

10.2. Effect of New Versions

You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.

10.3. Modified Versions

If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).

10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses

If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.

Exhibit A - Source Code Form License Notice
-------------------------------------------

  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.

If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.

You may add additional accurate notices of copyright ownership.

Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------

  This Source Code Form is "Incompatible With Secondary Licenses", as
  defined by the Mozilla Public License, v. 2.0.


================================================
FILE: examples/artillery-engine-example/README.md
================================================
# Artillery Engine Example

This repo contains the code for a simple "hello world" Artillery engine that shows how Artillery's
engine API works,  and can serve as a starting point for a custom engine.

## Usage

- Install dependencies with `npm install`
- Set up parent folder as `NODE_PATH` so this engine is loaded by Artillery: `export NODE_PATH=$(pwd)/..`
- Run the example script using this engine: `artillery run example.yaml`
### License

[MPL 2.0](https://www.mozilla.org/en-US/MPL/2.0/)


================================================
FILE: examples/artillery-engine-example/example.yaml
================================================
config:
  target: "system-under-test-endpoint"
  example:
    mandatoryString: "a configuration setting for our engine"
  phases:
    - arrivalRate: 1
      duration: 1
  engines:
    example: {}
scenarios:
  - name: "custom_example_engine_scenario"
    engine: example
    flow:
      - doSomething:
          id: 123
      - doSomething:
          id: 456


================================================
FILE: examples/artillery-engine-example/index.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const A = require('async');
const debug = require('debug')('engine:example');

// Simple example engine that recieves a prop and prints it when a 'doSomething'
// action is found.
// Serves as a modifiable example to build on top of for new engines
class ExampleEngine {
  // Artillery initializes each engine with the following arguments:
  //
  // - script is the entire script object, with .config and .scenarios properties
  // - events is an EventEmitter we can use to subscribe to events from Artillery, and
  //   to report custom metrics
  // - helpers is a collection of utility functions
  constructor(script, ee, helpers) {
    this.script = script;
    this.ee = ee;
    this.helpers = helpers;

    // This would typically be the endpoint we're testing
    this.target = script.config.target;

    const opts = { ...this.script.config.example };

    // We can add custom validations on those props
    if (!opts.mandatoryString) {
      throw new Error('mandatoryString setting must be set');
    }
  }

  // For each scenario in the script using this engine, Artillery calls this function
  // to create a VU function
  createScenario(scenarioSpec, ee) {
    const tasks = scenarioSpec.flow.map((rs) => this.step(rs, ee));

    return function scenario(initialContext, callback) {
      ee.emit('started');

      function vuInit(callback) {
        // we can run custom VU-specific init code here
        return callback(null, initialContext);
      }

      const steps = [vuInit].concat(tasks);

      A.waterfall(steps, function done(err, context) {
        if (err) {
          debug(err);
        }

        return callback(err, context);
      });
    };
  }

  // This is a convenience function where we delegate common actions like loop, log, and think,
  // and handle actions which are custom for our engine, i.e. the "doSomething" action in this case
  step(rs, ee) {
    const self = this;

    if (rs.loop) {
      const steps = rs.loop.map((loopStep) => this.step(loopStep, ee));

      return this.helpers.createLoopWithCount(rs.count || -1, steps, {});
    }

    if (rs.log) {
      return function log(context, callback) {
        return process.nextTick(() => {
          callback(null, context);
        });
      };
    }

    if (rs.think) {
      return this.helpers.createThink(rs, self.config?.defaults?.think || {});
    }

    if (rs.function) {
      return (context, callback) => {
        const func = self.script.config.processor[rs.function];
        if (!func) {
          return process.nextTick(() => {
            callback(null, context);
          });
        }

        return func(context, ee, () => callback(null, context));
      };
    }

    //
    // This is our custom action:
    //
    if (rs.doSomething) {
      return function example(context, callback) {
        console.log(
          'doSomething action with id:',
          self.helpers.template(rs.doSomething.id, context, true)
        );
        console.log('target is:', self.target);

        // Emit a metric to count the number of example actions performed:
        ee.emit('counter', 'example.action_count', 1);
        return callback(null, context);
      };
    }

    //
    // Ignore any unrecognized actions:
    //
    return function doNothing(context, callback) {
      return callback(null, context);
    };
  }
}

module.exports = ExampleEngine;


================================================
FILE: examples/artillery-engine-example/package.json
================================================
{
  "name": "artillery-engine-example",
  "version": "0.0.1",
  "description": "Engine template/example for Artillery",
  "main": "index.js",
  "scripts": {
    "test": "node test/index.js"
  },
  "keywords": [
    "artillery",
    "engine",
    "load"
  ],
  "author": "Juan Gil <jgil@artillery.io>",
  "license": "MPL-2.0",
  "devDependencies": {
    "tap": "^18.6.1",
    "tape": "^5.6.1"
  },
  "dependencies": {
    "async": "^3.2.4",
    "debug": "^4.3.4"
  }
}


================================================
FILE: examples/artillery-engine-example/test/index.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const { test } = require('tap');
const EventEmitter = require('node:events');

const ExampleEngine = require('..');

const script = {
  config: {
    target: 'my-endpoint',
    example: {
      mandatoryString: 'hello-world'
    }
  },
  scenarios: [
    {
      name: 'test scenario',
      engine: 'example',
      flow: [
        {
          doSomething: {
            id: 123
          }
        }
      ]
    }
  ]
};

test('Engine interface', async (t) => {
  const events = new EventEmitter();
  const engine = new ExampleEngine(script, events, {});
  const scenario = engine.createScenario(script.scenarios[0], events);

  t.match(engine.script, script, 'Engine constructor sets script');
  t.type(scenario, 'function', 'Engine.createScenario returns a function');
});


================================================
FILE: examples/artillery-plugin-hello-world/README.md
================================================
# artillery-hello-world-plugin

This is a "hello world" plugin for Artillery which shows:

- Artillery's plugin interface
- How a barebones plugin is constructed
- How to inspect test script properties in a plugin
- How to attach custom hooks to scenarios in a plugin to do something interesting

## Run the example scenario 👋

By default Artillery will look in Node.js package path for the plugin package (which is expected to have an `artillery-plugin-` prefix, so the package for the `hello-world` plugin is expected to be named `artillery-plugin-hello-world`).

We can add an extra look-up location with `ARTILLERY_PLUGIN_PATH`. This is useful when developing plugins.

From the folder where this README is located, run:

```sh
ARTILLERY_PLUGIN_PATH=`pwd`/.. DEBUG=plugin:hello-world artillery run test.yml
```

And we should see our greeting, debug messages from the plugin, and the counter in Artillery's output:

![greeting](./images/screenshot1.png)
![custom counter](./images/screenshot2.png)

## Learn more 📖

Check out these plugins for ideas of how to do more things:

- https://github.com/artilleryio/artillery-plugin-publish-metrics
- https://github.com/artilleryio/artillery-plugin-hls
- https://github.com/artilleryio/artillery-plugin-fuzzer
- https://github.com/artilleryio/artillery-plugin-expect

Artillery's extension APIs:

https://artillery.io/docs/guides/guides/extension-apis

Blog post on creating a custom plugin:

https://artillery.io/blog/extend-artillery-by-creating-your-own-plugins

## Write a plugin (and let us know!) ⚡

Artillery's plugin interface + the power of Node.js (there's an npm package for everything!) make it easy to extend Artillery with new functionality.

If you write a new plugin, let us know!

- Github Discussion board: https://github.com/artilleryio/artillery/discussions

💜


================================================
FILE: examples/artillery-plugin-hello-world/index.js
================================================
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const debug = require('debug')('plugin:hello-world');

module.exports.Plugin = ArtilleryHelloWorldPlugin;

function ArtilleryHelloWorldPlugin(script, events) {
  // This is the entirety of the test script - config and
  // scenarios
  this.script = script;
  // This is an EventEmitter, we can subscribe to:
  // 'stats' - fired when a new batch of metrics is available
  // 'done' - fired when all VUs are done
  // We can also use this EventEmitter to emit custom
  // metrics:
  // https://artillery.io/docs/guides/guides/extending.html#Tracking-custom-metrics
  this.events = events;

  // We can read our plugin's configuration:
  const pluginConfig = script.config.plugins['hello-world'];
  this.greeting = pluginConfig.greeting || 'hello, world';

  // But we could also read anything else defined in the test
  // script, e.g.:
  debug('target is:', script.config.target);

  //
  // Let's attach a beforeRequest hook to all scenarios
  // which will print a greeting before a request is made
  //
  // Create processor object if needed to hold our custom function:
  script.config.processor = script.config.processor || {};
  // Add our custom function:
  script.config.processor.pluginHelloWorldBeforeRequestHook = (
    _req,
    _vuContext,
    events,
    next
  ) => {
    // This a beforeRequest handler function:
    // https://artillery.io/docs/guides/guides/http-reference.html#beforeRequest

    console.log(this.greeting); // print greeting
    events.emit('counter', 'greeting_count', 1); // increase custom counter
    return next(); // the hook is done, go on to the next one (or let Artillery make the request)
  };
  // Attach the function to every scenario as a scenario-level hook:
  script.scenarios.forEach((scenario) => {
    scenario.beforeRequest = scenario.beforeRequest || [];
    scenario.beforeRequest.push('pluginHelloWorldBeforeRequestHook');
  });

  return this;
}

// Artillery will call this before it exits to give plugins
// a chance to clean up, e.g. by flushing any in-flight data,
// writing something to disk etc.
ArtilleryHelloWorldPlugin.prototype.cleanup = (done) => {
  debug('cleaning up');
  done(null);
};


================================================
FILE: examples/artillery-plugin-hello-world/package.json
================================================
{
  "name": "artillery-plugin-hello-world",
  "version": "1.0.0",
  "description": "This is a \"hello world\" plugin for Artillery which shows:",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "MPL-2.0",
  "dependencies": {
    "debug": "^4.3.1"
  }
}


================================================
FILE: examples/artillery-plugin-hello-world/test.yml
================================================
config:
  target: "http://asciiart.artillery.io:8080"
  phases:
    - arrivalRate: 1
      duration: 10
  plugins:
    hello-world:
      greeting: "Hello world! 👋"
scenarios:
  - flow:
      - get:
          url: "/"

================================================
FILE: examples/automated-checks/README.md
================================================
# Using automated checks

This is an example Artillery load test that includes:

1. A load configuration with 3 distinct phases that create a burst of traffic after a warm up period
2. Configuration for [`apdex`](https://docs.art/reference/extensions/apdex) and [`ensure`](https://docs.art/reference/extensions/ensure) plugins to set up automated scoring and checking of performance results from the test
3. Use of `metrics-by-endpoint` plugin to enable reporting of metrics for each individual URL in the test

Run the script with:

```
artillery run test-with-automated-checks.yml
```


================================================
FILE: examples/automated-checks/load-test-with-automated-checks.yml
================================================
# This an example Artillery load test that includes:
# - A load configuration with 3 distinct phases that create
#   a burst of traffic after a warm up period
# - How to use built-in "apdex" and "ensure" plugins to set up
#   automated scoring and checking of performance results from the test
# - Using metrics-by-endpoint plugin to enable reporting of metrics
#   for each individual URL in the test
config:
  # This is a test server run by team Artillery
  # It's designed to be highly scalable and withstand
  # traffic spikes of millions of requests per second
  target: http://asciiart.artillery.io:8080
  phases:
    - duration: 60
      arrivalRate: 1
      rampTo: 5
      name: Warm up phase
    - duration: 60
      arrivalRate: 5
      rampTo: 10
      name: Ramp up load
    - duration: 30
      arrivalRate: 10
      rampTo: 30
      name: Spike phase
  # Load a couple of useful plugins
  # https://docs.art/reference/extensions
  plugins:
    ensure: {}
    apdex: {}
    metrics-by-endpoint: {}
  # Set a threshold of 25ms for calculating Apdex scores
  # https://docs.art/reference/extensions/apdex
  apdex:
    threshold: 100
  # Configure automated checks
  # https://docs.art/reference/extensions/ensure
  ensure:
      thresholds:
        - http.response_time.p99: 100
        - http.response_time.p95: 75
scenarios:
  - flow:
      - loop:
        - get:
            url: "/dino"
        - get:
            url: "/pony"
        - get:
            url: "/armadillo"
        count: 100


================================================
FILE: examples/browser-load-testing-playwright/README.md
================================================
# Load testing and smoke testing with headless browsers

Artillery can run Playwright scripts as performance tests. This example shows you how to run a simple load test, a smoke test, and how to track custom metrics for part of the flow.

- [Why load test with headless browsers?](https://www.artillery.io/docs/playwright#why-load-test-with-headless-browsers)

> [!TIP]
> Artillery's uses YAML as its default configuration format, but Playwright tests can be written as TypeScript. The examples below are shown as both TypeScript-only, and YAML + TypeScript.

## Example 1: A simple load test

Run a simple load test using a plain Playwright script (recorded with `playwright codegen` - no Artillery-specific changes required):


```sh
# Run the TypeScript example:
npx artillery run browser-load-test.ts
```

```sh
# The same example configured with a separate YAML config file:
npx artillery run browser-load-test.yml
```

That's it! Artillery will create headless Chrome browsers that will run Playwright scenarios you provide.

## Example 2: A smoke test

This example shows how we can implement a smoke test (or a synthetic check) using a headless browser.

We make use of Artillery's [CSV payload](https://artillery.io/docs/guides/guides/test-script-reference.html#Payload-files) feature to specify the URLs we want to check, and [custom metric API](https://artillery.io/docs/guides/guides/extending.html#Tracking-custom-metrics) to track custom metrics.

For every row in the CSV file, we'll load the URL from the first column, and check that the page contains the text specified in the second column.

The test will load each page specified in the CSV file, and check that it contains the text

```sh
# Run the TypeScript example:
npx artillery run browser-smoke-test.ts
```

```sh
# The same example configured with a separate YAML config file:
npx artillery run browser-smoke-test.yml
```

## Example 3: Tracking custom metrics for part of the flow

A common usage scenario is reporting performance metrics only for one part of a test flow. For example, you may be testing an ecommerce app with the following steps:

1. Go to the homepage
2. Search for a product
3. Navigate to product page
4. Add product to cart
5. Login
6. Complete checkout:
  - Enter a discount code
  - Update billing info
  - Check out

You may want to report performance metrics only for part 6 of the flow. Artillery lets you do that with its [custom metrics API](https://www.artillery.io/docs/guides/guides/extension-apis#tracking-custom-metrics).

See the example in [./advanced-custom-metric-for-subflow.yml](./advanced-custom-metric-for-subflow.yml) and specifically the `multistepWithCustomMetrics()` test in [flows.js](./flows.js) for details.


## Creating Playwright scripts

You can use the built-in `playwright codegen` tool to generate test scripts quickly by performing user actions in the real browser. That's how the code in `flows.js` in this example was created. It's just a Playwright script, there's nothing Artillery specific about it. **Speed up test creation time by 10x.**

## Front-end AND back-end metrics

Artillery will emit both backend and browser-level performance metrics when running this test, so that you can see both how long resources such as static assets took to load, as well as page-level metrics, such as how long it took for pages to become interactive.

```
vusers.created_by_name.Dev account signup: .................. 10
vusers.created.total: ....................................... 10
vusers.completed: ........................................... 10
vusers.session_length:
  min: ...................................................... 3884.2
  max: ...................................................... 13846.2
  median: ................................................... 12711.5
  p95: ...................................................... 12968.3
  p99: ...................................................... 12968.3
browser.page_domcontentloaded: ........................... 20
browser.response_time:
  min: ...................................................... 0
  max: ...................................................... 1778.8
  median: ................................................... 37.7
  p95: ...................................................... 3828.5
  p99: ...................................................... 3828.5
browser.page_domcontentloaded.dominteractive:
  min: ...................................................... 297
  max: ...................................................... 2247
  median: ................................................... 1002.4
  p95: ...................................................... 1939.5
  p99: ...................................................... 1939.5
browser.page_domcontentloaded.dominteractive.https://artillery.io/:
  min: ...................................................... 427
  max: ...................................................... 2247
  median: ................................................... 1130.2
  p95: ...................................................... 1939.5
  p99: ...................................................... 1939.5
browser.page_domcontentloaded.dominteractive.https://artillery.io/pro/:
  min: ...................................................... 297
  max: ...................................................... 1927
  median: ................................................... 596
  p95: ...................................................... 1380.5
  p99: ...................................................... 1380.5
```

## Scaling browser tests

Running headless browsers in parallel will quickly exhaust CPU and memory of a single machine.

Artillery has built-in support for cloud-native distributed load testing on AWS Fargate or Azure Container Instances.

See our guide for [Distributed load testing](https://www.artillery.io/docs/load-testing-at-scale) for more information.


================================================
FILE: examples/browser-load-testing-playwright/browser-load-test.ts
================================================
export const config = {
  target: 'https://www.artillery.io',
  phases: [
    {
      arrivalRate: 1,
      duration: 10
    }
  ],
  engines: {
    playwright: {
      trace: true
    }
  }
};

export const before = {
  engine: 'playwright',
  testFunction: async function beforeFunctionHook(_page, userContext, _events) {
    // Any scenario variables we add via userContext.vars in this before hook will be available in every VU
    userContext.vars.testStartTime = new Date();
  }
};

export const scenarios = [
  {
    engine: 'playwright',
    name: 'check_out_core_concepts_scenario',
    testFunction: async function checkOutArtilleryCoreConceptsFlow(
      page,
      _userContext,
      _events,
      test
    ) {
      await test.step('Go to Artillery', async () => {
        const requestPromise = page.waitForRequest('https://artillery.io/');
        await page.goto('https://artillery.io/');
        const _req = await requestPromise;
      });
      await test.step('Go to docs', async () => {
        await page.getByRole('link', { name: 'Docs' }).first().click();
        await page.waitForURL('https://www.artillery.io/docs');
      });

      await test.step('Go to core concepts', async () => {
        await page
          .getByRole('link', {
            name: 'Start a new GitHub Discussion'
          })
          .click();

        await page.waitForURL(
          'https://github.com/artilleryio/artillery/discussions'
        );
      });
    }
  }
];


================================================
FILE: examples/browser-load-testing-playwright/browser-load-test.yml
================================================
config:
  target: "https://www.artillery.io"
  phases:
    - arrivalRate: 1
      duration: 10
  engines:
    playwright: {}
  processor: ./flows.js
scenarios:
  - name: "check_out_core_concepts_scenario"
    engine: playwright
    flowFunction: "checkOutArtilleryCoreConceptsFlow"


================================================
FILE: examples/browser-load-testing-playwright/browser-smoke-test.ts
================================================
import { checkPage } from './flows';
export const config = {
  target: 'https://www.artillery.io',
  phases: [
    {
      arrivalCount: 1,
      duration: 1
    }
  ],
  payload: {
    path: './pages.csv',
    fields: ['url', 'title'],
    loadAll: true,
    name: 'pageChecks'
  },
  engines: {
    playwright: {}
  }
};

export const scenarios = [
  {
    name: 'smoke_test_page',
    engine: 'playwright',
    testFunction: checkPage
  }
];


================================================
FILE: examples/browser-load-testing-playwright/browser-smoke-test.yml
================================================
config:
  target: "https://www.artillery.io"
  payload:
    - path: ./pages.csv
      fields:
        - "url"
        - "title"
      loadAll: true
      name: pageChecks
  engines:
    playwright: {}
  processor: ./flows.js
scenarios:
  - name: smoke_test_page
    engine: playwright
    flowFunction: checkPage


================================================
FILE: examples/browser-load-testing-playwright/browser-test-with-steps.yml
================================================
config:
  target: "https://www.artillery.io"
  phases:
    - arrivalRate: 1
      duration: 10
  engines:
    playwright: {}
  processor: ./flows.js
scenarios:
  - name: flow_with_multiple_steps
    engine: playwright
    flowFunction: "multistepWithCustomMetrics"


================================================
FILE: examples/browser-load-testing-playwright/flows.js
================================================
//
// The code in this function was generated with
// playwright codegen
// https://playwright.dev/docs/codegen
//
async function checkOutArtilleryCoreConceptsFlow(
  page,
  _userContext,
  _events,
  test
) {
  await test.step('Go to Artillery', async () => {
    const requestPromise = page.waitForRequest('https://artillery.io/');
    await page.goto('https://artillery.io/');
    const _req = await requestPromise;
  });
  await test.step('Go to docs', async () => {
    await page.getByRole('link', { name: 'Docs' }).first().click();
    await page.waitForURL('https://www.artillery.io/docs');
  });

  await test.step('Go to core concepts', async () => {
    await page
      .getByRole('link', {
        name: 'Review core concepts'
      })
      .click();

    await page.waitForURL(
      'https://www.artillery.io/docs/get-started/core-concepts'
    );
  });
}

//
// A simple smoke test using a headless browser:
//
async function checkPage(page, userContext, events) {
  // The pageChecks variable is created via the config.payload
  // section in the YML config file
  for (const { url, title } of userContext.vars.pageChecks) {
    const response = await page.goto(url);
    if (response.status() !== 200) {
      events.emit('counter', `user.status_check_failed.${url}`, 1);
    } else {
      events.emit('counter', `user.status_check_ok.${url}`, 1);
    }

    const isElementVisible = await page.getByText(title).isVisible();

    if (!isElementVisible) {
      events.emit('counter', `user.element_check_failed.${title}`, 1);
    }

    await page.reload();
  }
}

async function multistepWithCustomMetrics(page, _userContext, _events, test) {
  //1. we get the convenience step() helper from the test object.
  //More information: https://www.artillery.io/docs/reference/engines/playwright#teststep-argument
  const { step } = test;

  //2. We can now wrap parts of our Playwright script in step() calls
  await step('go_to_artillery_io', async () => {
    await page.goto('https://www.artillery.io');
  });

  await step('go_to_cloud_page', async () => {
    await page.goto('https://www.artillery.io/cloud');
  });

  await step('go_to_docs', async () => {
    await page.goto('https://www.artillery.io/docs');
  });

  // 3. latency metrics will be emitted automatically throughout the test for each step.
  // For more information on custom metrics, please see: https://www.artillery.io/docs/guides/guides/extension-apis#tracking-custom-metrics
}

module.exports = {
  checkOutArtilleryCoreConceptsFlow,
  checkPage,
  multistepWithCustomMetrics
};


================================================
FILE: examples/browser-load-testing-playwright/pages.csv
================================================
https://www.artillery.io/,trademark of Artillery Software Inc
https://www.artillery.io/docs,Get started
https://www.artillery.io/changelog,Feature updates and improvements to Artillery

================================================
FILE: examples/browser-playwright-reuse-authentication/README.md
================================================
# Reuse Authentication in Playwright tests

Playwright allows you to use `sessionStorage` to reuse authentication in your tests. This can be especially useful in Load Testing, where you might be interested in testing other parts of the application at scale, without having to exercise the login backend (which is sometimes third-party) with every VU.

This example shows you how to do that.

## Pre-requisites

Before running the example, install Artillery:

```sh
npm install artillery
```

## Example

The example leverages [`storageState`] similarly to [Playwright documentation](https://playwright.dev/docs/auth#basic-shared-account-in-all-tests). It's simple to set this up with Artillery, but there are some small differences:

* You set the `storageState` path in [`config.engines.playwright.contextOptions`](https://www.artillery.io/docs/reference/engines/playwright#configuration), instead of a Playwright config file. Note that the [`$dirname` utility](https://www.artillery.io/docs/reference/test-script#test-level-variables) is needed to resolve the full path for Playwright.
* A [before hook](https://www.artillery.io/docs/reference/test-script#before-and-after-sections) will run the setup function (`loginUserAndSaveStorage` in this example), rather than referencing it as a Playwright project.
* You will need to create the storageState JSON (`storage.json` in this example) file first as an empty object (`{}`), in the same directory where you run the test from. This is because the first time Artillery runs, it will run the `before` hook, and the file referenced in `config` won't be available.

That's it!

To run the fully configured example, run:

```sh 
npx artillery run scenario.yml
```

*Note: this example runs with headless disabled, so you can easily observe the login being reused.*

## Running the example in Fargate

Want to run 1,000 browsers at the same time? 10,000? more? Run your load tests on AWS Fargate with [built-in support in Artillery](https://www.artillery.io/docs/load-testing-at-scale/aws-fargate). Just make sure to tell Artillery to include the `storage.json` file. For example:

```yaml
  config:
    ...
    includeFiles:
        - ./storage.json
```

This ensures the file is bundled to Fargate workers correctly. You will also need to make sure the test is running using headless mode. Then, run the test:

```sh 
npx artillery run:fargate scenario.yml --count 2
```

*Note: `before` hooks run once per Fargate worker, so the authentication step will run as many times as the `--count` you set.*

## Playwright Version Compatibility

It's important to note that Artillery uses specific versions of Playwright, which are listed in our [documentation](https://www.artillery.io/docs/reference/engines/playwright#playwright-compatibility).

The `@playwright/test` version installed in your package.json should ideally match the version Artillery is currently using.

================================================
FILE: examples/browser-playwright-reuse-authentication/flow.js
================================================
const { expect } = require('@playwright/test');
const fs = require('node:fs');

async function loginUserAndSaveStorage(page, context) {
  // NOTE: we use the $dirname utility so Playwright can resolve the full path
  const storageState = JSON.parse(
    fs.readFileSync(`${context.vars.$dirname}/storage.json`, 'utf8')
  );
  if (Object.keys(storageState).length > 0) {
    console.log('Already logged in. Skipping login.');
    return;
  }

  //1. navigate to page and assert that we are not logged in
  await page.goto(context.vars.target);
  await expect(page.getByText('Authentication example')).toBeVisible();

  //2. click login button and make sure we are redirected to `/login`
  await page.getByRole('link', { name: 'Login' }).click();
  await page.waitForURL('**/login');

  //3. fill in your github username and click login button
  await page.getByLabel('username').fill(context.vars.githubUsername);
  await page.getByRole('button', { name: 'Login' }).click();

  //4. ensure we are redirected to profile page and logged in
  await page.waitForURL('**/profile-sg');
  await expect(page.getByText('Your GitHub profile')).toBeVisible();

  //5. save iron session cookie to storage.json
  // NOTE: we use the $dirname utility so Playwright can resolve the full path
  await page
    .context()
    .storageState({ path: `${context.vars.$dirname}/storage.json` });
}

async function goToProfilePageAndLogout(page, context, _events, test) {
  const { step } = test;
  const profileHeaderText = 'Profile (Static Generation, recommended)';

  await step('go_to_page', async () => {
    await page.goto(context.vars.target);
    await expect(page.getByText(profileHeaderText)).toBeVisible();
  });

  await step('go_to_profile_page', async () => {
    await page.getByRole('link', { name: profileHeaderText }).click();
    await page.waitForURL('**/profile-sg');
    await expect(page.getByText('Your Github Profile')).toBeVisible();
  });

  await step('logout', async () => {
    await page.getByRole('link', { name: 'Logout' }).click();
    await page.waitForURL('**/login');
  });
}

module.exports = {
  loginUserAndSaveStorage,
  goToProfilePageAndLogout
};


================================================
FILE: examples/browser-playwright-reuse-authentication/package.json
================================================
{
  "name": "browser-playwright-reuse-authentication",
  "version": "1.0.0",
  "description": "Playwright allows you to use `sessionStorage` to reuse authentication in your tests. This can be especially useful in Load Testing, where you might be interested in testing other parts of the application at scale, without having to exercise the login backend (which is sometimes third-party) with every VU.",
  "main": "flow.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@playwright/test": "1.45.3"
  }
}


================================================
FILE: examples/browser-playwright-reuse-authentication/scenario.yml
================================================
config:
  target: https://iron-session-example.vercel.app/
  phases:
    - arrivalRate: 1
      duration: 10
  engines:
    playwright:
      launchOptions:
        headless: false
      contextOptions:
        # NOTE: we use the $dirname utility so Playwright can resolve the full path
        storageState: "{{ $dirname }}/storage.json"
  processor: ./flow.js
  variables:
    githubUsername: "bernardobridge"
  # NOTE: add this if you want to run the test in fargate. make sure to remove headless:false too
  # includeFiles:
  #   - ./storage.json

before:
  engine: playwright
  flowFunction: loginUserAndSaveStorage

scenarios:
  - name: go_to_profile_page_and_logout
    engine: playwright
    flowFunction: goToProfilePageAndLogout


================================================
FILE: examples/browser-playwright-reuse-authentication/storage.json
================================================
{}


================================================
FILE: examples/browser-playwright-reuse-typescript/README.md
================================================
# Reusing Typescript Playwright code as Artillery code

This example shows you how you can reuse a pure Playwright codebase written in Typescript as Artillery tests.

The `e2e/` folder contains the Playwright test (`e2e/tests/get-issues.spec.ts`). The logic in that test has been abstracted to a helper in `e2e/helpers/index.ts`.

The `performance` folder contains the Artillery/Playwright test. Using the same helper, we can construct an Artillery test by importing it in our processor file (`./performance/processor.ts`) and calling it as the `testFunction` in our test (`./performance/search-for-ts-doc.yml`). The `target` used matches the `baseURL` from the playwright config in `e2e/playwright.config.ts`.

## Running the tests

First, run `npm install`.

To run the pure Playwright example:
`cd e2e && npx playwright run`

To run the same test as an Artillery test:
`cd performance && npx artillery run search-for-ts-doc.yml`

## Using a Page Object Model

In this example we didn't use a [Page Object Model](https://playwright.dev/docs/pom). However, similar concepts can be applied. You can have a centralised Page Object Model with methods for most UI actions, or even specific user flows, and then just call those as appropriate in both Playwright and Artillery tests.

## Playwright Version Compatibility

It's important to note that Artillery uses specific versions of Playwright, which are listed in our [documentation](https://www.artillery.io/docs/reference/engines/playwright#playwright-compatibility).

Your regular Playwright tests must use features that are compatible with the versions used by Artillery.

The `@playwright/test` version installed in your package.json should ideally match the version Artillery is currently using.

================================================
FILE: examples/browser-playwright-reuse-typescript/e2e/.gitignore
================================================
playwright-report/
test-results/

================================================
FILE: examples/browser-playwright-reuse-typescript/e2e/helpers/index.ts
================================================
import { type Page, expect } from '@playwright/test';

export const goToDocsAndSearch = async (page: Page, step) => {
  await step('go_to_artillery_io', async () => {
    await page.goto('/');
  });

  await step('go_to_docs', async () => {
    await page.getByRole('link', { name: 'Docs' }).first().click();
    await expect(page).toHaveURL('/docs');
    await expect(page.getByText('Get started')).toBeVisible();
  });

  await step('search_for_ts_doc_and_goto', async () => {
    await page
      .getByRole('searchbox', { name: 'Search documentation…' })
      .click();
    await page.keyboard.type('typescript', { delay: 100 });
    await page
      .getByRole('link', { name: 'processor - load custom code' })
      .click();
    await expect(page.getByText('processor - load custom code')).toBeVisible();
  });
};


================================================
FILE: examples/browser-playwright-reuse-typescript/e2e/playwright.config.ts
================================================
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: 'tests',
  reporter: 'html',
  use: {
    baseURL: 'https://www.artillery.io/'
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] }
    }
  ]
});


================================================
FILE: examples/browser-playwright-reuse-typescript/e2e/tests/get-issues.spec.ts
================================================
import { goToDocsAndSearch } from '../helpers';
import { test } from '@playwright/test';

test('search and go to doc page', async ({ page }) => {
  await goToDocsAndSearch(page, test.step);
});


================================================
FILE: examples/browser-playwright-reuse-typescript/package.json
================================================
{
  "name": "browser-playwright-reuse-typescript",
  "version": "1.0.0",
  "description": "This example shows you how you can reuse a pure Playwright codebase written in Typescript as Artillery tests.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@playwright/test": "1.45.3"
  }
}


================================================
FILE: examples/browser-playwright-reuse-typescript/performance/processor.ts
================================================
import { goToDocsAndSearch } from '../e2e/helpers';

export async function playwrightTest(page, vuContext, events, test) {
  const { step } = test;

  await goToDocsAndSearch(page, step);
}


================================================
FILE: examples/browser-playwright-reuse-typescript/performance/search-for-ts-doc.yml
================================================
config:
  target: "https://www.artillery.io/"
  phases:
    - duration: 1
      arrivalRate: 1
      name: "Phase 1"
  processor: "./processor.ts"
  engines:
    playwright: {}

scenarios:
  - engine: playwright
    testFunction: "playwrightTest"

================================================
FILE: examples/cicd/README.md
================================================
# Artillery CI/CD Examples

This repo contains examples of how to integrate [Artillery](https://artillery.io/) with different continuous integration and continuous delivery services.

## CI/CD examples

- [github-actions](./github-actions) - a GitHub Actions workflow for running Artillery load tests
- [azure-devops](./azure-devops) - an Azure Pipelines setup for running Artillery load tests
- [circleci](./circleci) - a CircleCI workflow for running Artillery load tests
- [gitlab-ci-cd](./gitlab-ci-cd) - a GitLab CI/CD setup for running Artillery load tests
- [jenkins](./jenkins) - a Jenkins Pipeline for running Artillery load tests
- [aws-codebuild](./aws-codebuild) - an AWS CodeBuild buildspec for running Artillery load tests

# Contributing

Would you like to share an example showing how to integrate Artillery with a CI/CD service not covered here? Send us a PR 💜


================================================
FILE: examples/cicd/aws-codebuild/README.md
================================================
# Load Testing With Artillery and AWS CodeBuild

This repo contains an example for running [Artillery](https://artillery.io/) load tests on AWS CodeBuild.

For more details, read the ["Integrating Artillery with AWS CodeBuild"](https://artillery.io/docs/guides/integration-guides/aws-codebuild.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## AWS CodeBuild buildspec

The [included AWS CodeBuild buildspec configuration file](buildspec.yml) is set up to run the load test, generate an HTML report, and store the artifact in an S3 bucket for later retrieval. You can also schedule the load test to run on a recurring schedule using Amazon EventBridge, as explained in the Artillery documentation.


================================================
FILE: examples/cicd/aws-codebuild/buildspec.yml
================================================
version: 0.2

phases:
  install:
    commands:
      - npm install -g artillery@latest
  pre_build:
    commands:
      - mkdir reports
  build:
    commands:
      - artillery run --output reports/report.json tests/performance/socket-io.yml

artifacts:
  files:
    - 'reports/*'
  name: artifacts/$CODEBUILD_BUILD_NUMBER


================================================
FILE: examples/cicd/aws-codebuild/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/cicd/azure-devops/README.md
================================================
# Load Testing With Artillery and Azure DevOps

This repo contains an example for running [Artillery](https://artillery.io/) load tests on [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) using [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/).

For more details, read the ["Integrating Artillery with Azure DevOps"](https://artillery.io/docs/guides/integration-guides/azure-devops.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## Azure Pipelines setup

The [included Azure Pipelines YAML file](azure-pipelines.yml) will trigger the load test after any code push to the `main` branch of the repository, and is set up to run on a schedule every day at 12:00 AM (UTC). The setup will also generate an HTML report and store the artifact for later retrieval.


================================================
FILE: examples/cicd/azure-devops/azure-pipelines.yml
================================================
trigger:
- main

schedules:
- cron: "0 0 * * *"
  displayName: 'Midnight (UTC) performance test'
  branches:
    include:
    - main

pool:
  vmImage: ubuntu-latest

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '12.x'
  displayName: 'Install Node.js v12.x'

- script: npm install -g artillery@latest
  displayName: 'Install Artillery'

- script: mkdir $(System.DefaultWorkingDirectory)/reports
  displayName: 'Make reports directory'

- script: artillery run --output reports/report.json tests/performance/socket-io.yml
  displayName: 'Execute load tests'

- publish: $(System.DefaultWorkingDirectory)/reports
  artifact: artillery-test-report


================================================
FILE: examples/cicd/azure-devops/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/cicd/circleci/.circleci/config.yml
================================================
version: 2.1

jobs:
  artillery:
    docker:
      - image: artilleryio/artillery:latest
    steps:
      - checkout

      - run:
          name: Make reports directory
          command: mkdir reports

      - run:
          name: Execute load tests
          command: /home/node/artillery/bin/artillery run --output reports/report.json tests/performance/socket-io.yml

      - store_artifacts:
          path: reports

workflows:
  load-tests:
    jobs:
      - artillery:
          filters:
            branches:
              only: main
  nightly:
    jobs:
      - artillery
    triggers:
      - schedule:
          cron: "0 0 * * *"
          filters:
            branches:
              only:
                - main


================================================
FILE: examples/cicd/circleci/README.md
================================================
# Load Testing With Artillery and CircleCI

This repo contains an example for running [Artillery](https://artillery.io/) load tests on CircleCI.

For more details, read the ["Integrating Artillery with CircleCI"](https://artillery.io/docs/guides/integration-guides/circleci.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## CircleCI workflow

The [included CircleCI configuration file](.circleci/config.yml) will trigger the load test after any code push to the `main` branch of the repository, and is set up to run on a schedule every day at 12:00 AM (UTC) against the `main` branch. The workflow will also generate an HTML report and store the artifact for later retrieval.


================================================
FILE: examples/cicd/circleci/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/cicd/github-actions/.github/workflows/load-test.yml
================================================
name: Artillery Socket.IO Load Test

on:
  push:
    branches:
      - main
  schedule:
    - cron: '0 0 * * *'

jobs:
  artillery:
    runs-on: ubuntu-latest

    container: artilleryio/artillery:latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Make reports directory
        run: mkdir reports

      - name: Execute load tests
        run: /home/node/artillery/bin/run run --output reports/report.json tests/performance/socket-io.yml

      - name: Generate HTML report
        run: /home/node/artillery/bin/run report --output reports/report.html reports/report.json

      - name: Archive test report
        uses: actions/upload-artifact@v2
        with:
          name: artillery-test-report
          path: reports/*


================================================
FILE: examples/cicd/github-actions/README.md
================================================
# Load Testing With Artillery and GitHub Actions

This repo contains an example for running [Artillery](https://artillery.io/) load tests on GitHub Actions.

For more details, read the ["Integrating Artillery with GitHub Actions"](https://artillery.io/docs/guides/integration-guides/github-actions.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## GitHub Actions workflow

The [included GitHub Actions workflow](.github/workflows/load-test.yml) will trigger the load test after any code push to the `main` branch of the repository, and is set up to run on a schedule every day at 12:00 AM (UTC). The workflow will also generate an HTML report and store the artifact for later retrieval.


================================================
FILE: examples/cicd/github-actions/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/cicd/gitlab-ci-cd/.gitlab-ci.yml
================================================
artillery:
  image:
    name: artilleryio/artillery:latest
    entrypoint: [""]
  script: |
    mkdir reports
    /home/node/artillery/bin/artillery run --output reports/report.json tests/performance/socket-io.yml
  artifacts:
    paths:
      - reports


================================================
FILE: examples/cicd/gitlab-ci-cd/README.md
================================================
# Load Testing With Artillery and GitLab CI/CD

This repo contains an example for running [Artillery](https://artillery.io/) load tests on GitLab CI/CD.

For more details, read the ["Integrating Artillery with GitLab CI/CD"](https://artillery.io/docs/guides/integration-guides/gitlab-ci-cd.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## GitHub Actions workflow

The [included GitLab CI/CD configuration file](.gitlab-ci.yml) will trigger the load test after any code push to the repository, generate an HTML report and store the artifact for later retrieval.


================================================
FILE: examples/cicd/gitlab-ci-cd/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/cicd/jenkins/Jenkinsfile
================================================
pipeline {
    agent {
        docker {
            image 'artilleryio/artillery:latest'
            args '-u root:root -i --entrypoint='
        }
    }

    triggers {
        cron('0 0 * * *')
    }

    stages {
        stage('Load Test') {
            steps {
                sh 'mkdir reports'
                sh '/home/node/artillery/bin/artillery run --output reports/report.json tests/performance/socket-io.yml'
            }
        }
    }

    post {
        success {
            archiveArtifacts 'reports/*'
        }
    }
}


================================================
FILE: examples/cicd/jenkins/README.md
================================================
# Load Testing With Artillery and Jenkins

This repo contains an example for running [Artillery](https://artillery.io/) load tests on Jenkins.

For more details, read the ["Integrating Artillery with Jenkins"](https://artillery.io/docs/guides/integration-guides/jenkins.html) section in the Artillery documentation.

## Artillery test script

The [example Artillery script](tests/performance/socket-io.yml) will test a running Socket.IO server. You can run the test script and see it in action: https://repl.artillery.io/?s=4ae41a53-1fa7-4256-9d1c-2a80202c1ca2&hR=true

## Jenkins Pipline

The [included Jenkins Pipeline configuration](Jenkinsfile) is set up to run the load test on a schedule every day at 12:00 AM (based on the Jenkins server timezone). The Pipeline will also generate an HTML report and store the artifact for later retrieval.


================================================
FILE: examples/cicd/jenkins/tests/performance/socket-io.yml
================================================
config:
  target: "http://lab.artillery.io"
  # As an example, we'll only run a single virtual user in this
  # test script. For real-world load testing, you'll want to
  # adjust your load phases according to your needs.
  phases:
    - duration: 1
      arrivalRate: 1
  ensure:
    maxErrorRate: 1
    max: 500

scenarios:
  - name: "emit_an_event"
    engine: "socketio"
    flow:
      - emit:
          channel: "echo"
          data: "Hello from Artillery"
        response:
          channel: "echoResponse"
          data: "Hello from Artillery"


================================================
FILE: examples/functional-testing-with-expect-plugin/.gitignore
================================================
node_modules


================================================
FILE: examples/functional-testing-with-expect-plugin/README.md
================================================
# Functional testing on Artillery

This example shows you how to run both load and functional tests with a single Artillery test script using the `artillery-plugin-expect` plugin.

## Running the API server

This example includes an Express.js application running an HTTP API using an in-memory SQLite 3 database.

First, install the server dependencies:

```shell
npm install
```

After installing the dependencies, start the API server:

```shell
node app.js
```

This command will start a server listening at http://localhost:3000/.

## Running Artillery tests

This directory contains a test script (`functional-load-tests.yml`) which defines two environments:

- `load` - this defines a load phase that generates 25 virtual users per second for 10 minutes.
- `functional` - this enables the `artillery-plugin-expect` plugin. We don't want to enable it in the `load` phase as it would generate a lot of console output

Once the API server is up and running, you can run either load tests or functional tests using the same test script, using the `--environment` flag.

To run load tests:

```shell
npx artillery run --environment load functional-load-tests.yml
```

To run functional tests:

```shell
npx artillery run --environment functional functional-load-tests.yml
```


================================================
FILE: examples/functional-testing-with-expect-plugin/app.js
================================================
const express = require('express');
const app = express();
const port = 3000;

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');

app.use(express.json());

app.post('/users', (req, res) => {
  if (req.body.username === '') {
    res.status(422).send({ error: 'username is missing' });
    return;
  }

  db.run(
    'INSERT INTO users (username) VALUES (?)',
    [req.body.username],
    function (err) {
      if (err === null) {
        res.status(201).send({ id: this.lastID, username: req.body.username });
      } else {
        res.status(500).send(err);
      }
    }
  );
});

app.get('/users/:id', (req, res) => {
  db.get('SELECT * FROM users WHERE id = ?', [req.params.id], (err, row) => {
    if (err !== null) {
      res.status(500).send(err);
      return;
    }

    if (row === undefined) {
      res.status(404).send({ error: 'User not found' });
    } else {
      res.status(200).send(row);
    }
  });
});

app.delete('/users/:id', (req, res) => {
  db.run('DELETE FROM users WHERE id = ?', [req.params.id], function (err) {
    if (err !== null) {
      res.status(500).send(err);
      return;
    }

    if (this.changes === 0) {
      res.status(404).send({ error: 'User not found' });
    } else {
      res.sendStatus(204);
    }
  });
});

app.listen(port, () => {
  db.run(`CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username TEXT NOT NULL UNIQUE
  )`);
  console.log(`App listening at http://localhost:${port}`);
});


================================================
FILE: examples/functional-testing-with-expect-plugin/functional-load-tests.yml
================================================
config:
  target: "http://localhost:3000"
  environments:
    load:
      phases:
        - duration: 10min
          arrivalRate: 25
    functional:
      # We don't need to specify a phase here. Artillery will
      # launch a single VU when there is no phase definition.
      plugins:
        expect: {}

scenarios:
  - flow:
    - post:
        url: "/users"
        json:
          username: "new-user"
        capture:
          - json: "$.id"
            as: id
        expect:
          - statusCode: 201
          - contentType: json
          - hasProperty: username
          - equals:
            - "new-user"

    - get:
        url: "/users/{{ id }}"
        expect:
          - statusCode: 200
          - contentType: json
          - hasProperty: username
          - equals:
            - "new-user"

    - delete:
        url: "/users/{{ id }}"
        expect:
          - statusCode: 204


================================================
FILE: examples/functional-testing-with-expect-plugin/package.json
================================================
{
  "name": "load-and-functional-tests",
  "version": "1.0.0",
  "description": "Running load and functional tests from a single Artillery test script",
  "main": "app.js",
  "scripts": {
    "test:load": "artillery run --environment load functional-load-tests.yml",
    "test:functional": "artillery run --environment functional functional-load-tests.yml"
  },
  "author": "Dennis Martinez",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "sqlite3": "^5.0.2"
  }
}


================================================
FILE: examples/generating-vu-tokens/README.md
================================================
# generating-vu-tokens

A common use-case when testing stateful APIs with Artillery is to generate a token that VUs can use for authentication (e.g. to use with an [OAuth2 Credentials Flow](https://auth0.com/docs/get-started/authentication-and-authorization-flow/client-credentials-flow)). This example shows the basic structure of how that can be done with Artillery:

- We can use a `before` block and a custom JS function to generate a token that will be shared by all VUs in the test (`sharedToken`)
- We can use a `function` step with a custom JS function to generate a token unique to each VU (`vuToken`)
- We can use a value stored in a variable (`sharedToken` or `vuToken`) in a request header for authentication (e.g. as a [Bearer token](https://oauth.net/2/bearer-tokens/#:~:text=Bearer%20Tokens%20are%20the%20predominant,such%20as%20JSON%20Web%20Tokens.))

Run the script with:

```
artillery run auth-with-token.yml
```

The output will look similar to the screenshot below. The value of `sharedToken` generated in the `before` block will be the same for every VU, whereas the value of VU-specific token in `vuToken` will differ between VUs.

![auth tokens artillery](./screenshot.png)

To turn this into a working test-case for your API, replace the example implementation of one (or both) of the custom JS functions to implement the token generation logic you need, and tweak the way in which those tokens are sent as appropriate for your API.


================================================
FILE: examples/generating-vu-tokens/auth-with-token.yml
================================================
config:
  target: http://asciiart.artillery.io:8080
  processor: "./helpers.js"
  phases:
    - arrivalCount: 10
      duration: 1
      
before:
  flow:
    - function: "generateSharedToken"

scenarios:
  - flow:
      - function: "generateVUToken"
      - log: "VU id: {{ $uuid }}"
      - log: "    shared token is: {{ sharedToken }}"
      - log: "    VU-specific token is: {{ vuToken }}"
      - get:
          headers:
            x-auth-one: "{{ sharedToken }}"
            x-auth-two: "{{ vuToken }}"
          url: "/"


================================================
FILE: examples/generating-vu-tokens/helpers.js
================================================
module.exports = {
  generateSharedToken,
  generateVUToken
};

function generateSharedToken(context, _events, done) {
  context.vars.sharedToken = `shared-token-${Date.now()}`;
  return done();
}

function generateVUToken(context, _events, done) {
  context.vars.vuToken = `vu-token-${Date.now()}`;
  return done();
}


================================================
FILE: examples/graphql-api-server/.gitignore
================================================
node_modules/
prisma/dev.db
prisma/dev.db-journal


================================================
FILE: examples/graphql-api-server/README.md
================================================
# Load testing an GraphQL service with Artillery

<img width="1012" alt="graphql-load-testing-gh" src="https://user-images.githubusercontent.com/1490/139409040-40f77144-24d0-4fba-b7f3-1a441148f69a.png">

This example shows you how to run load tests on a GraphQL API using Artillery.

📖 See the companion blog post: [Using Artillery to load test GraphQL APIs](https://artillery.io/blog/using-artillery-to-load-test-graphql-apis/).

## Running the GraphQL server

This example runs a GraphQL server using [Apollo Server](https://www.apollographql.com/docs/apollo-server/) and [Prisma](https://www.prisma.io/) with a SQLite 3 database for data persistence.

First, install the server dependencies:

```shell
npm install
```

Next, create the SQLite database and set up the required database tables by running the initial Prisma database migration:

```shell
npx prisma migrate dev
```

After installing the dependencies and setting up the database, start the GraphQL server:

```shell
node app.js
```

This command will start the GraphQL API server listening at http://localhost:4000/. Once the server is up and running, you can explore the server using the [Apollo Sandbox](https://studio.apollographql.com/sandbox/).

## Running Artillery test

This directory contains a test script (`graphql.yml`) which demonstrates how to use Artillery scenarios against a GraphQL server. The test script contains a scenario executing various queries and mutations on the GraphQL server.

Once the GraphQL server is up and running, execute the test script:

```
npx artillery run graphql.yml
```


================================================
FILE: examples/graphql-api-server/app.js
================================================
const { ApolloServer, gql } = require('apollo-server');
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

const typeDefs = gql`
  input UserInput {
    username: String
    email: String
  }

  type User {
    id: ID!
    username: String
    email: String
  }

  type Query {
    users: [User]
    user(id: ID!): User
    userByUsername(username: String!): User
    userByEmail(username: String!): User
  }

  type Mutation {
    createUser(input: UserInput): User
    updateUser(id: ID!, input: UserInput): User
    deleteUser(id: ID!): User
  }
`;

const resolvers = {
  Query: {
    users: async () => {
      return await prisma.user.findMany();
    },

    user: async (_, { id }) => {
      return await prisma.user.findUnique({
        where: { id: parseInt(id, 10) }
      });
    },

    userByEmail: async (_, { email }) => {
      return await prisma.user.findUnique({
        where: { email }
      });
    },

    userByUsername: async (_, { username }) => {
      return await prisma.user.findUnique({
        where: { username }
      });
    }
  },

  Mutation: {
    createUser: async (_, { input }) => {
      return await prisma.user.create({
        data: input
      });
    },

    updateUser: async (_, { id, input }) => {
      return await prisma.user.update({
        where: { id: parseInt(id, 10) },
        data: input
      });
    },

    deleteUser: async (_, { id }) => {
      return await prisma.user.delete({
        where: { id: parseInt(id, 10) }
      });
    }
  }
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});


================================================
FILE: examples/graphql-api-server/graphql.yaml
================================================
config:
  target: "http://localhost:4000/"
  phases:
    - duration: 60
      arrivalRate: 25

scenarios:
  - name: "crud_from_db_scenario"
    flow:
      - post:
          url: "/"
          json:
            query: |
              mutation CreateUserMutation($createUserInput: UserInput) {
                createUser(input: $createUserInput) {
                  id
                }
              }
            variables:
              createUserInput:
                username: "{{ $randomString() }}"
                email: "user-{{ $randomString() }}@artillery.io"
          capture:
            json: "$.data.createUser.id"
            as: "userId"

      - post:
          url: "/"
          json:
            query: |
              query UserQuery($userId: ID!) {
                user(id: $userId) {
                  username
                  email
                }
              }
            variables:
              userId: "{{ userId }}"

      - post:
          url: "/"
          json:
            query: |
              mutation UpdateUserMutation($userId: ID!, $updateUserInput: UserInput) {
                updateUser(id: $userId, input: $updateUserInput) {
                  username
                  email
                }
              }
            variables:
              userId: "{{ userId }}"
              updateUserInput:
                email: "user-{{ $randomString() }}@artillery.io"

      - post:
          url: "/"
          json:
            query: |
              mutation DeleteUserMutation($userId: ID!) {
                deleteUser(id: $userId) {
                  id
                }
              }
            variables:
              userId: "{{ userId }}"


================================================
FILE: examples/graphql-api-server/package.json
================================================
{
  "name": "graphql-api-server",
  "version": "1.0.0",
  "description": "Load testing a GraphQL API using Artillery",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Dennis Martinez",
  "license": "ISC",
  "dependencies": {
    "@prisma/client": "^3.1.1",
    "apollo-server": "^3.3.0",
    "graphql": "^15.6.0"
  },
  "devDependencies": {
    "prisma": "^3.1.1"
  }
}


================================================
FILE: examples/graphql-api-server/prisma/migrations/20211005051218_init/migration.sql
================================================
-- CreateTable
CREATE TABLE "User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "username" TEXT NOT NULL,
    "email" TEXT NOT NULL
);

-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");


================================================
FILE: examples/graphql-api-server/prisma/migrations/migration_lock.toml
================================================
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "sqlite"

================================================
FILE: examples/graphql-api-server/prisma/schema.prisma
================================================
datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id        Int     @id @default(autoincrement())
  username  String  @unique
  email     String  @unique
}


================================================
FILE: examples/http-file-uploads/.gitignore
================================================
node_modules
uploads/*
!uploads/.keep


================================================
FILE: examples/http-file-uploads/README.md
================================================
# HTTP file uploads

This example shows you how to perform HTTP file uploads from an Artillery test script.

## Running the HTTP server

This example includes an Express.js application running an HTTP server.

First, install the server dependencies:

```shell
npm install
```

After installing the dependencies, start the HTTP server:

```shell
npm run app:start
```

This command will start an HTTP server listening at http://localhost:3000/.

## Running Artillery tests

This directory contains a test script (`file-uploads.yml`) which demonstrates how you can upload files in your scenarios.

Once the HTTP server is up and running, execute the test script:

```
artillery run file-uploads.yml
```

## Cleaning up uploaded files

During the test run, Artillery will upload files to the HTTP server, which get stored in the `uploads` directory. For convenience, you can clean the directory by executing the following command:

```
npm run uploads:clean
```


================================================
FILE: examples/http-file-uploads/app.js
================================================
const express = require('express');
const app = express();
const upload = require('multer')({ dest: 'uploads/', preservePath: true });
const port = 3000;

app.post('/upload', upload.single('document'), (req, res) => {
  const { originalname, mimetype, size } = req.file;
  res.json({ originalname, mimetype, size });
});

app.listen(port, () => {
  console.log(`App listening at http://localhost:${port}`);
});


================================================
FILE: examples/http-file-uploads/file-uploads.yml
================================================
config:
  target: "http://localhost:3000"
  phases:
    - duration: 10min
      arrivalRate: 25

  # To randomize the files to upload during the test scenario,
  # set up variables with the names of the files to use. These
  # files are placed in the `/files` directory.
  variables:
    filename:
      - "artillery-logo.jpg"
      - "artillery-installation.pdf"
      - "sre-fundamental-rules.png"

scenarios:
  - flow:
    # The HTTP server has an endpoint (POST /upload) that accepts files
    # through the `document` field.
    - post:
        url: "/upload"
        formData:
          document:
            # The `fromFile` attribute tells Artillery to upload the
            # specified file. If the file cannot be read, this scenario
            # will report an ENOENT error.
            fromFile: "./files/{{ filename }}"


================================================
FILE: examples/http-file-uploads/package.json
================================================
{
  "name": "file-uploads",
  "version": "1.0.0",
  "description": "How to load-test HTTP file uploads with Artillery Pro",
  "main": "app.js",
  "scripts": {
    "test": "artillery run file-uploads.yml",
    "app:start": "node app.js",
    "uploads:clean": "del-cli 'uploads/*' '!uploads/.keep'"
  },
  "author": "Dennis Martinez",
  "license": "ISC",
  "dependencies": {
    "del-cli": "^4.0.1",
    "express": "^4.17.1",
    "multer": "^1.4.2"
  }
}


================================================
FILE: examples/http-file-uploads/uploads/.keep
================================================


================================================
FILE: examples/http-metrics-by-endpoint/endpoint-metrics.yml
================================================
config:
  target: http://asciiart.artillery.io:8080
  phases:
    - duration: 20
      arrivalRate: 1
  plugins:
    metrics-by-endpoint: {}
scenarios:
  - flow:
      - get:
          url: "/dino"
      - get:
          url: "/armadillo"
      - get:
          url: "/pony"


================================================
FILE: examples/http-set-custom-header/README.md
================================================
# Set custom HTTP header via custom JS function

This example shows how an HTTP header can be set via a hook function.

---

To test, run `nc` in server mode with:

```shell
nc -l 31337
```

and then run Artillery:

```shell
artillery run set-header.yml
```

You should see custom header `X-Dino` being set:

![Artillery custom HTTP header](./custom-header-artillery.png)

Tada! 🎉

================================================
FILE: examples/http-set-custom-header/helpers.js
================================================
const https = require('node:https');

// Set the value of a header to a custom value, which
// in this example comes from an HTTP call to another
// API
function setCustomHeader(req, _userContext, _ee, next) {
  let data = '';

  https
    .get('https://api.artillery.io/v1/dino', (res) => {
      res.on('data', (d) => {
        data += d;
      });

      res.on('end', () => {
        // Extract a string composed of letters + spaces + punctuation:
        const val = data.match(/^<([A-Za-z!\s]+)/m)[1].trim();
        // Use that as the value of our custom header:
        req.headers['x-dino'] = val;
        return next();
      });
    })
    .on('error', (e) => {
      return next(e);
    });
}

module.exports = {
  setCustomHeader
};


================================================
FILE: examples/http-set-custom-header/set-header.yml
================================================
config:
  target: "http://localhost:31337"
  processor: "./helpers.js"
  phases:
    - duration: 1
      arrivalCount: 1
scenarios:
  - name: set_custom_header
    flow:
      - get:
          url: "/"
          qs:
            foo: bar
          headers:
            content-type: application/json
            accept: application/json
          json: {}
          beforeRequest: setCustomHeader

================================================
FILE: examples/http-socketio-server/.gitignore
================================================
node_modules/


================================================
FILE: examples/http-socketio-server/README.md
================================================
# HTTP and Socket.IO server

## Running the server

First, install the server dependencies:

```shell
npm install
```

After installing the dependencies, start the server:

```shell
npm start
```

##### HTTP

`GET /movies`

returns a list of all the movies

```json
[
  {
    "id": 1,
    "releaseDate": "Dec 18 1985",
    "director": "Terry Gilliam",
    "title": "Brazil",
    "genre": "Black Comedy",
    "imdbRating": 8,
    "runningTimeMin": 136
  },
  {
    "id": 2,
    "releaseDate": "Feb 16 1996",
    "director": "Harold Becker",
    "title": "City Hall",
    "genre": "Drama",
    "imdbRating": 6.1,
    "runningTimeMin": 111
  }
  ...
]
```

`GET /movies/:id`

returns a single movie by its id

```json
{
  "id": 35,
  "releaseDate": "Oct 01 1999",
  "director": "David O. Russell",
  "title": "Three Kings",
  "genre": "Action",
  "imdbRating": 7.3,
  "runningTimeMin": 115
}
```

##### socket.io

The socket.io server listens to `echo` events and emits `echoResponse` events to the client, passing the received payload back


================================================
FILE: examples/http-socketio-server/app.js
================================================
const http = require('node:http');
const app = require('./http');
const socketio = require('./socketio');

const { log } = console;

const PORT = process.env.PORT || 3000;
const server = http.createServer(app);

socketio(server);

server.listen(PORT, () => {
  log(`Server listening on port ${PORT}`);
});


================================================
FILE: examples/http-socketio-server/data/movies.json
================================================
[
  {
    "id": 1,
    "releaseDate": "Dec 18 1985",
    "director": "Terry Gilliam",
    "title": "Brazil",
    "genre": "Black Comedy",
    "imdbRating": 8,
    "runningTimeMin": 136
  },
  {
    "id": 2,
    "releaseDate": "Feb 16 1996",
    "director": "Harold Becker",
    "title": "City Hall",
    "genre": "Drama",
    "imdbRating": 6.1,
    "runningTimeMin": 111
  },
  {
    "id": 3,
    "releaseDate": "Jul 12 1996",
    "director": "Edward Zwick",
    "title": "Courage Under Fire",
    "genre": "Drama",
    "imdbRating": 6.6,
    "runningTimeMin": 115
  },
  {
    "id": 4,
    "releaseDate": "May 31 1996",
    "director": "Rob Cohen",
    "title": "Dragonheart",
    "genre": "Adventure",
    "imdbRating": 6.2,
    "runningTimeMin": 108
  },
  {
    "id": 5,
    "releaseDate": "Jan 19 1996",
    "director": "Robert Rodriguez",
    "title": "From Dusk Till Dawn",
    "genre": "Horror",
    "imdbRating": 7.1,
    "runningTimeMin": 107
  },
  {
    "id": 6,
    "releaseDate": "Mar 08 1996",
    "director": "Joel Coen",
    "title": "Fargo",
    "genre": "Thriller/Suspense",
    "imdbRating": 8.3,
    "runningTimeMin": 87
  },
  {
    "id": 7,
    "releaseDate": "Oct 11 1996",
    "director": "Stephen Hopkins",
    "title": "The Ghost and the Darkness",
    "genre": "Action",
    "imdbRating": 6.6,
    "runningTimeMin": 109
  },
  {
    "id": 8,
    "releaseDate": "Feb 16 1996",
    "director": "Dennis Dugan",
    "title": "Happy Gilmore",
    "genre": "Comedy",
    "imdbRating": 6.9,
    "runningTimeMin": 92
  },
  {
    "id": 9,
    "releaseDate": "Jul 02 1996",
    "director": "Roland Emmerich",
    "title": "Independence Day",
    "genre": "Adventure",
    "imdbRating": 6.5,
    "runningTimeMin": 145
  },
  {
    "id": 10,
    "releaseDate": "Jun 13 1980",
    "director": "Michael Ritchie",
    "title": "The Island",
    "genre": "Adventure",
    "imdbRating": 6.9,
    "runningTimeMin": 138
  },
  {
    "id": 11,
    "releaseDate": "Jul 26 1996",
    "director": "Bobby Farrelly",
    "title": "Kingpin",
    "genre": "Comedy",
    "imdbRating": 6.7,
    "runningTimeMin": 113
  },
  {
    "id": 12,
    "releaseDate": "Oct 11 1996",
    "director": "Renny Harlin",
    "title": "The Long Kiss Goodnight",
    "genre": "Action",
    "imdbRating": 6.6,
    "runningTimeMin": 120
  },
  {
    "id": 13,
    "releaseDate": "Jul 18 1986",
    "director": "James Cameron",
    "title": "Aliens",
    "genre": "Action",
    "imdbRating": 7.5,
    "runningTimeMin": 137
  },
  {
    "id": 14,
    "releaseDate": "Dec 13 1996",
    "director": "Tim Burton",
    "title": "Mars Attacks!",
    "genre": "Comedy",
    "imdbRating": 6.3,
    "runningTimeMin": 110
  },
  {
    "id": 15,
    "releaseDate": "Nov 15 1996",
    "director": "Barbra Streisand",
    "title": "The Mirror Has Two Faces",
    "genre": "Romantic Comedy",
    "imdbRating": 6,
    "runningTimeMin": 127
  },
  {
    "id": 16,
    "releaseDate": "May 21 1996",
    "director": "Brian De Palma",
    "title": "Mission: Impossible",
    "genre": "Action",
    "imdbRating": 6.9,
    "runningTimeMin": 110
  },
  {
    "id": 17,
    "releaseDate": "Nov 15 1996",
    "director": "Anthony Minghella",
    "title": "The English Patient",
    "genre": "Drama",
    "imdbRating": 7.3,
    "runningTimeMin": 160
  },
  {
    "id": 18,
    "releaseDate": "Jul 05 1996",
    "director": "Jon Turteltaub",
    "title": "Phenomenon",
    "genre": "Drama",
    "imdbRating": 6.3,
    "runningTimeMin": 124
  },
  {
    "id": 19,
    "releaseDate": "Nov 08 1996",
    "director": "Ron Howard",
    "title": "Ransom",
    "genre": "Action",
    "imdbRating": 6.6,
    "runningTimeMin": 121
  },
  {
    "id": 20,
    "releaseDate": "Nov 01 1996",
    "director": "Baz Luhrmann",
    "title": "Romeo+Juliet",
    "genre": "Drama",
    "imdbRating": 6.5,
    "runningTimeMin": 120
  },
  {
    "id": 21,
    "releaseDate": "Jun 07 1996",
    "director": "Michael Bay",
    "title": "The Rock",
    "genre": "Action",
    "imdbRating": 7.2,
    "runningTimeMin": 136
  },
  {
    "id": 22,
    "releaseDate": "Nov 22 1996",
    "director": "Scott Hicks",
    "title": "Shine",
    "genre": "Drama",
    "imdbRating": 7.6,
    "runningTimeMin": 105
  },
  {
    "id": 23,
    "releaseDate": "Nov 06 1996",
    "director": "F. Gary Gray",
    "title": "Set It Off",
    "genre": "Drama",
    "imdbRating": 6.3,
    "runningTimeMin": 120
  },
  {
    "id": 24,
    "releaseDate": "Oct 18 1996",
    "director": "Barry Levinson",
    "title": "Sleepers",
    "genre": "Drama",
    "imdbRating": 7.3,
    "runningTimeMin": 105
  },
  {
    "id": 25,
    "releaseDate": "Aug 06 2004",
    "director": "Ryan Little",
    "title": "Saints and Soldiers",
    "genre": "Drama",
    "imdbRating": 7,
    "runningTimeMin": 90
  },
  {
    "id": 26,
    "releaseDate": "Aug 16 1996",
    "director": "Ron Shelton",
    "title": "Tin Cup",
    "genre": "Romantic Comedy",
    "imdbRating": 6.1,
    "runningTimeMin": 105
  },
  {
    "id": 27,
    "releaseDate": "Jul 19 1996",
    "director": "Danny Boyle",
    "title": "Trainspotting",
    "genre": "Drama",
    "imdbRating": 8.2,
    "runningTimeMin": 94
  },
  {
    "id": 28,
    "releaseDate": "Jul 24 1996",
    "director": "Joel Schumacher",
    "title": "A Time to Kill",
    "genre": "Drama",
    "imdbRating": 7.1,
    "runningTimeMin": 150
  },
  {
    "id": 29,
    "releaseDate": "Oct 04 1996",
    "director": "Tom Hanks",
    "title": "That Thing You Do!",
    "genre": "Drama",
    "imdbRating": 6.7,
    "runningTimeMin": 110
  },
  {
    "id": 30,
    "releaseDate": "May 10 1996",
    "director": "Jan De Bont",
    "title": "Twister",
    "genre": "Action",
    "imdbRating": 6,
    "runningTimeMin": 117
  },
  {
    "id": 31,
    "releaseDate": "Apr 23 2004",
    "director": "Gary Winick",
    "title": "13 Going On 30",
    "genre": "Comedy",
    "imdbRating": 6.1,
    "runningTimeMin": 98
  },
  {
    "id": 32,
    "releaseDate": "Nov 13 2009",
    "director": "Roland Emmerich",
    "title": 2012,
    "genre": "Action",
    "imdbRating": 6.2,
    "runningTimeMin": 158
  },
  {
    "id": 33,
    "releaseDate": "Jun 27 2003",
    "director": "Danny Boyle",
    "title": "28 Days Later...",
    "genre": "Horror",
    "imdbRating": 7.6,
    "runningTimeMin": 113
  },
  {
    "id": 34,
    "releaseDate": "Mar 09 2007",
    "director": "Zack Snyder",
    "title": 300,
    "genre": "Action",
    "imdbRating": 7.8,
    "runningTimeMin": 117
  },
  {
    "id": 35,
    "releaseDate": "Oct 01 1999",
    "director": "David O. Russell",
    "title": "Three Kings",
    "genre": "Action",
    "imdbRating": 7.3,
    "runningTimeMin": 115
  },
  {
    "id": 36,
    "releaseDate": "Sep 02 2007",
    "director": "James Mangold",
    "title": "3:10 to Yuma",
    "genre": "Western",
    "imdbRating": 7.9,
    "runningTimeMin": 117
  },
  {
    "id": 37,
    "releaseDate": "Aug 19 2005",
    "director": "Judd Apatow",
    "title": "The 40 Year-old Virgin",
    "genre": "Comedy",
    "imdbRating": 7.5,
    "runningTimeMin": 111
  },
  {
    "id": 38,
    "releaseDate": "Aug 12 2005",
    "director": "John Singleton",
    "title": "Four Brothers",
    "genre": "Drama",
    "imdbRating": 6.8,
    "runningTimeMin": 109
  },
  {
    "id": 39,
    "releaseDate": "Feb 13 2004",
    "director": "Peter Segal",
    "title": "50 First Dates",
    "genre": "Romantic Comedy",
    "imdbRating": 6.8,
    "runningTimeMin": 99
  },
  {
    "id": 40,
    "releaseDate": "Nov 08 2002",
    "director": "Curtis Hanson",
    "title": "8 Mile",
    "genre": "Drama",
    "imdbRating": 6.7,
    "runningTimeMin": 110
  },
  {
    "id": 41,
    "releaseDate": "May 17 2002",
    "director": "Paul Weitz",
    "title": "About a Boy",
    "genre": "Romantic Comedy",
    "imdbRating": 7.4,
    "runningTimeMin": 101
  },
  {
    "id": 42,
    "releaseDate": "Nov 20 1998",
    "director": "John Lasseter",
    "title": "A Bug's Life",
    "genre": "Adventure",
    "imdbRating": 7.3,
    "runningTimeMin": 96
  },
  {
    "id": 43,
    "releaseDate": "Feb 14 1997",
    "director": "Clint Eastwood",
    "title": "Absolute Power",
    "genre": "Thriller/Suspense",
    "imdbRating": 6.5,
    "runningTimeMin": 120
  },
  {
    "id": 44,
    "releaseDate": "Nov 12 2004",
    "director": "Brett Ratner",
    "title": "After the Sunset",
    "genre": "Action",
    "imdbRating": 6.2,
    "runningTimeMin": 97
  },
  {
    "id": 45,
    "releaseDate": "Nov 10 2006",
    "director": "Ridley Scott",
    "title": "A Good Year",
    "genre": "Drama",
    "imdbRating": 6.8,
    "runningTimeMin": 118
  },
  {
    "id": 46,
    "releaseDate": "Jul 25 1997",
    "director": "Wolfgang Peters
Download .txt
gitextract_y554pkx1/

├── .artilleryrc
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── bug_report.md
│   ├── dependabot.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── codeql-analysis.yml
│       ├── create-release-pr.yml
│       ├── docker-ecs-worker-image.yml
│       ├── docker-publish-artillery.yml
│       ├── examples.yml
│       ├── npm-publish-all-packages-canary.yml
│       ├── npm-publish-all-packages.yml
│       ├── npm-publish-artillery-engine-posthog.yml
│       ├── npm-publish-artillery-plugin-memory-inspector.yml
│       ├── npm-publish-artillery-types.yml
│       ├── npm-publish-specific-package.yml
│       ├── run-aws-tests-on-pr.yml
│       ├── run-distributed-tests.yml
│       ├── run-tests-windows.yml
│       ├── run-tests.yml
│       ├── s3-publish-cf-templates.yml
│       └── scripts/
│           ├── get-all-packages-by-name.js
│           ├── get-tests-in-package-location.js
│           ├── npm-command-retry.sh
│           └── replace-package-versions.js
├── .gitignore
├── .npmignore
├── .npmrc
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE-BSL.txt
├── LICENSE.txt
├── README.md
├── SECURITY.md
├── biome.json
├── commitlint.config.js
├── examples/
│   ├── README.md
│   ├── artillery-engine-example/
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── example.yaml
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── index.js
│   ├── artillery-plugin-hello-world/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test.yml
│   ├── automated-checks/
│   │   ├── README.md
│   │   └── load-test-with-automated-checks.yml
│   ├── browser-load-testing-playwright/
│   │   ├── README.md
│   │   ├── browser-load-test.ts
│   │   ├── browser-load-test.yml
│   │   ├── browser-smoke-test.ts
│   │   ├── browser-smoke-test.yml
│   │   ├── browser-test-with-steps.yml
│   │   ├── flows.js
│   │   └── pages.csv
│   ├── browser-playwright-reuse-authentication/
│   │   ├── README.md
│   │   ├── flow.js
│   │   ├── package.json
│   │   ├── scenario.yml
│   │   └── storage.json
│   ├── browser-playwright-reuse-typescript/
│   │   ├── README.md
│   │   ├── e2e/
│   │   │   ├── .gitignore
│   │   │   ├── helpers/
│   │   │   │   └── index.ts
│   │   │   ├── playwright.config.ts
│   │   │   └── tests/
│   │   │       └── get-issues.spec.ts
│   │   ├── package.json
│   │   └── performance/
│   │       ├── processor.ts
│   │       └── search-for-ts-doc.yml
│   ├── cicd/
│   │   ├── README.md
│   │   ├── aws-codebuild/
│   │   │   ├── README.md
│   │   │   ├── buildspec.yml
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── azure-devops/
│   │   │   ├── README.md
│   │   │   ├── azure-pipelines.yml
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── circleci/
│   │   │   ├── .circleci/
│   │   │   │   └── config.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── github-actions/
│   │   │   ├── .github/
│   │   │   │   └── workflows/
│   │   │   │       └── load-test.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   ├── gitlab-ci-cd/
│   │   │   ├── .gitlab-ci.yml
│   │   │   ├── README.md
│   │   │   └── tests/
│   │   │       └── performance/
│   │   │           └── socket-io.yml
│   │   └── jenkins/
│   │       ├── Jenkinsfile
│   │       ├── README.md
│   │       └── tests/
│   │           └── performance/
│   │               └── socket-io.yml
│   ├── functional-testing-with-expect-plugin/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── functional-load-tests.yml
│   │   └── package.json
│   ├── generating-vu-tokens/
│   │   ├── README.md
│   │   ├── auth-with-token.yml
│   │   └── helpers.js
│   ├── graphql-api-server/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── graphql.yaml
│   │   ├── package.json
│   │   └── prisma/
│   │       ├── migrations/
│   │       │   ├── 20211005051218_init/
│   │       │   │   └── migration.sql
│   │       │   └── migration_lock.toml
│   │       └── schema.prisma
│   ├── http-file-uploads/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── file-uploads.yml
│   │   ├── package.json
│   │   └── uploads/
│   │       └── .keep
│   ├── http-metrics-by-endpoint/
│   │   └── endpoint-metrics.yml
│   ├── http-set-custom-header/
│   │   ├── README.md
│   │   ├── helpers.js
│   │   └── set-header.yml
│   ├── http-socketio-server/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── data/
│   │   │   └── movies.json
│   │   ├── http-socket.yml
│   │   ├── http.js
│   │   ├── package.json
│   │   └── socketio.js
│   ├── k8s-testing-with-kubectl-artillery/
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── Dockerfile
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── data/
│   │   │   └── movies.json
│   │   ├── hack/
│   │   │   └── kind/
│   │   │       └── kind-with-registry.sh
│   │   ├── http.js
│   │   ├── k8s-deploy.yaml
│   │   └── package.json
│   ├── multiple-scenario-specs/
│   │   ├── README.md
│   │   ├── common-config.yml
│   │   └── scenarios/
│   │       ├── armadillo.yml
│   │       ├── dino.yml
│   │       └── pony.yml
│   ├── prometheus-grafana-dashboards/
│   │   ├── README.md
│   │   ├── dashboard-http-metrics-1652971310916.json
│   │   └── dashboard-vusers-metrics-1652971366368.json
│   ├── refresh-auth-token/
│   │   ├── README.md
│   │   ├── refresh.mjs
│   │   └── refresh.yml
│   ├── rpc-twirp-with-custom-function/
│   │   ├── README.md
│   │   ├── test/
│   │   │   ├── processor.mjs
│   │   │   └── scenario.yml
│   │   └── twirp/
│   │       ├── package.json
│   │       ├── protos/
│   │       │   ├── haberdasher.pb.js
│   │       │   └── haberdasher.proto
│   │       └── server/
│   │           ├── haberdasher/
│   │           │   └── index.js
│   │           └── index.js
│   ├── scenario-weights/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── package.json
│   │   └── scenario-weights.yml
│   ├── script-overrides/
│   │   ├── README.md
│   │   └── test.yaml
│   ├── soap-with-custom-function/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── processor.js
│   │   ├── server/
│   │   │   ├── MyService.wsdl
│   │   │   ├── app.js
│   │   │   └── package.json
│   │   └── soap.yml
│   ├── socket-io/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── package.json
│   │   ├── public/
│   │   │   └── index.html
│   │   └── socket-io.yml
│   ├── starter-kit/
│   │   ├── .gitignore
│   │   ├── package.json
│   │   ├── processors/
│   │   │   ├── _baseProcessor.js
│   │   │   ├── sample_task_01.js
│   │   │   └── sample_task_02.js
│   │   ├── reports/
│   │   │   └── .gitkeep
│   │   └── scenarios/
│   │       ├── sample_task_01.yaml
│   │       ├── sample_task_02.yaml
│   │       └── sample_task_03.yaml
│   ├── table-driven-functional-tests/
│   │   ├── README.md
│   │   ├── functional-test.yml
│   │   ├── package.json
│   │   └── request-response.csv
│   ├── tracetest/
│   │   └── README.md
│   ├── track-custom-metrics/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── custom-metrics.yml
│   │   ├── metrics.js
│   │   └── package.json
│   ├── using-cookies/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── app.js
│   │   ├── cookies.yml
│   │   └── package.json
│   ├── using-data-from-csv/
│   │   ├── csv/
│   │   │   └── urls.csv
│   │   └── website-test.yml
│   ├── using-data-from-redis/
│   │   ├── README.md
│   │   ├── package.json
│   │   ├── processor.js
│   │   ├── scenario.yml
│   │   └── scripts/
│   │       └── seed-redis-with-users.js
│   └── websockets/
│       ├── .gitignore
│       ├── README.md
│       ├── app.js
│       ├── my-functions.js
│       ├── package.json
│       └── test.yml
├── package.json
├── packages/
│   ├── artillery/
│   │   ├── Dockerfile
│   │   ├── Makefile
│   │   ├── README.md
│   │   ├── bin/
│   │   │   ├── run
│   │   │   └── run.cmd
│   │   ├── console-reporter.js
│   │   ├── doc/
│   │   │   └── CLA.md
│   │   ├── lib/
│   │   │   ├── artillery-global.js
│   │   │   ├── cli/
│   │   │   │   ├── banner.js
│   │   │   │   ├── common-flags.js
│   │   │   │   └── hooks/
│   │   │   │       └── version.js
│   │   │   ├── cmds/
│   │   │   │   ├── dino.js
│   │   │   │   ├── quick.js
│   │   │   │   ├── report.js
│   │   │   │   ├── run-aci.js
│   │   │   │   ├── run-fargate.js
│   │   │   │   ├── run-lambda.js
│   │   │   │   └── run.js
│   │   │   ├── console-capture.js
│   │   │   ├── console-reporter.js
│   │   │   ├── create-bom/
│   │   │   │   ├── built-in-plugins.js
│   │   │   │   └── create-bom.js
│   │   │   ├── dispatcher.js
│   │   │   ├── dist.js
│   │   │   ├── index.js
│   │   │   ├── launch-platform.js
│   │   │   ├── load-plugins.js
│   │   │   ├── platform/
│   │   │   │   ├── aws/
│   │   │   │   │   ├── aws-cloudwatch.js
│   │   │   │   │   ├── aws-create-sqs-queue.js
│   │   │   │   │   ├── aws-ensure-s3-bucket-exists.js
│   │   │   │   │   ├── aws-get-account-id.js
│   │   │   │   │   ├── aws-get-bucket-region.js
│   │   │   │   │   ├── aws-get-credentials.js
│   │   │   │   │   ├── aws-get-default-region.js
│   │   │   │   │   ├── aws-whoami.js
│   │   │   │   │   ├── constants.js
│   │   │   │   │   └── iam-cf-templates/
│   │   │   │   │       ├── aws-iam-fargate-cf-template.yml
│   │   │   │   │       ├── aws-iam-lambda-cf-template.yml
│   │   │   │   │       ├── gh-oidc-fargate.yml
│   │   │   │   │       └── gh-oidc-lambda.yml
│   │   │   │   ├── aws-ecs/
│   │   │   │   │   ├── ecs.js
│   │   │   │   │   ├── legacy/
│   │   │   │   │   │   ├── aws-util.js
│   │   │   │   │   │   ├── bom.js
│   │   │   │   │   │   ├── constants.js
│   │   │   │   │   │   ├── create-s3-client.js
│   │   │   │   │   │   ├── create-test.js
│   │   │   │   │   │   ├── errors.js
│   │   │   │   │   │   ├── find-public-subnets.js
│   │   │   │   │   │   ├── plugins/
│   │   │   │   │   │   │   ├── artillery-plugin-inspect-script/
│   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   └── artillery-plugin-sqs-reporter/
│   │   │   │   │   │   │       ├── azure-aqs.js
│   │   │   │   │   │   │       └── index.js
│   │   │   │   │   │   ├── plugins.js
│   │   │   │   │   │   ├── run-cluster.js
│   │   │   │   │   │   ├── sqs-reporter.js
│   │   │   │   │   │   ├── tags.js
│   │   │   │   │   │   ├── test-run-status.js
│   │   │   │   │   │   ├── time.js
│   │   │   │   │   │   └── util.js
│   │   │   │   │   └── worker/
│   │   │   │   │       ├── Dockerfile
│   │   │   │   │       ├── helpers.sh
│   │   │   │   │       └── loadgen-worker
│   │   │   │   ├── aws-lambda/
│   │   │   │   │   ├── dependencies.js
│   │   │   │   │   ├── index.js
│   │   │   │   │   ├── lambda-handler/
│   │   │   │   │   │   ├── a9-handler-dependencies.js
│   │   │   │   │   │   ├── a9-handler-helpers.js
│   │   │   │   │   │   ├── a9-handler-index.js
│   │   │   │   │   │   └── package.json
│   │   │   │   │   └── prices.js
│   │   │   │   ├── az/
│   │   │   │   │   ├── aci.js
│   │   │   │   │   ├── aqs-queue-consumer.js
│   │   │   │   │   └── regions.js
│   │   │   │   ├── cloud/
│   │   │   │   │   ├── api.js
│   │   │   │   │   ├── cloud.js
│   │   │   │   │   └── http-client.js
│   │   │   │   ├── local/
│   │   │   │   │   ├── artillery-worker-local.js
│   │   │   │   │   ├── index.js
│   │   │   │   │   └── worker.js
│   │   │   │   └── worker-states.js
│   │   │   ├── queue-consumer/
│   │   │   │   └── index.js
│   │   │   ├── stash.js
│   │   │   ├── telemetry.js
│   │   │   ├── util/
│   │   │   │   ├── await-on-ee.js
│   │   │   │   ├── generate-id.js
│   │   │   │   ├── parse-tag-string.js
│   │   │   │   ├── prepare-test-execution-plan.js
│   │   │   │   ├── sleep.js
│   │   │   │   └── validate-script.js
│   │   │   ├── util.js
│   │   │   └── utils-config.js
│   │   ├── man/
│   │   │   ├── artillery.1
│   │   │   └── artillery.1.md
│   │   ├── package.json
│   │   ├── test/
│   │   │   ├── cli/
│   │   │   │   ├── async-hooks-esm.test.js
│   │   │   │   ├── command-report.test.js
│   │   │   │   ├── command-run.test.js
│   │   │   │   ├── custom-plugin.test.js
│   │   │   │   ├── errors-and-warnings.test.js
│   │   │   │   ├── run-smoke.test.js
│   │   │   │   ├── run-typescript.test.js
│   │   │   │   ├── suggested-exit-codes.test.js
│   │   │   │   ├── unknown-engine.test.js
│   │   │   │   └── variables-from-external-files.test.js
│   │   │   ├── cloud-e2e/
│   │   │   │   ├── fargate/
│   │   │   │   │   ├── bom.test.js
│   │   │   │   │   ├── cloud-api-key.test.js
│   │   │   │   │   ├── cw-adot.test.js
│   │   │   │   │   ├── dd-adot.test.js
│   │   │   │   │   ├── ensure-plugin.test.js
│   │   │   │   │   ├── expect-plugin.test.js
│   │   │   │   │   ├── fixtures/
│   │   │   │   │   │   ├── adot/
│   │   │   │   │   │   │   ├── adot-cloudwatch.yml
│   │   │   │   │   │   │   ├── adot-dd-pass.yml
│   │   │   │   │   │   │   ├── flow.js
│   │   │   │   │   │   │   └── helpers.js
│   │   │   │   │   │   ├── cli-exit-conditions/
│   │   │   │   │   │   │   ├── with-expect-ensure.yml
│   │   │   │   │   │   │   └── with-expect.yml
│   │   │   │   │   │   ├── cli-kitchen-sink/
│   │   │   │   │   │   │   ├── kitchen-sink-env
│   │   │   │   │   │   │   └── kitchen-sink.yml
│   │   │   │   │   │   ├── cloud-api-key-load/
│   │   │   │   │   │   │   └── scenario.yml
│   │   │   │   │   │   ├── heartbeat/
│   │   │   │   │   │   │   └── heartbeat.yml
│   │   │   │   │   │   ├── large-output/
│   │   │   │   │   │   │   ├── lots-of-output.yml
│   │   │   │   │   │   │   └── processor.js
│   │   │   │   │   │   ├── memory-hog/
│   │   │   │   │   │   │   ├── memory-hog.yml
│   │   │   │   │   │   │   └── processor.js
│   │   │   │   │   │   ├── mixed-hierarchy/
│   │   │   │   │   │   │   ├── code/
│   │   │   │   │   │   │   │   ├── functions.js
│   │   │   │   │   │   │   │   ├── lib/
│   │   │   │   │   │   │   │   │   └── signer.js
│   │   │   │   │   │   │   │   ├── meow.js
│   │   │   │   │   │   │   │   └── set-url.js
│   │   │   │   │   │   │   ├── config/
│   │   │   │   │   │   │   │   ├── config-no-file-uploads.yml
│   │   │   │   │   │   │   │   └── config.yml
│   │   │   │   │   │   │   ├── data/
│   │   │   │   │   │   │   │   └── variables.csv
│   │   │   │   │   │   │   ├── package.json
│   │   │   │   │   │   │   └── scenarios/
│   │   │   │   │   │   │       ├── mixed-hierarchy-dino.yml
│   │   │   │   │   │   │       └── mixed-hierarchy-pony.yml
│   │   │   │   │   │   ├── simple-bom/
│   │   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   │   ├── deps/
│   │   │   │   │   │   │   │   ├── README.md
│   │   │   │   │   │   │   │   ├── data/
│   │   │   │   │   │   │   │   │   ├── lists.json
│   │   │   │   │   │   │   │   │   ├── names-local.csv
│   │   │   │   │   │   │   │   │   ├── names-prod.csv
│   │   │   │   │   │   │   │   │   ├── names-test.csv
│   │   │   │   │   │   │   │   │   └── user-data.csv
│   │   │   │   │   │   │   │   ├── dummy-util.js
│   │   │   │   │   │   │   │   ├── functions.js
│   │   │   │   │   │   │   │   ├── local-mod-dir/
│   │   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   │   └── not-included.json
│   │   │   │   │   │   │   └── simple-bom.yml
│   │   │   │   │   │   ├── ts-external-pkg/
│   │   │   │   │   │   │   ├── package.json
│   │   │   │   │   │   │   ├── processor.ts
│   │   │   │   │   │   │   └── with-external-foreign-pkg.yml
│   │   │   │   │   │   └── uses-ensure/
│   │   │   │   │   │       └── with-ensure.yaml
│   │   │   │   │   ├── heartbeat.test.js
│   │   │   │   │   ├── memory.test.js
│   │   │   │   │   ├── misc.test.js
│   │   │   │   │   └── processors.test.js
│   │   │   │   └── lambda/
│   │   │   │       ├── fixtures/
│   │   │   │       │   ├── dotenv/
│   │   │   │       │   │   ├── .env-test
│   │   │   │       │   │   ├── dotenv-test.yml
│   │   │   │       │   │   └── processor.js
│   │   │   │       │   ├── quick-loop-with-csv/
│   │   │   │       │   │   ├── blitz.yml
│   │   │   │       │   │   ├── config.yml
│   │   │   │       │   │   ├── helpers.js
│   │   │   │       │   │   └── test.csv
│   │   │   │       │   └── ts-external-pkg/
│   │   │   │       │       ├── package.json
│   │   │   │       │       ├── processor.ts
│   │   │   │       │       └── with-external-foreign-pkg.yml
│   │   │   │       ├── lambda-bom.test.js
│   │   │   │       ├── lambda-dotenv.test.js
│   │   │   │       ├── lambda-ensure.test.js
│   │   │   │       ├── lambda-expect.test.js
│   │   │   │       └── lambda-smoke.test.js
│   │   │   ├── data/
│   │   │   │   ├── calc-test-data-1.csv
│   │   │   │   ├── calc-test-data-2.csv
│   │   │   │   ├── geometric.json
│   │   │   │   ├── multi-period-local-report.json
│   │   │   │   ├── response-times-histograms.json
│   │   │   │   └── ssms-buckets.json
│   │   │   ├── helpers/
│   │   │   │   ├── expectations.js
│   │   │   │   ├── index.js
│   │   │   │   └── sleep.js
│   │   │   ├── index.js
│   │   │   ├── integration/
│   │   │   │   └── core/
│   │   │   │       ├── fixtures/
│   │   │   │       │   ├── http-file-upload-processor.js
│   │   │   │       │   └── http-file-upload.yml
│   │   │   │       └── http-file-upload.test.js
│   │   │   ├── lib/
│   │   │   │   ├── index.js
│   │   │   │   ├── run.sh
│   │   │   │   ├── test_util.js
│   │   │   │   └── validate-script.test.js
│   │   │   ├── plugins/
│   │   │   │   ├── artillery-plugin-dummy-csv-logger/
│   │   │   │   │   └── index.js
│   │   │   │   └── artillery-plugin-httphooks/
│   │   │   │       ├── index.js
│   │   │   │       └── package.json
│   │   │   ├── publish-metrics/
│   │   │   │   ├── fixtures/
│   │   │   │   │   ├── flow.js
│   │   │   │   │   ├── helpers.js
│   │   │   │   │   ├── http-trace.yml
│   │   │   │   │   └── playwright-trace.yml
│   │   │   │   └── tracing/
│   │   │   │       ├── http-trace-assertions.js
│   │   │   │       ├── http-trace.test.js
│   │   │   │       ├── playwright-trace-assertions.js
│   │   │   │       └── playwright-trace.test.js
│   │   │   ├── runner.sh
│   │   │   ├── scripts/
│   │   │   │   ├── environments.yaml
│   │   │   │   ├── environments2.json
│   │   │   │   ├── gh_215_add_token.json
│   │   │   │   ├── hello.json
│   │   │   │   ├── hello_config.json
│   │   │   │   ├── hello_plugin.json
│   │   │   │   ├── hello_with_xpath.json
│   │   │   │   ├── http/
│   │   │   │   │   ├── async_function.json
│   │   │   │   │   ├── error_code_function.json
│   │   │   │   │   ├── error_message_function.json
│   │   │   │   │   ├── processors.js
│   │   │   │   │   ├── simple_function.json
│   │   │   │   │   └── undefined_function.json
│   │   │   │   ├── local-urls.csv
│   │   │   │   ├── multiple_payloads.json
│   │   │   │   ├── pets.csv
│   │   │   │   ├── pets.txt
│   │   │   │   ├── processor.js
│   │   │   │   ├── ramp-regression-1682.json
│   │   │   │   ├── ramp.json
│   │   │   │   ├── report.json
│   │   │   │   ├── scenario-async-esm-hooks/
│   │   │   │   │   ├── helpers.mjs
│   │   │   │   │   └── test.yml
│   │   │   │   ├── scenario-cli-variables/
│   │   │   │   │   ├── processor.js
│   │   │   │   │   ├── scenario-with-other-nested-config.yml
│   │   │   │   │   └── scenario-with-variables.yml
│   │   │   │   ├── scenario-config-different-folder/
│   │   │   │   │   ├── __processor__/
│   │   │   │   │   │   └── index.js
│   │   │   │   │   ├── config/
│   │   │   │   │   │   ├── config-processor-backward-compatibility.yml
│   │   │   │   │   │   └── config.yml
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-named/
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-payload-with-envs/
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── artillery-config.yml
│   │   │   │   │   ├── data/
│   │   │   │   │   │   └── my-data.csv
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenario-with-custom-plugin/
│   │   │   │   │   ├── custom-plugin.yml
│   │   │   │   │   └── processor.js
│   │   │   │   ├── scenario-with-parallel/
│   │   │   │   │   ├── processor.js
│   │   │   │   │   └── scenario.yml
│   │   │   │   ├── scenarios-typescript/
│   │   │   │   │   ├── error.yml
│   │   │   │   │   ├── lodash.yml
│   │   │   │   │   └── processor.ts
│   │   │   │   ├── single_payload.json
│   │   │   │   ├── single_payload_object.json
│   │   │   │   ├── single_payload_options.json
│   │   │   │   ├── test-calc-server.yml
│   │   │   │   ├── test-suggest-exit-code.js
│   │   │   │   ├── test-suggest-exit-code.yml
│   │   │   │   ├── unknown_engine.json
│   │   │   │   ├── urls.csv
│   │   │   │   ├── wildcard_processor.js
│   │   │   │   ├── wildcard_socketio.json
│   │   │   │   ├── with-dotenv/
│   │   │   │   │   ├── my-vars
│   │   │   │   │   └── with-dotenv.yml
│   │   │   │   └── with-process-env/
│   │   │   │       ├── processor.js
│   │   │   │       ├── with-env.yml
│   │   │   │       └── with-processEnvironment.yml
│   │   │   ├── targets/
│   │   │   │   ├── calc-server.js
│   │   │   │   ├── gh_215_target.js
│   │   │   │   ├── http-file-upload-server.js
│   │   │   │   └── targetServer.js
│   │   │   ├── tinyproxy.conf
│   │   │   └── unit/
│   │   │       ├── before_after_hooks.test.js
│   │   │       ├── create-bom.test.js
│   │   │       ├── dist.test.js
│   │   │       ├── fargate-bom.test.js
│   │   │       ├── processor.js
│   │   │       ├── ssms-basic.test.js
│   │   │       ├── ssms-buckets.test.js
│   │   │       ├── ssms-multi-process.test.js
│   │   │       └── ssms-worker.js
│   │   ├── types.d.ts
│   │   └── util.js
│   ├── artillery-engine-playwright/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fargate.aws.js
│   │       ├── fixtures/
│   │       │   ├── processor.js
│   │       │   ├── processor.ts
│   │       │   ├── pw-acceptance-ts.yml
│   │       │   ├── pw-acceptance.yml
│   │       │   └── pw-url-normalization.yml
│   │       └── index.test.js
│   ├── artillery-engine-posthog/
│   │   ├── .gitignore
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── examples/
│   │   │   ├── example.yml
│   │   │   ├── example_js_logic.yml
│   │   │   └── logic.js
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       └── index.js
│   ├── artillery-plugin-apdex/
│   │   ├── LICENSE
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── processor.js
│   │       │   └── scenario.yml
│   │       └── index.spec.js
│   ├── artillery-plugin-ensure/
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── test/
│   │   │   ├── fixtures/
│   │   │   │   ├── processor.js
│   │   │   │   ├── scenario-custom-metrics.yml
│   │   │   │   └── scenario.yml
│   │   │   ├── index.spec.js
│   │   │   └── utils.unit.js
│   │   └── utils.js
│   ├── artillery-plugin-expect/
│   │   ├── .circleci/
│   │   │   └── config.yml
│   │   ├── .gitignore
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── expectations.js
│   │   │   └── formatters.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── cdn-test.yml
│   │       ├── index.js
│   │       ├── lib/
│   │       │   └── formatters.js
│   │       ├── mock-pets-server.yaml
│   │       ├── parallel.yml
│   │       ├── pets-fail-test.yaml
│   │       ├── pets-test.yaml
│   │       ├── run.sh
│   │       └── urls.csv
│   ├── artillery-plugin-fake-data/
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   └── package.json
│   ├── artillery-plugin-memory-inspector/
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── myProcessor.js
│   │       │   └── scenario.yml
│   │       ├── index.spec.js
│   │       ├── server/
│   │       │   └── server.js
│   │       └── util.js
│   ├── artillery-plugin-metrics-by-endpoint/
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── fixtures/
│   │       │   ├── scenario-parallel.yml
│   │       │   ├── scenario-templated-url.yml
│   │       │   └── scenario.yml
│   │       ├── index.spec.js
│   │       └── index.unit.js
│   ├── artillery-plugin-publish-metrics/
│   │   ├── .gitignore
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── cloudwatch.js
│   │   │   ├── datadog.js
│   │   │   ├── dynatrace/
│   │   │   │   └── index.js
│   │   │   ├── mixpanel.js
│   │   │   ├── newrelic/
│   │   │   │   ├── README.md
│   │   │   │   └── index.js
│   │   │   ├── open-telemetry/
│   │   │   │   ├── exporters.js
│   │   │   │   ├── file-span-exporter.js
│   │   │   │   ├── index.js
│   │   │   │   ├── metrics.js
│   │   │   │   ├── outlier-detection-processor.js
│   │   │   │   ├── tracing/
│   │   │   │   │   ├── base.js
│   │   │   │   │   ├── http.js
│   │   │   │   │   └── playwright.js
│   │   │   │   └── translators/
│   │   │   │       ├── vendor-adot.js
│   │   │   │       └── vendor-otel.js
│   │   │   ├── prometheus.js
│   │   │   ├── splunk/
│   │   │   │   ├── README.md
│   │   │   │   └── index.js
│   │   │   └── util.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── config-agent.yaml
│   │       ├── config-api.yaml
│   │       ├── config-dynatrace.yaml
│   │       ├── config-honeycomb.yaml
│   │       ├── config-influxdb-statsd.yaml
│   │       ├── config-mixpanel.yaml
│   │       ├── config-newrelic-api.yaml
│   │       ├── config-prometheus.yaml
│   │       ├── config-splunk.yaml
│   │       ├── config-statsd.yaml
│   │       ├── index.js
│   │       ├── scenario.yaml
│   │       └── unit/
│   │           ├── adot-translators.js
│   │           └── tracing.js
│   ├── artillery-plugin-slack/
│   │   ├── LICENSE.txt
│   │   ├── index.js
│   │   └── package.json
│   ├── commons/
│   │   ├── engine_util.js
│   │   ├── index.js
│   │   ├── jitter.js
│   │   └── package.json
│   ├── core/
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── LICENSE.txt
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── engine_http.js
│   │   │   ├── engine_socketio.js
│   │   │   ├── engine_ws.js
│   │   │   ├── is-idle-phase.js
│   │   │   ├── phases.js
│   │   │   ├── readers.js
│   │   │   ├── runner.js
│   │   │   ├── ssms.js
│   │   │   └── weighted-pick.js
│   │   ├── package.json
│   │   └── test/
│   │       ├── acceptance/
│   │       │   ├── arrivals.test.js
│   │       │   ├── basic-auth.test.js
│   │       │   ├── capture-ws.test.js
│   │       │   ├── capture.test.js
│   │       │   ├── conditional-requests.test.js
│   │       │   ├── config-variables.test.js
│   │       │   ├── cookies-http.test.js
│   │       │   ├── cookies-socketio.test.js
│   │       │   ├── headers.test.js
│   │       │   ├── loop.test.js
│   │       │   ├── misc/
│   │       │   │   ├── helper.js
│   │       │   │   ├── http.test.js
│   │       │   │   ├── large-payload.test.js
│   │       │   │   ├── multiple-phases.test.js
│   │       │   │   ├── socketio-with-args.test.js
│   │       │   │   ├── socketio-with-http.test.js
│   │       │   │   ├── socketio.test.js
│   │       │   │   ├── ws-proxy.test.js
│   │       │   │   └── ws.test.js
│   │       │   ├── multiple-payloads.test.js
│   │       │   ├── multiple-runners.test.js
│   │       │   ├── parallel.test.js
│   │       │   ├── probability.test.js
│   │       │   ├── think-time.test.js
│   │       │   ├── tls.test.js
│   │       │   ├── ws/
│   │       │   │   ├── scripts/
│   │       │   │   │   ├── subprotocols.json
│   │       │   │   │   └── ws-tls.json
│   │       │   │   ├── ws-subprotocols.test.js
│   │       │   │   └── ws-tls.test.js
│   │       │   └── ws-engine.test.js
│   │       ├── plugins/
│   │       │   ├── normal_plugin/
│   │       │   │   ├── index.js
│   │       │   │   └── package.json
│   │       │   └── packaged_plugin/
│   │       │       ├── index.js
│   │       │       └── package.json
│   │       ├── quarantine/
│   │       │   ├── concurrent-requests.test.js
│   │       │   ├── test_config_plugin_package.js
│   │       │   ├── test_engine_http.js
│   │       │   └── test_environments.js
│   │       ├── scripts/
│   │       │   ├── after_test.json
│   │       │   ├── all_features.json
│   │       │   ├── arrival_phases.json
│   │       │   ├── arrival_phases_time_format.json
│   │       │   ├── artillery_plugin.json
│   │       │   ├── before_test.json
│   │       │   ├── captures-regexp.json
│   │       │   ├── concurrent_requests_arrival_count.json
│   │       │   ├── concurrent_requests_arrival_rate.json
│   │       │   ├── concurrent_requests_multiple_phases.json
│   │       │   ├── concurrent_requests_ramp_to.json
│   │       │   ├── config_variables.json
│   │       │   ├── cookies.json
│   │       │   ├── cookies_malformed_response.json
│   │       │   ├── cookies_socketio.json
│   │       │   ├── data/
│   │       │   │   ├── pets.csv
│   │       │   │   └── urls.csv
│   │       │   ├── defaults_cookies.json
│   │       │   ├── express_socketio.json
│   │       │   ├── generators_http.json
│   │       │   ├── hello.json
│   │       │   ├── hello_basic_auth.json
│   │       │   ├── hello_environments.json
│   │       │   ├── hello_socketio.json
│   │       │   ├── hello_socketio_with_args.json
│   │       │   ├── hello_ws.json
│   │       │   ├── iftrue.json
│   │       │   ├── large_payload.json
│   │       │   ├── loop.json
│   │       │   ├── loop_infinite.json
│   │       │   ├── loop_nested_range.json
│   │       │   ├── loop_range.json
│   │       │   ├── multiple_payloads.json
│   │       │   ├── multiple_phases.json
│   │       │   ├── namespaces_socketio.json
│   │       │   ├── no_defaults_cookies.json
│   │       │   ├── parallel.json
│   │       │   ├── plugin_packaged_inner.json
│   │       │   ├── plugin_packaged_inner_override_outter.json
│   │       │   ├── plugin_packaged_outer.json
│   │       │   ├── plugin_statsd.json
│   │       │   ├── probability.json
│   │       │   ├── single_payload.json
│   │       │   ├── thinks_http.json
│   │       │   ├── tls-lax.json
│   │       │   ├── tls-strict.json
│   │       │   └── ws_proxy.json
│   │       ├── targets/
│   │       │   ├── certs/
│   │       │   │   ├── private-key.pem
│   │       │   │   └── public-cert.pem
│   │       │   ├── express_socketio.js
│   │       │   ├── simple.js
│   │       │   ├── simple_socketio.js
│   │       │   ├── simple_tls.js
│   │       │   ├── simple_ws.js
│   │       │   ├── socketio_args.js
│   │       │   ├── ws_proxy.js
│   │       │   └── ws_tls.js
│   │       └── unit/
│   │           ├── context_functions.test.js
│   │           ├── engine_http.test.js
│   │           ├── engine_socketio.test.js
│   │           ├── engine_ws.test.js
│   │           ├── interpolation.test.js
│   │           ├── large-json-payload-669kb.json
│   │           ├── large-json-payload-7.2mb.json
│   │           ├── phases.test.js
│   │           ├── readers.test.js
│   │           ├── templates.test.js
│   │           └── util.test.js
│   ├── skytrace/
│   │   ├── .editorconfig
│   │   ├── LICENSE
│   │   ├── README.md
│   │   ├── asciiart-flow.yml
│   │   ├── bin/
│   │   │   ├── dev
│   │   │   ├── dev.cmd
│   │   │   ├── run
│   │   │   └── run.cmd
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── commands/
│   │   │   │   ├── ping.ts
│   │   │   │   └── run.ts
│   │   │   ├── index.ts
│   │   │   └── telemetry.ts
│   │   └── tsconfig.json
│   └── types/
│       ├── .gitignore
│       ├── LICENSE
│       ├── definitions.ts
│       ├── generate-schema.js
│       ├── package.json
│       ├── plugins/
│       │   └── expect.ts
│       ├── schema/
│       │   ├── config/
│       │   │   └── phases.js
│       │   ├── config.js
│       │   ├── engines/
│       │   │   ├── common.js
│       │   │   ├── http.js
│       │   │   ├── playwright.js
│       │   │   ├── socketio.js
│       │   │   └── websocket.js
│       │   ├── index.js
│       │   ├── joi.helpers.js
│       │   ├── plugins/
│       │   │   ├── apdex.js
│       │   │   ├── ensure.js
│       │   │   ├── expect.js
│       │   │   ├── fake-data.js
│       │   │   ├── metrics-by-endpoint.js
│       │   │   ├── publish-metrics.js
│       │   │   └── slack.js
│       │   └── scenario.js
│       ├── test/
│       │   ├── config.phases.test.ts
│       │   ├── engine.arbitrary.test.ts
│       │   ├── engine.http.test.ts
│       │   ├── engine.socketio.test.ts
│       │   ├── engine.websocket.test.ts
│       │   ├── examples.test.ts
│       │   ├── helpers.ts
│       │   ├── plugin.expect.test.ts
│       │   ├── simple.test.ts
│       │   └── tsconfig.json
│       ├── tsconfig.json
│       └── tsconfig.schema.json
├── socket.yml
└── turbo.json
Download .txt
SYMBOL INDEX (849 symbols across 195 files)

FILE: .github/workflows/scripts/get-tests-in-package-location.js
  function scanDirectory (line 46) | function scanDirectory(location, baseLocation, packageName, suffix) {

FILE: examples/artillery-engine-example/index.js
  class ExampleEngine (line 11) | class ExampleEngine {
    method constructor (line 18) | constructor(script, ee, helpers) {
    method createScenario (line 36) | createScenario(scenarioSpec, ee) {
    method step (line 61) | step(rs, ee) {

FILE: examples/artillery-plugin-hello-world/index.js
  function ArtilleryHelloWorldPlugin (line 9) | function ArtilleryHelloWorldPlugin(script, events) {

FILE: examples/browser-load-testing-playwright/flows.js
  function checkOutArtilleryCoreConceptsFlow (line 6) | async function checkOutArtilleryCoreConceptsFlow(
  function checkPage (line 38) | async function checkPage(page, userContext, events) {
  function multistepWithCustomMetrics (line 59) | async function multistepWithCustomMetrics(page, _userContext, _events, t...

FILE: examples/browser-playwright-reuse-authentication/flow.js
  function loginUserAndSaveStorage (line 4) | async function loginUserAndSaveStorage(page, context) {
  function goToProfilePageAndLogout (line 37) | async function goToProfilePageAndLogout(page, context, _events, test) {

FILE: examples/browser-playwright-reuse-typescript/performance/processor.ts
  function playwrightTest (line 3) | async function playwrightTest(page, vuContext, events, test) {

FILE: examples/generating-vu-tokens/helpers.js
  function generateSharedToken (line 6) | function generateSharedToken(context, _events, done) {
  function generateVUToken (line 11) | function generateVUToken(context, _events, done) {

FILE: examples/graphql-api-server/prisma/migrations/20211005051218_init/migration.sql
  type "User" (line 2) | CREATE TABLE "User" (
  type "User" (line 9) | CREATE UNIQUE INDEX "User_username_key" ON "User"("username")
  type "User" (line 12) | CREATE UNIQUE INDEX "User_email_key" ON "User"("email")

FILE: examples/http-set-custom-header/helpers.js
  function setCustomHeader (line 6) | function setCustomHeader(req, _userContext, _ee, next) {

FILE: examples/http-socketio-server/app.js
  constant PORT (line 7) | const PORT = process.env.PORT || 3000;

FILE: examples/http-socketio-server/socketio.js
  function onEcho (line 9) | function onEcho(m) {
  function onDisconnect (line 15) | function onDisconnect() {

FILE: examples/k8s-testing-with-kubectl-artillery/app.js
  constant PORT (line 6) | const PORT = process.env.PORT || 3001;

FILE: examples/refresh-auth-token/refresh.mjs
  constant TOKEN_REFRESH_INTERVAL (line 1) | const TOKEN_REFRESH_INTERVAL = 1000 * 5;
  function refreshTokenIfNeeded (line 3) | async function refreshTokenIfNeeded(_requestParams, vuContext, _events) {
  function fetchToken (line 14) | async function fetchToken() {

FILE: examples/rpc-twirp-with-custom-function/test/processor.mjs
  function recordMetrics (line 6) | function recordMetrics(startedAt, ee, error) {
  function callRpcServer (line 21) | async function callRpcServer(_context, ee, _next) {

FILE: examples/rpc-twirp-with-custom-function/twirp/protos/haberdasher.pb.js
  function MakeHat (line 19) | async function MakeHat(size, config) {
  function MakeHatJSON (line 35) | async function MakeHatJSON(size, config) {
  function createHaberdasher (line 44) | function createHaberdasher(service) {

FILE: examples/rpc-twirp-with-custom-function/twirp/server/haberdasher/index.js
  function choose (line 3) | function choose(list) {

FILE: examples/rpc-twirp-with-custom-function/twirp/server/index.js
  constant PORT (line 5) | const PORT = 8080;

FILE: examples/track-custom-metrics/metrics.js
  function trackPets (line 3) | function trackPets(_req, res, _context, events, done) {
  function parseServerTimingLatency (line 18) | function parseServerTimingLatency(header, timingMetricName) {

FILE: examples/using-data-from-redis/processor.js
  function getUser (line 8) | async function getUser(context, _events) {

FILE: examples/using-data-from-redis/scripts/seed-redis-with-users.js
  constant USERS_COUNT (line 7) | const USERS_COUNT = 100;
  constant BATCH_SIZE (line 8) | const BATCH_SIZE = 5;
  function generateUser (line 17) | function generateUser() {
  function storeUsersInRedis (line 24) | async function storeUsersInRedis(users) {
  function seedUsers (line 35) | async function seedUsers() {

FILE: examples/websockets/my-functions.js
  function createRandomScore (line 3) | function createRandomScore(userContext, _events, done) {

FILE: packages/artillery-engine-playwright/index.js
  class PlaywrightEngine (line 4) | class PlaywrightEngine {
    method constructor (line 5) | constructor(script) {
    method createScenario (line 98) | createScenario(spec, events) {

FILE: packages/artillery-engine-playwright/test/fargate.aws.js
  constant TEST_URL (line 6) | const TEST_URL = 'https://www.artillery.io/';
  constant A9_PATH (line 18) | const A9_PATH = process.env.A9_PATH || '../artillery/bin/run';

FILE: packages/artillery-engine-playwright/test/fixtures/processor.js
  function artilleryPlaywrightFunction (line 21) | async function artilleryPlaywrightFunction(page, _vuContext, events, tes...
  function playwrightFunctionWithFailure (line 39) | async function playwrightFunctionWithFailure(page, _vuContext, events, t...
  function urlNormalizationTest (line 47) | async function urlNormalizationTest(page, _vuContext, events, test) {

FILE: packages/artillery-engine-playwright/test/fixtures/processor.ts
  function artilleryPlaywrightFunction (line 21) | async function artilleryPlaywrightFunction(
  function playwrightFunctionWithFailure (line 43) | async function playwrightFunctionWithFailure(

FILE: packages/artillery-engine-playwright/test/index.test.js
  constant TEST_URL (line 5) | const TEST_URL = 'https://www.artillery.io/';

FILE: packages/artillery-engine-posthog/examples/logic.js
  function generateIds (line 1) | function generateIds(context, _events, done) {

FILE: packages/artillery-engine-posthog/index.js
  class PosthogEngine (line 9) | class PosthogEngine {
    method constructor (line 10) | constructor(script, ee, helpers) {
    method customHandler (line 23) | customHandler(rs, ee) {
    method createScenario (line 84) | createScenario(scenarioSpec, ee) {
    method step (line 89) | step(rs, ee) {
    method compile (line 135) | compile(tasks, _scenarioSpec, ee) {

FILE: packages/artillery-plugin-apdex/index.js
  constant METRICS (line 7) | const METRICS = {
  class ApdexPlugin (line 13) | class ApdexPlugin {
    method constructor (line 14) | constructor(script, _events) {

FILE: packages/artillery-plugin-apdex/test/fixtures/processor.js
  function myAfterResponseHandler (line 1) | function myAfterResponseHandler(_req, _res, _context, _ee, next) {

FILE: packages/artillery-plugin-ensure/index.js
  class EnsurePlugin (line 14) | class EnsurePlugin {
    method constructor (line 15) | constructor(script, events) {
    method statsToVars (line 91) | static statsToVars(data) {
    method runChecks (line 120) | static runChecks(checks, vars) {

FILE: packages/artillery-plugin-ensure/test/fixtures/processor.js
  function runFibonacci (line 1) | function runFibonacci(_req, _context, ee, next) {

FILE: packages/artillery-plugin-ensure/utils.js
  function replaceMetricsWithHashes (line 10) | function replaceMetricsWithHashes(replacementsArray, targetString) {
  function getHashedVarToValueMap (line 34) | function getHashedVarToValueMap(varsWithHashes) {

FILE: packages/artillery-plugin-expect/index.js
  constant EXPECTATIONS (line 10) | const EXPECTATIONS = require('./lib/expectations');
  constant FORMATTERS (line 11) | const FORMATTERS = require('./lib/formatters');
  function ExpectationsPlugin (line 17) | function ExpectationsPlugin(script, events) {
  function expectationsPluginOnError (line 77) | function expectationsPluginOnError(
  function expectationsPluginCheckExpectations (line 95) | function expectationsPluginCheckExpectations(
  function maybeParseBody (line 202) | function maybeParseBody(res) {
  class FailedExpectationError (line 223) | class FailedExpectationError extends Error {
    method constructor (line 224) | constructor(message) {

FILE: packages/artillery-plugin-expect/lib/expectations.js
  function expectJmesPath (line 27) | function expectJmesPath(expectation, body, _req, _res, _userContext) {
  function expectCdnHit (line 50) | function expectCdnHit(expectation, _body, _req, res, _userContext) {
  function expectEquals (line 88) | function expectEquals(expectation, body, _req, _res, userContext) {
  function expectHasHeader (line 110) | function expectHasHeader(expectation, _body, _req, res, userContext) {
  function expectHeaderEquals (line 133) | function expectHeaderEquals(expectation, _body, _req, res, userContext) {
  function expectContentType (line 162) | function expectContentType(expectation, body, _req, res, userContext) {
  function expectStatusCode (line 204) | function expectStatusCode(expectation, _body, _req, res, userContext) {
  function expectNotStatusCode (line 227) | function expectNotStatusCode(expectation, _body, _req, res, userContext) {
  function checkProperty (line 253) | function checkProperty(
  function expectHasProperty (line 277) | function expectHasProperty(expectation, body, _req, _res, userContext) {
  function expectNotHasProperty (line 293) | function expectNotHasProperty(expectation, body, _req, _res, userContext) {
  function expectMatchesRegexp (line 310) | function expectMatchesRegexp(expectation, body, _req, _res, userContext) {

FILE: packages/artillery-plugin-expect/lib/formatters.js
  function silent (line 16) | function silent(_requestExpectation, _req, _res, _userContext) {
  function prettyPrint (line 20) | function prettyPrint(requestExpectations, req, res, userContext) {
  function printExchangeContext (line 52) | function printExchangeContext(req, res, userContext) {
  function jsonPrint (line 73) | function jsonPrint(requestExpectations, _req, _res, _userContext) {
  function prettyError (line 77) | function prettyError(requestExpectations, req, res, userContext) {
  function prepend (line 84) | function prepend(text, str) {

FILE: packages/artillery-plugin-fake-data/index.js
  function ArtilleryPluginFakeData (line 21) | function ArtilleryPluginFakeData(script, events) {

FILE: packages/artillery-plugin-memory-inspector/index.js
  function ArtilleryPluginMemoryInspector (line 27) | function ArtilleryPluginMemoryInspector(script, events) {

FILE: packages/artillery-plugin-memory-inspector/test/fixtures/myProcessor.js
  function myBeforeScenarioHandler (line 1) | function myBeforeScenarioHandler(context, _ee, next) {

FILE: packages/artillery-plugin-metrics-by-endpoint/index.js
  function MetricsByEndpoint (line 17) | function MetricsByEndpoint(script, _events) {
  function calculateBaseUrl (line 65) | function calculateBaseUrl(target, originalRequestUrl) {
  function getReqName (line 85) | function getReqName(target, originalRequestUrl, requestName) {
  function metricsByEndpoint_beforeRequest (line 95) | function metricsByEndpoint_beforeRequest(req, userContext, _events, done) {
  function metricsByEndpoint_onError (line 103) | function metricsByEndpoint_onError(err, req, userContext, events, done) {
  function metricsByEndpoint_afterResponse (line 123) | function metricsByEndpoint_afterResponse(req, res, userContext, events, ...
  function getServerTimingTotal (line 154) | function getServerTimingTotal(s) {

FILE: packages/artillery-plugin-publish-metrics/index.js
  constant REPORTERS_USING_OTEL (line 15) | const REPORTERS_USING_OTEL = [
  function Plugin (line 30) | function Plugin(script, events) {

FILE: packages/artillery-plugin-publish-metrics/lib/cloudwatch.js
  constant COUNTERS_STATS (line 13) | const COUNTERS_STATS = 'counters';
  constant RATES_STATS (line 14) | const RATES_STATS = 'rates';
  constant SUMMARIES_STATS (line 15) | const SUMMARIES_STATS = 'summaries';
  constant DEFAULT_UNIT (line 17) | const DEFAULT_UNIT = 'Count';
  constant DEFAULT_STATS_ALLOWED (line 19) | const DEFAULT_STATS_ALLOWED = ['p99', 'max', 'min', 'median', 'count'];
  constant STATS_KEYS (line 21) | const STATS_KEYS = ['p50', 'p75', 'p95', 'p99', 'p999', 'max', 'min', 'm...
  constant KNOWN_METRICS (line 23) | const KNOWN_METRICS = [
  constant KNOWN_UNITS (line 32) | const KNOWN_UNITS = {
  class CloudWatchReporter (line 45) | class CloudWatchReporter {
    method constructor (line 46) | constructor(config, events) {
    method isMetricValid (line 105) | isMetricValid(value) {
    method addMetric (line 114) | addMetric(name, value, unit = DEFAULT_UNIT) {
    method putMetric (line 159) | async putMetric() {
    method waitingForRequest (line 179) | async waitingForRequest() {
    method cleanup (line 189) | cleanup(done) {
  function createCloudWatchReporter (line 195) | function createCloudWatchReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/datadog.js
  function DatadogReporter (line 10) | function DatadogReporter(config, events, script) {
  function createDatadogReporter (line 247) | function createDatadogReporter(config, events, script) {
  function sanitize (line 251) | function sanitize(str) {
  function matchesPattern (line 261) | function matchesPattern(str, filters) {

FILE: packages/artillery-plugin-publish-metrics/lib/dynatrace/index.js
  class DynatraceReporter (line 5) | class DynatraceReporter {
    method constructor (line 6) | constructor(config, events, script) {
    method parseDimensions (line 128) | parseDimensions(dimensionList) {
    method parseProperties (line 142) | parseProperties(propertyList) {
    method shouldSendMetric (line 156) | shouldSendMetric(metricName, excluded, includeOnly) {
    method warnIfMetricNameNotValid (line 168) | warnIfMetricNameNotValid(metric) {
    method formatCountersForDynatrace (line 186) | formatCountersForDynatrace(counters, config, timestamp) {
    method formatRatesForDynatrace (line 207) | formatRatesForDynatrace(rates, config, timestamp) {
    method formatSummariesForDynatrace (line 225) | formatSummariesForDynatrace(summaries, config, timestamp) {
    method formMetricsPayload (line 248) | formMetricsPayload(counters, rates, summaries) {
    method formRequest (line 253) | formRequest(payload, type = 'metrics') {
    method sendRequest (line 265) | async sendRequest(url, options, type = 'metrics') {
    method waitingForRequest (line 293) | async waitingForRequest() {
    method cleanup (line 303) | cleanup(done) {
  function createDynatraceReporter (line 325) | function createDynatraceReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/mixpanel.js
  class MixPanelReporter (line 5) | class MixPanelReporter {
    method constructor (line 6) | constructor(config, events, script) {
    method sendToMixPanel (line 29) | sendToMixPanel(_config, events, script) {
    method formatProperties (line 43) | formatProperties(stats) {
    method cleanup (line 70) | cleanup(done) {
  function createMixPanelReporter (line 76) | function createMixPanelReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/newrelic/index.js
  class NewRelicReporter (line 4) | class NewRelicReporter {
    method constructor (line 5) | constructor(config, events, script) {
    method formatCountersForNewRelic (line 108) | formatCountersForNewRelic(counters, config) {
    method formatRatesForNewRelic (line 127) | formatRatesForNewRelic(rates, config) {
    method formatSummariesForNewRelic (line 146) | formatSummariesForNewRelic(summaries, config) {
    method parseAttributes (line 166) | parseAttributes(attributeList) {
    method createRequestBody (line 178) | createRequestBody(timestamp, interval, attributeList, metrics) {
    method sendStats (line 193) | async sendStats(url, licenseKey, body) {
    method shouldSendMetric (line 226) | shouldSendMetric(metricName, excluded, includeOnly) {
    method sendEvent (line 238) | async sendEvent(url, licenseKey, eventOptions) {
    method waitingForRequest (line 272) | async waitingForRequest() {
    method cleanup (line 282) | cleanup(done) {
  function createNewRelicReporter (line 304) | function createNewRelicReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/exporters.js
  method 'otlp-proto' (line 2) | 'otlp-proto'(options) {
  method 'otlp-http' (line 8) | 'otlp-http'(options) {
  method 'otlp-grpc' (line 14) | 'otlp-grpc'(options) {
  method 'otlp-proto' (line 23) | 'otlp-proto'(options) {
  method 'otlp-http' (line 29) | 'otlp-http'(options) {
  method 'otlp-grpc' (line 35) | 'otlp-grpc'(options) {
  method zipkin (line 41) | zipkin(options) {
  method __test (line 45) | __test(options) {
  function validateExporter (line 51) | function validateExporter(supportedExporters, exporter, type) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/file-span-exporter.js
  class FileSpanExporter (line 7) | class FileSpanExporter extends ConsoleSpanExporter {
    method constructor (line 8) | constructor(opts) {
    method _exportInfo (line 22) | _exportInfo(span) {
    method _sendSpans (line 28) | _sendSpans(spans, done) {
    method shutdown (line 42) | shutdown() {
    method setOutputPath (line 60) | setOutputPath(output) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/index.js
  class OTelReporter (line 27) | class OTelReporter {
    method constructor (line 28) | constructor(configList, events, script) {
    method debug (line 140) | debug(msg) {
    method warnIfDuplicateTracesConfigured (line 148) | warnIfDuplicateTracesConfigured(configList) {
    method translateToOtel (line 156) | translateToOtel(config) {
    method getEngines (line 160) | getEngines(scenarios) {
    method sendTraceTelemetry (line 168) | async sendTraceTelemetry(spanCount, reporterType) {
    method cleanup (line 203) | async cleanup(done) {
  function createOTelReporter (line 231) | function createOTelReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/metrics.js
  class OTelMetricsReporter (line 11) | class OTelMetricsReporter {
    method constructor (line 12) | constructor(config, events, resource) {
    method configure (line 44) | configure(config) {
    method shouldSendMetric (line 100) | shouldSendMetric(metricName, excluded, includeOnly) {
    method recordCounters (line 110) | recordCounters(counters, config) {
    method recordRates (line 123) | recordRates(rates, config) {
    method recordSummaries (line 139) | recordSummaries(summaries, config) {
    method cleanup (line 162) | async cleanup() {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/outlier-detection-processor.js
  class OutlierDetectionBatchSpanProcessor (line 3) | class OutlierDetectionBatchSpanProcessor extends BatchSpanProcessor {
    method constructor (line 4) | constructor(exporter, config) {
    method onEnd (line 9) | onEnd(span) {
    method onShutdown (line 41) | onShutdown() {
    method _isOutlier (line 53) | _isOutlier(span) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/tracing/base.js
  class OTelTraceConfig (line 16) | class OTelTraceConfig {
    method constructor (line 17) | constructor(config, resource) {
    method configure (line 26) | configure() {
    method shutDown (line 79) | async shutDown() {
  class OTelTraceBase (line 90) | class OTelTraceBase {
    method constructor (line 91) | constructor(config, script) {
    method setTracer (line 101) | setTracer(engine) {
    method startScenarioSpan (line 109) | startScenarioSpan(engine) {
    method endScenarioSpan (line 144) | endScenarioSpan(engine) {
    method otelTraceOnError (line 161) | otelTraceOnError(_scenarioErr, _req, _userContext, _ee, done) {
    method replaceSpanNameRegex (line 165) | replaceSpanNameRegex(spanName, replMap) {
    method waitOnPendingSpans (line 174) | async waitOnPendingSpans(pendingRequests, pendingScenarios, maxWaitTim...
    method cleanup (line 187) | async cleanup(engines) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/tracing/http.js
  class OTelHTTPTraceReporter (line 19) | class OTelHTTPTraceReporter extends OTelTraceBase {
    method constructor (line 20) | constructor(config, script) {
    method run (line 25) | run() {
    method startHTTPRequestSpan (line 56) | startHTTPRequestSpan(req, userContext, _events, done) {
    method endHTTPRequestSpan (line 107) | endHTTPRequestSpan(req, res, userContext, events, done) {
    method otelTraceOnError (line 180) | otelTraceOnError(err, req, userContext, events, done) {
    method tagResponseOutliers (line 225) | tagResponseOutliers(span, res, criteria) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/tracing/playwright.js
  class OTelPlaywrightTraceReporter (line 11) | class OTelPlaywrightTraceReporter extends OTelTraceBase {
    method run (line 12) | run() {
    method runOtelTracingForPlaywright (line 24) | async runOtelTracingForPlaywright(
    method step (line 186) | async step(parent, tracer, events, vuContext) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/translators/vendor-adot.js
  function getADOTRelevantReporterConfigs (line 6) | function getADOTRelevantReporterConfigs(publishMetricsConfig) {
  function resolveADOTConfigSettings (line 20) | function resolveADOTConfigSettings(options) {
  function getADOTConfig (line 32) | function getADOTConfig(adotRelevantConfigs) {
  function getADOTEnvVars (line 127) | function getADOTEnvVars(adotRelevantconfigs, dotenv) {

FILE: packages/artillery-plugin-publish-metrics/lib/open-telemetry/translators/vendor-otel.js
  function attributeListToObject (line 101) | function attributeListToObject(attributeList, reporterType) {

FILE: packages/artillery-plugin-publish-metrics/lib/prometheus.js
  constant COUNTERS_STATS (line 9) | const COUNTERS_STATS = 'counters', // counters stats
  constant RATES_STATS (line 9) | const COUNTERS_STATS = 'counters', // counters stats
  constant SUMMARIES_STATS (line 9) | const COUNTERS_STATS = 'counters', // counters stats
  class PrometheusReporter (line 13) | class PrometheusReporter {
    method constructor (line 14) | constructor(config, events) {
    method registerMetrics (line 68) | registerMetrics(prefix) {
    method tagsToLabels (line 96) | tagsToLabels(tags) {
    method toPrometheusKey (line 105) | toPrometheusKey(candidate) {
    method sendMetrics (line 109) | sendMetrics(_config, events) {
    method waitingForRequest (line 162) | async waitingForRequest() {
    method cleanup (line 172) | cleanup(done) {
  function createPrometheusReporter (line 178) | function createPrometheusReporter(config, events, script) {
  function isHttps (line 182) | function isHttps(href) {

FILE: packages/artillery-plugin-publish-metrics/lib/splunk/index.js
  class SplunkReporter (line 4) | class SplunkReporter {
    method constructor (line 5) | constructor(config, events, script) {
    method formatCountersForSplunk (line 90) | formatCountersForSplunk(counters, config, timestamp) {
    method formatRatesForSplunk (line 111) | formatRatesForSplunk(rates, config, timestamp) {
    method formatSummariesForSplunk (line 131) | formatSummariesForSplunk(summaries, config, timestamp) {
    method parseDimensions (line 153) | parseDimensions(dimensionList) {
    method formRequest (line 168) | formRequest(payload) {
    method sendRequest (line 179) | async sendRequest(url, payload, type) {
    method shouldSendMetric (line 201) | shouldSendMetric(metricName, excluded, includeOnly) {
    method waitingForRequest (line 213) | async waitingForRequest() {
    method cleanup (line 223) | cleanup(done) {
  function createSplunkReporter (line 237) | function createSplunkReporter(config, events, script) {

FILE: packages/artillery-plugin-publish-metrics/lib/util.js
  function sleep (line 9) | async function sleep(n) {
  function versionCheck (line 18) | function versionCheck(range) {
  function attachScenarioHooks (line 26) | function attachScenarioHooks(script, specs) {
  function addHelperFunction (line 47) | function addHelperFunction(script, name, func) {

FILE: packages/artillery-plugin-slack/index.js
  class SlackPlugin (line 4) | class SlackPlugin {
    method constructor (line 5) | constructor(script, events) {
    method getErrors (line 101) | getErrors(report) {
    method assembleSlackPayload (line 111) | assembleSlackPayload(report, ensureChecks) {
    method sendReport (line 245) | async sendReport(report, ensureChecks) {
    method cleanup (line 263) | async cleanup(done) {
  class SlackPluginError (line 269) | class SlackPluginError extends Error {
    method constructor (line 270) | constructor(message) {
  function formatDuration (line 277) | function formatDuration(durationInMs) {
  function maybePluralize (line 304) | function maybePluralize(amount, singular, plural = `${singular}s`) {

FILE: packages/artillery/lib/artillery-global.js
  function createGlobalObject (line 6) | async function createGlobalObject(_opts) {

FILE: packages/artillery/lib/cli/hooks/version.js
  function versionHook (line 4) | async function versionHook() {

FILE: packages/artillery/lib/cmds/dino.js
  class DinoCommand (line 8) | class DinoCommand extends Command {
    method run (line 9) | async run() {

FILE: packages/artillery/lib/cmds/quick.js
  class QuickCommand (line 15) | class QuickCommand extends Command {
    method run (line 16) | async run() {

FILE: packages/artillery/lib/cmds/report.js
  class ReportCommand (line 5) | class ReportCommand extends Command {
    method run (line 6) | async run() {

FILE: packages/artillery/lib/cmds/run-aci.js
  class RunACICommand (line 11) | class RunACICommand extends Command {
    method run (line 15) | async run() {

FILE: packages/artillery/lib/cmds/run-fargate.js
  class RunCommand (line 18) | class RunCommand extends Command {
    method run (line 23) | async run() {

FILE: packages/artillery/lib/cmds/run-lambda.js
  class RunLambdaCommand (line 6) | class RunLambdaCommand extends Command {
    method run (line 10) | async run() {

FILE: packages/artillery/lib/cmds/run.js
  class RunCommand (line 29) | class RunCommand extends Command {
    method run (line 34) | async run() {
  function gracefulShutdown (line 373) | async function gracefulShutdown(opts = { exitCode: 0 }) {
  function sendTelemetry (line 452) | async function sendTelemetry(script, flags, extraProps) {
  function checkDirExists (line 619) | function checkDirExists(output) {
  function getLogFilename (line 631) | function getLogFilename(output, nameFormat) {
  function getPluginMetricsToSuppress (line 658) | function getPluginMetricsToSuppress(script) {

FILE: packages/artillery/lib/console-capture.js
  function setupConsoleCapture (line 3) | function setupConsoleCapture() {

FILE: packages/artillery/lib/console-reporter.js
  constant SSMS (line 13) | const SSMS = require('@artilleryio/int-core').ssms.SSMS;
  function createConsoleReporter (line 17) | function createConsoleReporter(events, opts) {
  function ConsoleReporter (line 27) | function ConsoleReporter(opts) {
  function isCollectionMetric (line 337) | function isCollectionMetric(n) {
  function formatTimestamp (line 373) | function formatTimestamp(timestamp) {
  function underline (line 377) | function underline(text) {
  function excludeFromReporting (line 381) | function excludeFromReporting(name) {
  function padded (line 389) | function padded(str1, str2) {
  function printRates (line 402) | function printRates(rates, report) {
  function printCounters (line 408) | function printCounters(counters, report) {
  function printSummaries (line 415) | function printSummaries(summaries, report) {
  function shouldSuppressOutput (line 433) | function shouldSuppressOutput(currMetricName, suppressMetricsList) {

FILE: packages/artillery/lib/create-bom/create-bom.js
  constant BUILTIN_PLUGINS (line 17) | const BUILTIN_PLUGINS = require('./built-in-plugins');
  function createBOM (line 20) | async function createBOM(absoluteScriptPath, extraFiles, opts, callback) {
  function getPlugins (line 138) | function getPlugins(context, next) {
  function getCustomEngines (line 163) | function getCustomEngines(context, next) {
  function getVariableDataFiles (line 174) | function getVariableDataFiles(context, next) {
  function getExtraFiles (line 224) | function getExtraFiles(context, next) {
  function commonPrefix (line 243) | function commonPrefix(paths, separator) {
  function prettyPrint (line 285) | function prettyPrint(manifest) {

FILE: packages/artillery/lib/dist.js
  function divideWork (line 23) | function divideWork(script, numWorkers) {
  function scriptHasPayload (line 92) | function scriptHasPayload(script) {
  function handleArrivalCountPhase (line 96) | function handleArrivalCountPhase(workerScripts, phase, numWorkers) {
  function handleArrivalRatePhase (line 107) | function handleArrivalRatePhase(phase, numWorkers, workerScripts) {
  function handleRampToPhase (line 126) | function handleRampToPhase(phase, numWorkers, workerScripts) {
  function createWorkerScriptBases (line 147) | function createWorkerScriptBases(numWorkers, script) {
  function distribute (line 174) | function distribute(m, n) {
  function sum (line 199) | function sum(a) {

FILE: packages/artillery/lib/launch-platform.js
  function createLauncher (line 18) | async function createLauncher(script, payload, opts, launcherOpts) {
  class Launcher (line 33) | class Launcher {
    method constructor (line 34) | constructor(script, payload, opts, launcherOpts) {
    method initWorkerEvents (line 70) | async initWorkerEvents(workerEvents) {
    method initPlugins (line 163) | async initPlugins() {
    method handleAllWorkersFinished (line 234) | async handleAllWorkersFinished() {
    method flushWorkerMessages (line 270) | async flushWorkerMessages(maxAge = 9000) {
    method flushIntermediateMetrics (line 306) | async flushIntermediateMetrics(flushAll = false) {
    method emitIntermediatesForPeriod (line 368) | emitIntermediatesForPeriod(period) {
    method run (line 397) | async run() {
    method shutdown (line 417) | async shutdown() {

FILE: packages/artillery/lib/load-plugins.js
  function loadPluginsConfig (line 11) | function loadPluginsConfig(pluginSpecs) {
  function loadPlugins (line 25) | async function loadPlugins(pluginSpecs, testScript) {
  function loadPlugin (line 47) | async function loadPlugin(name, config, requirePaths, testScript) {

FILE: packages/artillery/lib/platform/aws-ecs/ecs.js
  class PlatformECS (line 27) | class PlatformECS {
    method constructor (line 28) | constructor(_script, _payload, opts, platformOpts) {
    method init (line 57) | async init() {
    method createIAMResources (line 77) | async createIAMResources(accountId, taskRoleName) {
    method createWorkerRole (line 85) | async createWorkerRole(accountId, taskRoleName) {
    method createWorker (line 191) | async createWorker() {}
    method prepareWorker (line 193) | async prepareWorker() {}
    method runWorker (line 195) | async runWorker() {}
    method stopWorker (line 197) | async stopWorker() {}
    method shutdown (line 199) | async shutdown() {}
  function ensureSSMParametersExist (line 202) | async function ensureSSMParametersExist(region) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/aws-util.js
  function ecsDescribeTasks (line 23) | async function ecsDescribeTasks(params, region) {
  function splitIntoSublists (line 37) | function splitIntoSublists(list, maxGroupSize) {
  function ensureParameterExists (line 53) | async function ensureParameterExists(ssmPath, defaultValue, type, region) {
  function parameterExists (line 61) | async function parameterExists(path, region) {
  function putParameter (line 80) | async function putParameter(path, value, type, region) {
  function getParameter (line 93) | async function getParameter(path, region) {
  function deleteParameter (line 115) | async function deleteParameter(path, region) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/bom.js
  constant BUILTIN_PLUGINS (line 12) | const BUILTIN_PLUGINS = require('./plugins').getAllPluginNames();
  constant BUILTIN_ENGINES (line 13) | const BUILTIN_ENGINES = require('./plugins').getOfficialEngines();
  function _convertToPosixPath (line 26) | function _convertToPosixPath(p) {
  function createBOM (line 31) | function createBOM(absoluteScriptPath, extraFiles, opts, callback) {
  function isLocalModule (line 176) | function isLocalModule(modName) {
  function applyScriptChanges (line 181) | function applyScriptChanges(context, next) {
  function getPlugins (line 193) | function getPlugins(context, next) {
  function getCustomEngines (line 217) | function getCustomEngines(context, next) {
  function getCustomJsDependencies (line 242) | function getCustomJsDependencies(context, next) {
  function getVariableDataFiles (line 315) | function getVariableDataFiles(context, next) {
  function getFileUploadPluginFiles (line 359) | function getFileUploadPluginFiles(context, next) {
  function getExtraFiles (line 383) | function getExtraFiles(context, next) {
  function getDotEnv (line 403) | function getDotEnv(context, next) {
  function expandDirectories (line 421) | function expandDirectories(context, next) {
  function commonPrefix (line 462) | function commonPrefix(paths, separator) {
  function prettyPrint (line 504) | function prettyPrint(manifest) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/constants.js
  constant DEFAULT_IMAGE_TAG (line 2) | const DEFAULT_IMAGE_TAG = pkgJson.version;
  constant WAIT_TIMEOUT_SEC (line 5) | let WAIT_TIMEOUT_SEC = 600;

FILE: packages/artillery/lib/platform/aws-ecs/legacy/create-s3-client.js
  function createS3Client (line 5) | function createS3Client(opts = {}) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/create-test.js
  function tryCreateTest (line 17) | function tryCreateTest(scriptPath, options) {
  function createTest (line 21) | async function createTest(scriptPath, options, callback) {
  function prepareManifest (line 86) | function prepareManifest(context, callback) {
  function printManifest (line 112) | function printManifest(context, callback) {
  function syncS3 (line 117) | async function syncS3(context) {
  function writeTestMetadata (line 199) | async function writeTestMetadata(context) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/errors.js
  class TestNotFoundError (line 1) | class TestNotFoundError extends Error {
    method constructor (line 2) | constructor(message) {
  class NoAvailableQueueError (line 8) | class NoAvailableQueueError extends Error {
    method constructor (line 9) | constructor(message) {
  class ClientServerVersionMismatchError (line 15) | class ClientServerVersionMismatchError extends Error {
    method constructor (line 16) | constructor(message) {
  class ConsoleOutputSerializeError (line 22) | class ConsoleOutputSerializeError extends Error {
    method constructor (line 23) | constructor(message) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/find-public-subnets.js
  class VPCSubnetFinder (line 9) | class VPCSubnetFinder {
    method constructor (line 10) | constructor(opts) {
    method getRouteTables (line 14) | async getRouteTables(vpcId) {
    method findDefaultVpc (line 29) | async findDefaultVpc() {
    method getSubnets (line 50) | async getSubnets(vpcId) {
    method isSubnetPublic (line 65) | isSubnetPublic(routeTables, subnetId) {
    method findPublicSubnets (line 119) | async findPublicSubnets(vpcId) {
  function main (line 134) | async function main() {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-inspect-script/index.js
  function ArtilleryInspectScriptPlugin (line 11) | function ArtilleryInspectScriptPlugin(script, events) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-sqs-reporter/azure-aqs.js
  function getAQS (line 11) | function getAQS() {
  constant AQS_SIZE_LIMIT (line 20) | const AQS_SIZE_LIMIT = 60 * 1024;
  function getBlobClient (line 24) | function getBlobClient() {
  function sendMessage (line 42) | async function sendMessage(queue, body, tags) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/plugins/artillery-plugin-sqs-reporter/index.js
  constant SQS_SIZE_LIMIT (line 12) | const SQS_SIZE_LIMIT = 950 * 1024;
  function ArtillerySQSPlugin (line 19) | function ArtillerySQSPlugin(script, events) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/run-cluster.js
  constant IS_FARGATE (line 89) | let IS_FARGATE = false;
  constant TEST_RUN_STATUS (line 91) | const TEST_RUN_STATUS = require('./test-run-status');
  function setupConsoleReporter (line 96) | function setupConsoleReporter(quiet) {
  function runCluster (line 135) | function runCluster(scriptPath, options) {
  function logProgress (line 146) | function logProgress(msg, opts = {}) {
  function tryRunCluster (line 161) | async function tryRunCluster(scriptPath, options, artilleryReporter) {
  function cleanupResources (line 817) | async function cleanupResources(context) {
  function checkFargateResourceConfig (line 864) | function checkFargateResourceConfig(cpu, memory) {
  function createArtilleryCluster (line 904) | async function createArtilleryCluster(context) {
  function checkTargetCluster (line 930) | async function checkTargetCluster(context) {
  function maybeGetSubnetIdsForFargate (line 955) | async function maybeGetSubnetIdsForFargate(context) {
  function createTestBundle (line 982) | async function createTestBundle(context) {
  function createADOTDefinitionIfNeeded (line 995) | async function createADOTDefinitionIfNeeded(context) {
  function ensureTaskExists (line 1057) | async function ensureTaskExists(context) {
  function checkCustomTaskRole (line 1227) | async function checkCustomTaskRole(context) {
  function gcQueues (line 1241) | async function gcQueues(context) {
  function deleteQueue (line 1283) | async function deleteQueue(context) {
  function createQueue (line 1300) | async function createQueue(context) {
  function getManifest (line 1349) | async function getManifest(context) {
  function generateTaskOverrides (line 1375) | async function generateTaskOverrides(context) {
  function setupDefaultECSParams (line 1506) | async function setupDefaultECSParams(context) {
  function launchLeadTask (line 1547) | async function launchLeadTask(context) {
  function ecsRunTask (line 1626) | async function ecsRunTask(context) {
  function waitForTasks2 (line 1702) | async function waitForTasks2(context) {
  function waitForWorkerSync (line 1794) | async function waitForWorkerSync(context) {
  function sendGoSignal (line 1828) | async function sendGoSignal(context) {
  function writeHeartbeat (line 1839) | async function writeHeartbeat(context) {
  function startHeartbeat (line 1855) | function startHeartbeat(context) {
  function listen (line 1863) | async function listen(context, ee) {
  function deregisterTaskDefinition (line 1975) | async function deregisterTaskDefinition(context) {
  function getLogFilename (line 2000) | function getLogFilename(output, userDefaultFilenameFormat) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/sqs-reporter.js
  class SqsReporter (line 11) | class SqsReporter extends EventEmitter {
    method constructor (line 12) | constructor(opts) {
    method _allWorkersDone (line 51) | _allWorkersDone() {
    method _fetchFromS3 (line 55) | async _fetchFromS3(s3Key) {
    method stop (line 65) | stop() {
    method start (line 72) | start() {
    method calculateSpread (line 380) | calculateSpread(stats) {
  function round (line 396) | function round(number, decimals) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/tags.js
  function parseTags (line 3) | function parseTags(input) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/time.js
  function sleep (line 6) | async function sleep(ms) {
  class Timeout (line 10) | class Timeout extends EventEmitter {
    method constructor (line 11) | constructor(duration) {
    method start (line 17) | start() {
    method stop (line 25) | stop() {
    method timedout (line 30) | timedout() {
  function timeStringToMs (line 37) | function timeStringToMs(timeStr) {

FILE: packages/artillery/lib/platform/aws-ecs/legacy/util.js
  function atob (line 44) | function atob(data) {
  function btoa (line 47) | function btoa(data) {
  function getBucketName (line 51) | async function getBucketName() {
  function formatError (line 62) | function formatError(err) {
  function listAllObjectsWithPrefix (line 68) | async function listAllObjectsWithPrefix(bucketName, prefix) {

FILE: packages/artillery/lib/platform/aws-lambda/dependencies.js
  function _uploadFileToS3 (line 33) | async function _uploadFileToS3(item, testRunId, bucketName) {
  function _syncS3 (line 61) | async function _syncS3(bomManifest, testRunId, bucketName) {

FILE: packages/artillery/lib/platform/aws-lambda/index.js
  function memoryToVCPU (line 54) | function memoryToVCPU(memMB) {
  class PlatformLambda (line 78) | class PlatformLambda {
    method constructor (line 79) | constructor(script, payload, opts, platformOpts) {
    method init (line 134) | async init() {
    method getDesiredWorkerCount (line 394) | getDesiredWorkerCount() {
    method startJob (line 398) | async startJob() {
    method createWorker (line 408) | async createWorker() {
    method runWorker (line 414) | async runWorker(workerId) {
    method stopWorker (line 489) | async stopWorker(_workerId) {
    method shutdown (line 493) | async shutdown() {
    method createLambdaRole (line 523) | async createLambdaRole() {
    method createOrUpdateLambdaFunctionIfNeeded (line 611) | async createOrUpdateLambdaFunctionIfNeeded() {
    method getLambdaFunctionConfiguration (line 639) | async getLambdaFunctionConfiguration() {
    method createFunctionNameWithHash (line 662) | createFunctionNameWithHash(_lambdaConfig) {
    method createLambda (line 687) | async createLambda(opts) {

FILE: packages/artillery/lib/platform/aws-lambda/lambda-handler/a9-handler-helpers.js
  function runProcess (line 9) | async function runProcess(name, args, { env, log }) {

FILE: packages/artillery/lib/platform/aws-lambda/lambda-handler/a9-handler-index.js
  constant TIMEOUT_THRESHOLD_MSEC (line 15) | const TIMEOUT_THRESHOLD_MSEC = 20 * 1000;
  class MQ (line 17) | class MQ {
    method constructor (line 18) | constructor({ region, queueUrl, attrs }) {
    method send (line 24) | async send(body) {
  function handler (line 45) | async function handler(event, context) {
  function execArtillery (line 180) | async function execArtillery(options) {

FILE: packages/artillery/lib/platform/aws/aws-cloudwatch.js
  function _putCloudwatchRetentionPolicy (line 12) | async function _putCloudwatchRetentionPolicy(
  function setCloudwatchRetention (line 31) | function setCloudwatchRetention(

FILE: packages/artillery/lib/platform/aws/aws-create-sqs-queue.js
  function createSQSQueue (line 10) | async function createSQSQueue(region, queueName) {

FILE: packages/artillery/lib/platform/aws/aws-get-bucket-region.js
  function getBucketRegion (line 3) | async function getBucketRegion(bucketName) {

FILE: packages/artillery/lib/platform/aws/aws-get-credentials.js
  function getSSOCredentials (line 14) | async function getSSOCredentials() {

FILE: packages/artillery/lib/platform/az/aci.js
  function streamToString (line 28) | async function streamToString(readableStream) {
  class PlatformAzureACI (line 41) | class PlatformAzureACI {
    method constructor (line 42) | constructor(script, variablePayload, opts, platformOpts) {
    method init (line 117) | async init() {
    method getDesiredWorkerCount (line 365) | getDesiredWorkerCount() {
    method startJob (line 369) | async startJob() {
    method shutdown (line 457) | async shutdown() {
    method sendGoSignal (line 491) | async sendGoSignal() {
    method createWorker (line 497) | async createWorker() {
    method runWorker (line 502) | async runWorker(workerId, opts = { isLeader: false }) {
    method stopWorker (line 653) | async stopWorker(_workerId) {}
    method checkLicense (line 655) | async checkLicense() {

FILE: packages/artillery/lib/platform/az/aqs-queue-consumer.js
  class AzureQueueConsumer (line 14) | class AzureQueueConsumer extends EventEmitter {
    method constructor (line 15) | constructor(
    method start (line 37) | async start() {
    method stop (line 79) | async stop() {

FILE: packages/artillery/lib/platform/cloud/api.js
  class Client (line 3) | class Client {
    method constructor (line 4) | constructor({ apiKey, baseUrl }) {
    method whoami (line 26) | async whoami() {
    method getStashDetails (line 37) | async getStashDetails({ orgId }) {
  function createClient (line 68) | function createClient(opts) {

FILE: packages/artillery/lib/platform/cloud/cloud.js
  class ArtilleryCloudPlugin (line 17) | class ArtilleryCloudPlugin {
    method constructor (line 18) | constructor(_script, _events, { flags }) {
    method init (line 213) | async init() {
    method _uploadAsset (line 303) | async _uploadAsset(localFilename) {
    method waitOnUnprocessedLogs (line 350) | async waitOnUnprocessedLogs(maxWaitTime) {
    method setGetStatusInterval (line 364) | setGetStatusInterval() {
    method _getLoadTestStatus (line 391) | async _getLoadTestStatus() {
    method _event (line 405) | async _event(eventName, eventPayload) {
    method cleanup (line 444) | cleanup(done) {

FILE: packages/artillery/lib/platform/cloud/http-client.js
  constant DEFAULT_TIMEOUT_MS (line 5) | const DEFAULT_TIMEOUT_MS = 20 * 10000;
  constant DEFAULT_RETRY_LIMIT (line 6) | const DEFAULT_RETRY_LIMIT = 3;
  function getCloudHttpClient (line 9) | async function getCloudHttpClient() {

FILE: packages/artillery/lib/platform/local/artillery-worker-local.js
  constant STATES (line 9) | const STATES = require('../worker-states');
  class ArtilleryWorker (line 25) | class ArtilleryWorker {
    method constructor (line 26) | constructor(opts) {
    method init (line 32) | async init(_opts) {
    method prepare (line 102) | async prepare(opts) {
    method run (line 130) | async run(opts) {
    method stop (line 140) | async stop() {
    method onError (line 144) | onError(err) {

FILE: packages/artillery/lib/platform/local/index.js
  constant STATES (line 9) | const STATES = require('../worker-states');
  class PlatformLocal (line 11) | class PlatformLocal {
    method constructor (line 12) | constructor(script, payload, opts, platformOpts) {
    method getDesiredWorkerCount (line 24) | getDesiredWorkerCount() {
    method startJob (line 28) | async startJob() {
    method init (line 76) | async init() {
    method createWorker (line 83) | async createWorker() {
    method prepareWorker (line 125) | async prepareWorker(workerId, opts) {
    method runWorker (line 129) | async runWorker(workerId, contextVarsString) {
    method stopWorker (line 135) | async stopWorker(workerId) {
    method shutdown (line 139) | async shutdown() {
    method runHook (line 151) | async runHook(hook, initialContextVars) {

FILE: packages/artillery/lib/platform/local/worker.js
  function onMessage (line 49) | async function onMessage(message) {
  function cleanup (line 85) | async function cleanup() {
  function createGlobalStashClient (line 102) | async function createGlobalStashClient(cliArgs) {
  function prepare (line 115) | async function prepare(opts) {
  function run (line 247) | async function run(opts) {
  function send (line 257) | function send(data) {

FILE: packages/artillery/lib/queue-consumer/index.js
  class QueueConsumer (line 5) | class QueueConsumer extends EventEmitter {
    method create (line 6) | create(opts = { poolSize: 30 }, queueConsumerOpts) {
    method constructor (line 39) | constructor(_opts) {
    method start (line 43) | start() {
    method stop (line 49) | stop() {

FILE: packages/artillery/lib/stash.js
  function init (line 4) | async function init(details) {
  function getStash (line 20) | async function getStash(options = {}) {

FILE: packages/artillery/lib/telemetry.js
  constant POSTHOG_TOKEN (line 11) | const POSTHOG_TOKEN = '_uzX-_WJoVmE_tsLvu0OFD2tpd0HGz72D5sU1zM2hbs';
  function capture (line 23) | async function capture(eventName, data) {

FILE: packages/artillery/lib/util.js
  constant YAML (line 5) | const YAML = require('js-yaml');
  function readScript (line 35) | async function readScript(scriptPath) {
  function parseScript (line 40) | async function parseScript(data) {
  function addOverrides (line 44) | async function addOverrides(script, flags) {
  function addVariables (line 65) | async function addVariables(script, flags) {
  function addDefaultPlugins (line 79) | function addDefaultPlugins(script) {
  function resolveConfigTemplates (line 101) | async function resolveConfigTemplates(script, flags, configPath, scriptP...
  function checkConfig (line 120) | async function checkConfig(script, scriptPath, flags) {
  function resolveConfigPath (line 205) | async function resolveConfigPath(script, flags, scriptPath) {
  function formatDuration (line 238) | function formatDuration(durationInMs) {
  function maybePluralize (line 264) | function maybePluralize(amount, singular, plural = `${singular}s`) {
  function padded (line 268) | function padded(str1, str2, length = 79, formatPadding = chalk.gray) {
  function maybeTruncate (line 279) | function maybeTruncate(str, length) {
  function rainbow (line 283) | function rainbow(str) {

FILE: packages/artillery/lib/util/await-on-ee.js
  function awaitOnEE (line 3) | async function awaitOnEE(ee, message, pollMs = 1000, maxWaitMs = Infinit...

FILE: packages/artillery/lib/util/generate-id.js
  function generateId (line 3) | function generateId(prefix = '') {

FILE: packages/artillery/lib/util/prepare-test-execution-plan.js
  function prepareTestExecutionPlan (line 22) | async function prepareTestExecutionPlan(inputFiles, flags, _args) {
  function readPayload (line 121) | async function readPayload(script) {
  function transpileTypeScript (line 148) | function transpileTypeScript(entryPoint, outputPath, userExternalPackage...
  function replaceProcessorIfTypescript (line 164) | function replaceProcessorIfTypescript(script, scriptPath) {

FILE: packages/artillery/lib/util/sleep.js
  function sleep (line 1) | async function sleep(ms) {

FILE: packages/artillery/lib/utils-config.js
  function readArtilleryConfig (line 6) | function readArtilleryConfig() {
  function updateArtilleryConfig (line 16) | function updateArtilleryConfig(data) {

FILE: packages/artillery/test/cli/custom-plugin.test.js
  function createServer (line 11) | function createServer() {

FILE: packages/artillery/test/cloud-e2e/fargate/bom.test.js
  constant A9_PATH (line 14) | const A9_PATH = toCorrectPath(process.env.A9_PATH || 'artillery');

FILE: packages/artillery/test/cloud-e2e/fargate/cloud-api-key.test.js
  constant A9_PATH (line 16) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/cw-adot.test.js
  constant A9_PATH (line 18) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/dd-adot.test.js
  constant A9_PATH (line 18) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/ensure-plugin.test.js
  constant A9_PATH (line 11) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/expect-plugin.test.js
  constant A9_PATH (line 11) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/adot/flow.js
  function simpleCheck (line 1) | async function simpleCheck(page, _userContext, _events, test) {

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/adot/helpers.js
  function getDatadogSpans (line 16) | async function getDatadogSpans(apiKey, appKey, testId, expectedTotalSpan...
  function getXRayTraces (line 69) | async function getXRayTraces(testId, expectedTraceNum) {

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/large-output/processor.js
  function logOutput (line 1) | function logOutput(_req, _res, _userContext, events, done) {

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/memory-hog/processor.js
  function hogSomeRam (line 6) | function hogSomeRam(_req, _context, _events, next) {

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/mixed-hierarchy/code/set-url.js
  function setUrl (line 5) | function setUrl(req, _res, _ctx, _ee, done) {

FILE: packages/artillery/test/cloud-e2e/fargate/fixtures/simple-bom/deps/functions.js
  function checkBundle (line 14) | function checkBundle(_req, _userContext, _events, done) {

FILE: packages/artillery/test/cloud-e2e/fargate/heartbeat.test.js
  constant A9_PATH (line 9) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant REGION (line 10) | const REGION = 'eu-west-1';
  constant CLUSTER (line 11) | const CLUSTER = 'artilleryio-cluster';
  constant HEARTBEAT_THRESHOLD_S (line 13) | const HEARTBEAT_THRESHOLD_S = 180;
  constant POLL_INTERVAL_MS (line 14) | const POLL_INTERVAL_MS = 30_000;
  constant POLL_TIMEOUT_MS (line 15) | const POLL_TIMEOUT_MS = 300_000;
  function listRunningTasks (line 20) | function listRunningTasks(startedBy) {
  function waitForOutput (line 30) | function waitForOutput(proc, pattern, timeoutMs = 180_000) {
  function extractTestId (line 53) | function extractTestId(output) {

FILE: packages/artillery/test/cloud-e2e/fargate/memory.test.js
  constant A9_PATH (line 5) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/misc.test.js
  constant A9_PATH (line 13) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/fargate/processors.test.js
  constant A9_PATH (line 15) | const A9_PATH = process.env.A9_PATH || 'artillery';

FILE: packages/artillery/test/cloud-e2e/lambda/fixtures/dotenv/processor.js
  function getFruit (line 1) | function getFruit(_context, ee, next) {

FILE: packages/artillery/test/cloud-e2e/lambda/fixtures/quick-loop-with-csv/helpers.js
  function maybeSleep (line 3) | function maybeSleep(_req, _context, _events, done) {
  function emitCsvCounters (line 13) | function emitCsvCounters(context, events, done) {

FILE: packages/artillery/test/cloud-e2e/lambda/lambda-bom.test.js
  constant A9_PATH (line 17) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant ARCHITECTURE (line 18) | const ARCHITECTURE = getImageArchitecture();

FILE: packages/artillery/test/cloud-e2e/lambda/lambda-dotenv.test.js
  constant A9_PATH (line 15) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant ARCHITECTURE (line 16) | const ARCHITECTURE = getImageArchitecture();

FILE: packages/artillery/test/cloud-e2e/lambda/lambda-ensure.test.js
  constant A9_PATH (line 23) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant ARCHITECTURE (line 24) | const ARCHITECTURE = getImageArchitecture();

FILE: packages/artillery/test/cloud-e2e/lambda/lambda-expect.test.js
  constant A9_PATH (line 22) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant ARCHITECTURE (line 23) | const ARCHITECTURE = getImageArchitecture();

FILE: packages/artillery/test/cloud-e2e/lambda/lambda-smoke.test.js
  constant A9_PATH (line 23) | const A9_PATH = process.env.A9_PATH || 'artillery';
  constant ARCHITECTURE (line 24) | const ARCHITECTURE = getImageArchitecture();

FILE: packages/artillery/test/helpers/index.js
  function execute (line 9) | async function execute(args, options) {
  function deleteFile (line 21) | async function deleteFile(path) {
  function returnTmpPath (line 26) | function returnTmpPath(fileName) {
  function getRootPath (line 30) | async function getRootPath(filename) {
  function generateTmpReportPath (line 34) | function generateTmpReportPath(testName, extension) {
  function getTestTags (line 42) | function getTestTags(additionalTags) {
  function getTestId (line 62) | function getTestId(outputString) {

FILE: packages/artillery/test/helpers/sleep.js
  function sleep (line 1) | async function sleep(ms) {

FILE: packages/artillery/test/integration/core/fixtures/http-file-upload-processor.js
  function getResponse (line 3) | function getResponse(_req, res, _context, _ee, next) {

FILE: packages/artillery/test/integration/core/http-file-upload.test.js
  function calculateFileHash (line 21) | async function calculateFileHash(filePath) {

FILE: packages/artillery/test/plugins/artillery-plugin-dummy-csv-logger/index.js
  function Plugin (line 11) | function Plugin(_config, ee) {

FILE: packages/artillery/test/plugins/artillery-plugin-httphooks/index.js
  function httpHooks (line 7) | function httpHooks(script) {
  function afterResponseFn (line 21) | function afterResponseFn(_req, _res, _userContext, _events, done) {

FILE: packages/artillery/test/publish-metrics/fixtures/flow.js
  function simpleCheck (line 3) | async function simpleCheck(page, _userContext, _events, test) {
  function simpleError (line 27) | async function simpleError(page, _userContext, _events, test) {

FILE: packages/artillery/test/publish-metrics/fixtures/helpers.js
  function getTestId (line 3) | function getTestId(outputString) {
  function setDynamicHTTPTraceExpectations (line 9) | function setDynamicHTTPTraceExpectations(expectedOutcome) {
  function setDynamicPlaywrightTraceExpectations (line 23) | function setDynamicPlaywrightTraceExpectations(expectedOutcome) {

FILE: packages/artillery/test/publish-metrics/tracing/http-trace-assertions.js
  function runHttpTraceAssertions (line 69) | async function runHttpTraceAssertions(t, testRunData, expectedOutcome) {

FILE: packages/artillery/test/publish-metrics/tracing/playwright-trace-assertions.js
  function runPlaywrightTraceAssertions (line 47) | async function runPlaywrightTraceAssertions(t, testRunData, expectedOutc...

FILE: packages/artillery/test/scripts/http/processors.js
  function simpleFunction (line 3) | function simpleFunction(_context, ee, next) {
  function asyncFunction (line 10) | async function asyncFunction(_context, ee, next) {
  function otherFunction (line 21) | function otherFunction(_context, ee, next) {
  function errorCodeFunction (line 26) | function errorCodeFunction(_context, _ee, next) {
  function errorMessageFunction (line 30) | function errorMessageFunction(_context, _ee, next) {

FILE: packages/artillery/test/scripts/processor.js
  function printHello (line 10) | function printHello(_req, _ctx, _events, done) {
  function _doNothing (line 18) | function _doNothing(_req, _ctx, _events, done) {
  function createNewVar (line 23) | function createNewVar(ctx, _events, done) {
  function rewriteUrl (line 29) | function rewriteUrl(req, _ctx, _events, done) {
  function checkGlobal (line 34) | function checkGlobal(_ctx, _events, done) {

FILE: packages/artillery/test/scripts/scenario-cli-variables/processor.js
  function myAfterResponseHandler (line 1) | function myAfterResponseHandler(req, _res, context, _ee, next) {

FILE: packages/artillery/test/scripts/scenario-config-different-folder/__processor__/index.js
  function setId (line 1) | function setId(context, _ee, next) {

FILE: packages/artillery/test/scripts/scenario-with-custom-plugin/processor.js
  function processorFn (line 1) | function processorFn() {

FILE: packages/artillery/test/scripts/scenario-with-parallel/processor.js
  function beforeReqInParallel (line 1) | function beforeReqInParallel(req, context, ee, next) {
  function afterReqInParallel (line 7) | function afterReqInParallel(req, _res, context, ee, next) {

FILE: packages/artillery/test/scripts/test-suggest-exit-code.js
  function setNonZeroCode (line 5) | function setNonZeroCode(_req, _res, _vuContext, _events, next) {

FILE: packages/artillery/test/scripts/with-process-env/processor.js
  function myBeforeRequestHandler (line 1) | function myBeforeRequestHandler(req, _res, context, _ee, next) {

FILE: packages/artillery/test/targets/gh_215_target.js
  function register (line 23) | function register(_req, _h) {

FILE: packages/artillery/test/targets/targetServer.js
  function createServer (line 13) | function createServer(host, port) {
  function createCalcServer (line 19) | function createCalcServer(host, port) {
  function double (line 44) | function double(req, h) {
  function inc (line 64) | function inc(req, h) {

FILE: packages/artillery/test/unit/before_after_hooks.test.js
  function runServer (line 205) | function runServer() {

FILE: packages/artillery/test/unit/ssms-multi-process.test.js
  constant MEASUREMENTS (line 16) | const MEASUREMENTS = [];
  function round (line 470) | function round(number, decimals) {

FILE: packages/artillery/test/unit/ssms-worker.js
  function main (line 22) | async function main() {

FILE: packages/artillery/types.d.ts
  type Stash (line 21) | type Stash = Redis | null;
  type GetStashOptions (line 37) | interface GetStashOptions {
  type Config (line 65) | type Config = {
  type Scenario (line 118) | type Scenario = {
  type PlaywrightEngineScenarioTestFunction (line 154) | type PlaywrightEngineScenarioTestFunction = string | ((page: Page, userC...
  type VUContext (line 156) | type VUContext = {
  type VUEvents (line 161) | type VUEvents = {
  type PlaywrightEngineTestParam (line 165) | type PlaywrightEngineTestParam = {
  type PlaywrightEngineConfig (line 169) | type PlaywrightEngineConfig = {
  type PlaywrightEngineTraceConfig (line 225) | type PlaywrightEngineTraceConfig = {
  type TestPhase (line 238) | type TestPhase = {
  type PayloadConfig (line 277) | type PayloadConfig = {

FILE: packages/commons/engine_util.js
  function createThink (line 38) | function createThink(requestSpec, opts) {
  function createLoopWithCount (line 73) | function createLoopWithCount(count, steps, opts) {
  function createParallel (line 164) | function createParallel(steps, opts) {
  function isProbableEnough (line 184) | function isProbableEnough(obj) {
  function template (line 198) | function template(o, context, inPlace) {
  function templateObjectOrArray (line 255) | function templateObjectOrArray(o, context) {
  function renderVariables (line 291) | function renderVariables(str, vars) {
  function evil (line 326) | function evil(sandbox, code) {
  function parseLoopCount (line 336) | function parseLoopCount(countSpec) {
  function isCaptureFailed (line 361) | function isCaptureFailed(v, defaultStrict) {
  function ensurePropertyIsAList (line 381) | function ensurePropertyIsAList(obj, prop) {
  function captureOrMatch (line 390) | function captureOrMatch(params, response, context, done) {
  function parseSpec (line 500) | function parseSpec(spec, response) {
  function parseJSON (line 548) | function parseJSON(body, callback) {
  function dummyParser (line 565) | function dummyParser(body, callback) {
  function extractJSONPath (line 570) | function extractJSONPath(doc, expr, opts) {
  function extractRegExp (line 600) | function extractRegExp(doc, expr, opts) {
  function extractHeader (line 635) | function extractHeader(headers, headerName) {
  function extractCheerio (line 639) | function extractCheerio(doc, expr, opts) {
  function dummyExtractor (line 655) | function dummyExtractor() {
  function isJSON (line 662) | function isJSON(res) {
  function isXML (line 673) | function isXML(res) {
  function randomInt (line 681) | function randomInt(low, high) {
  function sanitiseValue (line 685) | function sanitiseValue(value) {

FILE: packages/commons/jitter.js
  function jitter (line 9) | function jitter(sApprox) {

FILE: packages/core/index.js
  function updateGlobalObject (line 5) | async function updateGlobalObject(opts = {}) {
  function main (line 84) | async function main() {

FILE: packages/core/lib/engine_http.js
  constant USER_AGENT (line 11) | const USER_AGENT = 'Artillery (https://artillery.io)';
  constant GOT_OPTION_NAMES (line 32) | const GOT_OPTION_NAMES = [
  constant DEFAULT_AGENT_OPTIONS (line 56) | const DEFAULT_AGENT_OPTIONS = {
  function createAgents (line 61) | function createAgents(proxies, opts) {
  function HttpEngine (line 100) | function HttpEngine(script) {
  function responseProcessor (line 567) | function responseProcessor(isLast, res, body, done) {
  function lastRequest (line 955) | function lastRequest(res, requestParams) {
  function maybePrependBase (line 1047) | function maybePrependBase(uri, config) {
  function lowcaseKeys (line 1058) | function lowcaseKeys(h) {
  function runOnErrorHooks (line 1064) | function runOnErrorHooks(

FILE: packages/core/lib/engine_socketio.js
  function SocketIoEngine (line 19) | function SocketIoEngine(script) {
  function markEndTime (line 48) | function markEndTime(ee, _, startedAt) {
  function isResponseRequired (line 55) | function isResponseRequired(spec) {
  function isAcknowledgeRequired (line 61) | function isAcknowledgeRequired(spec) {
  function isValid (line 65) | function isValid(data, response) {
  function processResponse (line 99) | function processResponse(ee, data, response, context, callback) {
  function preStep (line 330) | function preStep(context, callback) {
  function zero (line 403) | function zero(callback, context) {

FILE: packages/core/lib/engine_ws.js
  function WSEngine (line 16) | function WSEngine(script) {
  function getMessageHandler (line 35) | function getMessageHandler(context, params, ee, timeout, callback) {
  function getWsOptions (line 230) | function getWsOptions(config) {
  function getWsInstance (line 247) | function getWsInstance(config, scenarioSpec, context, cb) {
  function zero (line 301) | function zero(cb) {
  function one (line 307) | function one(context, cb) {
  function getWsConfig (line 348) | function getWsConfig(config) {

FILE: packages/core/lib/is-idle-phase.js
  function isIdlePhase (line 5) | function isIdlePhase(phase) {

FILE: packages/core/lib/phases.js
  function sleep (line 17) | async function sleep(ms) {
  function phaser (line 23) | function phaser(phaseSpecs) {
  function createPause (line 105) | function createPause(spec, ee) {
  function createRamp (line 120) | function createRamp(spec, ee) {
  function createArrivalCount (line 207) | function createArrivalCount(spec, ee) {
  function createArrivalRate (line 234) | function createArrivalRate(spec, ee) {

FILE: packages/core/lib/readers.js
  function createReader (line 9) | function createReader(order, spec) {
  function createSequencedReader (line 24) | function createSequencedReader() {
  function createEverythingReader (line 37) | function createEverythingReader(spec) {
  function createRandomReader (line 64) | function createRandomReader() {

FILE: packages/core/lib/runner.js
  function loadEngines (line 37) | function loadEngines(
  function loadProcessor (line 76) | async function loadProcessor(script, options) {
  function prepareScript (line 101) | function prepareScript(script, payload) {
  function runner (line 138) | async function runner(script, payload, options, callback) {
  function run (line 209) | function run(script, ee, options, runState, contextVars) {
  function runScenario (line 262) | function runScenario(script, metrics, runState, contextVars, options) {
  function datafileVariables (line 405) | function datafileVariables(script) {
  function inlineVariables (line 433) | function inlineVariables(script) {
  function createContext (line 452) | function createContext(script, contextVars, additionalProperties = {}) {
  function $randomNumber (line 502) | function $randomNumber(min, max) {
  function $randomString (line 506) | function $randomString(length = 10) {
  function handleScriptHook (line 519) | async function handleScriptHook(hook, script, hookEvents, contextVars = ...

FILE: packages/core/lib/ssms.js
  constant MAX_METRIC_NAME_LENGTH (line 15) | const MAX_METRIC_NAME_LENGTH = 1024;
  class SSMS (line 17) | class SSMS extends EventEmitter {
    method constructor (line 18) | constructor(_options) {
    method stop (line 56) | stop() {
    method report (line 67) | static report(pds) {
    method empty (line 72) | static empty(ts) {
    method summarizeHistogram (line 88) | static summarizeHistogram(h) {
    method legacyReport (line 93) | static legacyReport(pd) {
    method mergeBuckets (line 177) | static mergeBuckets(periodData) {
    method pack (line 272) | static pack(periods) {
    method cloneHistogram (line 334) | static cloneHistogram(h) {
    method serializeMetrics (line 338) | static serializeMetrics(pd) {
    method deserializeMetrics (line 356) | static deserializeMetrics(pd) {
    method getBucketIds (line 366) | getBucketIds() {
    method counter (line 377) | counter(name, value) {
    method incr (line 381) | incr(name, value, t) {
    method summary (line 390) | summary(name, value) {
    method histogram (line 394) | histogram(name, value, t) {
    method rate (line 402) | rate(name, t) {
    method getMetrics (line 406) | getMetrics(period) {
    method _aggregateHistograms (line 444) | _aggregateHistograms(upToTimeslice) {
    method _aggregateCounters (line 477) | _aggregateCounters(upToTimeslice) {
    method _aggregateRates (line 511) | _aggregateRates(upToTimeslice) {
    method aggregate (line 568) | aggregate(forceAll) {
    method _emitPeriods (line 583) | _emitPeriods() {
    method _maybeEmitMostRecentPeriod (line 596) | _maybeEmitMostRecentPeriod() {
  function normalizeTs (line 606) | function normalizeTs(epochMs, windowSize = 10) {
  function round (line 624) | function round(number, decimals) {
  function summarizeHistogram (line 630) | function summarizeHistogram(h) {
  function stringify (line 647) | function stringify(value, space) {
  function parse (line 651) | function parse(text) {
  function replacer (line 655) | function replacer(_key, value) {
  function reviver (line 667) | function reviver(_key, value) {
  function isBufferLike (line 686) | function isBufferLike(x) {
  function isArray (line 692) | function isArray(x) {
  function isString (line 696) | function isString(x) {
  function isObject (line 700) | function isObject(x) {
  function min (line 708) | function min(values) {
  function max (line 713) | function max(values) {

FILE: packages/core/lib/weighted-pick.js
  function create (line 10) | function create(list) {
  function bench (line 28) | function bench() {

FILE: packages/core/test/plugins/normal_plugin/index.js
  function normalPlugin (line 5) | function normalPlugin(_config, ee) {

FILE: packages/core/test/plugins/packaged_plugin/index.js
  function packagedPlugin (line 5) | function packagedPlugin(_config, ee) {

FILE: packages/core/test/quarantine/test_config_plugin_package.js
  function runTest (line 31) | function runTest(t, scriptName) {

FILE: packages/core/test/targets/express_socketio.js
  function handler (line 33) | function handler(_req, res) {
  function setsCookie (line 39) | function setsCookie(_req, res) {
  function expectsCookie (line 45) | function expectsCookie(req, res) {
  function stats (line 61) | function stats(_req, res) {

FILE: packages/core/test/targets/simple.js
  constant REQUEST_COUNT (line 4) | let REQUEST_COUNT = 0;
  constant COOKIES (line 5) | const COOKIES = {};
  constant LARGE_RESPONSE (line 15) | const LARGE_RESPONSE = JSON.stringify({
  function route (line 66) | function route(server) {
  function ok (line 204) | function ok(_req, _h) {
  function index (line 212) | function index(_req, _h) {
  function postIndex (line 216) | function postIndex(_req, h) {
  function create (line 220) | function create(req, h) {
  function read (line 228) | function read(req, h) {
  function stats (line 238) | function stats(_req, _h) {
  function setsCookie (line 250) | function setsCookie(_req, h) {
  function expectsCookie (line 257) | function expectsCookie(req, h) {
  function getJourneys (line 272) | function getJourneys(_req, h) {
  function getJourney (line 299) | function getJourney(req, h) {
  function getDevices (line 323) | function getDevices(_req, h) {
  function putDevice (line 357) | function putDevice(req, h) {

FILE: packages/core/test/targets/simple_socketio.js
  function createTestServer (line 5) | function createTestServer() {

FILE: packages/core/test/targets/simple_ws.js
  function handleProtocols (line 26) | function handleProtocols(protocols, _request) {

FILE: packages/core/test/targets/socketio_args.js
  function handler (line 6) | function handler(_req, res) {

FILE: packages/core/test/unit/engine_http.test.js
  constant THINKTIME_SEC (line 14) | const THINKTIME_SEC = 1;
  function onStarted (line 155) | function onStarted() {

FILE: packages/core/test/unit/engine_ws.test.js
  function setup (line 28) | function setup() {
  function teardown (line 49) | function teardown(sandbox) {

FILE: packages/core/test/unit/phases.test.js
  function testRamp (line 192) | function testRamp(t, phaseSpec) {

FILE: packages/core/test/unit/readers.test.js
  function readPayloadData (line 51) | function readPayloadData(reader) {

FILE: packages/skytrace/src/commands/ping.ts
  constant YAML (line 18) | const YAML = require('js-yaml');
  function fmt (line 25) | function fmt(val: any, padTo: number = 8) {
  function parse (line 31) | function parse(str: string) {
  constant VERBS (line 61) | const VERBS = [
  class PingCommand (line 73) | class PingCommand extends Command {
    method log (line 81) | log(...args: any) {
    method run (line 87) | async run() {

FILE: packages/skytrace/src/commands/run.ts
  class RunCommand (line 14) | class RunCommand extends Command {
    method runFlow (line 18) | async runFlow(flowFilePath: string, opts: any) {
    method run (line 111) | async run() {

FILE: packages/skytrace/src/telemetry.ts
  constant POSTHOG_TOKEN (line 10) | const POSTHOG_TOKEN = '_uzX-_WJoVmE_tsLvu0OFD2tpd0HGz72D5sU1zM2hbs';

FILE: packages/types/definitions.ts
  type TestScript (line 3) | type TestScript = {
  type Config (line 29) | type Config = {
  type PlaywrightEngineConfig (line 96) | type PlaywrightEngineConfig = {
  type PayloadConfig (line 137) | type PayloadConfig = {
  type Scenarios (line 186) | type Scenarios = Array<Scenario>;
  type HttpConfig (line 188) | type HttpConfig = {
  type WebSocketConfig (line 241) | type WebSocketConfig = {
  type TestPhase (line 261) | type TestPhase = {
  type Scenario (line 305) | type Scenario = {
  type FixedLoop (line 394) | type FixedLoop = {
  type DynamicLoop (line 402) | type DynamicLoop = {
  type BaseFlow (line 411) | type BaseFlow =
  type HttpResponseMatch (line 434) | type HttpResponseMatch = {
  type HttpFlow (line 439) | type HttpFlow =
  type WebSocketFlow (line 472) | type WebSocketFlow =
  type SocketIoFlow (line 491) | type SocketIoFlow =
  type DefaultHttpRequest (line 509) | type DefaultHttpRequest = {
  type HttpRequestWithBody (line 592) | type HttpRequestWithBody = DefaultHttpRequest &
  type TestPhaseCapture (line 614) | type TestPhaseCapture =

FILE: packages/types/plugins/expect.ts
  type ExpectPluginConfig (line 1) | type ExpectPluginConfig = {
  type ExpectPluginMetrics (line 34) | type ExpectPluginMetrics = {

FILE: packages/types/test/examples.test.ts
  constant ROOT_DIR (line 6) | const ROOT_DIR = path.resolve(__dirname, '../../..');
  function fromExample (line 8) | function fromExample(testScriptPath: string) {

FILE: packages/types/test/helpers.ts
  function validateTestScript (line 14) | function validateTestScript(scriptText: string) {
Copy disabled (too large) Download .json
Condensed preview — 770 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (12,032K chars).
[
  {
    "path": ".artilleryrc",
    "chars": 68,
    "preview": "{\n  \"logFilenameFormat\": \"[artillery_report_]YMMDD_HHmmSS[.json]\"\n}\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 506,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n<!--\nThank you f"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 148,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n    exclude-p"
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 336,
    "preview": "## Description\n\n<!-- PR description goes here.\n\nWhy the change is needed, and any details to help code reviewers.\n\n-->\n\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "chars": 2346,
    "preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
  },
  {
    "path": ".github/workflows/create-release-pr.yml",
    "chars": 3133,
    "preview": "name: Create Release PR\n\non:\n  workflow_dispatch:\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  create"
  },
  {
    "path": ".github/workflows/docker-ecs-worker-image.yml",
    "chars": 9293,
    "preview": "name: Build & publish ECS/Fargate worker image to ECR\n\non:\n  workflow_dispatch:\n    inputs:\n      SHOULD_BUILD_ARM64:\n  "
  },
  {
    "path": ".github/workflows/docker-publish-artillery.yml",
    "chars": 1874,
    "preview": "name: Publish Docker image for Artillery\n\non:\n  workflow_dispatch:\n    # this will override the latest image, so only tr"
  },
  {
    "path": ".github/workflows/examples.yml",
    "chars": 4472,
    "preview": "name: Examples\n\non:\n  push:\n    branches: [main]\n  pull_request:\n  workflow_dispatch:\n\nenv:\n  ARTILLERY_BINARY_PATH: ${{"
  },
  {
    "path": ".github/workflows/npm-publish-all-packages-canary.yml",
    "chars": 4339,
    "preview": "name: Publish packages to NPM (canary)\non:\n  push:\n    branches:\n      - main\n    paths:\n      - 'packages/artillery/**'"
  },
  {
    "path": ".github/workflows/npm-publish-all-packages.yml",
    "chars": 4514,
    "preview": "name: Publish packages to NPM\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - main\n    paths:\n      #If there are"
  },
  {
    "path": ".github/workflows/npm-publish-artillery-engine-posthog.yml",
    "chars": 680,
    "preview": "name: Publish artillery-engine-posthog to npm\non:\n  push:\n    branches:\n      - main\n    paths:\n      - packages/artille"
  },
  {
    "path": ".github/workflows/npm-publish-artillery-plugin-memory-inspector.yml",
    "chars": 694,
    "preview": "name: Publish artillery-plugin-memory-inspector to npm\non:\n  push:\n    branches:\n      - main\n    paths:\n      - package"
  },
  {
    "path": ".github/workflows/npm-publish-artillery-types.yml",
    "chars": 746,
    "preview": "name: Publish @artilleryio/types to npm\non:\n  push:\n    branches:\n      - main\n    paths:\n      - packages/types/package"
  },
  {
    "path": ".github/workflows/npm-publish-specific-package.yml",
    "chars": 2367,
    "preview": "name: Publish specific package to NPM\non:\n  workflow_dispatch:\n    inputs:\n      CHANNEL:\n        description: 'Channel "
  },
  {
    "path": ".github/workflows/run-aws-tests-on-pr.yml",
    "chars": 2109,
    "preview": "name: Run AWS tests (on PR)\n\non:\n  pull_request_target:\n    branches: [main]\n    #opened, reopened and synchronize will "
  },
  {
    "path": ".github/workflows/run-distributed-tests.yml",
    "chars": 6212,
    "preview": "name: Run distributed tests\n\non:\n  workflow_call:\n    inputs:\n      COMMIT_SHA:\n        type: string\n      ARTILLERY_VER"
  },
  {
    "path": ".github/workflows/run-tests-windows.yml",
    "chars": 1728,
    "preview": "name: Run Windows tests\n\non:\n  workflow_dispatch:\n    inputs:\n      ECR_IMAGE_VERSION:\n        description: 'ECR image v"
  },
  {
    "path": ".github/workflows/run-tests.yml",
    "chars": 2725,
    "preview": "name: Run tests\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  workflow_dispatch:\n\njobs:\n  gen"
  },
  {
    "path": ".github/workflows/s3-publish-cf-templates.yml",
    "chars": 2340,
    "preview": "name: Publish CloudFormation templates to AWS S3\n\non:\n  workflow_call:\n    inputs:\n      canary:\n        type: boolean\n "
  },
  {
    "path": ".github/workflows/scripts/get-all-packages-by-name.js",
    "chars": 335,
    "preview": "const fs = require('node:fs');\n\nconst packageNames = [];\nfs.readdirSync('packages').forEach((pkg) => {\n  if (fs.statSync"
  },
  {
    "path": ".github/workflows/scripts/get-tests-in-package-location.js",
    "chars": 1800,
    "preview": "const fs = require('node:fs');\nconst path = require('node:path');\n\n/**\n * This script is used to discover all the tests "
  },
  {
    "path": ".github/workflows/scripts/npm-command-retry.sh",
    "chars": 794,
    "preview": "#!/bin/bash\n\n# This is necessary because npm commands can fail intermittently due to network issues\n# The script retries"
  },
  {
    "path": ".github/workflows/scripts/replace-package-versions.js",
    "chars": 2570,
    "preview": "const fs = require('node:fs');\nconst path = require('node:path');\n\nconst packagesDir = '../../../packages';\nconst commit"
  },
  {
    "path": ".gitignore",
    "chars": 256,
    "preview": ".idea\n*.iml\nnpm-debug.log\ndump.rdb\nnode_modules\ncomponents\nbuild\n.tap\nresults.xml\nconfig.json\n.DS_Store\n*/.DS_Store\n*/*/"
  },
  {
    "path": ".npmignore",
    "chars": 233,
    "preview": "test/\n.idea\n*.iml\nnpm-debug.log\ndump.rdb\nnode_modules\ncomponents\nbuild\nresults.tap\nresults.xml\nconfig.json\n.DS_Store\n*/."
  },
  {
    "path": ".npmrc",
    "chars": 20,
    "preview": "ignore-scripts=true\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5219,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2690,
    "preview": "# Artillery.io Contributors Guide\n\n## Need to get in touch?\n\nAll project discussions should happen in the [issue tracker"
  },
  {
    "path": "LICENSE-BSL.txt",
    "chars": 2997,
    "preview": "Business Source License\n=======================\n\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Rese"
  },
  {
    "path": "LICENSE.txt",
    "chars": 15884,
    "preview": "Mozilla Public License, version 2.0\n\n1. Definitions\n\n1.1. “Contributor”\n\n     means each individual or legal entity that"
  },
  {
    "path": "README.md",
    "chars": 2775,
    "preview": "<div align=\"center\">\n  <a href=\"./packages/artillery#readme\"><img src=\"./packages/artillery/artillery-logo.svg\" width=\"8"
  },
  {
    "path": "SECURITY.md",
    "chars": 426,
    "preview": "# Security Policy\n\n## Supported Versions\n\nThe following versions of Artillery are currently being supported with securit"
  },
  {
    "path": "biome.json",
    "chars": 536,
    "preview": "{\n  \"$schema\": \"https://biomejs.dev/schemas/2.3.3/schema.json\",\n  \"formatter\": {\n    \"enabled\": false\n  },\n  \"linter\": {"
  },
  {
    "path": "commitlint.config.js",
    "chars": 244,
    "preview": "const config = require('@commitlint/config-conventional');\n\nconst types = config.rules['type-enum'][2].concat(['dep']);\n"
  },
  {
    "path": "examples/README.md",
    "chars": 2802,
    "preview": "<p align=\"center\">\n<img width=\"1012\" alt=\"artillery-examples\" src=\"https://user-images.githubusercontent.com/1490/139437"
  },
  {
    "path": "examples/artillery-engine-example/.gitignore",
    "chars": 230,
    "preview": ".idea\n*.iml\nnpm-debug.log\ndump.rdb\nnode_modules\ncomponents\nbuild\nresults.tap\nresults.xml\nconfig.json\n.DS_Store\n*/.DS_Sto"
  },
  {
    "path": "examples/artillery-engine-example/LICENSE",
    "chars": 16725,
    "preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
  },
  {
    "path": "examples/artillery-engine-example/README.md",
    "chars": 496,
    "preview": "# Artillery Engine Example\n\nThis repo contains the code for a simple \"hello world\" Artillery engine that shows how Artil"
  },
  {
    "path": "examples/artillery-engine-example/example.yaml",
    "chars": 358,
    "preview": "config:\n  target: \"system-under-test-endpoint\"\n  example:\n    mandatoryString: \"a configuration setting for our engine\"\n"
  },
  {
    "path": "examples/artillery-engine-example/index.js",
    "chars": 3591,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "examples/artillery-engine-example/package.json",
    "chars": 468,
    "preview": "{\n  \"name\": \"artillery-engine-example\",\n  \"version\": \"0.0.1\",\n  \"description\": \"Engine template/example for Artillery\",\n"
  },
  {
    "path": "examples/artillery-engine-example/test/index.js",
    "chars": 983,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "examples/artillery-plugin-hello-world/README.md",
    "chars": 1829,
    "preview": "# artillery-hello-world-plugin\n\nThis is a \"hello world\" plugin for Artillery which shows:\n\n- Artillery's plugin interfac"
  },
  {
    "path": "examples/artillery-plugin-hello-world/index.js",
    "chars": 2367,
    "preview": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not "
  },
  {
    "path": "examples/artillery-plugin-hello-world/package.json",
    "chars": 352,
    "preview": "{\n  \"name\": \"artillery-plugin-hello-world\",\n  \"version\": \"1.0.0\",\n  \"description\": \"This is a \\\"hello world\\\" plugin for"
  },
  {
    "path": "examples/artillery-plugin-hello-world/test.yml",
    "chars": 217,
    "preview": "config:\n  target: \"http://asciiart.artillery.io:8080\"\n  phases:\n    - arrivalRate: 1\n      duration: 10\n  plugins:\n    h"
  },
  {
    "path": "examples/automated-checks/README.md",
    "chars": 587,
    "preview": "# Using automated checks\n\nThis is an example Artillery load test that includes:\n\n1. A load configuration with 3 distinct"
  },
  {
    "path": "examples/automated-checks/load-test-with-automated-checks.yml",
    "chars": 1507,
    "preview": "# This an example Artillery load test that includes:\n# - A load configuration with 3 distinct phases that create\n#   a b"
  },
  {
    "path": "examples/browser-load-testing-playwright/README.md",
    "chars": 5944,
    "preview": "# Load testing and smoke testing with headless browsers\n\nArtillery can run Playwright scripts as performance tests. This"
  },
  {
    "path": "examples/browser-load-testing-playwright/browser-load-test.ts",
    "chars": 1481,
    "preview": "export const config = {\n  target: 'https://www.artillery.io',\n  phases: [\n    {\n      arrivalRate: 1,\n      duration: 10"
  },
  {
    "path": "examples/browser-load-testing-playwright/browser-load-test.yml",
    "chars": 282,
    "preview": "config:\n  target: \"https://www.artillery.io\"\n  phases:\n    - arrivalRate: 1\n      duration: 10\n  engines:\n    playwright"
  },
  {
    "path": "examples/browser-load-testing-playwright/browser-smoke-test.ts",
    "chars": 445,
    "preview": "import { checkPage } from './flows';\nexport const config = {\n  target: 'https://www.artillery.io',\n  phases: [\n    {\n   "
  },
  {
    "path": "examples/browser-load-testing-playwright/browser-smoke-test.yml",
    "chars": 313,
    "preview": "config:\n  target: \"https://www.artillery.io\"\n  payload:\n    - path: ./pages.csv\n      fields:\n        - \"url\"\n        - "
  },
  {
    "path": "examples/browser-load-testing-playwright/browser-test-with-steps.yml",
    "chars": 265,
    "preview": "config:\n  target: \"https://www.artillery.io\"\n  phases:\n    - arrivalRate: 1\n      duration: 10\n  engines:\n    playwright"
  },
  {
    "path": "examples/browser-load-testing-playwright/flows.js",
    "chars": 2575,
    "preview": "//\n// The code in this function was generated with\n// playwright codegen\n// https://playwright.dev/docs/codegen\n//\nasync"
  },
  {
    "path": "examples/browser-load-testing-playwright/pages.csv",
    "chars": 184,
    "preview": "https://www.artillery.io/,trademark of Artillery Software Inc\nhttps://www.artillery.io/docs,Get started\nhttps://www.arti"
  },
  {
    "path": "examples/browser-playwright-reuse-authentication/README.md",
    "chars": 2914,
    "preview": "# Reuse Authentication in Playwright tests\n\nPlaywright allows you to use `sessionStorage` to reuse authentication in you"
  },
  {
    "path": "examples/browser-playwright-reuse-authentication/flow.js",
    "chars": 2169,
    "preview": "const { expect } = require('@playwright/test');\nconst fs = require('node:fs');\n\nasync function loginUserAndSaveStorage(p"
  },
  {
    "path": "examples/browser-playwright-reuse-authentication/package.json",
    "chars": 616,
    "preview": "{\n  \"name\": \"browser-playwright-reuse-authentication\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Playwright allows you to "
  },
  {
    "path": "examples/browser-playwright-reuse-authentication/scenario.yml",
    "chars": 739,
    "preview": "config:\n  target: https://iron-session-example.vercel.app/\n  phases:\n    - arrivalRate: 1\n      duration: 10\n  engines:\n"
  },
  {
    "path": "examples/browser-playwright-reuse-authentication/storage.json",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/README.md",
    "chars": 1750,
    "preview": "# Reusing Typescript Playwright code as Artillery code\n\nThis example shows you how you can reuse a pure Playwright codeb"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/e2e/.gitignore",
    "chars": 32,
    "preview": "playwright-report/\ntest-results/"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/e2e/helpers/index.ts",
    "chars": 822,
    "preview": "import { type Page, expect } from '@playwright/test';\n\nexport const goToDocsAndSearch = async (page: Page, step) => {\n  "
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/e2e/playwright.config.ts",
    "chars": 286,
    "preview": "import { defineConfig, devices } from '@playwright/test';\n\nexport default defineConfig({\n  testDir: 'tests',\n  reporter:"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/e2e/tests/get-issues.spec.ts",
    "chars": 194,
    "preview": "import { goToDocsAndSearch } from '../helpers';\nimport { test } from '@playwright/test';\n\ntest('search and go to doc pag"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/package.json",
    "chars": 416,
    "preview": "{\n  \"name\": \"browser-playwright-reuse-typescript\",\n  \"version\": \"1.0.0\",\n  \"description\": \"This example shows you how yo"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/performance/processor.ts",
    "chars": 190,
    "preview": "import { goToDocsAndSearch } from '../e2e/helpers';\n\nexport async function playwrightTest(page, vuContext, events, test)"
  },
  {
    "path": "examples/browser-playwright-reuse-typescript/performance/search-for-ts-doc.yml",
    "chars": 246,
    "preview": "config:\n  target: \"https://www.artillery.io/\"\n  phases:\n    - duration: 1\n      arrivalRate: 1\n      name: \"Phase 1\"\n  p"
  },
  {
    "path": "examples/cicd/README.md",
    "chars": 878,
    "preview": "# Artillery CI/CD Examples\n\nThis repo contains examples of how to integrate [Artillery](https://artillery.io/) with diff"
  },
  {
    "path": "examples/cicd/aws-codebuild/README.md",
    "chars": 950,
    "preview": "# Load Testing With Artillery and AWS CodeBuild\n\nThis repo contains an example for running [Artillery](https://artillery"
  },
  {
    "path": "examples/cicd/aws-codebuild/buildspec.yml",
    "chars": 323,
    "preview": "version: 0.2\n\nphases:\n  install:\n    commands:\n      - npm install -g artillery@latest\n  pre_build:\n    commands:\n      "
  },
  {
    "path": "examples/cicd/aws-codebuild/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/cicd/azure-devops/README.md",
    "chars": 1057,
    "preview": "# Load Testing With Artillery and Azure DevOps\n\nThis repo contains an example for running [Artillery](https://artillery."
  },
  {
    "path": "examples/cicd/azure-devops/azure-pipelines.yml",
    "chars": 652,
    "preview": "trigger:\n- main\n\nschedules:\n- cron: \"0 0 * * *\"\n  displayName: 'Midnight (UTC) performance test'\n  branches:\n    include"
  },
  {
    "path": "examples/cicd/azure-devops/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/cicd/circleci/.circleci/config.yml",
    "chars": 725,
    "preview": "version: 2.1\n\njobs:\n  artillery:\n    docker:\n      - image: artilleryio/artillery:latest\n    steps:\n      - checkout\n\n  "
  },
  {
    "path": "examples/cicd/circleci/README.md",
    "chars": 929,
    "preview": "# Load Testing With Artillery and CircleCI\n\nThis repo contains an example for running [Artillery](https://artillery.io/)"
  },
  {
    "path": "examples/cicd/circleci/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/cicd/github-actions/.github/workflows/load-test.yml",
    "chars": 778,
    "preview": "name: Artillery Socket.IO Load Test\n\non:\n  push:\n    branches:\n      - main\n  schedule:\n    - cron: '0 0 * * *'\n\njobs:\n "
  },
  {
    "path": "examples/cicd/github-actions/README.md",
    "chars": 940,
    "preview": "# Load Testing With Artillery and GitHub Actions\n\nThis repo contains an example for running [Artillery](https://artiller"
  },
  {
    "path": "examples/cicd/github-actions/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/cicd/gitlab-ci-cd/.gitlab-ci.yml",
    "chars": 254,
    "preview": "artillery:\n  image:\n    name: artilleryio/artillery:latest\n    entrypoint: [\"\"]\n  script: |\n    mkdir reports\n    /home/"
  },
  {
    "path": "examples/cicd/gitlab-ci-cd/README.md",
    "chars": 815,
    "preview": "# Load Testing With Artillery and GitLab CI/CD\n\nThis repo contains an example for running [Artillery](https://artillery."
  },
  {
    "path": "examples/cicd/gitlab-ci-cd/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/cicd/jenkins/Jenkinsfile",
    "chars": 540,
    "preview": "pipeline {\n    agent {\n        docker {\n            image 'artilleryio/artillery:latest'\n            args '-u root:root "
  },
  {
    "path": "examples/cicd/jenkins/README.md",
    "chars": 847,
    "preview": "# Load Testing With Artillery and Jenkins\n\nThis repo contains an example for running [Artillery](https://artillery.io/) "
  },
  {
    "path": "examples/cicd/jenkins/tests/performance/socket-io.yml",
    "chars": 555,
    "preview": "config:\n  target: \"http://lab.artillery.io\"\n  # As an example, we'll only run a single virtual user in this\n  # test scr"
  },
  {
    "path": "examples/functional-testing-with-expect-plugin/.gitignore",
    "chars": 13,
    "preview": "node_modules\n"
  },
  {
    "path": "examples/functional-testing-with-expect-plugin/README.md",
    "chars": 1278,
    "preview": "# Functional testing on Artillery\n\nThis example shows you how to run both load and functional tests with a single Artill"
  },
  {
    "path": "examples/functional-testing-with-expect-plugin/app.js",
    "chars": 1498,
    "preview": "const express = require('express');\nconst app = express();\nconst port = 3000;\n\nconst sqlite3 = require('sqlite3').verbos"
  },
  {
    "path": "examples/functional-testing-with-expect-plugin/functional-load-tests.yml",
    "chars": 909,
    "preview": "config:\n  target: \"http://localhost:3000\"\n  environments:\n    load:\n      phases:\n        - duration: 10min\n          ar"
  },
  {
    "path": "examples/functional-testing-with-expect-plugin/package.json",
    "chars": 489,
    "preview": "{\n  \"name\": \"load-and-functional-tests\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Running load and functional tests from "
  },
  {
    "path": "examples/generating-vu-tokens/README.md",
    "chars": 1458,
    "preview": "# generating-vu-tokens\n\nA common use-case when testing stateful APIs with Artillery is to generate a token that VUs can "
  },
  {
    "path": "examples/generating-vu-tokens/auth-with-token.yml",
    "chars": 528,
    "preview": "config:\n  target: http://asciiart.artillery.io:8080\n  processor: \"./helpers.js\"\n  phases:\n    - arrivalCount: 10\n      d"
  },
  {
    "path": "examples/generating-vu-tokens/helpers.js",
    "chars": 319,
    "preview": "module.exports = {\n  generateSharedToken,\n  generateVUToken\n};\n\nfunction generateSharedToken(context, _events, done) {\n "
  },
  {
    "path": "examples/graphql-api-server/.gitignore",
    "chars": 50,
    "preview": "node_modules/\nprisma/dev.db\nprisma/dev.db-journal\n"
  },
  {
    "path": "examples/graphql-api-server/README.md",
    "chars": 1581,
    "preview": "# Load testing an GraphQL service with Artillery\n\n<img width=\"1012\" alt=\"graphql-load-testing-gh\" src=\"https://user-imag"
  },
  {
    "path": "examples/graphql-api-server/app.js",
    "chars": 1691,
    "preview": "const { ApolloServer, gql } = require('apollo-server');\nconst { PrismaClient } = require('@prisma/client');\n\nconst prism"
  },
  {
    "path": "examples/graphql-api-server/graphql.yaml",
    "chars": 1706,
    "preview": "config:\n  target: \"http://localhost:4000/\"\n  phases:\n    - duration: 60\n      arrivalRate: 25\n\nscenarios:\n  - name: \"cru"
  },
  {
    "path": "examples/graphql-api-server/package.json",
    "chars": 433,
    "preview": "{\n  \"name\": \"graphql-api-server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Load testing a GraphQL API using Artillery\",\n "
  },
  {
    "path": "examples/graphql-api-server/prisma/migrations/20211005051218_init/migration.sql",
    "chars": 301,
    "preview": "-- CreateTable\nCREATE TABLE \"User\" (\n    \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n    \"username\" TEXT NOT NULL,\n"
  },
  {
    "path": "examples/graphql-api-server/prisma/migrations/migration_lock.toml",
    "chars": 122,
    "preview": "# Please do not edit this file manually\n# It should be added in your version-control system (i.e. Git)\nprovider = \"sqlit"
  },
  {
    "path": "examples/graphql-api-server/prisma/schema.prisma",
    "chars": 245,
    "preview": "datasource db {\n  provider = \"sqlite\"\n  url      = \"file:./dev.db\"\n}\n\ngenerator client {\n  provider = \"prisma-client-js\""
  },
  {
    "path": "examples/http-file-uploads/.gitignore",
    "chars": 38,
    "preview": "node_modules\nuploads/*\n!uploads/.keep\n"
  },
  {
    "path": "examples/http-file-uploads/README.md",
    "chars": 959,
    "preview": "# HTTP file uploads\n\nThis example shows you how to perform HTTP file uploads from an Artillery test script.\n\n## Running "
  },
  {
    "path": "examples/http-file-uploads/app.js",
    "chars": 411,
    "preview": "const express = require('express');\nconst app = express();\nconst upload = require('multer')({ dest: 'uploads/', preserve"
  },
  {
    "path": "examples/http-file-uploads/file-uploads.yml",
    "chars": 834,
    "preview": "config:\n  target: \"http://localhost:3000\"\n  phases:\n    - duration: 10min\n      arrivalRate: 25\n\n  # To randomize the fi"
  },
  {
    "path": "examples/http-file-uploads/package.json",
    "chars": 453,
    "preview": "{\n  \"name\": \"file-uploads\",\n  \"version\": \"1.0.0\",\n  \"description\": \"How to load-test HTTP file uploads with Artillery Pr"
  },
  {
    "path": "examples/http-file-uploads/uploads/.keep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/http-metrics-by-endpoint/endpoint-metrics.yml",
    "chars": 275,
    "preview": "config:\n  target: http://asciiart.artillery.io:8080\n  phases:\n    - duration: 20\n      arrivalRate: 1\n  plugins:\n    met"
  },
  {
    "path": "examples/http-set-custom-header/README.md",
    "chars": 380,
    "preview": "# Set custom HTTP header via custom JS function\n\nThis example shows how an HTTP header can be set via a hook function.\n\n"
  },
  {
    "path": "examples/http-set-custom-header/helpers.js",
    "chars": 746,
    "preview": "const https = require('node:https');\n\n// Set the value of a header to a custom value, which\n// in this example comes fro"
  },
  {
    "path": "examples/http-set-custom-header/set-header.yml",
    "chars": 395,
    "preview": "config:\n  target: \"http://localhost:31337\"\n  processor: \"./helpers.js\"\n  phases:\n    - duration: 1\n      arrivalCount: 1"
  },
  {
    "path": "examples/http-socketio-server/.gitignore",
    "chars": 14,
    "preview": "node_modules/\n"
  },
  {
    "path": "examples/http-socketio-server/README.md",
    "chars": 1038,
    "preview": "# HTTP and Socket.IO server\n\n## Running the server\n\nFirst, install the server dependencies:\n\n```shell\nnpm install\n```\n\nA"
  },
  {
    "path": "examples/http-socketio-server/app.js",
    "chars": 306,
    "preview": "const http = require('node:http');\nconst app = require('./http');\nconst socketio = require('./socketio');\n\nconst { log }"
  },
  {
    "path": "examples/http-socketio-server/data/movies.json",
    "chars": 29104,
    "preview": "[\n  {\n    \"id\": 1,\n    \"releaseDate\": \"Dec 18 1985\",\n    \"director\": \"Terry Gilliam\",\n    \"title\": \"Brazil\",\n    \"genre\""
  },
  {
    "path": "examples/http-socketio-server/http-socket.yml",
    "chars": 786,
    "preview": "config:\n  target: \"http://localhost:3000\"\n  phases:\n    - duration: 30\n      arrivalRate: 5\n\nbefore:\n  flow:\n    - post:"
  },
  {
    "path": "examples/http-socketio-server/http.js",
    "chars": 886,
    "preview": "const express = require('express');\nconst cookieParser = require('cookie-parser');\n\nconst app = express();\n\nconst respon"
  },
  {
    "path": "examples/http-socketio-server/package.json",
    "chars": 389,
    "preview": "{\n  \"name\": \"test-endpoints\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Artillery.io - HTTP and Socket.IO test server\",\n  "
  },
  {
    "path": "examples/http-socketio-server/socketio.js",
    "chars": 642,
    "preview": "const socketio = require('socket.io');\n\nconst { log } = console;\n\nmodule.exports = (server) => {\n  const io = socketio(s"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/.dockerignore",
    "chars": 27,
    "preview": ".eslintrc.js\n/node_modules\n"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/.gitignore",
    "chars": 14,
    "preview": "node_modules/\n"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/Dockerfile",
    "chars": 151,
    "preview": "FROM node:16-alpine\n\nWORKDIR /app\n\nCOPY package.json package-lock.json ./\n\nRUN npm --production install\n\nCOPY . .\n\nEXPOS"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/Makefile",
    "chars": 2208,
    "preview": "THIS_FILE := $(lastword $(MAKEFILE_LIST))\n\n# VERSION defines the project version for the bundle.\n# Update this value whe"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/README.md",
    "chars": 9769,
    "preview": "# Kubernetes testing with kubectl-artillery\n\nThis example uses the [kubectl-artillery](https://github.com/artilleryio/ku"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/app.js",
    "chars": 247,
    "preview": "const http = require('node:http');\nconst app = require('./http');\n\nconst { log } = console;\n\nconst PORT = process.env.PO"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/data/movies.json",
    "chars": 29104,
    "preview": "[\n  {\n    \"id\": 1,\n    \"releaseDate\": \"Dec 18 1985\",\n    \"director\": \"Terry Gilliam\",\n    \"title\": \"Brazil\",\n    \"genre\""
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/hack/kind/kind-with-registry.sh",
    "chars": 1837,
    "preview": "#!/bin/bash\nset -o errexit\nset -o posix\n\n# full directory name of the script no matter where it is being called from\nscr"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/http.js",
    "chars": 1055,
    "preview": "const express = require('express');\nconst cookieParser = require('cookie-parser');\n\nconst app = express();\n\nconst respon"
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/k8s-deploy.yaml",
    "chars": 1061,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: movie-browser\n  labels:\n    app: movie-browser\nspec:\n  replicas: "
  },
  {
    "path": "examples/k8s-testing-with-kubectl-artillery/package.json",
    "chars": 376,
    "preview": "{\n  \"name\": \"movie-browser-test-endpoints\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Artillery.io - Movie Browser HTTP te"
  },
  {
    "path": "examples/multiple-scenario-specs/README.md",
    "chars": 2078,
    "preview": "# Separating scenarios into separate files\n\nThis example shows how an Artillery test suite can be organized into individ"
  },
  {
    "path": "examples/multiple-scenario-specs/common-config.yml",
    "chars": 105,
    "preview": "config:\n  target: http://asciizoo.artillery.io:8080\n  plugins:\n    metrics-by-endpoint: {}\n    expect: {}"
  },
  {
    "path": "examples/multiple-scenario-specs/scenarios/armadillo.yml",
    "chars": 127,
    "preview": "scenarios:\n  - name: armadillo\n    flow:\n      - get:\n          url: \"/armadillo\"\n          expect:\n            statusCo"
  },
  {
    "path": "examples/multiple-scenario-specs/scenarios/dino.yml",
    "chars": 117,
    "preview": "scenarios:\n  - name: dino\n    flow:\n      - get:\n          url: \"/dino\"\n          expect:\n            statusCode: 200"
  },
  {
    "path": "examples/multiple-scenario-specs/scenarios/pony.yml",
    "chars": 117,
    "preview": "scenarios:\n  - name: pony\n    flow:\n      - get:\n          url: \"/pony\"\n          expect:\n            statusCode: 200"
  },
  {
    "path": "examples/prometheus-grafana-dashboards/README.md",
    "chars": 1258,
    "preview": "# Prometheus Grafana Dashboards\n\nThis a collection of Grafana dashboards that visualise Artillery test result data colle"
  },
  {
    "path": "examples/prometheus-grafana-dashboards/dashboard-http-metrics-1652971310916.json",
    "chars": 13417,
    "preview": "{\n  \"__inputs\": [\n    {\n      \"name\": \"DS_PROMETHEUS\",\n      \"label\": \"Prometheus\",\n      \"description\": \"\",\n      \"type"
  },
  {
    "path": "examples/prometheus-grafana-dashboards/dashboard-vusers-metrics-1652971366368.json",
    "chars": 15883,
    "preview": "{\n  \"__inputs\": [\n    {\n      \"name\": \"DS_PROMETHEUS\",\n      \"label\": \"Prometheus\",\n      \"description\": \"\",\n      \"type"
  },
  {
    "path": "examples/refresh-auth-token/README.md",
    "chars": 2826,
    "preview": "# refresh-auth-token example\n\nThis example shows how you can refresh an authentication token used by individual VUs as t"
  },
  {
    "path": "examples/refresh-auth-token/refresh.mjs",
    "chars": 734,
    "preview": "const TOKEN_REFRESH_INTERVAL = 1000 * 5; // 5 seconds\n\nexport async function refreshTokenIfNeeded(_requestParams, vuCont"
  },
  {
    "path": "examples/refresh-auth-token/refresh.yml",
    "chars": 813,
    "preview": "config:\n  target: http://asciizoo.artillery.io:8080\n  processor: ./refresh.mjs\nscenarios:\n  - name: \"refresh_auth_token\""
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/README.md",
    "chars": 2161,
    "preview": "# Load testing an RPC service created with Twirp\n\n[Twirp](https://github.com/twitchtv/twirp) is a simple RPC framework f"
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/test/processor.mjs",
    "chars": 966,
    "preview": "import { client } from 'twirpscript';\nimport { MakeHat } from '../twirp/protos/haberdasher.pb.js';\n\nclient.baseURL = 'ht"
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/test/scenario.yml",
    "chars": 201,
    "preview": "config:\n  target: \"http://localhost:8080\"\n  phases:\n    - duration: 10\n      arrivalRate: 30\n      name: \"Phase 1\"\n  pro"
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/twirp/package.json",
    "chars": 197,
    "preview": "{\n  \"name\": \"twirp\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"start\": \"node ./"
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/twirp/protos/haberdasher.pb.js",
    "chars": 5939,
    "preview": "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n// Source: example/protos/haberdasher.proto\n\nimport * "
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/twirp/protos/haberdasher.proto",
    "chars": 451,
    "preview": "syntax = \"proto3\";\n\n// Haberdasher service makes hats for clients.\nservice Haberdasher {\n  // MakeHat produces a hat of "
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/twirp/server/haberdasher/index.js",
    "chars": 509,
    "preview": "import { createHaberdasher } from '../../../../../examples/rpc-twirp-with-custom-function/twirp/protos/haberdasher.pb.js"
  },
  {
    "path": "examples/rpc-twirp-with-custom-function/twirp/server/index.js",
    "chars": 891,
    "preview": "import { createServer } from 'node:http';\nimport { createTwirpServer } from 'twirpscript';\nimport { habderdasherHandler "
  },
  {
    "path": "examples/scenario-weights/.gitignore",
    "chars": 13,
    "preview": "node_modules\n"
  },
  {
    "path": "examples/scenario-weights/README.md",
    "chars": 1286,
    "preview": "# Setting scenario weights\n\nThis example shows how you can modify how Artillery selects a scenario for a virtual user du"
  },
  {
    "path": "examples/scenario-weights/app.js",
    "chars": 408,
    "preview": "const express = require('express');\nconst app = express();\nconst port = 3000;\n\napp.use(express.json());\n\napp.get('/commo"
  },
  {
    "path": "examples/scenario-weights/package.json",
    "chars": 367,
    "preview": "{\n  \"name\": \"scenario-weights\",\n  \"version\": \"1.0.0\",\n  \"description\": \"See how to change how often a scenario is run in"
  },
  {
    "path": "examples/scenario-weights/scenario-weights.yml",
    "chars": 1145,
    "preview": "# In Artillery, each VU will be assigned to one of the defined\n# scenarios. By default, each scenario has a weight of 1,"
  },
  {
    "path": "examples/script-overrides/README.md",
    "chars": 1227,
    "preview": "# Overriding values dynamically\n\nThis example shows how values in an Artillery script can be changed dynamically.\n\nA typ"
  },
  {
    "path": "examples/script-overrides/test.yaml",
    "chars": 467,
    "preview": "config:\n  target: http://asciiart.artillery.io:8080\n  environments:\n    # Informal short run:\n    smoke:\n      phases:\n "
  },
  {
    "path": "examples/soap-with-custom-function/README.md",
    "chars": 2222,
    "preview": "# SOAP Load Testing Example\n\nArtillery doesn't have an official SOAP engine, but it's still possible to test SOAP with i"
  },
  {
    "path": "examples/soap-with-custom-function/package.json",
    "chars": 228,
    "preview": "{\n  \"name\": \"soap-with-custom-function\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"scripts\": {\n    \"test\": \"npx arti"
  },
  {
    "path": "examples/soap-with-custom-function/processor.js",
    "chars": 1013,
    "preview": "const soap = require('soap');\n\nlet client;\nconst setupSoapClientIfNeeded = async (context) => {\n  const url = `${context"
  },
  {
    "path": "examples/soap-with-custom-function/server/MyService.wsdl",
    "chars": 1785,
    "preview": "<definitions name=\"AddNumbersService\"\n             targetNamespace=\"http://example.com/addNumbers.wsdl\"\n             xml"
  },
  {
    "path": "examples/soap-with-custom-function/server/app.js",
    "chars": 629,
    "preview": "const soap = require('soap');\nconst express = require('express');\nconst bodyParser = require('body-parser');\n\nconst serv"
  },
  {
    "path": "examples/soap-with-custom-function/server/package.json",
    "chars": 302,
    "preview": "{\n  \"name\": \"server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\""
  },
  {
    "path": "examples/soap-with-custom-function/soap.yml",
    "chars": 200,
    "preview": "config:\n  target: \"http://localhost:8000\"\n  phases:\n    - duration: 2\n      arrivalRate: 4\n      name: \"Phase 1\"\n  proce"
  },
  {
    "path": "examples/socket-io/.gitignore",
    "chars": 14,
    "preview": "node_modules/\n"
  },
  {
    "path": "examples/socket-io/README.md",
    "chars": 960,
    "preview": "# Socket.IO load testing example\n\nThis example shows you how to test a [Socket.IO](https://socket.io/) server using Arti"
  },
  {
    "path": "examples/socket-io/app.js",
    "chars": 436,
    "preview": "const io = require('socket.io')(8080, {\n  path: '/',\n  serveClient: false\n});\n\nconst personalisedNamespace = io.of('/per"
  },
  {
    "path": "examples/socket-io/package.json",
    "chars": 286,
    "preview": "{\n  \"name\": \"socket-io\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Artillery.io - Socket.IO example\",\n  \"main\": \"app.js\",\n"
  },
  {
    "path": "examples/socket-io/public/index.html",
    "chars": 476,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Artillery.io - Socket.IO example</title>\n    <link"
  },
  {
    "path": "examples/socket-io/socket-io.yml",
    "chars": 633,
    "preview": "config:\n  target: \"http://localhost:8080\"\n  phases:\n    - duration: 60\n      arrivalRate: 25\n\nscenarios:\n  - name: \"emit"
  },
  {
    "path": "examples/starter-kit/.gitignore",
    "chars": 23,
    "preview": "node_modules\nreports/**"
  },
  {
    "path": "examples/starter-kit/package.json",
    "chars": 427,
    "preview": "{\n  \"name\": \"artillery-starter-kit\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Artillery.io Starter Kit\",\n  \"scripts\": {\n "
  },
  {
    "path": "examples/starter-kit/processors/_baseProcessor.js",
    "chars": 755,
    "preview": "var faker = require('faker');\n\nmodule.exports = {\n  generateRandomData: (userContext, _events, done) => {\n    userContex"
  },
  {
    "path": "examples/starter-kit/processors/sample_task_01.js",
    "chars": 289,
    "preview": "var _faker = require('faker');\nvar base = require('./_baseProcessor');\n\nmodule.exports = {\n  doSomething: (userContext, "
  },
  {
    "path": "examples/starter-kit/processors/sample_task_02.js",
    "chars": 289,
    "preview": "var _faker = require('faker');\nvar base = require('./_baseProcessor');\n\nmodule.exports = {\n  doSomethingElse: (userConte"
  },
  {
    "path": "examples/starter-kit/reports/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/starter-kit/scenarios/sample_task_01.yaml",
    "chars": 380,
    "preview": "version: 1\r\nconfig:\r\n  target: \"https://run.mocky.io\"\r\n  phases:\r\n    - duration: 30\r\n      arrivalRate: 3\r\n      maxVus"
  },
  {
    "path": "examples/starter-kit/scenarios/sample_task_02.yaml",
    "chars": 598,
    "preview": "version: 1\r\nconfig:\r\n  target: \"https://api.somewebsite.com\"\r\n  phases:\r\n    - duration: 30\r\n      arrivalRate: 3\r\n     "
  },
  {
    "path": "examples/starter-kit/scenarios/sample_task_03.yaml",
    "chars": 2128,
    "preview": "version: 1\r\nconfig:\r\n  target: \"https://api.someservice.com\"\r\n  phases:\r\n    - name: \"Warming up the application\"\r\n     "
  },
  {
    "path": "examples/table-driven-functional-tests/README.md",
    "chars": 711,
    "preview": "# Table-driven functional tests with Artillery\n\nThis example shows how you can drive functional testing with Artillery w"
  },
  {
    "path": "examples/table-driven-functional-tests/functional-test.yml",
    "chars": 718,
    "preview": "config:\n  target: http://asciiart.artillery.io:8080\n  payload:\n    - path: ./request-response.csv\n      fields: [url, co"
  },
  {
    "path": "examples/table-driven-functional-tests/package.json",
    "chars": 363,
    "preview": "{\n  \"name\": \"table-driven-functional-tests\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts"
  },
  {
    "path": "examples/table-driven-functional-tests/request-response.csv",
    "chars": 55,
    "preview": "/,200\n/dino,200\nhttps://play.artillery.io/notapath,404\n"
  },
  {
    "path": "examples/tracetest/README.md",
    "chars": 1981,
    "preview": "# Tracetest\n\n[Tracetest.io](https://tracetest.io/) is a modern testing tool that leverages distributed tracing to run ob"
  },
  {
    "path": "examples/track-custom-metrics/.gitignore",
    "chars": 13,
    "preview": "node_modules\n"
  },
  {
    "path": "examples/track-custom-metrics/README.md",
    "chars": 804,
    "preview": "# Tracking custom metrics example\n\nThis example shows you how to track custom metrics when testing an API using Artiller"
  },
  {
    "path": "examples/track-custom-metrics/app.js",
    "chars": 537,
    "preview": "const express = require('express');\nconst serverTiming = require('server-timing');\nconst app = express();\nconst port = 3"
  },
  {
    "path": "examples/track-custom-metrics/custom-metrics.yml",
    "chars": 280,
    "preview": "config:\n  target: \"http://localhost:3000\"\n  processor: \"./metrics.js\"\n  phases:\n    - arrivalRate: 25\n      duration: 60"
  },
  {
    "path": "examples/track-custom-metrics/metrics.js",
    "chars": 813,
    "preview": "module.exports = { trackPets };\n\nfunction trackPets(_req, res, _context, events, done) {\n  // After every response, incr"
  },
  {
    "path": "examples/track-custom-metrics/package.json",
    "chars": 269,
    "preview": "{\n  \"name\": \"track-custom-metrics\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Artillery.io - Custom metrics example\",\n  \"m"
  },
  {
    "path": "examples/using-cookies/.gitignore",
    "chars": 13,
    "preview": "node_modules\n"
  },
  {
    "path": "examples/using-cookies/README.md",
    "chars": 839,
    "preview": "# Using cookies when testing HTTP services\n\nThis example shows you how Artillery works with cookies when testing HTTP se"
  },
  {
    "path": "examples/using-cookies/app.js",
    "chars": 887,
    "preview": "const express = require('express');\nconst cookieParser = require('cookie-parser');\nconst app = express();\nconst port = 3"
  },
  {
    "path": "examples/using-cookies/cookies.yml",
    "chars": 1563,
    "preview": "config:\n  target: \"http://localhost:3000\"\n  phases:\n    - duration: 10min\n      arrivalRate: 25\n  variables:\n    email:\n"
  },
  {
    "path": "examples/using-cookies/package.json",
    "chars": 372,
    "preview": "{\n  \"name\": \"using-cookies\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Using cookies when testing HTTP services with Artil"
  },
  {
    "path": "examples/using-data-from-csv/csv/urls.csv",
    "chars": 24,
    "preview": "/\n/dino\n/pony\n/armadillo"
  },
  {
    "path": "examples/using-data-from-csv/website-test.yml",
    "chars": 434,
    "preview": "config:\n  target: http://asciiart.artillery.io:8080\n  phases:\n    - arrivalCount: 300\n      duration: 5min\n  payload:\n  "
  }
]

// ... and 570 more files (download for full content)

About this extraction

This page contains the full source code of the artilleryio/artillery GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 770 files (27.7 MB), approximately 2.7M tokens, and a symbol index with 849 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!