diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..c272b36b581 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + groups: + gh-actions-packages: + patterns: + - "*" diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml index 4f4808decf6..f7c5b73b65c 100644 --- a/.github/workflows/actionlint.yml +++ b/.github/workflows/actionlint.yml @@ -5,13 +5,15 @@ on: push: branches: [master] schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup # NOTE: Ok this next bit seems unnecessary, right? The problem is that # this repo is currently incompatible with npm, at least with the @@ -24,7 +26,7 @@ jobs: npm init -y - name: actionlint id: actionlint - uses: raven-actions/actionlint@v2 + uses: raven-actions/actionlint@01fce4f43a270a612932cb1c64d40505a029f821 # v2.0.0 with: matcher: true fail-on-error: true diff --git a/.github/workflows/all-green.yml b/.github/workflows/all-green.yml index e3e38e0eb9f..c8b808ee7d6 100644 --- a/.github/workflows/all-green.yml +++ b/.github/workflows/all-green.yml @@ -5,7 +5,13 @@ on: branches: - master schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: @@ -15,7 +21,7 @@ jobs: checks: read contents: read steps: - - uses: wechuli/allcheckspassed@v1 + - uses: wechuli/allcheckspassed@2e5e8bbc775f5680ed5d02e3a22e2fc7219792ac # v1.1.0 with: retries: 20 # once per minute, some checks take up to 15 min checks_exclude: devflow.* diff --git a/.github/workflows/appsec.yml b/.github/workflows/appsec.yml index 85457177fdd..74ddfaa9cfa 100644 --- a/.github/workflows/appsec.yml +++ b/.github/workflows/appsec.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,16 +17,16 @@ jobs: macos: runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: yarn test:appsec:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest @@ -33,18 +35,18 @@ jobs: - run: yarn test:appsec:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 windows: runs-on: windows-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '18' - uses: ./.github/actions/install - run: yarn test:appsec:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 ldapjs: runs-on: ubuntu-latest @@ -62,14 +64,14 @@ jobs: LDAP_USERS: 'user01,user02' LDAP_PASSWORDS: 'password1,password2' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 postgres: runs-on: ubuntu-latest @@ -85,7 +87,7 @@ jobs: PLUGINS: pg|knex SERVICES: postgres steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest @@ -94,7 +96,7 @@ jobs: - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/20 - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 mysql: runs-on: ubuntu-latest @@ -110,42 +112,42 @@ jobs: PLUGINS: mysql|mysql2|sequelize SERVICES: mysql steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/18 - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/20 - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 express: runs-on: ubuntu-latest env: PLUGINS: express|body-parser|cookie-parser|multer steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 graphql: runs-on: ubuntu-latest env: PLUGINS: apollo-server|apollo-server-express|apollo-server-fastify|apollo-server-core steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 mongodb-core: runs-on: ubuntu-latest @@ -158,14 +160,14 @@ jobs: PLUGINS: express-mongo-sanitize|mquery SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 mongoose: runs-on: ubuntu-latest @@ -178,21 +180,21 @@ jobs: PLUGINS: mongoose SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 sourcing: runs-on: ubuntu-latest env: PLUGINS: cookie steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/18 @@ -201,7 +203,7 @@ jobs: - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 next: strategy: @@ -233,9 +235,9 @@ jobs: PLUGINS: next PACKAGE_VERSION_RANGE: ${{ matrix.range }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: yarn node-version: ${{ matrix.version }} @@ -245,26 +247,26 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: appsec-${{ github.job }}-${{ matrix.version }}-${{ matrix.range_clean }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 lodash: runs-on: ubuntu-latest env: PLUGINS: lodash steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 integration: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - run: yarn install - uses: ./.github/actions/node/oldest - run: yarn test:integration:appsec @@ -276,39 +278,39 @@ jobs: env: PLUGINS: passport-local|passport-http steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 template: runs-on: ubuntu-latest env: PLUGINS: handlebars|pug steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 node-serialize: runs-on: ubuntu-latest env: PLUGINS: node-serialize steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:appsec:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:appsec:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.github/workflows/ci-visibility-performance.yml b/.github/workflows/ci-visibility-performance.yml index 2a24980b4d5..ef3444fb02e 100644 --- a/.github/workflows/ci-visibility-performance.yml +++ b/.github/workflows/ci-visibility-performance.yml @@ -6,7 +6,9 @@ on: branches: - master schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -19,7 +21,7 @@ jobs: env: ROBOT_CI_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.ROBOT_CI_GITHUB_PERSONAL_ACCESS_TOKEN }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/18 - name: CI Visibility Performance Overhead Test run: yarn bench:e2e:ci-visibility diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 520773eac6d..910bacfda07 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,11 +34,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 with: languages: ${{ matrix.language }} config-file: .github/codeql_config.yml @@ -48,7 +48,7 @@ jobs: # queries: ./path/to/local/query, your-org/your-repo/queries@main - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8 diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index f0d329b76bd..d6503ff654b 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,11 +17,11 @@ jobs: shimmer: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest - run: yarn test:shimmer:ci - uses: ./.github/actions/node/latest - run: yarn test:shimmer:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.github/workflows/datadog-static-analysis.yml b/.github/workflows/datadog-static-analysis.yml index 18d46339dcd..929a96662de 100644 --- a/.github/workflows/datadog-static-analysis.yml +++ b/.github/workflows/datadog-static-analysis.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * jobs: static-analysis: @@ -13,7 +15,7 @@ jobs: name: Datadog Static Analyzer steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Check code meets quality and security standards id: datadog-static-analysis uses: DataDog/datadog-static-analyzer-github-action@v1 diff --git a/.github/workflows/debugger.yml b/.github/workflows/debugger.yml index ba621e3ff50..1d21fd05dfd 100644 --- a/.github/workflows/debugger.yml +++ b/.github/workflows/debugger.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,7 +17,7 @@ jobs: ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -32,4 +34,4 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: debugger - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.github/workflows/instrumentations.yml b/.github/workflows/instrumentations.yml index 177099197ea..7c3c48605ed 100644 --- a/.github/workflows/instrumentations.yml +++ b/.github/workflows/instrumentations.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -25,7 +27,7 @@ jobs: env: PLUGINS: check_require_cache steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test multer: @@ -33,7 +35,7 @@ jobs: env: PLUGINS: multer steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test passport: @@ -41,7 +43,7 @@ jobs: env: PLUGINS: passport steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test passport-http: @@ -49,7 +51,7 @@ jobs: env: PLUGINS: passport-http steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test passport-local: @@ -57,5 +59,5 @@ jobs: env: PLUGINS: passport-local steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test diff --git a/.github/workflows/lambda.yml b/.github/workflows/lambda.yml index 5545e80adc4..0e62dad7799 100644 --- a/.github/workflows/lambda.yml +++ b/.github/workflows/lambda.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,7 +17,7 @@ jobs: ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -29,4 +31,4 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: lambda - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.github/workflows/llmobs.yml b/.github/workflows/llmobs.yml index 0209f58fc93..3ac0aece3e8 100644 --- a/.github/workflows/llmobs.yml +++ b/.github/workflows/llmobs.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,7 +17,7 @@ jobs: sdk: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -29,14 +31,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: llmobs-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 openai: runs-on: ubuntu-latest env: PLUGINS: openai steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -46,7 +48,7 @@ jobs: - uses: ./.github/actions/node/latest - run: yarn test:llmobs:plugins:ci shell: bash - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 - if: always() uses: ./.github/actions/testagent/logs with: @@ -57,7 +59,7 @@ jobs: env: PLUGINS: langchain steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -67,7 +69,7 @@ jobs: - uses: ./.github/actions/node/latest - run: yarn test:llmobs:plugins:ci shell: bash - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 - if: always() uses: ./.github/actions/testagent/logs with: @@ -78,7 +80,7 @@ jobs: env: PLUGINS: aws-sdk steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -88,7 +90,7 @@ jobs: - uses: ./.github/actions/node/latest - run: yarn test:llmobs:plugins:ci shell: bash - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 - if: always() uses: ./.github/actions/testagent/logs with: diff --git a/.github/workflows/package-size.yml b/.github/workflows/package-size.yml index b6fee75c4c4..6b822a8fd7c 100644 --- a/.github/workflows/package-size.yml +++ b/.github/workflows/package-size.yml @@ -3,7 +3,9 @@ name: Package Size on: pull_request: schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,13 +17,13 @@ jobs: permissions: pull-requests: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '20' - run: yarn - name: Compute module size tree and report - uses: qard/heaviest-objects-in-the-universe@v1 + uses: qard/heaviest-objects-in-the-universe@e2af4ff3a88e5fe507bd2de1943b015ba2ddda66 # v1.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 4ee5836448e..941e9cf1086 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -54,10 +56,10 @@ jobs: SERVICES: aerospike PACKAGE_VERSION_RANGE: ${{ matrix.range }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} - run: yarn config set ignore-engines true @@ -69,7 +71,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }}-${{ matrix.node-version }}-${{ matrix.range_clean }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 amqp10: runs-on: ubuntu-latest @@ -86,7 +88,7 @@ jobs: SERVICES: qpid DD_DATA_STREAMS_ENABLED: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream amqplib: @@ -100,7 +102,7 @@ jobs: PLUGINS: amqplib SERVICES: rabbitmq steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream apollo: @@ -108,7 +110,7 @@ jobs: env: PLUGINS: apollo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream avsc: @@ -117,7 +119,7 @@ jobs: PLUGINS: avsc DD_DATA_STREAMS_ENABLED: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream aws-sdk: @@ -160,11 +162,11 @@ jobs: SERVICES: localstack localstack-legacy DD_DATA_STREAMS_ENABLED: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} - run: yarn test:plugins:ci @@ -172,14 +174,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }}-${{ matrix.node-version }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 axios: runs-on: ubuntu-latest env: PLUGINS: axios steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/upstream azure-functions: @@ -187,7 +189,7 @@ jobs: env: PLUGINS: azure-functions steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test bluebird: @@ -195,7 +197,7 @@ jobs: env: PLUGINS: bluebird steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test body-parser: @@ -203,7 +205,7 @@ jobs: env: PLUGINS: body-parser steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test bunyan: @@ -211,7 +213,7 @@ jobs: env: PLUGINS: bunyan steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream cassandra: @@ -225,7 +227,7 @@ jobs: PLUGINS: cassandra-driver SERVICES: cassandra steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test child_process: @@ -233,7 +235,7 @@ jobs: env: PLUGINS: child_process steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/oldest @@ -242,14 +244,14 @@ jobs: - run: yarn test:plugins:ci - uses: ./.github/actions/node/latest - run: yarn test:plugins:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 cookie-parser: runs-on: ubuntu-latest env: PLUGINS: cookie-parser steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test couchbase: @@ -273,23 +275,23 @@ jobs: PACKAGE_VERSION_RANGE: ${{ matrix.range }} DD_INJECT_FORCE: 'true' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} - run: yarn config set ignore-engines true - run: yarn test:plugins:ci --ignore-engines - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 connect: runs-on: ubuntu-latest env: PLUGINS: connect steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream cucumber: @@ -297,7 +299,7 @@ jobs: env: PLUGINS: cucumber steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test # TODO: fix performance issues and test more Node versions @@ -306,7 +308,7 @@ jobs: env: PLUGINS: cypress steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -315,14 +317,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 dd-trace-api: runs-on: ubuntu-latest env: PLUGINS: dd-trace-api steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test dns: @@ -330,7 +332,7 @@ jobs: env: PLUGINS: dns steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -344,7 +346,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 elasticsearch: runs-on: ubuntu-latest @@ -359,7 +361,7 @@ jobs: PLUGINS: elasticsearch SERVICES: elasticsearch steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -369,14 +371,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 express: runs-on: ubuntu-latest env: PLUGINS: express steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test express-mongo-sanitize: @@ -391,7 +393,7 @@ jobs: PACKAGE_NAMES: express-mongo-sanitize SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test fastify: @@ -399,7 +401,7 @@ jobs: env: PLUGINS: fastify steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test fetch: @@ -407,7 +409,7 @@ jobs: env: PLUGINS: fetch steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test fs: @@ -415,7 +417,7 @@ jobs: env: PLUGINS: fs steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test generic-pool: @@ -423,7 +425,7 @@ jobs: env: PLUGINS: generic-pool steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test google-cloud-pubsub: @@ -437,7 +439,7 @@ jobs: PLUGINS: google-cloud-pubsub SERVICES: gpubsub steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test graphql: @@ -445,7 +447,7 @@ jobs: env: PLUGINS: graphql steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream grpc: @@ -453,7 +455,7 @@ jobs: env: PLUGINS: grpc steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test hapi: @@ -461,7 +463,7 @@ jobs: env: PLUGINS: hapi steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test http: @@ -472,11 +474,11 @@ jobs: env: PLUGINS: http steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.node-version }} - run: yarn test:plugins:ci @@ -484,14 +486,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }}-${{ matrix.node-version }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 http2: runs-on: ubuntu-latest env: PLUGINS: http2 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -505,7 +507,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # TODO: fix performance issues and test more Node versions jest: @@ -513,7 +515,7 @@ jobs: env: PLUGINS: jest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -522,7 +524,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 kafkajs: runs-on: ubuntu-latest @@ -548,7 +550,7 @@ jobs: PLUGINS: kafkajs SERVICES: kafka steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test knex: @@ -556,7 +558,7 @@ jobs: env: PLUGINS: knex steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test koa: @@ -564,7 +566,7 @@ jobs: env: PLUGINS: koa steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream langchain: @@ -572,7 +574,7 @@ jobs: env: PLUGINS: langchain steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -582,7 +584,7 @@ jobs: - uses: ./.github/actions/node/latest - run: yarn test:plugins:ci shell: bash - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 - if: always() uses: ./.github/actions/testagent/logs with: @@ -603,7 +605,7 @@ jobs: PLUGINS: limitd-client SERVICES: limitd steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mariadb: @@ -620,7 +622,7 @@ jobs: PLUGINS: mariadb SERVICES: mariadb steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test memcached: @@ -634,7 +636,7 @@ jobs: PLUGINS: memcached SERVICES: memcached steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test microgateway-core: @@ -642,7 +644,7 @@ jobs: env: PLUGINS: microgateway-core steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mocha: @@ -650,7 +652,7 @@ jobs: env: PLUGINS: mocha steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test moleculer: @@ -658,7 +660,7 @@ jobs: env: PLUGINS: moleculer steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mongodb: @@ -673,7 +675,7 @@ jobs: PACKAGE_NAMES: mongodb SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mongodb-core: @@ -688,7 +690,7 @@ jobs: PACKAGE_NAMES: mongodb-core,express-mongo-sanitize SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mongoose: @@ -702,7 +704,7 @@ jobs: PLUGINS: mongoose SERVICES: mongo steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mysql: @@ -719,7 +721,7 @@ jobs: PLUGINS: mysql SERVICES: mysql steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test mysql2: @@ -736,7 +738,7 @@ jobs: PLUGINS: mysql2 SERVICES: mysql2 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test net: @@ -744,7 +746,7 @@ jobs: env: PLUGINS: net steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -758,7 +760,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # TODO: fix performance issues and test more Node versions next: @@ -791,7 +793,7 @@ jobs: PLUGINS: next PACKAGE_VERSION_RANGE: ${{ matrix.range }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -800,14 +802,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }}-${{ matrix.version }}-${{ matrix.range_clean }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 openai: runs-on: ubuntu-latest env: PLUGINS: openai steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test opensearch: @@ -824,7 +826,7 @@ jobs: PLUGINS: opensearch SERVICES: opensearch steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test # TODO: Install the Oracle client on the host and test Node >=16. @@ -866,8 +868,8 @@ jobs: run: | curl -LO https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: cache: yarn node-version: '16' @@ -875,14 +877,14 @@ jobs: - run: yarn config set ignore-engines true - run: yarn services --ignore-engines - run: yarn test:plugins --ignore-engines - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 paperplane: runs-on: ubuntu-latest env: PLUGINS: paperplane steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -892,7 +894,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 # TODO: re-enable upstream tests if it ever stops being flaky pino: @@ -900,7 +902,7 @@ jobs: env: PLUGINS: pino steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -913,7 +915,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 postgres: runs-on: ubuntu-latest @@ -929,7 +931,7 @@ jobs: PLUGINS: pg SERVICES: postgres steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test promise: @@ -937,7 +939,7 @@ jobs: env: PLUGINS: promise steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream promise-js: @@ -945,7 +947,7 @@ jobs: env: PLUGINS: promise-js steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test protobufjs: @@ -954,7 +956,7 @@ jobs: PLUGINS: protobufjs DD_DATA_STREAMS_ENABLED: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream q: @@ -962,7 +964,7 @@ jobs: env: PLUGINS: q steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test redis: @@ -976,7 +978,7 @@ jobs: PLUGINS: redis|ioredis # TODO: move ioredis to its own job SERVICES: redis steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test restify: @@ -984,7 +986,7 @@ jobs: env: PLUGINS: restify steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test rhea: @@ -1002,7 +1004,7 @@ jobs: SERVICES: qpid DD_DATA_STREAMS_ENABLED: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test-and-upstream router: @@ -1010,7 +1012,7 @@ jobs: env: PLUGINS: router steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test sharedb: @@ -1018,7 +1020,7 @@ jobs: env: PLUGINS: sharedb steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -1028,7 +1030,7 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 tedious: runs-on: ubuntu-latest @@ -1045,7 +1047,7 @@ jobs: PLUGINS: tedious SERVICES: mssql steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/testagent/start - uses: ./.github/actions/node/setup - uses: ./.github/actions/install @@ -1056,14 +1058,14 @@ jobs: uses: ./.github/actions/testagent/logs with: suffix: plugins-${{ github.job }} - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 undici: runs-on: ubuntu-latest env: PLUGINS: undici steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test url: @@ -1071,7 +1073,7 @@ jobs: env: PLUGINS: url steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test when: @@ -1079,7 +1081,7 @@ jobs: env: PLUGINS: when steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test winston: @@ -1087,5 +1089,5 @@ jobs: env: PLUGINS: winston steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/plugins/test diff --git a/.github/workflows/pr-labels.yml b/.github/workflows/pr-labels.yml index 3045b1241c5..9bb7034a5e4 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -8,7 +8,7 @@ jobs: label: runs-on: ubuntu-latest steps: - - uses: mheap/github-action-required-labels@v5 + - uses: mheap/github-action-required-labels@388fd6af37b34cdfe5a23b37060e763217e58b03 # v5.5.0 with: mode: exactly count: 1 diff --git a/.github/workflows/prepare-release-proposal.yml b/.github/workflows/prepare-release-proposal.yml index b21feecb4db..60ed7a2bef7 100644 --- a/.github/workflows/prepare-release-proposal.yml +++ b/.github/workflows/prepare-release-proposal.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 ref: ${{ matrix.base-branch }} @@ -36,7 +36,7 @@ jobs: - name: Configure node - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 - name: Install dependencies run: | diff --git a/.github/workflows/profiling.yml b/.github/workflows/profiling.yml index 91cabc19363..008fc3192de 100644 --- a/.github/workflows/profiling.yml +++ b/.github/workflows/profiling.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,17 +17,17 @@ jobs: macos: runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: yarn test:profiler:ci - run: yarn test:integration:profiler - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/18 @@ -37,16 +39,16 @@ jobs: - uses: ./.github/actions/node/latest - run: yarn test:profiler:ci - run: yarn test:integration:profiler - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 windows: runs-on: windows-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '18' - uses: ./.github/actions/install - run: yarn test:profiler:ci - run: yarn test:integration:profiler - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.github/workflows/project.yml b/.github/workflows/project.yml index cfd7dbc245c..56af8d3af9f 100644 --- a/.github/workflows/project.yml +++ b/.github/workflows/project.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -21,8 +23,8 @@ jobs: version: [18, 20, 22, latest] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} # Disable core dumps since some integration tests intentionally abort and core dump generation takes around 5-10s @@ -37,8 +39,8 @@ jobs: version: [12, 14.0.0, 14, 16.0.0, 16, 18.0.0, 18.1.0, 20.0.0, 22.0.0] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} - uses: ./.github/actions/install @@ -50,8 +52,8 @@ jobs: version: ['0.8', '0.10', '0.12', '4', '6', '8', '10', '12.0.0'] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} - run: node ./init @@ -70,8 +72,8 @@ jobs: DD_CIVISIBILITY_AGENTLESS_ENABLED: 1 DD_API_KEY: ${{ secrets.DD_API_KEY_CI_APP }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} - name: Install Google Chrome @@ -114,10 +116,10 @@ jobs: DD_CIVISIBILITY_AGENTLESS_ENABLED: 1 DD_API_KEY: ${{ secrets.DD_API_KEY_CI_APP }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} - run: yarn config set ignore-engines true @@ -135,10 +137,10 @@ jobs: DD_CIVISIBILITY_AGENTLESS_ENABLED: 1 DD_API_KEY: ${{ secrets.DD_API_KEY_CI_APP }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: 20 - run: yarn test:integration:vitest @@ -148,7 +150,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: yarn lint @@ -156,7 +158,7 @@ jobs: typescript: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: yarn type:test @@ -165,7 +167,7 @@ jobs: verify-yaml: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: node scripts/verify-ci-config.js diff --git a/.github/workflows/rebase-release-proposal.yml b/.github/workflows/rebase-release-proposal.yml index 3ec2f1022a8..b3f2de07c66 100644 --- a/.github/workflows/rebase-release-proposal.yml +++ b/.github/workflows/rebase-release-proposal.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 @@ -66,7 +66,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 token: ${{ secrets.GH_ACCESS_TOKEN_RELEASE }} diff --git a/.github/workflows/release-3.yml b/.github/workflows/release-3.yml index 591ec87dd51..b7b9521780f 100644 --- a/.github/workflows/release-3.yml +++ b/.github/workflows/release-3.yml @@ -19,8 +19,8 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: registry-url: 'https://registry.npmjs.org' - run: npm publish --tag latest-node14 --provenance diff --git a/.github/workflows/release-4.yml b/.github/workflows/release-4.yml index ebf5b3abf81..4c90b33e8d4 100644 --- a/.github/workflows/release-4.yml +++ b/.github/workflows/release-4.yml @@ -21,8 +21,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: registry-url: 'https://registry.npmjs.org' - run: npm publish --tag latest-node16 --provenance diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 9ec03bc5b0c..29bdad8742b 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -12,8 +12,8 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: registry-url: 'https://registry.npmjs.org' - uses: ./.github/actions/install diff --git a/.github/workflows/release-latest.yml b/.github/workflows/release-latest.yml index 5fd7115edca..45961d77a12 100644 --- a/.github/workflows/release-latest.yml +++ b/.github/workflows/release-latest.yml @@ -23,8 +23,8 @@ jobs: outputs: pkgjson: ${{ steps.pkg.outputs.json }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: registry-url: 'https://registry.npmjs.org' - run: npm publish --provenance @@ -44,8 +44,8 @@ jobs: contents: write needs: ['publish'] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 - id: pkg run: | content=`cat ./package.json | tr '\n' ' '` @@ -57,7 +57,7 @@ jobs: yarn yarn build mv out /tmp/out - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: gh-pages - name: Deploy diff --git a/.github/workflows/release-proposal.yml b/.github/workflows/release-proposal.yml index ea5e5ea2875..7361deb647a 100644 --- a/.github/workflows/release-proposal.yml +++ b/.github/workflows/release-proposal.yml @@ -8,10 +8,10 @@ jobs: check_labels: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 - run: npm i -g @bengl/branch-diff - run: | mkdir -p ~/.config/changelog-maker diff --git a/.github/workflows/serverless-integration-test.yml b/.github/workflows/serverless-integration-test.yml index 4f48e66f208..2654c305011 100644 --- a/.github/workflows/serverless-integration-test.yml +++ b/.github/workflows/serverless-integration-test.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * jobs: integration: @@ -18,18 +20,18 @@ jobs: version: [18, latest] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - - uses: actions/setup-node@v4 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: ${{ matrix.version }} - name: Authenticate to Google Cloud - uses: 'google-github-actions/auth@v2' + uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 with: service_account: ${{ secrets.SERVERLESS_GCP_SERVICE_ACCOUNT }} workload_identity_provider: ${{ secrets.SERVERLESS_GCP_WORKLOAD_IDENTITY_PROVIDER }} - name: Setup Google Cloud SDK - uses: 'google-github-actions/setup-gcloud@v2' + uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - name: Run serverless integration test run: yarn test:integration:serverless diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index 73c3da60833..949d74e5b0f 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -6,20 +6,22 @@ on: branches: [master] workflow_dispatch: {} schedule: - - cron: "0 4 * * *" + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * jobs: build-artifacts: runs-on: ubuntu-latest steps: - name: Checkout dd-trace-js - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: dd-trace-js - name: Pack dd-trace-js run: mkdir -p ./binaries && echo /binaries/$(npm pack --pack-destination ./binaries ./dd-trace-js) > ./binaries/nodejs-load-from-npm - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: system_tests_binaries path: ./binaries/**/* @@ -49,11 +51,11 @@ jobs: steps: - name: Checkout system tests - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: repository: 'DataDog/system-tests' - name: Checkout dd-trace-js - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: 'binaries/dd-trace-js' - name: Build runner @@ -76,7 +78,7 @@ jobs: if: ${{ always() }} run: tar -czvf artifact.tar.gz $(ls | grep logs) - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 if: ${{ always() }} with: name: logs_${{ matrix.weblog-variant }}-${{ matrix.scenario }} diff --git a/.github/workflows/tracing.yml b/.github/workflows/tracing.yml index b98e6b4a03c..91cd377a3f9 100644 --- a/.github/workflows/tracing.yml +++ b/.github/workflows/tracing.yml @@ -5,7 +5,9 @@ on: push: branches: [master] schedule: - - cron: '0 4 * * *' + - cron: 0 4 * * * + - cron: 20 4 * * * + - cron: 40 4 * * * concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} @@ -15,16 +17,16 @@ jobs: macos: runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - run: yarn test:trace:core:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/node/setup - uses: ./.github/actions/install - uses: ./.github/actions/node/18 @@ -33,15 +35,15 @@ jobs: - run: yarn test:trace:core:ci - uses: ./.github/actions/node/latest - run: yarn test:trace:core:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 windows: runs-on: windows-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 with: node-version: '18' - uses: ./.github/actions/install - run: yarn test:trace:core:ci - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 00000000000..123ac74a0a3 --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +ignore-engines true diff --git a/benchmark/sirun/appsec-iast/insecure-bank.js b/benchmark/sirun/appsec-iast/insecure-bank.js index c8930910396..d07ab7c762f 100644 --- a/benchmark/sirun/appsec-iast/insecure-bank.js +++ b/benchmark/sirun/appsec-iast/insecure-bank.js @@ -1,5 +1,5 @@ const http = require('http') -const app = require('/opt/insecure-bank-js/app') +const app = require('/opt/insecure-bank-js/app') // eslint-disable-line import/no-absolute-path const { port } = require('./common') diff --git a/benchmark/sirun/appsec/insecure-bank.js b/benchmark/sirun/appsec/insecure-bank.js index c8930910396..d07ab7c762f 100644 --- a/benchmark/sirun/appsec/insecure-bank.js +++ b/benchmark/sirun/appsec/insecure-bank.js @@ -1,5 +1,5 @@ const http = require('http') -const app = require('/opt/insecure-bank-js/app') +const app = require('/opt/insecure-bank-js/app') // eslint-disable-line import/no-absolute-path const { port } = require('./common') diff --git a/eslint.config.mjs b/eslint.config.mjs index 8b83488c08e..0b75ab22a47 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,19 +1,24 @@ -import mocha from 'eslint-plugin-mocha' -import n from 'eslint-plugin-n' -import stylistic from '@stylistic/eslint-plugin-js' -import globals from 'globals' import path from 'node:path' import { fileURLToPath } from 'node:url' -import js from '@eslint/js' + import { FlatCompat } from '@eslint/eslintrc' +import js from '@eslint/js' +import stylistic from '@stylistic/eslint-plugin-js' +import mocha from 'eslint-plugin-mocha' +import n from 'eslint-plugin-n' +import globals from 'globals' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all -}) +const compat = new FlatCompat({ baseDirectory: __dirname }) + +const TEST_FILES = [ + 'packages/*/test/**/*.js', + 'packages/*/test/**/*.mjs', + 'integration-tests/**/*.js', + 'integration-tests/**/*.mjs', + '**/*.spec.js' +] export default [ { @@ -31,9 +36,13 @@ export default [ 'packages/dd-trace/src/appsec/blocked_templates.js', // TODO Why is this ignored? 'packages/dd-trace/src/payload-tagging/jsonpath-plus.js' // Vendored ] - }, ...compat.extends('eslint:recommended', 'standard', 'plugin:mocha/recommended'), { + }, + { name: '@eslint/js/recommnded', ...js.configs.recommended }, + ...compat.extends('standard').map((config, i) => ({ name: config.name || `standard/${i + 1}`, ...config })), + { + name: 'dd-trace/defaults', + plugins: { - mocha, n, '@stylistic/js': stylistic }, @@ -48,47 +57,43 @@ export default [ settings: { node: { - version: '>=16.0.0' + // Used by `eslint-plugin-n` to determine the minimum version of Node.js to support. + // Normally setting this in the `package.json` engines field is enough, but when we have more than one active + // major release line at the same time, we need to specify the lowest version here to ensure backporting will + // not fail. + version: '>=18.0.0' } }, rules: { '@stylistic/js/max-len': ['error', { code: 120, tabWidth: 2 }], - '@stylistic/js/object-curly-newline': ['error', { - multiline: true, - consistent: true - }], + '@stylistic/js/object-curly-newline': ['error', { multiline: true, consistent: true }], '@stylistic/js/object-curly-spacing': ['error', 'always'], - 'import/no-absolute-path': 'off', 'import/no-extraneous-dependencies': 'error', - 'n/no-callback-literal': 'off', 'n/no-restricted-require': ['error', ['diagnostics_channel']], 'no-console': 'error', - 'no-prototype-builtins': 'off', - 'no-unused-expressions': 'off', - 'no-var': 'error', - 'prefer-const': 'error', - 'standard/no-callback-literal': 'off' + 'no-prototype-builtins': 'off', // Override (turned on by @eslint/js/recommnded) + 'no-unused-expressions': 'off', // Override (turned on by standard) + 'no-var': 'error' // Override (set to warn in standard) } }, { - files: [ - 'packages/*/test/**/*.js', - 'packages/*/test/**/*.mjs', - 'integration-tests/**/*.js', - 'integration-tests/**/*.mjs', - '**/*.spec.js' - ], + name: 'mocha/recommnded', + ...mocha.configs.flat.recommended, + files: TEST_FILES + }, + { + name: 'dd-trace/tests/all', + files: TEST_FILES, languageOptions: { globals: { - ...globals.mocha, - sinon: false, - expect: false, - proxyquire: false, - withVersions: false, - withPeerService: false, - withNamingSchema: false, - withExports: false + sinon: 'readonly', + expect: 'readonly', + proxyquire: 'readonly', + withVersions: 'readonly', + withPeerService: 'readonly', + withNamingSchema: 'readonly', + withExports: 'readonly' } }, rules: { @@ -101,11 +106,11 @@ export default [ 'mocha/no-sibling-hooks': 'off', 'mocha/no-skipped-tests': 'off', 'mocha/no-top-level-hooks': 'off', - 'n/handle-callback-err': 'off', - 'no-loss-of-precision': 'off' + 'n/handle-callback-err': 'off' } }, { + name: 'dd-trace/tests/integration', files: [ 'integration-tests/**/*.js', 'integration-tests/**/*.mjs', diff --git a/index.d.ts b/index.d.ts index 8d3fdf24ded..7b5a345ddfd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -85,10 +85,6 @@ interface Tracer extends opentracing.Tracer { * span will finish when that callback is called. * * The function doesn't accept a callback and doesn't return a promise, in * which case the span will finish at the end of the function execution. - * - * If the `orphanable` option is set to false, the function will not be traced - * unless there is already an active span or `childOf` option. Note that this - * option is deprecated and has been removed in version 4.0. */ trace (name: string, fn: (span: tracer.Span) => T): T; trace (name: string, fn: (span: tracer.Span, done: (error?: Error) => void) => T): T; @@ -659,13 +655,13 @@ declare namespace tracer { * * 'anonymous': will hash user IDs and user logins before collecting them * * 'anon': alias for 'anonymous' * * 'safe': deprecated alias for 'anonymous' - * + * * * 'identification': will collect user IDs and logins without redaction * * 'ident': alias for 'identification' * * 'extended': deprecated alias for 'identification' - * + * * * 'disabled': will not collect user IDs and logins - * + * * Unknown values will be considered as 'disabled' * @default 'identification' */ diff --git a/integration-tests/.eslintrc.json b/integration-tests/.eslintrc.json deleted file mode 100644 index b1afdd3cc9d..00000000000 --- a/integration-tests/.eslintrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": [ - "../.eslintrc.json" - ], - "env": { - "mocha": true - }, - "rules": { - "no-unused-expressions": 0, - "handle-callback-err": 0 - } -} diff --git a/integration-tests/appsec/esm-app/custom-noop-hooks.mjs b/integration-tests/appsec/esm-app/custom-noop-hooks.mjs new file mode 100644 index 00000000000..9641f541057 --- /dev/null +++ b/integration-tests/appsec/esm-app/custom-noop-hooks.mjs @@ -0,0 +1,13 @@ +'use strict' + +function dummyOperation (a) { + return a + 'should have ' + 'dummy operation to be rewritten' + ' without crashing' +} + +export async function initialize () { + dummyOperation('should have') +} + +export async function load (url, context, nextLoad) { + return nextLoad(url, context) +} diff --git a/integration-tests/appsec/esm-app/index.mjs b/integration-tests/appsec/esm-app/index.mjs new file mode 100644 index 00000000000..44dce0b46dc --- /dev/null +++ b/integration-tests/appsec/esm-app/index.mjs @@ -0,0 +1,25 @@ +'use strict' + +import childProcess from 'node:child_process' +import express from 'express' +import Module from 'node:module' +import './worker.mjs' + +const app = express() +const port = process.env.APP_PORT || 3000 + +app.get('/cmdi-vulnerable', (req, res) => { + childProcess.execSync(`ls ${req.query.args}`) + + res.end() +}) + +app.use('/more', (await import('./more.mjs')).default) + +app.listen(port, () => { + process.send({ port }) +}) + +Module.register('./custom-noop-hooks.mjs', { + parentURL: import.meta.url +}) diff --git a/integration-tests/appsec/esm-app/more.mjs b/integration-tests/appsec/esm-app/more.mjs new file mode 100644 index 00000000000..444e46b761d --- /dev/null +++ b/integration-tests/appsec/esm-app/more.mjs @@ -0,0 +1,11 @@ +import express from 'express' +import childProcess from 'node:child_process' + +const router = express.Router() +router.get('/cmdi-vulnerable', (req, res) => { + childProcess.execSync(`ls ${req.query.args}`) + + res.end() +}) + +export default router diff --git a/integration-tests/appsec/esm-app/worker-dep.mjs b/integration-tests/appsec/esm-app/worker-dep.mjs new file mode 100644 index 00000000000..5b967fff099 --- /dev/null +++ b/integration-tests/appsec/esm-app/worker-dep.mjs @@ -0,0 +1,7 @@ +'use strict' + +function dummyOperation (a) { + return a + 'dummy operation with concat in worker-dep' +} + +dummyOperation('should not crash') diff --git a/integration-tests/appsec/esm-app/worker.mjs b/integration-tests/appsec/esm-app/worker.mjs new file mode 100644 index 00000000000..7f7672c4bc7 --- /dev/null +++ b/integration-tests/appsec/esm-app/worker.mjs @@ -0,0 +1,16 @@ +import { Worker, isMainThread } from 'node:worker_threads' +import { URL } from 'node:url' +import './worker-dep.mjs' + +if (isMainThread) { + const worker = new Worker(new URL(import.meta.url)) + worker.on('error', (e) => { + throw e + }) +} else { + dummyOperation('should not crash') +} + +function dummyOperation (a) { + return a + 'dummy operation with concat' +} diff --git a/integration-tests/appsec/iast.esm.spec.js b/integration-tests/appsec/iast.esm.spec.js new file mode 100644 index 00000000000..98c654b8b56 --- /dev/null +++ b/integration-tests/appsec/iast.esm.spec.js @@ -0,0 +1,94 @@ +'use strict' + +const { createSandbox, spawnProc, FakeAgent } = require('../helpers') +const path = require('path') +const getPort = require('get-port') +const Axios = require('axios') +const { assert } = require('chai') + +describe('ESM', () => { + let axios, sandbox, cwd, appPort, appFile, agent, proc + + before(async function () { + this.timeout(process.platform === 'win32' ? 90000 : 30000) + sandbox = await createSandbox(['express']) + appPort = await getPort() + cwd = sandbox.folder + appFile = path.join(cwd, 'appsec', 'esm-app', 'index.mjs') + + axios = Axios.create({ + baseURL: `http://localhost:${appPort}` + }) + }) + + after(async function () { + await sandbox.remove() + }) + + const nodeOptionsList = [ + '--import dd-trace/initialize.mjs', + '--require dd-trace/init.js --loader dd-trace/loader-hook.mjs' + ] + + nodeOptionsList.forEach(nodeOptions => { + describe(`with NODE_OPTIONS=${nodeOptions}`, () => { + beforeEach(async () => { + agent = await new FakeAgent().start() + + proc = await spawnProc(appFile, { + cwd, + env: { + DD_TRACE_AGENT_PORT: agent.port, + APP_PORT: appPort, + DD_IAST_ENABLED: 'true', + DD_IAST_REQUEST_SAMPLING: '100', + NODE_OPTIONS: nodeOptions + } + }) + }) + + afterEach(async () => { + proc.kill() + await agent.stop() + }) + + function verifySpan (payload, verify) { + let err + for (let i = 0; i < payload.length; i++) { + const trace = payload[i] + for (let j = 0; j < trace.length; j++) { + try { + verify(trace[j]) + return + } catch (e) { + err = err || e + } + } + } + throw err + } + + it('should detect COMMAND_INJECTION vulnerability', async function () { + await axios.get('/cmdi-vulnerable?args=-la') + + await agent.assertMessageReceived(({ payload }) => { + verifySpan(payload, span => { + assert.property(span.meta, '_dd.iast.json') + assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"') + }) + }, null, 1, true) + }) + + it('should detect COMMAND_INJECTION vulnerability in imported file', async () => { + await axios.get('/more/cmdi-vulnerable?args=-la') + + await agent.assertMessageReceived(({ payload }) => { + verifySpan(payload, span => { + assert.property(span.meta, '_dd.iast.json') + assert.include(span.meta['_dd.iast.json'], '"COMMAND_INJECTION"') + }) + }, null, 1, true) + }) + }) + }) +}) diff --git a/integration-tests/cucumber/cucumber.spec.js b/integration-tests/cucumber/cucumber.spec.js index ebda279f8c6..3dfef057fd1 100644 --- a/integration-tests/cucumber/cucumber.spec.js +++ b/integration-tests/cucumber/cucumber.spec.js @@ -42,7 +42,8 @@ const { DI_DEBUG_ERROR_FILE_SUFFIX, DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX, DI_DEBUG_ERROR_LINE_SUFFIX, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') @@ -206,6 +207,7 @@ versions.forEach(version => { assert.equal(testModuleId.toString(10), testModuleEventContent.test_module_id.toString(10)) assert.equal(testSessionId.toString(10), testSessionEventContent.test_session_id.toString(10)) assert.equal(meta[TEST_SOURCE_FILE].startsWith('ci-visibility/features'), true) + assert.equal(meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'false') // Can read DD_TAGS assert.propertyVal(meta, 'test.customtag', 'customvalue') assert.propertyVal(meta, 'test.customtag2', 'customvalue2') @@ -228,7 +230,8 @@ versions.forEach(version => { env: { ...envVars, DD_TAGS: 'test.customtag:customvalue,test.customtag2:customvalue2', - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' } @@ -1996,5 +1999,35 @@ versions.forEach(version => { }) }) }) + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const eventsPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), (payloads) => { + const events = payloads.flatMap(({ payload }) => payload.events) + + const tests = events.filter(event => event.type === 'test').map(event => event.content) + tests.forEach(test => { + assert.equal(test.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'true') + }) + }) + + childProcess = exec( + runTestsCommand, + { + cwd, + env: { + ...getCiVisAgentlessConfig(receiver.port), + DD_SERVICE: 'my-service' + }, + stdio: 'pipe' + } + ) + + childProcess.on('exit', () => { + eventsPromise.then(() => { + done() + }).catch(done) + }) + }) }) }) diff --git a/integration-tests/cypress-esm-config.mjs b/integration-tests/cypress-esm-config.mjs index 92888de62e7..d5881f41af0 100644 --- a/integration-tests/cypress-esm-config.mjs +++ b/integration-tests/cypress-esm-config.mjs @@ -4,7 +4,7 @@ import cypress from 'cypress' async function runCypress () { await cypress.run({ config: { - defaultCommandTimeout: 100, + defaultCommandTimeout: 1000, e2e: { setupNodeEvents (on, config) { if (process.env.CYPRESS_ENABLE_INCOMPATIBLE_PLUGIN) { diff --git a/integration-tests/cypress.config.js b/integration-tests/cypress.config.js index 799ca06df8c..529980e298c 100644 --- a/integration-tests/cypress.config.js +++ b/integration-tests/cypress.config.js @@ -4,7 +4,7 @@ const cypressFailFast = require('cypress-fail-fast/plugin') const ddTracePlugin = require('dd-trace/ci/cypress/plugin') module.exports = { - defaultCommandTimeout: 100, + defaultCommandTimeout: 1000, e2e: { setupNodeEvents (on, config) { if (process.env.CYPRESS_ENABLE_INCOMPATIBLE_PLUGIN) { diff --git a/integration-tests/cypress/cypress.spec.js b/integration-tests/cypress/cypress.spec.js index d1fda8baa23..a2dd81a74f5 100644 --- a/integration-tests/cypress/cypress.spec.js +++ b/integration-tests/cypress/cypress.spec.js @@ -1,5 +1,6 @@ 'use strict' +const http = require('http') const { exec } = require('child_process') const getPort = require('get-port') @@ -36,7 +37,8 @@ const { TEST_CODE_OWNERS, TEST_SESSION_NAME, TEST_LEVEL_EVENT_TYPES, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants') @@ -74,7 +76,7 @@ moduleTypes.forEach(({ describe(`cypress@${version} ${type}`, function () { this.retries(2) this.timeout(60000) - let sandbox, cwd, receiver, childProcess, webAppPort + let sandbox, cwd, receiver, childProcess, webAppPort, secondWebAppServer if (type === 'commonJS') { testCommand = testCommand(version) @@ -91,6 +93,9 @@ moduleTypes.forEach(({ after(async () => { await sandbox.remove() await new Promise(resolve => webAppServer.close(resolve)) + if (secondWebAppServer) { + await new Promise(resolve => secondWebAppServer.close(resolve)) + } }) beforeEach(async function () { @@ -322,6 +327,7 @@ moduleTypes.forEach(({ assert.equal(testSessionId.toString(10), testSessionEventContent.test_session_id.toString(10)) assert.equal(meta[TEST_SOURCE_FILE].startsWith('cypress/e2e/'), true) // Can read DD_TAGS + assert.propertyVal(meta, DD_TEST_IS_USER_PROVIDED_SERVICE, 'false') assert.propertyVal(meta, 'test.customtag', 'customvalue') assert.propertyVal(meta, 'test.customtag2', 'customvalue2') assert.exists(metrics[DD_HOST_CPU_COUNT]) @@ -341,7 +347,8 @@ moduleTypes.forEach(({ ...restEnvVars, CYPRESS_BASE_URL: `http://localhost:${webAppPort}`, DD_TAGS: 'test.customtag:customvalue,test.customtag2:customvalue2', - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' } @@ -1636,5 +1643,93 @@ moduleTypes.forEach(({ }) }) }) + + // cy.origin is not available in old versions of Cypress + if (version === 'latest') { + it('does not crash for multi origin tests', async () => { + const { + NODE_OPTIONS, // NODE_OPTIONS dd-trace config does not work with cypress + ...restEnvVars + } = getCiVisEvpProxyConfig(receiver.port) + + const secondWebAppPort = await getPort() + + secondWebAppServer = http.createServer((req, res) => { + res.setHeader('Content-Type', 'text/html') + res.writeHead(200) + res.end(` + + +
Hella World
+ + `) + }) + + secondWebAppServer.listen(secondWebAppPort) + + const specToRun = 'cypress/e2e/multi-origin.js' + + childProcess = exec( + version === 'latest' ? testCommand : `${testCommand} --spec ${specToRun}`, + { + cwd, + env: { + ...restEnvVars, + CYPRESS_BASE_URL: `http://localhost:${webAppPort}`, + CYPRESS_BASE_URL_SECOND: `http://localhost:${secondWebAppPort}`, + SPEC_PATTERN: specToRun + }, + stdio: 'pipe' + } + ) + + await receiver + .gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), payloads => { + const events = payloads.flatMap(({ payload }) => payload.events) + assert.equal(events.length, 4) + + const test = events.find(event => event.type === 'test').content + assert.equal(test.resource, 'cypress/e2e/multi-origin.js.tests multiple origins') + assert.equal(test.meta[TEST_STATUS], 'pass') + }) + }) + } + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const receiverPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), payloads => { + const events = payloads.flatMap(({ payload }) => payload.events) + + const testEvents = events.filter(event => event.type === 'test') + + testEvents.forEach(({ content: { meta } }) => { + assert.propertyVal(meta, DD_TEST_IS_USER_PROVIDED_SERVICE, 'true') + }) + }, 25000) + + const { + NODE_OPTIONS, // NODE_OPTIONS dd-trace config does not work with cypress + ...restEnvVars + } = getCiVisEvpProxyConfig(receiver.port) + + childProcess = exec( + testCommand, + { + cwd, + env: { + ...restEnvVars, + CYPRESS_BASE_URL: `http://localhost:${webAppPort}`, + DD_SERVICE: 'my-service' + }, + stdio: 'pipe' + } + ) + + childProcess.on('exit', () => { + receiverPromise.then(() => { + done() + }).catch(done) + }) + }) }) }) diff --git a/integration-tests/cypress/e2e/multi-origin.js b/integration-tests/cypress/e2e/multi-origin.js new file mode 100644 index 00000000000..d59ed2b70a1 --- /dev/null +++ b/integration-tests/cypress/e2e/multi-origin.js @@ -0,0 +1,14 @@ +/* eslint-disable */ + +it('tests multiple origins', () => { + // Visit first site + cy.visit('/'); + cy.get('.hello-world') + .should('have.text', 'Hello World') + + // Visit second site + cy.origin(Cypress.env('BASE_URL_SECOND'), () => { + cy.visit('/') + cy.get('.hella-world').should('have.text', 'Hella World') + }); +}); diff --git a/integration-tests/jest/jest.spec.js b/integration-tests/jest/jest.spec.js index 784ea393e5a..35413ea7e60 100644 --- a/integration-tests/jest/jest.spec.js +++ b/integration-tests/jest/jest.spec.js @@ -39,7 +39,8 @@ const { DI_DEBUG_ERROR_PREFIX, DI_DEBUG_ERROR_FILE_SUFFIX, DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX, - DI_DEBUG_ERROR_LINE_SUFFIX + DI_DEBUG_ERROR_LINE_SUFFIX, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants') @@ -179,6 +180,7 @@ describe('jest CommonJS', () => { tests.forEach(testEvent => { assert.equal(testEvent.meta[TEST_SOURCE_FILE].startsWith('ci-visibility/test/ci-visibility-test'), true) assert.exists(testEvent.metrics[TEST_SOURCE_START]) + assert.equal(testEvent.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'false') // Can read DD_TAGS assert.propertyVal(testEvent.meta, 'test.customtag', 'customvalue') assert.propertyVal(testEvent.meta, 'test.customtag2', 'customvalue2') @@ -199,7 +201,8 @@ describe('jest CommonJS', () => { env: { ...envVars, DD_TAGS: 'test.customtag:customvalue,test.customtag2:customvalue2', - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' }) @@ -2905,4 +2908,34 @@ describe('jest CommonJS', () => { }) }) }) + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const eventsPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), (payloads) => { + const events = payloads.flatMap(({ payload }) => payload.events) + const tests = events.filter(event => event.type === 'test').map(event => event.content) + tests.forEach(test => { + assert.equal(test.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'true') + }) + }) + + childProcess = exec( + runTestsWithCoverageCommand, + { + cwd, + env: { + ...getCiVisEvpProxyConfig(receiver.port), + TESTS_TO_RUN: 'test/ci-visibility-test', + DD_SERVICE: 'my-service' + }, + stdio: 'inherit' + } + ) + + childProcess.on('exit', () => { + eventsPromise.then(() => { + done() + }).catch(done) + }) + }) }) diff --git a/integration-tests/mocha/mocha.spec.js b/integration-tests/mocha/mocha.spec.js index 21e7670d077..86d9491b3f0 100644 --- a/integration-tests/mocha/mocha.spec.js +++ b/integration-tests/mocha/mocha.spec.js @@ -41,7 +41,8 @@ const { DI_DEBUG_ERROR_FILE_SUFFIX, DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX, DI_DEBUG_ERROR_LINE_SUFFIX, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants') @@ -174,6 +175,7 @@ describe('mocha CommonJS', function () { tests.forEach(testEvent => { assert.equal(testEvent.meta[TEST_SOURCE_FILE].startsWith('ci-visibility/test/ci-visibility-test'), true) assert.exists(testEvent.metrics[TEST_SOURCE_START]) + assert.equal(testEvent.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'false') // Can read DD_TAGS assert.propertyVal(testEvent.meta, 'test.customtag', 'customvalue') assert.propertyVal(testEvent.meta, 'test.customtag2', 'customvalue2') @@ -194,7 +196,8 @@ describe('mocha CommonJS', function () { env: { ...envVars, DD_TAGS: 'test.customtag:customvalue,test.customtag2:customvalue2', - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' }) @@ -2520,4 +2523,38 @@ describe('mocha CommonJS', function () { }) }) }) + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const eventsPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), (payloads) => { + const events = payloads.flatMap(({ payload }) => payload.events) + + const tests = events.filter(event => event.type === 'test').map(event => event.content) + tests.forEach(test => { + assert.equal(test.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'true') + }) + }) + + childProcess = exec( + runTestsWithCoverageCommand, + { + cwd, + env: { + ...getCiVisAgentlessConfig(receiver.port), + TESTS_TO_RUN: JSON.stringify([ + './test/ci-visibility-test.js', + './test/ci-visibility-test-2.js' + ]), + DD_SERVICE: 'my-service' + }, + stdio: 'inherit' + } + ) + + childProcess.on('exit', () => { + eventsPromise.then(() => { + done() + }).catch(done) + }) + }) }) diff --git a/integration-tests/playwright/playwright.spec.js b/integration-tests/playwright/playwright.spec.js index 691a09b4d13..03ff3accd0d 100644 --- a/integration-tests/playwright/playwright.spec.js +++ b/integration-tests/playwright/playwright.spec.js @@ -25,7 +25,8 @@ const { TEST_CODE_OWNERS, TEST_SESSION_NAME, TEST_LEVEL_EVENT_TYPES, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants') @@ -147,6 +148,7 @@ versions.forEach((version) => { assert.equal( testEvent.content.meta[TEST_SOURCE_FILE].startsWith('ci-visibility/playwright-tests/'), true ) + assert.equal(testEvent.content.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'false') // Can read DD_TAGS assert.propertyVal(testEvent.content.meta, 'test.customtag', 'customvalue') assert.propertyVal(testEvent.content.meta, 'test.customtag2', 'customvalue2') @@ -176,7 +178,8 @@ versions.forEach((version) => { ...envVars, PW_BASE_URL: `http://localhost:${webAppPort}`, DD_TAGS: 'test.customtag:customvalue,test.customtag2:customvalue2', - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' } @@ -848,5 +851,34 @@ versions.forEach((version) => { }) }) } + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const receiverPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url === '/api/v2/citestcycle', (payloads) => { + const events = payloads.flatMap(({ payload }) => payload.events) + + const tests = events.filter(event => event.type === 'test').map(event => event.content) + tests.forEach(test => { + assert.equal(test.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'true') + }) + }) + + childProcess = exec( + './node_modules/.bin/playwright test -c playwright.config.js', + { + cwd, + env: { + ...getCiVisAgentlessConfig(receiver.port), + PW_BASE_URL: `http://localhost:${webAppPort}`, + DD_SERVICE: 'my-service' + }, + stdio: 'pipe' + } + ) + + childProcess.on('exit', () => { + receiverPromise.then(() => done()).catch(done) + }) + }) }) }) diff --git a/integration-tests/vitest/vitest.spec.js b/integration-tests/vitest/vitest.spec.js index eb53b395202..56f060ce509 100644 --- a/integration-tests/vitest/vitest.spec.js +++ b/integration-tests/vitest/vitest.spec.js @@ -30,7 +30,8 @@ const { DI_DEBUG_ERROR_FILE_SUFFIX, DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX, DI_DEBUG_ERROR_LINE_SUFFIX, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../packages/dd-trace/src/plugins/util/test') const { DD_HOST_CPU_COUNT } = require('../../packages/dd-trace/src/plugins/util/env') @@ -160,6 +161,7 @@ versions.forEach((version) => { testEvents.forEach(test => { assert.equal(test.content.meta[TEST_COMMAND], 'vitest run') assert.exists(test.content.metrics[DD_HOST_CPU_COUNT]) + assert.equal(test.content.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'false') }) testSuiteEvents.forEach(testSuite => { @@ -180,7 +182,8 @@ versions.forEach((version) => { env: { ...getCiVisAgentlessConfig(receiver.port), NODE_OPTIONS: '--import dd-trace/register.js -r dd-trace/ci/init', // ESM requires more flags - DD_TEST_SESSION_NAME: 'my-test-session' + DD_TEST_SESSION_NAME: 'my-test-session', + DD_SERVICE: undefined }, stdio: 'pipe' } @@ -1298,5 +1301,38 @@ versions.forEach((version) => { }) }) }) + + it('sets _dd.test.is_user_provided_service to true if DD_SERVICE is used', (done) => { + const eventsPromise = receiver + .gatherPayloadsMaxTimeout(({ url }) => url === '/api/v2/citestcycle', payloads => { + const events = payloads.flatMap(({ payload }) => payload.events) + + const tests = events.filter(event => event.type === 'test').map(test => test.content) + tests.forEach(test => { + assert.equal(test.meta[DD_TEST_IS_USER_PROVIDED_SERVICE], 'true') + }) + }) + + childProcess = exec( + './node_modules/.bin/vitest run', + { + cwd, + env: { + ...getCiVisAgentlessConfig(receiver.port), + TEST_DIR: 'ci-visibility/vitest-tests/early-flake-detection*', + NODE_OPTIONS: '--import dd-trace/register.js -r dd-trace/ci/init', + DD_SERVICE: 'my-service' + }, + stdio: 'pipe' + } + ) + + childProcess.on('exit', (exitCode) => { + eventsPromise.then(() => { + assert.equal(exitCode, 1) + done() + }).catch(done) + }) + }) }) }) diff --git a/package.json b/package.json index 13d4315b4fa..ae0233bd096 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dd-trace", - "version": "5.35.0", + "version": "5.36.0", "description": "Datadog APM tracing client for JavaScript", "main": "index.js", "typings": "index.d.ts", @@ -13,7 +13,7 @@ "type:doc": "cd docs && yarn && yarn build", "type:test": "cd docs && yarn && yarn test", "lint": "node scripts/check_licenses.js && eslint . && yarn audit", - "lint-fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit", + "lint:fix": "node scripts/check_licenses.js && eslint . --fix && yarn audit", "release:proposal": "node scripts/release/proposal", "services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services", "test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'", @@ -83,7 +83,7 @@ "dependencies": { "@datadog/libdatadog": "^0.4.0", "@datadog/native-appsec": "8.4.0", - "@datadog/native-iast-rewriter": "2.6.1", + "@datadog/native-iast-rewriter": "2.8.0", "@datadog/native-iast-taint-tracking": "3.2.0", "@datadog/native-metrics": "^3.1.0", "@datadog/pprof": "5.5.1", @@ -117,7 +117,7 @@ "devDependencies": { "@apollo/server": "^4.11.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "^9.11.1", + "@eslint/js": "^8.57.1", "@msgpack/msgpack": "^3.0.0-beta3", "@stylistic/eslint-plugin-js": "^2.8.0", "@types/node": "^16.0.0", diff --git a/packages/.eslintrc.json b/packages/.eslintrc.json deleted file mode 100644 index 9ae4e0ef309..00000000000 --- a/packages/.eslintrc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": [ - "../.eslintrc.json" - ], - "env": { - "mocha": true - }, - "globals": { - "expect": true, - "sinon": true, - "proxyquire": true, - "withNamingSchema": true, - "withVersions": true, - "withExports": true, - "withPeerService": true - }, - "rules": { - "no-unused-expressions": 0, - "handle-callback-err": 0 - } -} diff --git a/packages/datadog-core/index.js b/packages/datadog-core/index.js index 617ba328f92..c403bc990bd 100644 --- a/packages/datadog-core/index.js +++ b/packages/datadog-core/index.js @@ -1,5 +1,5 @@ 'use strict' -const storage = require('./src/storage') +const { storage } = require('./src/storage') module.exports = { storage } diff --git a/packages/datadog-core/src/storage.js b/packages/datadog-core/src/storage.js index fb5d889e555..9ece966a6e5 100644 --- a/packages/datadog-core/src/storage.js +++ b/packages/datadog-core/src/storage.js @@ -2,66 +2,111 @@ const { AsyncLocalStorage } = require('async_hooks') -class DatadogStorage { - constructor () { - this._storage = new AsyncLocalStorage() - } - - disable () { - this._storage.disable() - } - +/** + * This is exactly the same as AsyncLocalStorage, with the exception that it + * uses a WeakMap to store the store object. This is because ALS stores the + * store object as a property of the resource object, which causes all sorts + * of problems with logging and memory. We substitute the `store` object with + * a "handle" object, which is used as a key in a WeakMap, where the values + * are the real store objects. + * + * @template T + */ +class DatadogStorage extends AsyncLocalStorage { + /** + * + * @param store {DatadogStorage} + */ enterWith (store) { const handle = {} stores.set(handle, store) - this._storage.enterWith(handle) - } - - exit (callback, ...args) { - this._storage.exit(callback, ...args) + super.enterWith(handle) } - // TODO: Refactor the Scope class to use a span-only store and remove this. + /** + * This is method is a passthrough to the real `getStore()`, so that, when we + * need it, we can use the handle rather than our mapped store. + * + * It's only here because stores are currently used for a bunch of things, + * and we don't want to hold on to all of them in spans + * (see opentracing/span.js). Using a namespaced storage for spans would + * solve this. + * + * TODO: Refactor the Scope class to use a span-only store and remove this. + * + * @returns {{}} + */ getHandle () { - return this._storage.getStore() + return super.getStore() } + /** + * Here, we replicate the behavior of the original `getStore()` method by + * passing in the handle, which we retrieve by calling it on super. Handles + * retrieved through `getHandle()` can also be passed in to be used as the + * key. This is useful if you've stashed a handle somewhere and want to + * retrieve the store with it. + * + * @param handle {{}} + * @returns {T | undefined} + */ getStore (handle) { if (!handle) { - handle = this._storage.getStore() + handle = super.getStore() } return stores.get(handle) } + /** + * Here, we replicate the behavior of the original `run()` method. We ensure + * that our `enterWith()` is called internally, so that the handle to the + * store is set. As an optimization, we use super for getStore and enterWith + * when dealing with the parent store, so that we don't have to access the + * WeakMap. + * @template R + * @template TArgs extends any[] + * @param store {DatadogStorage} + * @param fn {() => R} + * @param args {TArgs} + * @returns {void} + */ run (store, fn, ...args) { - const prior = this._storage.getStore() + const prior = super.getStore() this.enterWith(store) try { return Reflect.apply(fn, null, args) } finally { - this._storage.enterWith(prior) + super.enterWith(prior) } } } +/** + * This is the map from handles to real stores, used in the class above. + * @template T + * @type {WeakMap} + */ +const stores = new WeakMap() + +/** + * For convenience, we use the `storage` function as a registry of namespaces + * corresponding to DatadogStorage instances. This lets us have separate + * storages for separate purposes. + * @type {Map} + */ const storages = Object.create(null) -const legacyStorage = new DatadogStorage() -const storage = function (namespace) { +/** + * + * @param namespace {string} the namespace to use + * @returns {DatadogStorage} + */ +function storage (namespace) { if (!storages[namespace]) { storages[namespace] = new DatadogStorage() } return storages[namespace] } -storage.disable = legacyStorage.disable.bind(legacyStorage) -storage.enterWith = legacyStorage.enterWith.bind(legacyStorage) -storage.exit = legacyStorage.exit.bind(legacyStorage) -storage.getHandle = legacyStorage.getHandle.bind(legacyStorage) -storage.getStore = legacyStorage.getStore.bind(legacyStorage) -storage.run = legacyStorage.run.bind(legacyStorage) - -const stores = new WeakMap() - -module.exports = storage +module.exports = { storage } diff --git a/packages/datadog-core/test/storage.spec.js b/packages/datadog-core/test/storage.spec.js index e5bca4e7d5d..f2145f8c04f 100644 --- a/packages/datadog-core/test/storage.spec.js +++ b/packages/datadog-core/test/storage.spec.js @@ -16,17 +16,17 @@ describe('storage', () => { }) afterEach(() => { - testStorage.enterWith(undefined) + testStorage('legacy').enterWith(undefined) testStorage2.enterWith(undefined) }) it('should enter a store', done => { const store = 'foo' - testStorage.enterWith(store) + testStorage('legacy').enterWith(store) setImmediate(() => { - expect(testStorage.getStore()).to.equal(store) + expect(testStorage('legacy').getStore()).to.equal(store) done() }) }) @@ -35,11 +35,11 @@ describe('storage', () => { const store = 'foo' const store2 = 'bar' - testStorage.enterWith(store) + testStorage('legacy').enterWith(store) testStorage2.enterWith(store2) setImmediate(() => { - expect(testStorage.getStore()).to.equal(store) + expect(testStorage('legacy').getStore()).to.equal(store) expect(testStorage2.getStore()).to.equal(store2) done() }) @@ -52,7 +52,7 @@ describe('storage', () => { it('should not have its store referenced by the underlying async resource', () => { const resource = executionAsyncResource() - testStorage.enterWith({ internal: 'internal' }) + testStorage('legacy').enterWith({ internal: 'internal' }) for (const sym of Object.getOwnPropertySymbols(resource)) { if (sym.toString() === 'Symbol(kResourceStore)' && resource[sym]) { diff --git a/packages/datadog-instrumentations/src/jest.js b/packages/datadog-instrumentations/src/jest.js index bc01fecc150..d4f01cf7e5d 100644 --- a/packages/datadog-instrumentations/src/jest.js +++ b/packages/datadog-instrumentations/src/jest.js @@ -313,10 +313,11 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) { const asyncResource = asyncResources.get(event.test) if (status === 'fail') { + const shouldSetProbe = this.isDiEnabled && willBeRetried && numTestExecutions === 1 asyncResource.runInAsyncScope(() => { testErrCh.publish({ error: formatJestError(event.test.errors[0]), - shouldSetProbe: this.isDiEnabled && willBeRetried && numTestExecutions === 1, + shouldSetProbe, promises }) }) @@ -336,18 +337,13 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) { testFinishCh.publish({ status, testStartLine: getTestLineStart(event.test.asyncError, this.testSuite), - promises, - shouldRemoveProbe: this.isDiEnabled && !willBeRetried + promises }) }) if (promises.isProbeReady) { await promises.isProbeReady } - - if (promises.isProbeRemoved) { - await promises.isProbeRemoved - } } if (event.name === 'test_skip' || event.name === 'test_todo') { const asyncResource = new AsyncResource('bound-anonymous-fn') diff --git a/packages/datadog-instrumentations/test/body-parser.spec.js b/packages/datadog-instrumentations/test/body-parser.spec.js index 482ba5e772d..5e057f7ea8c 100644 --- a/packages/datadog-instrumentations/test/body-parser.spec.js +++ b/packages/datadog-instrumentations/test/body-parser.spec.js @@ -77,7 +77,7 @@ withVersions('body-parser', 'body-parser', version => { let payload function handler (data) { - store = storage.getStore() + store = storage('legacy').getStore() payload = data } bodyParserReadCh.subscribe(handler) diff --git a/packages/datadog-instrumentations/test/generic-pool.spec.js b/packages/datadog-instrumentations/test/generic-pool.spec.js index eee62a991ea..9276bf7ae0f 100644 --- a/packages/datadog-instrumentations/test/generic-pool.spec.js +++ b/packages/datadog-instrumentations/test/generic-pool.spec.js @@ -27,11 +27,11 @@ describe('Instrumentation', () => { it('should run the acquire() callback in context where acquire() was called', done => { const store = 'store' - storage.run(store, () => { + storage('legacy').run(store, () => { // eslint-disable-next-line n/handle-callback-err pool.acquire((err, resource) => { pool.release(resource) - expect(storage.getStore()).to.equal(store) + expect(storage('legacy').getStore()).to.equal(store) done() }) }) @@ -56,20 +56,20 @@ describe('Instrumentation', () => { const store = 'store' const store2 = 'store2' - storage.run(store, () => { + storage('legacy').run(store, () => { pool.acquire() .then(resource => { pool.release(resource) - expect(storage.getStore()).to.equal(store) + expect(storage('legacy').getStore()).to.equal(store) }) .catch(done) }) - storage.run(store2, () => { + storage('legacy').run(store2, () => { pool.acquire() .then(resource => { pool.release(resource) - expect(storage.getStore()).to.equal(store2) + expect(storage('legacy').getStore()).to.equal(store2) done() }) .catch(done) diff --git a/packages/datadog-instrumentations/test/helpers/instrument.spec.js b/packages/datadog-instrumentations/test/helpers/instrument.spec.js index d433c17510a..5cee991cc54 100644 --- a/packages/datadog-instrumentations/test/helpers/instrument.spec.js +++ b/packages/datadog-instrumentations/test/helpers/instrument.spec.js @@ -10,12 +10,12 @@ const { AsyncResource } = require('../../src/helpers/instrument') describe('helpers/instrument', () => { describe('AsyncResource', () => { it('should bind statically', () => { - storage.run('test1', () => { + storage('legacy').run('test1', () => { const tested = AsyncResource.bind(() => { - expect(storage.getStore()).to.equal('test1') + expect(storage('legacy').getStore()).to.equal('test1') }) - storage.run('test2', () => { + storage('legacy').run('test2', () => { tested() }) }) @@ -34,12 +34,12 @@ describe('helpers/instrument', () => { }) it('should bind a specific instance', () => { - storage.run('test1', () => { + storage('legacy').run('test1', () => { const asyncResource = new AsyncResource('test') - storage.run('test2', () => { + storage('legacy').run('test2', () => { const tested = asyncResource.bind((a, b, c) => { - expect(storage.getStore()).to.equal('test1') + expect(storage('legacy').getStore()).to.equal('test1') expect(test.asyncResource).to.equal(asyncResource) expect(test).to.have.length(3) }) diff --git a/packages/datadog-instrumentations/test/helpers/promise.js b/packages/datadog-instrumentations/test/helpers/promise.js index 3f2d328c055..043b7805f02 100644 --- a/packages/datadog-instrumentations/test/helpers/promise.js +++ b/packages/datadog-instrumentations/test/helpers/promise.js @@ -32,18 +32,18 @@ module.exports = (name, factory, versionRange) => { let promise = new Promise((resolve, reject) => { setImmediate(() => { - storage.run('promise', () => { + storage('legacy').run('promise', () => { resolve() }) }) }) - storage.run(store, () => { + storage('legacy').run(store, () => { for (let i = 0; i < promise.then.length; i++) { const args = new Array(i + 1) args[i] = () => { - expect(storage.getStore()).to.equal(store) + expect(storage('legacy').getStore()).to.equal(store) } promise = promise.then.apply(promise, args) @@ -54,23 +54,23 @@ module.exports = (name, factory, versionRange) => { }) it('should run the catch() callback in the context where catch() was called', () => { - const store = storage.getStore() + const store = storage('legacy').getStore() let promise = new Promise((resolve, reject) => { setImmediate(() => { - storage.run('promise', () => { + storage('legacy').run('promise', () => { reject(new Error()) }) }) }) - storage.run(store, () => { + storage('legacy').run(store, () => { promise = promise .catch(err => { throw err }) .catch(() => { - expect(storage.getStore()).to.equal(store) + expect(storage('legacy').getStore()).to.equal(store) }) }) @@ -78,7 +78,7 @@ module.exports = (name, factory, versionRange) => { }) it('should allow to run without a scope if not available when calling then()', () => { - storage.run(null, () => { + storage('legacy').run(null, () => { const promise = new Promise((resolve, reject) => { setImmediate(() => { resolve() @@ -87,7 +87,7 @@ module.exports = (name, factory, versionRange) => { return promise .then(() => { - expect(storage.getStore()).to.be.null + expect(storage('legacy').getStore()).to.be.null }) }) }) diff --git a/packages/datadog-instrumentations/test/knex.spec.js b/packages/datadog-instrumentations/test/knex.spec.js index 3c9e9c6bd29..329536fb9b7 100644 --- a/packages/datadog-instrumentations/test/knex.spec.js +++ b/packages/datadog-instrumentations/test/knex.spec.js @@ -24,10 +24,10 @@ describe('Instrumentation', () => { afterEach(() => client.destroy()) it('should propagate context', () => - storage.run(store, () => + storage('legacy').run(store, () => client.raw('PRAGMA user_version') .finally(() => { - expect(storage.getStore()).to.equal(store) + expect(storage('legacy').getStore()).to.equal(store) }) .catch(() => {}) ) diff --git a/packages/datadog-instrumentations/test/multer.spec.js b/packages/datadog-instrumentations/test/multer.spec.js index f7edcee6cd3..8bd01b5af49 100644 --- a/packages/datadog-instrumentations/test/multer.spec.js +++ b/packages/datadog-instrumentations/test/multer.spec.js @@ -86,7 +86,7 @@ withVersions('multer', 'multer', version => { let payload function handler (data) { - store = storage.getStore() + store = storage('legacy').getStore() payload = data } multerReadCh.subscribe(handler) diff --git a/packages/datadog-instrumentations/test/passport-http.spec.js b/packages/datadog-instrumentations/test/passport-http.spec.js index 5cb0282ec2f..4d647c09fce 100644 --- a/packages/datadog-instrumentations/test/passport-http.spec.js +++ b/packages/datadog-instrumentations/test/passport-http.spec.js @@ -174,7 +174,7 @@ withVersions('passport-http', 'passport-http', version => { it('should block when subscriber aborts', async () => { subscriberStub = sinon.spy(({ abortController }) => { - storage.getStore().req.res.writeHead(403).end('Blocked') + storage('legacy').getStore().req.res.writeHead(403).end('Blocked') abortController.abort() }) diff --git a/packages/datadog-instrumentations/test/passport-local.spec.js b/packages/datadog-instrumentations/test/passport-local.spec.js index bcfc2e56dc9..7b5795fef0f 100644 --- a/packages/datadog-instrumentations/test/passport-local.spec.js +++ b/packages/datadog-instrumentations/test/passport-local.spec.js @@ -154,7 +154,7 @@ withVersions('passport-local', 'passport-local', version => { it('should block when subscriber aborts', async () => { subscriberStub = sinon.spy(({ abortController }) => { - storage.getStore().req.res.writeHead(403).end('Blocked') + storage('legacy').getStore().req.res.writeHead(403).end('Blocked') abortController.abort() }) diff --git a/packages/datadog-instrumentations/test/passport.spec.js b/packages/datadog-instrumentations/test/passport.spec.js index 1d5b63c7e3d..5d39a75f01b 100644 --- a/packages/datadog-instrumentations/test/passport.spec.js +++ b/packages/datadog-instrumentations/test/passport.spec.js @@ -145,7 +145,7 @@ withVersions('passport', 'passport', version => { const cookie = login.headers['set-cookie'][0] subscriberStub.callsFake(({ abortController }) => { - const res = storage.getStore().req.res + const res = storage('legacy').getStore().req.res res.writeHead(403) res.constructor.prototype.end.call(res, 'Blocked') abortController.abort() diff --git a/packages/datadog-plugin-aerospike/src/index.js b/packages/datadog-plugin-aerospike/src/index.js index fb4bd6a6d0a..2f8407bda11 100644 --- a/packages/datadog-plugin-aerospike/src/index.js +++ b/packages/datadog-plugin-aerospike/src/index.js @@ -20,7 +20,7 @@ class AerospikePlugin extends DatabasePlugin { bindStart (ctx) { const { commandName, commandArgs } = ctx const resourceName = commandName.slice(0, commandName.indexOf('Command')) - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : null const meta = getMeta(resourceName, commandArgs) diff --git a/packages/datadog-plugin-apollo/src/gateway/fetch.js b/packages/datadog-plugin-apollo/src/gateway/fetch.js index fc1a3d82837..22189680596 100644 --- a/packages/datadog-plugin-apollo/src/gateway/fetch.js +++ b/packages/datadog-plugin-apollo/src/gateway/fetch.js @@ -10,7 +10,7 @@ class ApolloGatewayFetchPlugin extends ApolloBasePlugin { } bindStart (ctx) { - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : null const spanData = { diff --git a/packages/datadog-plugin-apollo/src/gateway/index.js b/packages/datadog-plugin-apollo/src/gateway/index.js index e94f19d38ca..97710116135 100644 --- a/packages/datadog-plugin-apollo/src/gateway/index.js +++ b/packages/datadog-plugin-apollo/src/gateway/index.js @@ -25,7 +25,7 @@ class ApolloGatewayPlugin extends CompositePlugin { constructor (...args) { super(...args) this.addSub('apm:apollo:gateway:general:error', (ctx) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (!span) return span.setTag('error', ctx.error) diff --git a/packages/datadog-plugin-apollo/src/gateway/request.js b/packages/datadog-plugin-apollo/src/gateway/request.js index 740f487c759..efeff8f458e 100644 --- a/packages/datadog-plugin-apollo/src/gateway/request.js +++ b/packages/datadog-plugin-apollo/src/gateway/request.js @@ -15,7 +15,7 @@ class ApolloGatewayRequestPlugin extends ApolloBasePlugin { } bindStart (ctx) { - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : null const spanData = { childOf, diff --git a/packages/datadog-plugin-aws-sdk/src/base.js b/packages/datadog-plugin-aws-sdk/src/base.js index bb0d5675280..283fddfcdab 100644 --- a/packages/datadog-plugin-aws-sdk/src/base.js +++ b/packages/datadog-plugin-aws-sdk/src/base.js @@ -67,13 +67,13 @@ class BaseAwsSdkPlugin extends ClientPlugin { span.addTags(requestTags) } - const store = storage.getStore() + const store = storage('legacy').getStore() this.enter(span, store) }) this.addSub(`apm:aws:request:region:${this.serviceIdentifier}`, region => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return const { span } = store if (!span) return @@ -82,7 +82,7 @@ class BaseAwsSdkPlugin extends ClientPlugin { }) this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response, cbExists = false }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return const { span } = store if (!span) return diff --git a/packages/datadog-plugin-aws-sdk/src/services/kinesis.js b/packages/datadog-plugin-aws-sdk/src/services/kinesis.js index cdbd7c077e9..0bd457a90f6 100644 --- a/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +++ b/packages/datadog-plugin-aws-sdk/src/services/kinesis.js @@ -21,7 +21,7 @@ class Kinesis extends BaseAwsSdkPlugin { this.addSub('apm:aws:response:start:kinesis', obj => { const { request, response } = obj - const store = storage.getStore() + const store = storage('legacy').getStore() const plugin = this // if we have either of these operations, we want to store the streamName param @@ -49,7 +49,7 @@ class Kinesis extends BaseAwsSdkPlugin { } // get the stream name that should have been stored previously - const { streamName } = storage.getStore() + const { streamName } = storage('legacy').getStore() // extract DSM context after as we might not have a parent-child but may have a DSM context this.responseExtractDSMContext( @@ -59,7 +59,7 @@ class Kinesis extends BaseAwsSdkPlugin { }) this.addSub('apm:aws:response:finish:kinesis', err => { - const { span } = storage.getStore() + const { span } = storage('legacy').getStore() this.finish(span, null, err) }) } @@ -79,7 +79,7 @@ class Kinesis extends BaseAwsSdkPlugin { if (!params || !params.StreamName) return const streamName = params.StreamName - storage.enterWith({ ...store, streamName }) + storage('legacy').enterWith({ ...store, streamName }) } responseExtract (params, operation, response) { diff --git a/packages/datadog-plugin-aws-sdk/src/services/sqs.js b/packages/datadog-plugin-aws-sdk/src/services/sqs.js index 9857e46bf28..092465cf67f 100644 --- a/packages/datadog-plugin-aws-sdk/src/services/sqs.js +++ b/packages/datadog-plugin-aws-sdk/src/services/sqs.js @@ -20,7 +20,7 @@ class Sqs extends BaseAwsSdkPlugin { this.addSub('apm:aws:response:start:sqs', obj => { const { request, response } = obj - const store = storage.getStore() + const store = storage('legacy').getStore() const plugin = this const contextExtraction = this.responseExtract(request.params, request.operation, response) let span @@ -47,7 +47,7 @@ class Sqs extends BaseAwsSdkPlugin { }) this.addSub('apm:aws:response:finish:sqs', err => { - const { span } = storage.getStore() + const { span } = storage('legacy').getStore() this.finish(span, null, err) }) } diff --git a/packages/datadog-plugin-azure-functions/src/index.js b/packages/datadog-plugin-azure-functions/src/index.js index c2f9783c039..fe27db2d3f8 100644 --- a/packages/datadog-plugin-azure-functions/src/index.js +++ b/packages/datadog-plugin-azure-functions/src/index.js @@ -24,7 +24,7 @@ class AzureFunctionsPlugin extends TracingPlugin { bindStart (ctx) { const { functionName, methodName } = ctx - const store = storage.getStore() + const store = storage('legacy').getStore() const span = this.startSpan(this.operationName(), { service: this.serviceName(), diff --git a/packages/datadog-plugin-child_process/test/index.spec.js b/packages/datadog-plugin-child_process/test/index.spec.js index bd29b9abdfe..800cfd22dad 100644 --- a/packages/datadog-plugin-child_process/test/index.spec.js +++ b/packages/datadog-plugin-child_process/test/index.spec.js @@ -216,7 +216,7 @@ describe('Child process plugin', () => { describe('end', () => { it('should not call setTag if neither error nor result is passed', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.end({}) @@ -226,7 +226,7 @@ describe('Child process plugin', () => { }) it('should call setTag with proper code when result is a buffer', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.end({ result: Buffer.from('test') }) @@ -236,7 +236,7 @@ describe('Child process plugin', () => { }) it('should call setTag with proper code when result is a string', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.end({ result: 'test' }) @@ -246,7 +246,7 @@ describe('Child process plugin', () => { }) it('should call setTag with proper code when an error is thrown', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.end({ error: { status: -1 } }) @@ -258,7 +258,7 @@ describe('Child process plugin', () => { describe('asyncEnd', () => { it('should call setTag with undefined code if neither error nor result is passed', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.asyncEnd({}) @@ -268,7 +268,7 @@ describe('Child process plugin', () => { }) it('should call setTag with proper code when a proper code is returned', () => { - sinon.stub(storage, 'getStore').returns({ span: spanStub }) + sinon.stub(storage('legacy'), 'getStore').returns({ span: spanStub }) const shellPlugin = new ChildProcessPlugin(tracerStub, configStub) shellPlugin.asyncEnd({ result: 0 }) @@ -396,7 +396,7 @@ describe('Child process plugin', () => { parentSpan.finish() tracer.scope().activate(parentSpan, done) } else { - storage.enterWith({}) + storage('legacy').enterWith({}) done() } }) @@ -425,7 +425,7 @@ describe('Child process plugin', () => { it('should maintain previous span after the execution', (done) => { const res = childProcess[methodName]('ls') - const span = storage.getStore()?.span + const span = storage('legacy').getStore()?.span expect(span).to.be.equals(parentSpan) if (async) { res.on('close', () => { @@ -440,7 +440,7 @@ describe('Child process plugin', () => { if (async) { it('should maintain previous span in the callback', (done) => { childProcess[methodName]('ls', () => { - const span = storage.getStore()?.span + const span = storage('legacy').getStore()?.span expect(span).to.be.equals(parentSpan) done() }) diff --git a/packages/datadog-plugin-couchbase/src/index.js b/packages/datadog-plugin-couchbase/src/index.js index cb764875de7..8208dbb0b57 100644 --- a/packages/datadog-plugin-couchbase/src/index.js +++ b/packages/datadog-plugin-couchbase/src/index.js @@ -42,7 +42,7 @@ class CouchBasePlugin extends StoragePlugin { super(...args) this.addSubs('query', ({ resource, bucket, seedNodes }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = this.startSpan( 'query', { 'span.type': 'sql', @@ -64,7 +64,7 @@ class CouchBasePlugin extends StoragePlugin { _addCommandSubs (name) { this.addSubs(name, ({ bucket, collection, seedNodes }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = this.startSpan(name, {}, store, { bucket, collection, seedNodes }) this.enter(span, store) }) diff --git a/packages/datadog-plugin-cucumber/src/index.js b/packages/datadog-plugin-cucumber/src/index.js index 7454c87560b..1c0cc85a26e 100644 --- a/packages/datadog-plugin-cucumber/src/index.js +++ b/packages/datadog-plugin-cucumber/src/index.js @@ -213,7 +213,7 @@ class CucumberPlugin extends CiPlugin { isParallel, promises }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSuite = getTestSuitePath(testFileAbsolutePath, this.sourceRoot) const testSourceFile = getTestSuitePath(testFileAbsolutePath, this.repositoryRoot) @@ -231,7 +231,7 @@ class CucumberPlugin extends CiPlugin { this.activeTestSpan = testSpan // Time we give the breakpoint to be hit - if (promises && this.runningTestProbeId) { + if (promises && this.runningTestProbe) { promises.hitBreakpointPromise = new Promise((resolve) => { setTimeout(resolve, BREAKPOINT_HIT_GRACE_PERIOD_MS) }) @@ -239,7 +239,7 @@ class CucumberPlugin extends CiPlugin { }) this.addSub('ci:cucumber:test:retry', ({ isFirstAttempt, error }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store.span if (!isFirstAttempt) { span.setTag(TEST_IS_RETRY, 'true') @@ -248,8 +248,8 @@ class CucumberPlugin extends CiPlugin { if (isFirstAttempt && this.di && error && this.libraryConfig?.isDiEnabled) { const probeInformation = this.addDiProbe(error) if (probeInformation) { - const { probeId, stackIndex } = probeInformation - this.runningTestProbeId = probeId + const { file, line, stackIndex } = probeInformation + this.runningTestProbe = { file, line } this.testErrorStackIndex = stackIndex // TODO: we're not waiting for setProbePromise to be resolved, so there might be race conditions } @@ -260,7 +260,7 @@ class CucumberPlugin extends CiPlugin { }) this.addSub('ci:cucumber:test-step:start', ({ resource }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : store const span = this.tracer.startSpan('cucumber.step', { childOf, @@ -313,7 +313,7 @@ class CucumberPlugin extends CiPlugin { isEfdRetry, isFlakyRetry }) => { - const span = storage.getStore().span + const span = storage('legacy').getStore().span const statusTag = isStep ? 'step.status' : TEST_STATUS span.setTag(statusTag, status) @@ -359,16 +359,16 @@ class CucumberPlugin extends CiPlugin { this.tracer._exporter.flush() } this.activeTestSpan = null - if (this.runningTestProbeId) { - this.removeDiProbe(this.runningTestProbeId) - this.runningTestProbeId = null + if (this.runningTestProbe) { + this.removeDiProbe(this.runningTestProbe) + this.runningTestProbe = null } } }) this.addSub('ci:cucumber:error', (err) => { if (err) { - const span = storage.getStore().span + const span = storage('legacy').getStore().span span.setTag('error', err) } }) diff --git a/packages/datadog-plugin-cypress/src/cypress-plugin.js b/packages/datadog-plugin-cypress/src/cypress-plugin.js index 31d4d282f64..67487e47dbb 100644 --- a/packages/datadog-plugin-cypress/src/cypress-plugin.js +++ b/packages/datadog-plugin-cypress/src/cypress-plugin.js @@ -32,7 +32,8 @@ const { getTestSessionName, TEST_SESSION_NAME, TEST_LEVEL_EVENT_TYPES, - TEST_RETRY_REASON + TEST_RETRY_REASON, + DD_TEST_IS_USER_PROVIDED_SERVICE } = require('../../dd-trace/src/plugins/util/test') const { isMarkedAsUnskippable } = require('../../datadog-plugin-jest/src/util') const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants') @@ -222,6 +223,10 @@ class CypressPlugin { this.tracer = tracer this.cypressConfig = cypressConfig + // we have to do it here because the tracer is not initialized in the constructor + this.testEnvironmentMetadata[DD_TEST_IS_USER_PROVIDED_SERVICE] = + tracer._tracer._config.isServiceUserProvided ? 'true' : 'false' + this.libraryConfigurationPromise = getLibraryConfiguration(this.tracer, this.testConfiguration) .then((libraryConfigurationResponse) => { if (libraryConfigurationResponse.err) { diff --git a/packages/datadog-plugin-cypress/src/support.js b/packages/datadog-plugin-cypress/src/support.js index 6e31e9e45a1..749a25d7f66 100644 --- a/packages/datadog-plugin-cypress/src/support.js +++ b/packages/datadog-plugin-cypress/src/support.js @@ -4,6 +4,10 @@ let isKnownTestsEnabled = false let knownTestsForSuite = [] let suiteTests = [] let earlyFlakeDetectionNumRetries = 0 +// We need to grab the original window as soon as possible, +// in case the test changes the origin. If the test does change the origin, +// any call to `cy.window()` will result in a cross origin error. +let originalWindow // If the test is using multi domain with cy.origin, trying to access // window properties will result in a cross origin error. @@ -61,6 +65,9 @@ beforeEach(function () { this.skip() } }) + cy.window().then(win => { + originalWindow = win + }) }) before(function () { @@ -78,39 +85,39 @@ before(function () { }) after(() => { - cy.window().then(win => { - if (safeGetRum(win)) { - win.dispatchEvent(new Event('beforeunload')) + try { + if (safeGetRum(originalWindow)) { + originalWindow.dispatchEvent(new Event('beforeunload')) } - }) + } catch (e) { + // ignore error. It's usually a multi origin issue. + } }) afterEach(function () { - cy.window().then(win => { - const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest - const testInfo = { - testName: currentTest.fullTitle(), - testSuite: Cypress.mocha.getRootSuite().file, - testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute, - state: currentTest.state, - error: currentTest.err, - isNew: currentTest._ddIsNew, - isEfdRetry: currentTest._ddIsEfdRetry - } - try { - testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line - } catch (e) {} + const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest + const testInfo = { + testName: currentTest.fullTitle(), + testSuite: Cypress.mocha.getRootSuite().file, + testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute, + state: currentTest.state, + error: currentTest.err, + isNew: currentTest._ddIsNew, + isEfdRetry: currentTest._ddIsEfdRetry + } + try { + testInfo.testSourceLine = Cypress.mocha.getRunner().currentRunnable.invocationDetails.line + } catch (e) {} - if (safeGetRum(win)) { - testInfo.isRUMActive = true - } - let coverage - try { - coverage = win.__coverage__ - } catch (e) { - // ignore error and continue - } - cy.task('dd:afterEach', { test: testInfo, coverage }) - }) + if (safeGetRum(originalWindow)) { + testInfo.isRUMActive = true + } + let coverage + try { + coverage = originalWindow.__coverage__ + } catch (e) { + // ignore error and continue + } + cy.task('dd:afterEach', { test: testInfo, coverage }) }) diff --git a/packages/datadog-plugin-dns/test/index.spec.js b/packages/datadog-plugin-dns/test/index.spec.js index 1457bb869d8..cdea26de614 100644 --- a/packages/datadog-plugin-dns/test/index.spec.js +++ b/packages/datadog-plugin-dns/test/index.spec.js @@ -232,7 +232,7 @@ describe('Plugin', () => { clearTimeout(timer) }) - storage.run({ noop: true }, () => { + storage('legacy').run({ noop: true }, () => { resolver.resolve('lvh.me', () => {}) }) }) diff --git a/packages/datadog-plugin-fastify/test/tracing.spec.js b/packages/datadog-plugin-fastify/test/tracing.spec.js index c8924c98dfd..41f1632b15a 100644 --- a/packages/datadog-plugin-fastify/test/tracing.spec.js +++ b/packages/datadog-plugin-fastify/test/tracing.spec.js @@ -309,7 +309,7 @@ describe('Plugin', () => { const storage = new AsyncLocalStorage() const store = {} - global.getStore = () => storage.getStore() + global.getStore = () => storage('legacy').getStore() app.addHook('onRequest', (request, reply, next) => { storage.run(store, () => next()) diff --git a/packages/datadog-plugin-fetch/test/index.spec.js b/packages/datadog-plugin-fetch/test/index.spec.js index 1d20d375d79..bf18053952f 100644 --- a/packages/datadog-plugin-fetch/test/index.spec.js +++ b/packages/datadog-plugin-fetch/test/index.spec.js @@ -338,13 +338,13 @@ describe('Plugin', function () { clearTimeout(timer) }) - const store = storage.getStore() + const store = storage('legacy').getStore() - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) fetch(`http://localhost:${port}/user`).catch(() => {}) - storage.enterWith(store) + storage('legacy').enterWith(store) }) }) }) diff --git a/packages/datadog-plugin-grpc/src/client.js b/packages/datadog-plugin-grpc/src/client.js index db8dd89b9bf..1afe14ac8c3 100644 --- a/packages/datadog-plugin-grpc/src/client.js +++ b/packages/datadog-plugin-grpc/src/client.js @@ -20,7 +20,7 @@ class GrpcClientPlugin extends ClientPlugin { } bindStart (message) { - const store = storage.getStore() + const store = storage('legacy').getStore() const { metadata, path, type } = message const metadataFilter = this.config.metadataFilter const method = getMethodMetadata(path, type) diff --git a/packages/datadog-plugin-grpc/src/server.js b/packages/datadog-plugin-grpc/src/server.js index 0b599a1283d..938a87ec988 100644 --- a/packages/datadog-plugin-grpc/src/server.js +++ b/packages/datadog-plugin-grpc/src/server.js @@ -27,7 +27,7 @@ class GrpcServerPlugin extends ServerPlugin { } bindStart (message) { - const store = storage.getStore() + const store = storage('legacy').getStore() const { name, metadata, type } = message const metadataFilter = this.config.metadataFilter const childOf = extract(this.tracer, metadata) diff --git a/packages/datadog-plugin-hapi/src/index.js b/packages/datadog-plugin-hapi/src/index.js index b72df6951b0..d08715f40d8 100644 --- a/packages/datadog-plugin-hapi/src/index.js +++ b/packages/datadog-plugin-hapi/src/index.js @@ -15,7 +15,7 @@ class HapiPlugin extends RouterPlugin { this._requestSpans = new WeakMap() this.addSub('apm:hapi:request:handle', ({ req }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store && store.span this.setFramework(req, 'hapi', this.config) diff --git a/packages/datadog-plugin-hapi/test/index.spec.js b/packages/datadog-plugin-hapi/test/index.spec.js index 48093e29044..a222acfd880 100644 --- a/packages/datadog-plugin-hapi/test/index.spec.js +++ b/packages/datadog-plugin-hapi/test/index.spec.js @@ -351,11 +351,11 @@ describe('Plugin', () => { }) it('should persist AsyncLocalStorage context', (done) => { - const als = new AsyncLocalStorage() + const storage = new AsyncLocalStorage() const path = '/path' server.ext('onRequest', (request, h) => { - als.enterWith({ path: request.path }) + storage.enterWith({ path: request.path }) return reply(request, h) }) @@ -363,7 +363,7 @@ describe('Plugin', () => { method: 'GET', path, handler: async (request, h) => { - expect(als.getStore()).to.deep.equal({ path }) + expect(storage.getStore()).to.deep.equal({ path }) done() return h.response ? h.response() : h() } diff --git a/packages/datadog-plugin-http/src/client.js b/packages/datadog-plugin-http/src/client.js index 2bc408e648b..bf1e416e62f 100644 --- a/packages/datadog-plugin-http/src/client.js +++ b/packages/datadog-plugin-http/src/client.js @@ -21,7 +21,7 @@ class HttpClientPlugin extends ClientPlugin { bindStart (message) { const { args, http = {} } = message - const store = storage.getStore() + const store = storage('legacy').getStore() const options = args.options const agent = options.agent || options._defaultAgent || http.globalAgent || {} const protocol = options.protocol || agent.protocol || 'http:' diff --git a/packages/datadog-plugin-http/src/server.js b/packages/datadog-plugin-http/src/server.js index dcf4614819e..1b16d077f95 100644 --- a/packages/datadog-plugin-http/src/server.js +++ b/packages/datadog-plugin-http/src/server.js @@ -22,7 +22,7 @@ class HttpServerPlugin extends ServerPlugin { } start ({ req, res, abortController }) { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = web.startSpan( this.tracer, { diff --git a/packages/datadog-plugin-http/test/client.spec.js b/packages/datadog-plugin-http/test/client.spec.js index ff2d220d0cd..73b2b949f62 100644 --- a/packages/datadog-plugin-http/test/client.spec.js +++ b/packages/datadog-plugin-http/test/client.spec.js @@ -922,15 +922,15 @@ describe('Plugin', () => { }) appListener = server(app, port => { - const store = storage.getStore() + const store = storage('legacy').getStore() - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) const req = http.request(tracer._tracer._url.href) req.on('error', () => {}) req.end() - storage.enterWith(store) + storage('legacy').enterWith(store) }) }) } diff --git a/packages/datadog-plugin-http2/src/client.js b/packages/datadog-plugin-http2/src/client.js index 296f1161e59..603cc712a41 100644 --- a/packages/datadog-plugin-http2/src/client.js +++ b/packages/datadog-plugin-http2/src/client.js @@ -36,7 +36,7 @@ class Http2ClientPlugin extends ClientPlugin { const uri = `${sessionDetails.protocol}//${sessionDetails.host}:${sessionDetails.port}${pathname}` const allowed = this.config.filter(uri) - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store && allowed ? store.span : null const span = this.startSpan(this.operationName(), { childOf, @@ -85,7 +85,7 @@ class Http2ClientPlugin extends ClientPlugin { return parentStore } - return storage.getStore() + return storage('legacy').getStore() } configure (config) { @@ -98,7 +98,7 @@ class Http2ClientPlugin extends ClientPlugin { store.span.setTag(HTTP_STATUS_CODE, status) if (!this.config.validateStatus(status)) { - storage.run(store, () => this.addError()) + storage('legacy').run(store, () => this.addError()) } addHeaderTags(store.span, headers, HTTP_RESPONSE_HEADERS, this.config) diff --git a/packages/datadog-plugin-http2/src/server.js b/packages/datadog-plugin-http2/src/server.js index 50e98d1737b..36305299249 100644 --- a/packages/datadog-plugin-http2/src/server.js +++ b/packages/datadog-plugin-http2/src/server.js @@ -17,7 +17,7 @@ class Http2ServerPlugin extends ServerPlugin { } start ({ req, res }) { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = web.startSpan( this.tracer, { diff --git a/packages/datadog-plugin-jest/src/index.js b/packages/datadog-plugin-jest/src/index.js index f82899f20d1..3ec965efdbd 100644 --- a/packages/datadog-plugin-jest/src/index.js +++ b/packages/datadog-plugin-jest/src/index.js @@ -291,6 +291,7 @@ class JestPlugin extends CiPlugin { if (isJestWorker) { this.tracer._exporter.flush() } + this.removeAllDiProbes() }) /** @@ -317,15 +318,15 @@ class JestPlugin extends CiPlugin { }) this.addSub('ci:jest:test:start', (test) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = this.startTestSpan(test) this.enter(span, store) this.activeTestSpan = span }) - this.addSub('ci:jest:test:finish', ({ status, testStartLine, promises, shouldRemoveProbe }) => { - const span = storage.getStore().span + this.addSub('ci:jest:test:finish', ({ status, testStartLine }) => { + const span = storage('legacy').getStore().span span.setTag(TEST_STATUS, status) if (testStartLine) { span.setTag(TEST_SOURCE_START, testStartLine) @@ -346,15 +347,11 @@ class JestPlugin extends CiPlugin { span.finish() finishAllTraceSpans(span) this.activeTestSpan = null - if (shouldRemoveProbe && this.runningTestProbeId) { - promises.isProbeRemoved = withTimeout(this.removeDiProbe(this.runningTestProbeId), 2000) - this.runningTestProbeId = null - } }) this.addSub('ci:jest:test:err', ({ error, shouldSetProbe, promises }) => { if (error) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && store.span) { const span = store.span span.setTag(TEST_STATUS, 'fail') @@ -362,9 +359,7 @@ class JestPlugin extends CiPlugin { if (shouldSetProbe) { const probeInformation = this.addDiProbe(error) if (probeInformation) { - const { probeId, setProbePromise, stackIndex } = probeInformation - this.runningTestProbeId = probeId - this.testErrorStackIndex = stackIndex + const { setProbePromise } = probeInformation promises.isProbeReady = withTimeout(setProbePromise, 2000) } } diff --git a/packages/datadog-plugin-langchain/src/tracing.js b/packages/datadog-plugin-langchain/src/tracing.js index f9a7daf3de2..b9485fcd62e 100644 --- a/packages/datadog-plugin-langchain/src/tracing.js +++ b/packages/datadog-plugin-langchain/src/tracing.js @@ -61,7 +61,7 @@ class LangChainTracingPlugin extends TracingPlugin { } }, false) - const store = storage.getStore() || {} + const store = storage('legacy').getStore() || {} ctx.currentStore = { ...store, span } return ctx.currentStore diff --git a/packages/datadog-plugin-limitd-client/test/index.spec.js b/packages/datadog-plugin-limitd-client/test/index.spec.js index 4aa0be9c432..c1852d2296e 100644 --- a/packages/datadog-plugin-limitd-client/test/index.spec.js +++ b/packages/datadog-plugin-limitd-client/test/index.spec.js @@ -29,12 +29,12 @@ describe('Plugin', () => { it('should propagate context', done => { const span = {} - storage.run(span, () => { + storage('legacy').run(span, () => { limitd.take('user', 'test', function (err, resp) { if (err) return done(err) try { - expect(storage.getStore()).to.equal(span) + expect(storage('legacy').getStore()).to.equal(span) done() } catch (e) { done(e) diff --git a/packages/datadog-plugin-mariadb/src/index.js b/packages/datadog-plugin-mariadb/src/index.js index 1468292f72e..ff6488795d4 100644 --- a/packages/datadog-plugin-mariadb/src/index.js +++ b/packages/datadog-plugin-mariadb/src/index.js @@ -13,12 +13,12 @@ class MariadbPlugin extends MySQLPlugin { super(...args) this.addSub(`apm:${this.component}:pool:skip`, () => { - skippedStore = storage.getStore() - storage.enterWith({ noop: true }) + skippedStore = storage('legacy').getStore() + storage('legacy').enterWith({ noop: true }) }) this.addSub(`apm:${this.component}:pool:unskip`, () => { - storage.enterWith(skippedStore) + storage('legacy').enterWith(skippedStore) skippedStore = undefined }) } diff --git a/packages/datadog-plugin-mocha/src/index.js b/packages/datadog-plugin-mocha/src/index.js index f4c9b063328..5918a3a5db5 100644 --- a/packages/datadog-plugin-mocha/src/index.js +++ b/packages/datadog-plugin-mocha/src/index.js @@ -155,13 +155,13 @@ class MochaPlugin extends CiPlugin { if (itrCorrelationId) { testSuiteSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId) } - const store = storage.getStore() + const store = storage('legacy').getStore() this.enter(testSuiteSpan, store) this._testSuites.set(testSuite, testSuiteSpan) }) this.addSub('ci:mocha:test-suite:finish', (status) => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && store.span) { const span = store.span // the test status of the suite may have been set in ci:mocha:test-suite:error already @@ -174,7 +174,7 @@ class MochaPlugin extends CiPlugin { }) this.addSub('ci:mocha:test-suite:error', (err) => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && store.span) { const span = store.span span.setTag('error', err) @@ -183,7 +183,7 @@ class MochaPlugin extends CiPlugin { }) this.addSub('ci:mocha:test:start', (testInfo) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = this.startTestSpan(testInfo) this.enter(span, store) @@ -195,7 +195,7 @@ class MochaPlugin extends CiPlugin { }) this.addSub('ci:mocha:test:finish', ({ status, hasBeenRetried, isLastRetry }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span) { @@ -219,15 +219,15 @@ class MochaPlugin extends CiPlugin { span.finish() finishAllTraceSpans(span) this.activeTestSpan = null - if (this.di && this.libraryConfig?.isDiEnabled && this.runningTestProbeId && isLastRetry) { - this.removeDiProbe(this.runningTestProbeId) - this.runningTestProbeId = null + if (this.di && this.libraryConfig?.isDiEnabled && this.runningTestProbe && isLastRetry) { + this.removeDiProbe(this.runningTestProbe) + this.runningTestProbe = null } } }) this.addSub('ci:mocha:test:skip', (testInfo) => { - const store = storage.getStore() + const store = storage('legacy').getStore() // skipped through it.skip, so the span is not created yet // for this test if (!store) { @@ -237,7 +237,7 @@ class MochaPlugin extends CiPlugin { }) this.addSub('ci:mocha:test:error', (err) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (err && span) { if (err.constructor.name === 'Pending' && !this.forbidPending) { @@ -250,7 +250,7 @@ class MochaPlugin extends CiPlugin { }) this.addSub('ci:mocha:test:retry', ({ isFirstAttempt, willBeRetried, err, test }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span) { span.setTag(TEST_STATUS, 'fail') @@ -275,8 +275,8 @@ class MochaPlugin extends CiPlugin { if (isFirstAttempt && willBeRetried && this.di && this.libraryConfig?.isDiEnabled) { const probeInformation = this.addDiProbe(err) if (probeInformation) { - const { probeId, stackIndex } = probeInformation - this.runningTestProbeId = probeId + const { file, line, stackIndex } = probeInformation + this.runningTestProbe = { file, line } this.testErrorStackIndex = stackIndex test._ddShouldWaitForHitProbe = true // TODO: we're not waiting for setProbePromise to be resolved, so there might be race conditions diff --git a/packages/datadog-plugin-mongoose/test/index.spec.js b/packages/datadog-plugin-mongoose/test/index.spec.js index 305ddeca31c..35092db5aa8 100644 --- a/packages/datadog-plugin-mongoose/test/index.spec.js +++ b/packages/datadog-plugin-mongoose/test/index.spec.js @@ -12,7 +12,8 @@ describe('Plugin', () => { describe('mongoose', () => { withVersions('mongoose', ['mongoose'], (version) => { const specificVersion = require(`../../../versions/mongoose@${version}`).version() - if (NODE_MAJOR === 14 && semver.satisfies(specificVersion, '>=8')) return + if ((NODE_MAJOR === 14 && semver.satisfies(specificVersion, '>=8')) || + semver.satisfies(specificVersion, '>=8.10.0')) return let mongoose diff --git a/packages/datadog-plugin-next/src/index.js b/packages/datadog-plugin-next/src/index.js index 1dff5bec4e9..eeb7fb1675d 100644 --- a/packages/datadog-plugin-next/src/index.js +++ b/packages/datadog-plugin-next/src/index.js @@ -20,7 +20,7 @@ class NextPlugin extends ServerPlugin { } bindStart ({ req, res }) { - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : store const span = this.tracer.startSpan(this.operationName(), { childOf, @@ -43,7 +43,7 @@ class NextPlugin extends ServerPlugin { error ({ span, error }) { if (!span) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return span = store.span @@ -53,7 +53,7 @@ class NextPlugin extends ServerPlugin { } finish ({ req, res, nextRequest = {} }) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return @@ -85,7 +85,7 @@ class NextPlugin extends ServerPlugin { } pageLoad ({ page, isAppPath = false, isStatic = false }) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return diff --git a/packages/datadog-plugin-openai/src/tracing.js b/packages/datadog-plugin-openai/src/tracing.js index 30208999e03..e411b8181ad 100644 --- a/packages/datadog-plugin-openai/src/tracing.js +++ b/packages/datadog-plugin-openai/src/tracing.js @@ -60,7 +60,7 @@ class OpenAiTracingPlugin extends TracingPlugin { bindStart (ctx) { const { methodName, args, basePath, apiKey } = ctx const payload = normalizeRequestPayload(methodName, args) - const store = storage.getStore() || {} + const store = storage('legacy').getStore() || {} const span = this.startSpan('openai.request', { service: this.config.service, diff --git a/packages/datadog-plugin-playwright/src/index.js b/packages/datadog-plugin-playwright/src/index.js index 8fd8ac6fef0..56601abf051 100644 --- a/packages/datadog-plugin-playwright/src/index.js +++ b/packages/datadog-plugin-playwright/src/index.js @@ -68,7 +68,7 @@ class PlaywrightPlugin extends CiPlugin { }) this.addSub('ci:playwright:test-suite:start', (testSuiteAbsolutePath) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir) const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot) @@ -102,7 +102,7 @@ class PlaywrightPlugin extends CiPlugin { }) this.addSub('ci:playwright:test-suite:finish', ({ status, error }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store && store.span if (!span) return if (error) { @@ -121,7 +121,7 @@ class PlaywrightPlugin extends CiPlugin { }) this.addSub('ci:playwright:test:start', ({ testName, testSuiteAbsolutePath, testSourceLine, browserName }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.rootDir) const testSourceFile = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot) const span = this.startTestSpan(testName, testSuite, testSourceFile, testSourceLine, browserName) @@ -129,7 +129,7 @@ class PlaywrightPlugin extends CiPlugin { this.enter(span, store) }) this.addSub('ci:playwright:test:finish', ({ testStatus, steps, error, extraTags, isNew, isEfdRetry, isRetry }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store && store.span if (!span) return diff --git a/packages/datadog-plugin-rhea/src/consumer.js b/packages/datadog-plugin-rhea/src/consumer.js index 56aad8f7b9d..a504c94029d 100644 --- a/packages/datadog-plugin-rhea/src/consumer.js +++ b/packages/datadog-plugin-rhea/src/consumer.js @@ -11,7 +11,7 @@ class RheaConsumerPlugin extends ConsumerPlugin { super(...args) this.addTraceSub('dispatch', ({ state }) => { - const span = storage.getStore().span + const span = storage('legacy').getStore().span span.setTag('amqp.delivery.state', state) }) } diff --git a/packages/datadog-plugin-router/src/index.js b/packages/datadog-plugin-router/src/index.js index 439f2d08332..96874fc7e54 100644 --- a/packages/datadog-plugin-router/src/index.js +++ b/packages/datadog-plugin-router/src/index.js @@ -29,7 +29,7 @@ class RouterPlugin extends WebPlugin { context.middleware.push(span) } - const store = storage.getStore() + const store = storage('legacy').getStore() this._storeStack.push(store) this.enter(span, store) @@ -94,7 +94,7 @@ class RouterPlugin extends WebPlugin { } _getStoreSpan () { - const store = storage.getStore() + const store = storage('legacy').getStore() return store && store.span } diff --git a/packages/datadog-plugin-selenium/src/index.js b/packages/datadog-plugin-selenium/src/index.js index 2ff542e9e73..2f3cada3abb 100644 --- a/packages/datadog-plugin-selenium/src/index.js +++ b/packages/datadog-plugin-selenium/src/index.js @@ -39,7 +39,7 @@ class SeleniumPlugin extends CiPlugin { browserVersion, isRumActive }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (!span) { return diff --git a/packages/datadog-plugin-vitest/src/index.js b/packages/datadog-plugin-vitest/src/index.js index c4f94548f10..2aa88f2f38b 100644 --- a/packages/datadog-plugin-vitest/src/index.js +++ b/packages/datadog-plugin-vitest/src/index.js @@ -70,7 +70,7 @@ class VitestPlugin extends CiPlugin { isRetryReasonEfd }) => { const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.repositoryRoot) - const store = storage.getStore() + const store = storage('legacy').getStore() const extraTags = { [TEST_SOURCE_FILE]: testSuite @@ -102,7 +102,7 @@ class VitestPlugin extends CiPlugin { }) this.addSub('ci:vitest:test:finish-time', ({ status, task }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span // we store the finish time to finish at a later hook @@ -114,7 +114,7 @@ class VitestPlugin extends CiPlugin { }) this.addSub('ci:vitest:test:pass', ({ task }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span) { @@ -128,15 +128,15 @@ class VitestPlugin extends CiPlugin { }) this.addSub('ci:vitest:test:error', ({ duration, error, shouldSetProbe, promises }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span) { if (shouldSetProbe && this.di) { const probeInformation = this.addDiProbe(error) if (probeInformation) { - const { probeId, stackIndex, setProbePromise } = probeInformation - this.runningTestProbeId = probeId + const { file, line, stackIndex, setProbePromise } = probeInformation + this.runningTestProbe = { file, line } this.testErrorStackIndex = stackIndex promises.setProbePromise = setProbePromise } @@ -221,13 +221,13 @@ class VitestPlugin extends CiPlugin { } }) this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'suite') - const store = storage.getStore() + const store = storage('legacy').getStore() this.enter(testSuiteSpan, store) this.testSuiteSpan = testSuiteSpan }) this.addSub('ci:vitest:test-suite:finish', ({ status, onFinish }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span) { span.setTag(TEST_STATUS, status) @@ -237,13 +237,13 @@ class VitestPlugin extends CiPlugin { this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite') // TODO: too frequent flush - find for method in worker to decrease frequency this.tracer._exporter.flush(onFinish) - if (this.runningTestProbeId) { - this.removeDiProbe(this.runningTestProbeId) + if (this.runningTestProbe) { + this.removeDiProbe(this.runningTestProbe) } }) this.addSub('ci:vitest:test-suite:error', ({ error }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store?.span if (span && error) { span.setTag('error', error) diff --git a/packages/dd-trace/src/appsec/graphql.js b/packages/dd-trace/src/appsec/graphql.js index 2f715717d27..3d2603c0e33 100644 --- a/packages/dd-trace/src/appsec/graphql.js +++ b/packages/dd-trace/src/appsec/graphql.js @@ -30,7 +30,7 @@ function disable () { } function onGraphqlStartResolve ({ context, resolverInfo }) { - const req = storage.getStore()?.req + const req = storage('legacy').getStore()?.req if (!req) return @@ -49,7 +49,7 @@ function onGraphqlStartResolve ({ context, resolverInfo }) { } function enterInApolloMiddleware (data) { - const req = data?.req || storage.getStore()?.req + const req = data?.req || storage('legacy').getStore()?.req if (!req) return graphqlRequestData.set(req, { @@ -59,7 +59,7 @@ function enterInApolloMiddleware (data) { } function enterInApolloServerCoreRequest () { - const req = storage.getStore()?.req + const req = storage('legacy').getStore()?.req if (!req) return graphqlRequestData.set(req, { @@ -69,13 +69,13 @@ function enterInApolloServerCoreRequest () { } function exitFromApolloMiddleware (data) { - const req = data?.req || storage.getStore()?.req + const req = data?.req || storage('legacy').getStore()?.req const requestData = graphqlRequestData.get(req) if (requestData) requestData.inApolloMiddleware = false } function enterInApolloRequest () { - const req = storage.getStore()?.req + const req = storage('legacy').getStore()?.req const requestData = graphqlRequestData.get(req) if (requestData?.inApolloMiddleware) { @@ -85,7 +85,7 @@ function enterInApolloRequest () { } function beforeWriteApolloGraphqlResponse ({ abortController, abortData }) { - const req = storage.getStore()?.req + const req = storage('legacy').getStore()?.req if (!req) return const requestData = graphqlRequestData.get(req) diff --git a/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js index 81322788186..03582a3064a 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/code-injection-analyzer.js @@ -15,7 +15,7 @@ class CodeInjectionAnalyzer extends InjectionAnalyzer { onConfigure () { this.addSub('datadog:eval:call', ({ script }) => { if (!this.evalInstrumentedInc) { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = getIastContext(store) const tags = INSTRUMENTED_SINK.formatTags(CODE_INJECTION) diff --git a/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js index e6d4ef3aa74..b73c069a5f0 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js @@ -38,7 +38,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer { this.configureSanitizers() const onStart = ({ filters }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && !store.nosqlAnalyzed && filters?.length) { filters.forEach(filter => { this.analyze({ filter }, store) @@ -51,14 +51,14 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer { const onStartAndEnterWithStore = (message) => { const store = onStart(message || {}) if (store) { - storage.enterWith({ ...store, nosqlAnalyzed: true, nosqlParentStore: store }) + storage('legacy').enterWith({ ...store, nosqlAnalyzed: true, nosqlParentStore: store }) } } const onFinish = () => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store?.nosqlParentStore) { - storage.enterWith(store.nosqlParentStore) + storage('legacy').enterWith(store.nosqlParentStore) } } @@ -74,7 +74,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer { configureSanitizers () { this.addNotSinkSub('datadog:express-mongo-sanitize:filter:finish', ({ sanitizedProperties, req }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = getIastContext(store) if (iastContext) { // do nothing if we are not in an iast request @@ -100,7 +100,7 @@ class NosqlInjectionMongodbAnalyzer extends InjectionAnalyzer { }) this.addNotSinkSub('datadog:express-mongo-sanitize:sanitize:finish', ({ sanitizedObject }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = getIastContext(store) if (iastContext) { // do nothing if we are not in an iast request diff --git a/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js index 625dbde9150..c74d1e34029 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js @@ -29,7 +29,7 @@ class PathTraversalAnalyzer extends InjectionAnalyzer { onConfigure () { this.addSub('apm:fs:operation:start', (obj) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const outOfReqOrChild = !store?.fs?.root // we could filter out all the nested fs.operations based on store.fs.root @@ -84,7 +84,7 @@ class PathTraversalAnalyzer extends InjectionAnalyzer { } analyze (value) { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) if (!iastContext) { return } diff --git a/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js index 8f7ca5a39ed..2e6415e36a0 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js @@ -38,18 +38,18 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer { } getStoreAndAnalyze (query, dialect) { - const parentStore = storage.getStore() + const parentStore = storage('legacy').getStore() if (parentStore) { this.analyze(query, parentStore, dialect) - storage.enterWith({ ...parentStore, sqlAnalyzed: true, sqlParentStore: parentStore }) + storage('legacy').enterWith({ ...parentStore, sqlAnalyzed: true, sqlParentStore: parentStore }) } } returnToParentStore () { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && store.sqlParentStore) { - storage.enterWith(store.sqlParentStore) + storage('legacy').enterWith(store.sqlParentStore) } } @@ -59,7 +59,7 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer { } analyze (value, store, dialect) { - store = store || storage.getStore() + store = store || storage('legacy').getStore() if (!(store && store.sqlAnalyzed)) { super.analyze(value, store, dialect) } diff --git a/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js b/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js index 1cb244dbbdc..bc495f44c75 100644 --- a/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +++ b/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js @@ -91,7 +91,7 @@ class Analyzer extends SinkIastPlugin { return store && !iastContext } - analyze (value, store = storage.getStore(), meta) { + analyze (value, store = storage('legacy').getStore(), meta) { const iastContext = getIastContext(store) if (this._isInvalidContext(store, iastContext)) return @@ -99,7 +99,7 @@ class Analyzer extends SinkIastPlugin { } analyzeAll (...values) { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = getIastContext(store) if (this._isInvalidContext(store, iastContext)) return diff --git a/packages/dd-trace/src/appsec/iast/context/context-plugin.js b/packages/dd-trace/src/appsec/iast/context/context-plugin.js index f074f1fd40f..d65b68258ae 100644 --- a/packages/dd-trace/src/appsec/iast/context/context-plugin.js +++ b/packages/dd-trace/src/appsec/iast/context/context-plugin.js @@ -48,7 +48,7 @@ class IastContextPlugin extends IastPlugin { let isRequestAcquired = false let iastContext - const store = storage.getStore() + const store = storage('legacy').getStore() if (store) { const topContext = this.getTopContext() const rootSpan = this.getRootSpan(store) @@ -70,7 +70,7 @@ class IastContextPlugin extends IastPlugin { } finishContext () { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store) { const topContext = this.getTopContext() const iastContext = iastContextFunctions.getIastContext(store, topContext) diff --git a/packages/dd-trace/src/appsec/iast/iast-plugin.js b/packages/dd-trace/src/appsec/iast/iast-plugin.js index 42dab0a4af1..839c2884823 100644 --- a/packages/dd-trace/src/appsec/iast/iast-plugin.js +++ b/packages/dd-trace/src/appsec/iast/iast-plugin.js @@ -62,12 +62,12 @@ class IastPlugin extends Plugin { _getTelemetryHandler (iastSub) { return () => { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) iastSub.increaseExecuted(iastContext) } } - _execHandlerAndIncMetric ({ handler, metric, tags, iastContext = getIastContext(storage.getStore()) }) { + _execHandlerAndIncMetric ({ handler, metric, tags, iastContext = getIastContext(storage('legacy').getStore()) }) { try { const result = handler() if (iastTelemetry.isEnabled()) { diff --git a/packages/dd-trace/src/appsec/iast/index.js b/packages/dd-trace/src/appsec/iast/index.js index 9330bfdbbb1..f185f315030 100644 --- a/packages/dd-trace/src/appsec/iast/index.js +++ b/packages/dd-trace/src/appsec/iast/index.js @@ -57,7 +57,7 @@ function disable () { function onIncomingHttpRequestStart (data) { if (data?.req) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store) { const topContext = web.getContext(data.req) if (topContext) { @@ -82,7 +82,7 @@ function onIncomingHttpRequestStart (data) { function onIncomingHttpRequestEnd (data) { if (data?.req) { - const store = storage.getStore() + const store = storage('legacy').getStore() const topContext = web.getContext(data.req) const iastContext = iastContextFunctions.getIastContext(store, topContext) if (iastContext?.rootSpan) { diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js b/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js new file mode 100644 index 00000000000..76c8ddfc176 --- /dev/null +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/constants.js @@ -0,0 +1,6 @@ +'use strict' + +module.exports = { + LOG_MESSAGE: 'LOG', + REWRITTEN_MESSAGE: 'REWRITTEN' +} diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js b/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js index 9e236666619..b9c5e538d2e 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js @@ -39,7 +39,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { onConfigure () { const onRequestBody = ({ req }) => { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) if (iastContext && iastContext.body !== req.body) { this._taintTrackingHandler(HTTP_REQUEST_BODY, req, 'body', iastContext) iastContext.body = req.body @@ -70,7 +70,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { { channelName: 'apm:express:middleware:next', tag: HTTP_REQUEST_BODY }, ({ req }) => { if (req && req.body !== null && typeof req.body === 'object') { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) if (iastContext && iastContext.body !== req.body) { this._taintTrackingHandler(HTTP_REQUEST_BODY, req, 'body', iastContext) iastContext.body = req.body @@ -115,7 +115,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { this.addSub( { channelName: 'apm:graphql:resolve:start', tag: HTTP_REQUEST_BODY }, (data) => { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) const source = data.context?.source const ranges = source && getRanges(iastContext, source) if (ranges?.length) { @@ -128,7 +128,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { this.addSub( { channelName: 'datadog:url:parse:finish' }, ({ input, base, parsed, isURL }) => { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) let ranges if (base) { @@ -157,7 +157,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { const origRange = this._taintedURLs.get(context.urlObject) if (!origRange) return - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) if (!iastContext) return context.result = @@ -168,7 +168,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { this.addInstrumentedSource('http', [HTTP_REQUEST_HEADER_VALUE, HTTP_REQUEST_HEADER_NAME]) } - _taintTrackingHandler (type, target, property, iastContext = getIastContext(storage.getStore())) { + _taintTrackingHandler (type, target, property, iastContext = getIastContext(storage('legacy').getStore())) { if (!property) { taintObject(iastContext, target, type) } else if (target[property]) { @@ -177,7 +177,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { } _cookiesTaintTrackingHandler (target) { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) // Prevent tainting cookie names since it leads to taint literal string with same value. taintObject(iastContext, target, HTTP_REQUEST_COOKIE_VALUE) } @@ -206,7 +206,7 @@ class TaintTrackingPlugin extends SourceIastPlugin { this.taintUrl(req, iastContext) } - _taintDatabaseResult (result, dbOrigin, iastContext = getIastContext(storage.getStore()), name) { + _taintDatabaseResult (result, dbOrigin, iastContext = getIastContext(storage('legacy').getStore()), name) { if (!iastContext) return result if (this._rowsToTaint === 0) return result diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js b/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js index 1435978d03c..ac95722a996 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js @@ -22,7 +22,7 @@ class KafkaConsumerIastPlugin extends SourceIastPlugin { } taintKafkaMessage (message) { - const iastContext = getIastContext(storage.getStore()) + const iastContext = getIastContext(storage('legacy').getStore()) if (iastContext && message) { const { key, value } = message diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs new file mode 100644 index 00000000000..c5db0445cea --- /dev/null +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs @@ -0,0 +1,65 @@ +'use strict' + +import path from 'path' +import { URL } from 'url' +import { getName } from '../telemetry/verbosity.js' +import { isNotLibraryFile, isPrivateModule } from './filter.js' +import constants from './constants.js' + +const currentUrl = new URL(import.meta.url) +const ddTraceDir = path.join(currentUrl.pathname, '..', '..', '..', '..', '..', '..') + +let port, rewriter + +export async function initialize (data) { + if (rewriter) return Promise.reject(new Error('ALREADY INITIALIZED')) + + const { csiMethods, telemetryVerbosity, chainSourceMap } = data + port = data.port + + const iastRewriter = await import('@datadog/native-iast-rewriter') + + const { NonCacheRewriter } = iastRewriter.default + + rewriter = new NonCacheRewriter({ + csiMethods, + telemetryVerbosity: getName(telemetryVerbosity), + chainSourceMap + }) +} + +export async function load (url, context, nextLoad) { + const result = await nextLoad(url, context) + + if (!port) return result + if (!result.source) return result + if (url.includes(ddTraceDir) || url.includes('iitm=true')) return result + + try { + if (isPrivateModule(url) && isNotLibraryFile(url)) { + const rewritten = rewriter.rewrite(result.source.toString(), url) + + if (rewritten?.content) { + result.source = rewritten.content || result.source + const data = { url, rewritten } + port.postMessage({ type: constants.REWRITTEN_MESSAGE, data }) + } + } + } catch (e) { + const newErrObject = { + message: e.message, + stack: e.stack + } + + const data = { + level: 'error', + messages: ['[ASM] Error rewriting file %s', url, newErrObject] + } + port.postMessage({ + type: constants.LOG_MESSAGE, + data + }) + } + + return result +} diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js index d2279f39d26..aeaa0afff45 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js @@ -12,10 +12,7 @@ const telemetryRewriter = { information (content, filename, rewriter) { const response = this.off(content, filename, rewriter) - const metrics = response.metrics - if (metrics && metrics.instrumentedPropagation) { - INSTRUMENTED_PROPAGATION.inc(undefined, metrics.instrumentedPropagation) - } + incrementTelemetry(response.metrics) return response } @@ -30,4 +27,16 @@ function getRewriteFunction (rewriter) { } } -module.exports = { getRewriteFunction } +function incrementTelemetry (metrics) { + if (metrics?.instrumentedPropagation) { + INSTRUMENTED_PROPAGATION.inc(undefined, metrics.instrumentedPropagation) + } +} + +function incrementTelemetryIfNeeded (metrics) { + if (iastTelemetry.verbosity !== Verbosity.OFF) { + incrementTelemetry(metrics) + } +} + +module.exports = { getRewriteFunction, incrementTelemetryIfNeeded } diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js index 168408d5261..9b446f2416e 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js @@ -1,18 +1,23 @@ 'use strict' const Module = require('module') +const { pathToFileURL } = require('url') +const { MessageChannel } = require('worker_threads') const shimmer = require('../../../../../datadog-shimmer') const { isPrivateModule, isNotLibraryFile } = require('./filter') const { csiMethods } = require('./csi-methods') const { getName } = require('../telemetry/verbosity') -const { getRewriteFunction } = require('./rewriter-telemetry') +const { getRewriteFunction, incrementTelemetryIfNeeded } = require('./rewriter-telemetry') const dc = require('dc-polyfill') const log = require('../../../log') +const { isMainThread } = require('worker_threads') +const { LOG_MESSAGE, REWRITTEN_MESSAGE } = require('./constants') const hardcodedSecretCh = dc.channel('datadog:secrets:result') let rewriter -let getPrepareStackTrace +let getPrepareStackTrace, cacheRewrittenSourceMap let kSymbolPrepareStackTrace +let esmRewriterEnabled = false let getRewriterOriginalPathAndLineFromSourceMap = function (path, line, column) { return { path, line, column } @@ -46,6 +51,7 @@ function getRewriter (telemetryVerbosity) { const Rewriter = iastRewriter.Rewriter getPrepareStackTrace = iastRewriter.getPrepareStackTrace kSymbolPrepareStackTrace = iastRewriter.kSymbolPrepareStackTrace + cacheRewrittenSourceMap = iastRewriter.cacheRewrittenSourceMap const chainSourceMap = isFlagPresent('--enable-source-maps') const getOriginalPathAndLineFromSourceMap = iastRewriter.getOriginalPathAndLineFromSourceMap @@ -104,6 +110,24 @@ function getCompileMethodFn (compileMethod) { } } +function esmRewritePostProcess (rewritten, filename) { + const { literalsResult, metrics } = rewritten + + if (metrics?.status === 'modified') { + if (filename.startsWith('file://')) { + filename = filename.substring(7) + } + + cacheRewrittenSourceMap(filename, rewritten.content) + } + + incrementTelemetryIfNeeded(metrics) + + if (literalsResult && hardcodedSecretCh.hasSubscribers) { + hardcodedSecretCh.publish(literalsResult) + } +} + function enableRewriter (telemetryVerbosity) { try { const rewriter = getRewriter(telemetryVerbosity) @@ -114,11 +138,65 @@ function enableRewriter (telemetryVerbosity) { } shimmer.wrap(Module.prototype, '_compile', compileMethod => getCompileMethodFn(compileMethod)) } + + enableEsmRewriter(telemetryVerbosity) } catch (e) { log.error('[ASM] Error enabling TaintTracking Rewriter', e) } } +function isEsmConfigured () { + const hasLoaderArg = isFlagPresent('--loader') || isFlagPresent('--experimental-loader') + if (hasLoaderArg) return true + + const initializeLoaded = Object.keys(require.cache).find(file => file.includes('import-in-the-middle/hook.js')) + return !!initializeLoaded +} + +function enableEsmRewriter (telemetryVerbosity) { + if (isMainThread && Module.register && !esmRewriterEnabled && isEsmConfigured()) { + esmRewriterEnabled = true + + const { port1, port2 } = new MessageChannel() + + port1.on('message', (message) => { + const { type, data } = message + switch (type) { + case LOG_MESSAGE: + log[data.level]?.(...data.messages) + break + + case REWRITTEN_MESSAGE: + esmRewritePostProcess(data.rewritten, data.url) + break + } + }) + + port1.unref() + port2.unref() + + const chainSourceMap = isFlagPresent('--enable-source-maps') + const data = { + port: port2, + csiMethods, + telemetryVerbosity, + chainSourceMap + } + + try { + Module.register('./rewriter-esm.mjs', { + parentURL: pathToFileURL(__filename), + transferList: [port2], + data + }) + } catch (e) { + log.error('[ASM] Error enabling ESM Rewriter', e) + port1.close() + port2.close() + } + } +} + function disableRewriter () { shimmer.unwrap(Module.prototype, '_compile') diff --git a/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js b/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js index 6b1554d6449..160afe3d957 100644 --- a/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +++ b/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js @@ -39,7 +39,7 @@ function getTransactionId (iastContext) { } function getContextDefault () { - const store = storage.getStore() + const store = storage('legacy').getStore() return iastContextFunctions.getIastContext(store) } diff --git a/packages/dd-trace/src/appsec/index.js b/packages/dd-trace/src/appsec/index.js index 9c948290525..63d56ee5d2f 100644 --- a/packages/dd-trace/src/appsec/index.js +++ b/packages/dd-trace/src/appsec/index.js @@ -91,7 +91,7 @@ function onRequestBodyParsed ({ req, res, body, abortController }) { if (body === undefined || body === null) return if (!req) { - const store = storage.getStore() + const store = storage('legacy').getStore() req = store?.req } @@ -186,7 +186,7 @@ function incomingHttpEndTranslator ({ req, res }) { } function onPassportVerify ({ framework, login, user, success, abortController }) { - const store = storage.getStore() + const store = storage('legacy').getStore() const rootSpan = store?.req && web.root(store.req) if (!rootSpan) { @@ -200,7 +200,7 @@ function onPassportVerify ({ framework, login, user, success, abortController }) } function onPassportDeserializeUser ({ user, abortController }) { - const store = storage.getStore() + const store = storage('legacy').getStore() const rootSpan = store?.req && web.root(store.req) if (!rootSpan) { @@ -217,7 +217,7 @@ function onRequestQueryParsed ({ req, res, query, abortController }) { if (!query || typeof query !== 'object') return if (!req) { - const store = storage.getStore() + const store = storage('legacy').getStore() req = store?.req } diff --git a/packages/dd-trace/src/appsec/rasp/command_injection.js b/packages/dd-trace/src/appsec/rasp/command_injection.js index 62546e2b6a6..7b0c55da814 100644 --- a/packages/dd-trace/src/appsec/rasp/command_injection.js +++ b/packages/dd-trace/src/appsec/rasp/command_injection.js @@ -27,7 +27,7 @@ function disable () { function analyzeCommandInjection ({ file, fileArgs, shell, abortController }) { if (!file) return - const store = storage.getStore() + const store = storage('legacy').getStore() const req = store?.req if (!req) return diff --git a/packages/dd-trace/src/appsec/rasp/fs-plugin.js b/packages/dd-trace/src/appsec/rasp/fs-plugin.js index 71f9cf3c6b5..dbd267b95e2 100644 --- a/packages/dd-trace/src/appsec/rasp/fs-plugin.js +++ b/packages/dd-trace/src/appsec/rasp/fs-plugin.js @@ -14,9 +14,9 @@ const enabledFor = { let fsPlugin -function enterWith (fsProps, store = storage.getStore()) { +function enterWith (fsProps, store = storage('legacy').getStore()) { if (store && !store.fs?.opExcluded) { - storage.enterWith({ + storage('legacy').enterWith({ ...store, fs: { ...store.fs, @@ -42,7 +42,7 @@ class AppsecFsPlugin extends Plugin { } _onFsOperationStart () { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store) { enterWith({ root: store.fs?.root === undefined }, store) } @@ -53,9 +53,9 @@ class AppsecFsPlugin extends Plugin { } _onFsOperationFinishOrRenderEnd () { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store?.fs?.parentStore) { - storage.enterWith(store.fs.parentStore) + storage('legacy').enterWith(store.fs.parentStore) } } } diff --git a/packages/dd-trace/src/appsec/rasp/lfi.js b/packages/dd-trace/src/appsec/rasp/lfi.js index 657369ad0fd..80f6bd0a086 100644 --- a/packages/dd-trace/src/appsec/rasp/lfi.js +++ b/packages/dd-trace/src/appsec/rasp/lfi.js @@ -47,7 +47,7 @@ function onFirstReceivedRequest () { } function analyzeLfi (ctx) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return const { req, fs, res } = store diff --git a/packages/dd-trace/src/appsec/rasp/sql_injection.js b/packages/dd-trace/src/appsec/rasp/sql_injection.js index 157723258f7..a5bac20beae 100644 --- a/packages/dd-trace/src/appsec/rasp/sql_injection.js +++ b/packages/dd-trace/src/appsec/rasp/sql_injection.js @@ -49,7 +49,7 @@ function analyzePgSqlInjection (ctx) { } function analyzeSqlInjection (query, dbSystem, abortController) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return const { req, res } = store @@ -91,7 +91,7 @@ function hasAddressesObjectInputAddress (addressesObject) { function clearQuerySet ({ payload }) { if (!payload) return - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store) return const { req } = store diff --git a/packages/dd-trace/src/appsec/rasp/ssrf.js b/packages/dd-trace/src/appsec/rasp/ssrf.js index 7d429d74549..e65e00b0bd6 100644 --- a/packages/dd-trace/src/appsec/rasp/ssrf.js +++ b/packages/dd-trace/src/appsec/rasp/ssrf.js @@ -19,7 +19,7 @@ function disable () { } function analyzeSsrf (ctx) { - const store = storage.getStore() + const store = storage('legacy').getStore() const req = store?.req const outgoingUrl = (ctx.args.options?.uri && format(ctx.args.options.uri)) ?? ctx.args.uri diff --git a/packages/dd-trace/src/appsec/reporter.js b/packages/dd-trace/src/appsec/reporter.js index c2f9bac6cbc..8f16a1a513a 100644 --- a/packages/dd-trace/src/appsec/reporter.js +++ b/packages/dd-trace/src/appsec/reporter.js @@ -102,7 +102,7 @@ function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}) { } function reportMetrics (metrics, raspRule) { - const store = storage.getStore() + const store = storage('legacy').getStore() const rootSpan = store?.req && web.root(store.req) if (!rootSpan) return @@ -117,7 +117,7 @@ function reportMetrics (metrics, raspRule) { } function reportAttack (attackData) { - const store = storage.getStore() + const store = storage('legacy').getStore() const req = store?.req const rootSpan = web.root(req) if (!rootSpan) return @@ -162,7 +162,7 @@ function isFingerprintDerivative (derivative) { function reportDerivatives (derivatives) { if (!derivatives) return - const req = storage.getStore()?.req + const req = storage('legacy').getStore()?.req const rootSpan = web.root(req) if (!rootSpan) return diff --git a/packages/dd-trace/src/appsec/sdk/user_blocking.js b/packages/dd-trace/src/appsec/sdk/user_blocking.js index 162251b10c5..e0000ba1ac9 100644 --- a/packages/dd-trace/src/appsec/sdk/user_blocking.js +++ b/packages/dd-trace/src/appsec/sdk/user_blocking.js @@ -34,7 +34,7 @@ function checkUserAndSetUser (tracer, user) { function blockRequest (tracer, req, res) { if (!req || !res) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store) { req = req || store.req res = res || store.res diff --git a/packages/dd-trace/src/appsec/waf/index.js b/packages/dd-trace/src/appsec/waf/index.js index a14a5313a92..b025a123f46 100644 --- a/packages/dd-trace/src/appsec/waf/index.js +++ b/packages/dd-trace/src/appsec/waf/index.js @@ -48,7 +48,7 @@ function update (newRules) { function run (data, req, raspRule) { if (!req) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store || !store.req) { log.warn('[ASM] Request object not available in waf.run') return diff --git a/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js b/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js index c823ac30a56..df892054786 100644 --- a/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +++ b/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js @@ -119,6 +119,8 @@ class TestVisDynamicInstrumentation { const onHit = this.onHitBreakpointByProbeId.get(probeId) if (onHit) { onHit({ snapshot }) + } else { + log.warn('Received a breakpoint hit for an unknown probe') } }).unref() diff --git a/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js b/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js index 2b20b5703f9..de41291da73 100644 --- a/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +++ b/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js @@ -93,11 +93,14 @@ async function addBreakpoint (probe) { probe.location = { file, lines: [String(line)] } const script = findScriptFromPartialPath(file) - if (!script) throw new Error(`No loaded script found for ${file}`) + if (!script) { + log.error(`No loaded script found for ${file}`) + throw new Error(`No loaded script found for ${file}`) + } const [path, scriptId, sourceMapURL] = script - log.debug(`Adding breakpoint at ${path}:${line}`) + log.warn(`Adding breakpoint at ${path}:${line}`) let lineNumber = line @@ -109,15 +112,19 @@ async function addBreakpoint (probe) { } } - const { breakpointId } = await session.post('Debugger.setBreakpoint', { - location: { - scriptId, - lineNumber: lineNumber - 1 - } - }) + try { + const { breakpointId } = await session.post('Debugger.setBreakpoint', { + location: { + scriptId, + lineNumber: lineNumber - 1 + } + }) - breakpointIdToProbe.set(breakpointId, probe) - probeIdToBreakpointId.set(probe.id, breakpointId) + breakpointIdToProbe.set(breakpointId, probe) + probeIdToBreakpointId.set(probe.id, breakpointId) + } catch (e) { + log.error(`Error setting breakpoint at ${path}:${line}:`, e) + } } function start () { diff --git a/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js b/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js index 8a0ba970bc9..9cd37098143 100644 --- a/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +++ b/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js @@ -17,13 +17,13 @@ class TestApiManualPlugin extends CiPlugin { this.sourceRoot = process.cwd() this.unconfiguredAddSub('dd-trace:ci:manual:test:start', ({ testName, testSuite }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSuiteRelative = getTestSuitePath(testSuite, this.sourceRoot) const testSpan = this.startTestSpan(testName, testSuiteRelative) this.enter(testSpan, store) }) this.unconfiguredAddSub('dd-trace:ci:manual:test:finish', ({ status, error }) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSpan = store && store.span if (testSpan) { testSpan.setTag(TEST_STATUS, status) @@ -35,7 +35,7 @@ class TestApiManualPlugin extends CiPlugin { } }) this.unconfiguredAddSub('dd-trace:ci:manual:test:addTags', (tags) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const testSpan = store && store.span if (testSpan) { testSpan.addTags(tags) diff --git a/packages/dd-trace/src/config.js b/packages/dd-trace/src/config.js index 2beff234924..7e4299a0d74 100644 --- a/packages/dd-trace/src/config.js +++ b/packages/dd-trace/src/config.js @@ -518,6 +518,7 @@ class Config { this._setValue(defaults, 'ciVisAgentlessLogSubmissionEnabled', false) this._setValue(defaults, 'legacyBaggageEnabled', true) this._setValue(defaults, 'isTestDynamicInstrumentationEnabled', false) + this._setValue(defaults, 'isServiceUserProvided', false) this._setValue(defaults, 'logInjection', false) this._setValue(defaults, 'lookup', undefined) this._setValue(defaults, 'inferredProxyServicesEnabled', false) @@ -1156,6 +1157,7 @@ class Config { this._setString(calc, 'ciVisibilityTestSessionName', DD_TEST_SESSION_NAME) this._setBoolean(calc, 'ciVisAgentlessLogSubmissionEnabled', isTrue(DD_AGENTLESS_LOG_SUBMISSION_ENABLED)) this._setBoolean(calc, 'isTestDynamicInstrumentationEnabled', isTrue(DD_TEST_DYNAMIC_INSTRUMENTATION_ENABLED)) + this._setBoolean(calc, 'isServiceUserProvided', !!this._env.service) } this._setString(calc, 'dogstatsd.hostname', this._getHostname()) this._setBoolean(calc, 'isGitUploadEnabled', diff --git a/packages/dd-trace/src/data_streams_context.js b/packages/dd-trace/src/data_streams_context.js index e3c62d35e25..b266eb2cf61 100644 --- a/packages/dd-trace/src/data_streams_context.js +++ b/packages/dd-trace/src/data_streams_context.js @@ -2,14 +2,14 @@ const { storage } = require('../../datadog-core') const log = require('./log') function getDataStreamsContext () { - const store = storage.getStore() + const store = storage('legacy').getStore() return (store && store.dataStreamsContext) || null } function setDataStreamsContext (dataStreamsContext) { log.debug(() => `Setting new DSM Context: ${JSON.stringify(dataStreamsContext)}.`) - if (dataStreamsContext) storage.enterWith({ ...(storage.getStore()), dataStreamsContext }) + if (dataStreamsContext) storage('legacy').enterWith({ ...(storage('legacy').getStore()), dataStreamsContext }) } module.exports = { diff --git a/packages/dd-trace/src/exporters/common/agents.js b/packages/dd-trace/src/exporters/common/agents.js index 33bb18d583f..beeda0bfdbf 100644 --- a/packages/dd-trace/src/exporters/common/agents.js +++ b/packages/dd-trace/src/exporters/common/agents.js @@ -26,7 +26,7 @@ function createAgentClass (BaseAgent) { } _noop (callback) { - return storage.run({ noop: true }, callback) + return storage('legacy').run({ noop: true }, callback) } } diff --git a/packages/dd-trace/src/exporters/common/request.js b/packages/dd-trace/src/exporters/common/request.js index 2ff90236ee8..62aa28964b3 100644 --- a/packages/dd-trace/src/exporters/common/request.js +++ b/packages/dd-trace/src/exporters/common/request.js @@ -126,9 +126,9 @@ function request (data, options, callback) { activeRequests++ - const store = storage.getStore() + const store = storage('legacy').getStore() - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) const req = client.request(options, onResponse) @@ -146,7 +146,7 @@ function request (data, options, callback) { req.end() } - storage.enterWith(store) + storage('legacy').enterWith(store) } // TODO: Figure out why setTimeout is needed to avoid losing the async context diff --git a/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js b/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js index 45c3b0813a1..05646d86115 100644 --- a/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +++ b/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js @@ -29,7 +29,7 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin { if (modelName.includes('embed')) { return } - const span = storage.getStore()?.span + const span = storage('legacy').getStore()?.span this.setLLMObsTags({ request, span, response, modelProvider, modelName }) }) diff --git a/packages/dd-trace/src/log/writer.js b/packages/dd-trace/src/log/writer.js index 322c703b2b3..f826cfe9322 100644 --- a/packages/dd-trace/src/log/writer.js +++ b/packages/dd-trace/src/log/writer.js @@ -15,11 +15,11 @@ let logger = defaultLogger let logChannel = new LogChannel() function withNoop (fn) { - const store = storage.getStore() + const store = storage('legacy').getStore() - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) fn() - storage.enterWith(store) + storage('legacy').enterWith(store) } function unsubscribeAll () { diff --git a/packages/dd-trace/src/noop/span.js b/packages/dd-trace/src/noop/span.js index 554fe7423ba..fdd8c2dc585 100644 --- a/packages/dd-trace/src/noop/span.js +++ b/packages/dd-trace/src/noop/span.js @@ -6,7 +6,7 @@ const { storage } = require('../../../datadog-core') // TODO: noop storage? class NoopSpan { constructor (tracer, parent) { - this._store = storage.getHandle() + this._store = storage('legacy').getHandle() this._noopTracer = tracer this._noopContext = this._createContext(parent) } diff --git a/packages/dd-trace/src/opentracing/propagation/text_map.js b/packages/dd-trace/src/opentracing/propagation/text_map.js index 82bc9f2b30f..fd7d32760cb 100644 --- a/packages/dd-trace/src/opentracing/propagation/text_map.js +++ b/packages/dd-trace/src/opentracing/propagation/text_map.js @@ -325,6 +325,7 @@ class TextMapPropagator { if (context === null) { context = extractedContext if (this._config.tracePropagationExtractFirst) { + this._extractBaggageItems(carrier, context) return context } } else { @@ -344,10 +345,7 @@ class TextMapPropagator { } } - if (this._hasPropagationStyle('extract', 'baggage') && carrier.baggage) { - context = context || new DatadogSpanContext() - this._extractBaggageItems(carrier, context) - } + this._extractBaggageItems(carrier, context) return context || this._extractSqsdContext(carrier) } @@ -596,6 +594,9 @@ class TextMapPropagator { } _extractBaggageItems (carrier, spanContext) { + if (!this._hasPropagationStyle('extract', 'baggage')) return + if (!carrier || !carrier.baggage) return + if (!spanContext) return const baggages = carrier.baggage.split(',') for (const keyValue of baggages) { if (!keyValue.includes('=')) { diff --git a/packages/dd-trace/src/opentracing/span.js b/packages/dd-trace/src/opentracing/span.js index 2c464b2ed1a..252ec463adc 100644 --- a/packages/dd-trace/src/opentracing/span.js +++ b/packages/dd-trace/src/opentracing/span.js @@ -65,7 +65,7 @@ class DatadogSpan { this._debug = debug this._processor = processor this._prioritySampler = prioritySampler - this._store = storage.getHandle() + this._store = storage('legacy').getHandle() this._duration = undefined this._events = [] diff --git a/packages/dd-trace/src/plugin_manager.js b/packages/dd-trace/src/plugin_manager.js index c1b326dc767..7b200217fb2 100644 --- a/packages/dd-trace/src/plugin_manager.js +++ b/packages/dd-trace/src/plugin_manager.js @@ -143,6 +143,7 @@ module.exports = class PluginManager { ciVisibilityTestSessionName, ciVisAgentlessLogSubmissionEnabled, isTestDynamicInstrumentationEnabled, + isServiceUserProvided, middlewareTracingEnabled } = this._tracerConfig @@ -155,7 +156,8 @@ module.exports = class PluginManager { headers: headerTags || [], ciVisibilityTestSessionName, ciVisAgentlessLogSubmissionEnabled, - isTestDynamicInstrumentationEnabled + isTestDynamicInstrumentationEnabled, + isServiceUserProvided } if (logInjection !== undefined) { diff --git a/packages/dd-trace/src/plugins/apollo.js b/packages/dd-trace/src/plugins/apollo.js index 94ab360e921..1c0d6aa98fd 100644 --- a/packages/dd-trace/src/plugins/apollo.js +++ b/packages/dd-trace/src/plugins/apollo.js @@ -7,7 +7,7 @@ class ApolloBasePlugin extends TracingPlugin { static get kind () { return 'server' } bindStart (ctx) { - const store = storage.getStore() + const store = storage('legacy').getStore() const childOf = store ? store.span : null const span = this.startSpan(this.getOperationName(), { diff --git a/packages/dd-trace/src/plugins/ci_plugin.js b/packages/dd-trace/src/plugins/ci_plugin.js index 287d3e6d55d..d08462a813c 100644 --- a/packages/dd-trace/src/plugins/ci_plugin.js +++ b/packages/dd-trace/src/plugins/ci_plugin.js @@ -45,6 +45,7 @@ module.exports = class CiPlugin extends Plugin { constructor (...args) { super(...args) + this.fileLineToProbeId = new Map() this.rootDir = process.cwd() // fallback in case :session:start events are not emitted this.addSub(`ci:${this.constructor.id}:library-configuration`, ({ onDone }) => { @@ -335,7 +336,22 @@ module.exports = class CiPlugin extends Plugin { }) } - removeDiProbe (probeId) { + removeAllDiProbes () { + if (this.fileLineToProbeId.size === 0) { + return Promise.resolve() + } + log.debug('Removing all Dynamic Instrumentation probes') + return Promise.all(Array.from(this.fileLineToProbeId.keys()) + .map((fileLine) => { + const [file, line] = fileLine.split(':') + return this.removeDiProbe({ file, line }) + })) + } + + removeDiProbe ({ file, line }) { + const probeId = this.fileLineToProbeId.get(`${file}:${line}`) + log.warn(`Removing probe from ${file}:${line}, with id: ${probeId}`) + this.fileLineToProbeId.delete(probeId) return this.di.removeProbe(probeId) } @@ -346,9 +362,27 @@ module.exports = class CiPlugin extends Plugin { log.warn('Could not add breakpoint for dynamic instrumentation') return } + log.debug('Adding breakpoint for Dynamic Instrumentation') + + this.testErrorStackIndex = stackIndex + const activeProbeKey = `${file}:${line}` + + if (this.fileLineToProbeId.has(activeProbeKey)) { + log.warn('Probe already set for this line') + const oldProbeId = this.fileLineToProbeId.get(activeProbeKey) + return { + probeId: oldProbeId, + setProbePromise: Promise.resolve(), + stackIndex, + file, + line + } + } const [probeId, setProbePromise] = this.di.addLineProbe({ file, line }, this.onDiBreakpointHit.bind(this)) + this.fileLineToProbeId.set(activeProbeKey, probeId) + return { probeId, setProbePromise, diff --git a/packages/dd-trace/src/plugins/log_plugin.js b/packages/dd-trace/src/plugins/log_plugin.js index b0812ea46d3..f4e329c05fd 100644 --- a/packages/dd-trace/src/plugins/log_plugin.js +++ b/packages/dd-trace/src/plugins/log_plugin.js @@ -40,7 +40,7 @@ module.exports = class LogPlugin extends Plugin { super(...args) this.addSub(`apm:${this.constructor.id}:log`, (arg) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const span = store && store.span // NOTE: This needs to run whether or not there is a span diff --git a/packages/dd-trace/src/plugins/plugin.js b/packages/dd-trace/src/plugins/plugin.js index e8d9c911a69..9d39320747d 100644 --- a/packages/dd-trace/src/plugins/plugin.js +++ b/packages/dd-trace/src/plugins/plugin.js @@ -10,7 +10,7 @@ class Subscription { constructor (event, handler) { this._channel = dc.channel(event) this._handler = (message, name) => { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store || !store.noop) { handler(message, name) } @@ -30,7 +30,7 @@ class StoreBinding { constructor (event, transform) { this._channel = dc.channel(event) this._transform = data => { - const store = storage.getStore() + const store = storage('legacy').getStore() return !store || !store.noop ? transform(data) @@ -39,11 +39,11 @@ class StoreBinding { } enable () { - this._channel.bindStore(storage, this._transform) + this._channel.bindStore(storage('legacy'), this._transform) } disable () { - this._channel.unbindStore(storage, this._transform) + this._channel.unbindStore(storage('legacy')) } } @@ -62,14 +62,14 @@ module.exports = class Plugin { } enter (span, store) { - store = store || storage.getStore() - storage.enterWith({ ...store, span }) + store = store || storage('legacy').getStore() + storage('legacy').enterWith({ ...store, span }) } // TODO: Implement filters on resource name for all plugins. /** Prevents creation of spans here and for all async descendants. */ skip () { - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) } addSub (channelName, handler) { @@ -91,7 +91,7 @@ module.exports = class Plugin { } addError (error) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (!store || !store.span) return diff --git a/packages/dd-trace/src/plugins/tracing.js b/packages/dd-trace/src/plugins/tracing.js index e384b8cb7a7..b928eda2abf 100644 --- a/packages/dd-trace/src/plugins/tracing.js +++ b/packages/dd-trace/src/plugins/tracing.js @@ -16,7 +16,7 @@ class TracingPlugin extends Plugin { } get activeSpan () { - const store = storage.getStore() + const store = storage('legacy').getStore() return store && store.span } @@ -102,7 +102,7 @@ class TracingPlugin extends Plugin { } startSpan (name, { childOf, kind, meta, metrics, service, resource, type } = {}, enter = true) { - const store = storage.getStore() + const store = storage('legacy').getStore() if (store && childOf === undefined) { childOf = store.span } @@ -126,7 +126,7 @@ class TracingPlugin extends Plugin { // TODO: Remove this after migration to TracingChannel is done. if (enter) { - storage.enterWith({ ...store, span }) + storage('legacy').enterWith({ ...store, span }) } return span diff --git a/packages/dd-trace/src/plugins/util/git.js b/packages/dd-trace/src/plugins/util/git.js index 47707a48679..10fa7494b00 100644 --- a/packages/dd-trace/src/plugins/util/git.js +++ b/packages/dd-trace/src/plugins/util/git.js @@ -37,8 +37,8 @@ function sanitizedExec ( durationMetric, errorMetric ) { - const store = storage.getStore() - storage.enterWith({ noop: true }) + const store = storage('legacy').getStore() + storage('legacy').enterWith({ noop: true }) let startTime if (operationMetric) { @@ -64,7 +64,7 @@ function sanitizedExec ( log.error('Git plugin error executing command', err) return '' } finally { - storage.enterWith(store) + storage('legacy').enterWith(store) } } diff --git a/packages/dd-trace/src/plugins/util/test.js b/packages/dd-trace/src/plugins/util/test.js index 2d8ce1a1d33..407676d5c57 100644 --- a/packages/dd-trace/src/plugins/util/test.js +++ b/packages/dd-trace/src/plugins/util/test.js @@ -108,6 +108,8 @@ const TEST_LEVEL_EVENT_TYPES = [ 'test_session_end' ] +const DD_TEST_IS_USER_PROVIDED_SERVICE = '_dd.test.is_user_provided_service' + // Dynamic instrumentation - Test optimization integration tags const DI_ERROR_DEBUG_INFO_CAPTURED = 'error.debug_info_captured' const DI_DEBUG_ERROR_PREFIX = '_dd.debug.error' @@ -199,7 +201,8 @@ module.exports = { DI_DEBUG_ERROR_SNAPSHOT_ID_SUFFIX, DI_DEBUG_ERROR_FILE_SUFFIX, DI_DEBUG_ERROR_LINE_SUFFIX, - getFormattedError + getFormattedError, + DD_TEST_IS_USER_PROVIDED_SERVICE } // Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19 @@ -275,6 +278,7 @@ function getTestEnvironmentMetadata (testFramework, config) { const metadata = { [TEST_FRAMEWORK]: testFramework, + [DD_TEST_IS_USER_PROVIDED_SERVICE]: (config && config.isServiceUserProvided) ? 'true' : 'false', ...gitMetadata, ...ciMetadata, ...userProvidedGitMetadata, diff --git a/packages/dd-trace/src/profiling/exporters/agent.js b/packages/dd-trace/src/profiling/exporters/agent.js index 6ad63486a87..b467a84dd9e 100644 --- a/packages/dd-trace/src/profiling/exporters/agent.js +++ b/packages/dd-trace/src/profiling/exporters/agent.js @@ -40,8 +40,8 @@ function countStatusCode (statusCode) { function sendRequest (options, form, callback) { const request = options.protocol === 'https:' ? httpsRequest : httpRequest - const store = storage.getStore() - storage.enterWith({ noop: true }) + const store = storage('legacy').getStore() + storage('legacy').enterWith({ noop: true }) requestCounter.inc() const start = perf.now() const req = request(options, res => { @@ -65,7 +65,7 @@ function sendRequest (options, form, callback) { sizeDistribution.track(form.size()) form.pipe(req) } - storage.enterWith(store) + storage('legacy').enterWith(store) } function getBody (stream, callback) { diff --git a/packages/dd-trace/src/profiling/profilers/wall.js b/packages/dd-trace/src/profiling/profilers/wall.js index bcc7959074f..4769f049b98 100644 --- a/packages/dd-trace/src/profiling/profilers/wall.js +++ b/packages/dd-trace/src/profiling/profilers/wall.js @@ -25,7 +25,7 @@ const ProfilingContext = Symbol('NativeWallProfiler.ProfilingContext') let kSampleCount function getActiveSpan () { - const store = storage.getStore() + const store = storage('legacy').getStore() return store && store.span } diff --git a/packages/dd-trace/src/scope.js b/packages/dd-trace/src/scope.js index 9b96ff565ea..75cb7409066 100644 --- a/packages/dd-trace/src/scope.js +++ b/packages/dd-trace/src/scope.js @@ -8,7 +8,7 @@ const originals = new WeakMap() class Scope { active () { - const store = storage.getStore() + const store = storage('legacy').getStore() return (store && store.span) || null } @@ -16,10 +16,10 @@ class Scope { activate (span, callback) { if (typeof callback !== 'function') return callback - const oldStore = storage.getStore() - const newStore = span ? storage.getStore(span._store) : oldStore + const oldStore = storage('legacy').getStore() + const newStore = span ? storage('legacy').getStore(span._store) : oldStore - storage.enterWith({ ...newStore, span }) + storage('legacy').enterWith({ ...newStore, span }) try { return callback() @@ -30,7 +30,7 @@ class Scope { throw e } finally { - storage.enterWith(oldStore) + storage('legacy').enterWith(oldStore) } } diff --git a/packages/dd-trace/src/tracer.js b/packages/dd-trace/src/tracer.js index 64b6b1be52d..243e25575a5 100644 --- a/packages/dd-trace/src/tracer.js +++ b/packages/dd-trace/src/tracer.js @@ -3,13 +3,11 @@ const Tracer = require('./opentracing/tracer') const tags = require('../../../ext/tags') const Scope = require('./scope') -const { storage } = require('../../datadog-core') const { isError } = require('./util') const { setStartupLogConfig } = require('./startup-log') const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants') const { DataStreamsProcessor } = require('./datastreams/processor') const { DsmPathwayCodec } = require('./datastreams/pathway') -const { DD_MAJOR } = require('../../../version') const DataStreamsContext = require('./data_streams_context') const { DataStreamsCheckpointer } = require('./data_streams') const { flushStartupLogs } = require('../../datadog-instrumentations/src/check_require_cache') @@ -60,10 +58,6 @@ class DatadogTracer extends Tracer { childOf: this.scope().active() }, options) - if (!options.childOf && options.orphanable === false && DD_MAJOR < 4) { - return fn(null, () => {}) - } - const span = this.startSpan(name, options) addTags(span, options) @@ -106,19 +100,11 @@ class DatadogTracer extends Tracer { const tracer = this return function () { - const store = storage.getStore() - - if (store && store.noop) return fn.apply(this, arguments) - let optionsObj = options if (typeof optionsObj === 'function' && typeof fn === 'function') { optionsObj = optionsObj.apply(this, arguments) } - if (optionsObj && optionsObj.orphanable === false && !tracer.scope().active() && DD_MAJOR < 4) { - return fn.apply(this, arguments) - } - const lastArgId = arguments.length - 1 const cb = arguments[lastArgId] diff --git a/packages/dd-trace/test/.eslintrc.json b/packages/dd-trace/test/.eslintrc.json deleted file mode 100644 index 3a9e197c393..00000000000 --- a/packages/dd-trace/test/.eslintrc.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": [ - "../../../.eslintrc.json" - ], - "parserOptions": { - "ecmaVersion": 2022 - }, - "env": { - "mocha": true, - "es2022": true - }, - "globals": { - "expect": true, - "sinon": true, - "proxyquire": true, - "withVersions": true - }, - "rules": { - "no-unused-expressions": 0, - "handle-callback-err": 0, - "no-loss-of-precision": 0 - } -} diff --git a/packages/dd-trace/test/appsec/graphql.spec.js b/packages/dd-trace/test/appsec/graphql.spec.js index c8a7221828a..308103fad87 100644 --- a/packages/dd-trace/test/appsec/graphql.spec.js +++ b/packages/dd-trace/test/appsec/graphql.spec.js @@ -95,7 +95,7 @@ describe('GraphQL', () => { describe('onGraphqlStartResolve', () => { beforeEach(() => { sinon.stub(waf, 'run').returns(['']) - sinon.stub(storage, 'getStore').returns({ req: {} }) + sinon.stub(storage('legacy'), 'getStore').returns({ req: {} }) sinon.stub(web, 'root').returns({}) graphql.enable() }) @@ -131,7 +131,7 @@ describe('GraphQL', () => { user: [{ id: '1234' }] } - storage.getStore().req = undefined + storage('legacy').getStore().req = undefined startGraphqlResolve.publish({ context, resolverInfo }) @@ -160,7 +160,7 @@ describe('GraphQL', () => { const res = {} beforeEach(() => { - sinon.stub(storage, 'getStore').returns({ req, res }) + sinon.stub(storage('legacy'), 'getStore').returns({ req, res }) graphql.enable() graphqlMiddlewareChannel.start.publish({ req, res }) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/code-injection-analyzer.express.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/code-injection-analyzer.express.plugin.spec.js index 9b2fcf2b36c..49c650328df 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/code-injection-analyzer.express.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/code-injection-analyzer.express.plugin.spec.js @@ -49,7 +49,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -110,7 +110,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -149,7 +149,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -188,7 +188,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -228,7 +228,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -269,7 +269,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -311,7 +311,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) @@ -353,7 +353,7 @@ describe('Code injection vulnerability', () => { testThatRequestHasVulnerability({ fn: (req, res) => { const source = '1 + 2' - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/command-injection-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/command-injection-analyzer.spec.js index 248a310ab90..144d150eac3 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/command-injection-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/command-injection-analyzer.spec.js @@ -9,7 +9,7 @@ describe('command injection analyzer', () => { prepareTestServerForIast('command injection analyzer', (testThatRequestHasVulnerability, testThatRequestHasNoVulnerability) => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const command = newTaintedString(iastContext, 'ls -la', 'param', 'Request') const childProcess = require('child_process') diff --git a/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.ldapjs.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.ldapjs.plugin.spec.js index 6e0e68dc54e..b81d063471d 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.ldapjs.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.ldapjs.plugin.spec.js @@ -47,7 +47,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { describe('has vulnerability', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let filter = '(objectClass=*)' @@ -84,7 +84,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { describe('context is not null after search end event', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let filter = '(objectClass=*)' @@ -95,7 +95,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { return reject(err) } searchRes.on('end', () => { - const storeEnd = storage.getStore() + const storeEnd = storage('legacy').getStore() const iastCtxEnd = iastContextFunctions.getIastContext(storeEnd) expect(iastCtxEnd).to.not.be.undefined @@ -109,7 +109,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { describe('remove listener should work as expected', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let filter = '(objectClass=*)' @@ -144,7 +144,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { if (err) { reject(err) } else { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let filter = '(objectClass=*)' @@ -155,7 +155,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { return reject(err) } searchRes.on('end', () => { - const storeEnd = storage.getStore() + const storeEnd = storage('legacy').getStore() const iastCtxEnd = iastContextFunctions.getIastContext(storeEnd) expect(iastCtxEnd).to.not.be.undefined @@ -199,7 +199,7 @@ describe('ldap-injection-analyzer with ldapjs', () => { describe('has vulnerability', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let filter = '(objectClass=*)' diff --git a/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.spec.js index c8af2de6846..5f50f8ab197 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/ldap-injection-analyzer.spec.js @@ -93,8 +93,16 @@ describe('ldap-injection-analyzer', () => { const getStore = sinon.stub().returns(store) const getIastContext = sinon.stub().returns(iastContext) + const datadogCore = { + storage: () => { + return { + getStore + } + } + } + const iastPlugin = proxyquire('../../../../src/appsec/iast/iast-plugin', { - '../../../../datadog-core': { storage: { getStore } }, + '../../../../datadog-core': datadogCore, './iast-context': { getIastContext } }) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/path-traversal-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/path-traversal-analyzer.spec.js index 3fe86dacd8d..f914006b5e0 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/path-traversal-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/path-traversal-analyzer.spec.js @@ -186,7 +186,7 @@ prepareTestServerForIast('integration test', (testThatRequestHasVulnerability, t describe(description, () => { describe('vulnerable', () => { testThatRequestHasVulnerability(function () { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const callArgs = [...args] if (vulnerableIndex > -1) { diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.knex.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.knex.plugin.spec.js index a5dddc6b888..12524327a79 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.knex.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.knex.plugin.spec.js @@ -48,7 +48,7 @@ describe('sql-injection-analyzer with knex', () => { describe('simple raw query', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' @@ -70,7 +70,7 @@ describe('sql-injection-analyzer with knex', () => { describe('nested raw query', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let taintedSql = 'SELECT 1' @@ -90,7 +90,7 @@ describe('sql-injection-analyzer with knex', () => { describe('nested raw query - onRejected as then argument', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let taintedSql = 'SELECT 1' @@ -110,7 +110,7 @@ describe('sql-injection-analyzer with knex', () => { describe('nested raw query - with catch', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let taintedSql = 'SELECT 1' @@ -131,7 +131,7 @@ describe('sql-injection-analyzer with knex', () => { describe('nested raw query - asCallback', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let taintedSql = 'SELECT 1' diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql.plugin.spec.js index c740e424ecf..1c802b5634b 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql.plugin.spec.js @@ -47,7 +47,7 @@ describe('sql-injection-analyzer with mysql', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') @@ -97,7 +97,7 @@ describe('sql-injection-analyzer with mysql', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql2.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql2.plugin.spec.js index b692402c03c..962ba2dbf71 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql2.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.mysql2.plugin.spec.js @@ -29,7 +29,7 @@ describe('sql-injection-analyzer with mysql2', () => { describe('has vulnerability', () => { testThatRequestHasVulnerability(() => { return new Promise((resolve, reject) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.pg.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.pg.plugin.spec.js index 082034ce307..f0409ea8758 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.pg.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.pg.plugin.spec.js @@ -60,7 +60,7 @@ describe('sql-injection-analyzer with pg', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') @@ -95,7 +95,7 @@ describe('sql-injection-analyzer with pg', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') @@ -107,7 +107,7 @@ describe('sql-injection-analyzer with pg', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' sql = newTaintedString(iastCtx, sql, 'param', 'Request') diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.sequelize.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.sequelize.plugin.spec.js index b54c64b4186..69b874e263b 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.sequelize.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.sequelize.plugin.spec.js @@ -34,7 +34,7 @@ describe('sql-injection-analyzer with sequelize', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' @@ -53,7 +53,7 @@ module.exports = function (sequelize, sql) { const filepath = path.join(os.tmpdir(), 'test-sequelize-sqli.js') fs.writeFileSync(filepath, externalFileContent) - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) let sql = 'SELECT 1' diff --git a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js index 8c4d26103d3..938c96a02c4 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/sql-injection-analyzer.spec.js @@ -133,8 +133,16 @@ describe('sql-injection-analyzer', () => { const getStore = sinon.stub().returns(store) const getIastContext = sinon.stub().returns(iastContext) + const datadogCore = { + storage: () => { + return { + getStore + } + } + } + const iastPlugin = proxyquire('../../../../src/appsec/iast/iast-plugin', { - '../../../../datadog-core': { storage: { getStore } }, + '../../../../datadog-core': datadogCore, './iast-context': { getIastContext } }) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/ssrf-analyzer.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/ssrf-analyzer.spec.js index d578007b948..56105197622 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/ssrf-analyzer.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/ssrf-analyzer.spec.js @@ -79,7 +79,7 @@ describe('ssrf analyzer', () => { describe(requestMethodData.httpMethodName, () => { describe('with url', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const url = newTaintedString(iastContext, pluginName + '://www.google.com', 'param', 'Request') @@ -97,7 +97,7 @@ describe('ssrf analyzer', () => { describe('with options', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const host = newTaintedString(iastContext, 'www.google.com', 'param', 'Request') @@ -126,7 +126,7 @@ describe('ssrf analyzer', () => { describe('http2', () => { testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const url = newTaintedString(iastContext, 'http://www.datadoghq.com', 'param', 'Request') diff --git a/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.handlebars.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.handlebars.plugin.spec.js index b3398543a04..2704cc2afef 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.handlebars.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.handlebars.plugin.spec.js @@ -22,14 +22,14 @@ describe('template-injection-analyzer with handlebars', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', 'Request') lib.compile(template) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.compile(template) @@ -51,14 +51,14 @@ describe('template-injection-analyzer with handlebars', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', 'Request') lib.precompile(template) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.precompile(template) @@ -80,7 +80,7 @@ describe('template-injection-analyzer with handlebars', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const partial = newTaintedString(iastContext, source, 'param', 'Request') @@ -88,7 +88,7 @@ describe('template-injection-analyzer with handlebars', () => { }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const partial = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.pug.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.pug.plugin.spec.js index 574f256fd53..f07b2b57cac 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.pug.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/template-injection-analyzer.pug.plugin.spec.js @@ -22,14 +22,14 @@ describe('template-injection-analyzer with pug', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', 'Request') lib.compile(template) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.compile(template) @@ -52,14 +52,14 @@ describe('template-injection-analyzer with pug', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', 'Request') lib.compileClient(template) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.compileClient(template) @@ -81,14 +81,14 @@ describe('template-injection-analyzer with pug', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', 'Request') lib.compileClientWithDependenciesTracked(template, {}) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const template = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.compileClientWithDependenciesTracked(template, {}) @@ -110,14 +110,14 @@ describe('template-injection-analyzer with pug', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', 'Request') lib.render(str) }, 'TEMPLATE_INJECTION') testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, source, 'param', SQL_ROW_VALUE) lib.render(str) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/untrusted-deserialization-analyzer.node-serialize.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/untrusted-deserialization-analyzer.node-serialize.plugin.spec.js index b027aa07cae..904e8df95af 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/untrusted-deserialization-analyzer.node-serialize.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/untrusted-deserialization-analyzer.node-serialize.plugin.spec.js @@ -21,7 +21,7 @@ describe('untrusted-deserialization-analyzer with node-serialize', () => { }) testThatRequestHasVulnerability(() => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const str = newTaintedString(iastContext, obj, 'query', 'Request') lib.unserialize(str) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/unvalidated-redirect-analyzer.express.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/unvalidated-redirect-analyzer.express.plugin.spec.js index 2686f6e2d1b..6df6879889d 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/unvalidated-redirect-analyzer.express.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/unvalidated-redirect-analyzer.express.plugin.spec.js @@ -28,7 +28,7 @@ describe('Unvalidated Redirect vulnerability', () => { prepareTestServerForIastInExpress('in express', version, (testThatRequestHasVulnerability, testThatRequestHasNoVulnerability) => { testThatRequestHasVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'https://app.com?id=tron', 'param', 'Request') redirectFunctions.insecureWithResHeaderMethod('location', location, res) @@ -41,7 +41,7 @@ describe('Unvalidated Redirect vulnerability', () => { }) testThatRequestHasVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'http://user@app.com/', 'param', 'Request') redirectFunctions.insecureWithResRedirectMethod(location, res) @@ -54,7 +54,7 @@ describe('Unvalidated Redirect vulnerability', () => { }) testThatRequestHasVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'http://user@app.com/', 'param', 'Request') redirectFunctions.insecureWithResLocationMethod(location, res) @@ -67,7 +67,7 @@ describe('Unvalidated Redirect vulnerability', () => { }) testThatRequestHasNoVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'http://user@app.com/', 'pathParam', 'Request') res.header('X-test', location) diff --git a/packages/dd-trace/test/appsec/iast/analyzers/vulnerability-analyzer.express.plugin.spec.js b/packages/dd-trace/test/appsec/iast/analyzers/vulnerability-analyzer.express.plugin.spec.js index b386a7ba0af..f55e6045932 100644 --- a/packages/dd-trace/test/appsec/iast/analyzers/vulnerability-analyzer.express.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/analyzers/vulnerability-analyzer.express.plugin.spec.js @@ -45,7 +45,7 @@ describe('Vulnerability Analyzer plugin', () => { prepareTestServerForIastInExpress('should find original source line minified or not', version, (testThatRequestHasVulnerability, testThatRequestHasNoVulnerability) => { testThatRequestHasVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'https://app.com?id=tron', 'param', 'Request') redirectMinFunctions.insecureWithResHeaderMethod('location', location, res) @@ -58,7 +58,7 @@ describe('Vulnerability Analyzer plugin', () => { }) testThatRequestHasVulnerability((req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastCtx = iastContextFunctions.getIastContext(store) const location = newTaintedString(iastCtx, 'https://app.com?id=tron', 'param', 'Request') redirectFunctions.insecureWithResHeaderMethod('location', location, res) diff --git a/packages/dd-trace/test/appsec/iast/context/context-plugin.spec.js b/packages/dd-trace/test/appsec/iast/context/context-plugin.spec.js index e08e3565c41..db5f76987e3 100644 --- a/packages/dd-trace/test/appsec/iast/context/context-plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/context/context-plugin.spec.js @@ -120,7 +120,7 @@ describe('IastContextPlugin', () => { let getStore beforeEach(() => { - getStore = sinon.stub(storage, 'getStore') + getStore = sinon.stub(storage('legacy'), 'getStore') getStore.returns(store) }) @@ -203,7 +203,7 @@ describe('IastContextPlugin', () => { const store = {} beforeEach(() => { - sinon.stub(storage, 'getStore').returns(store) + sinon.stub(storage('legacy'), 'getStore').returns(store) }) it('should send the vulnerabilities if any', () => { diff --git a/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js b/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js index 21696d3b70f..acf585ec52b 100644 --- a/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/iast-plugin.spec.js @@ -12,7 +12,7 @@ const SOURCE_TYPE = TagKey.SOURCE_TYPE describe('IAST Plugin', () => { const loadChannel = channel('dd-trace:instrumentation:load') - let logError, addSubMock, getIastContext, configureMock, datadogCore + let logError, addSubMock, getIastContext, configureMock, legacyStorage const handler = () => { throw new Error('handler error') @@ -44,10 +44,8 @@ describe('IAST Plugin', () => { } } - datadogCore = { - storage: { - getStore: sinon.stub() - } + legacyStorage = { + getStore: () => sinon.stub() } const iastPluginMod = proxyquire('../../../src/appsec/iast/iast-plugin', { @@ -62,7 +60,7 @@ describe('IAST Plugin', () => { isEnabled: () => false }, './telemetry/metrics': {}, - '../../../../datadog-core': datadogCore + '../../../../datadog-core': { storage: () => legacyStorage } }) iastPlugin = new iastPluginMod.IastPlugin() }) diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/plugin.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/plugin.spec.js index af575ce9652..5d15dafdf28 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/plugin.spec.js @@ -27,8 +27,10 @@ describe('IAST Taint tracking plugin', () => { const store = {} const datadogCore = { - storage: { - getStore: () => store + storage: () => { + return { + getStore: () => store + } } } diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter-telemetry.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter-telemetry.spec.js index 8b3b3a76ad4..dad93283282 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter-telemetry.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter-telemetry.spec.js @@ -6,7 +6,7 @@ const { INSTRUMENTED_PROPAGATION } = require('../../../../src/appsec/iast/teleme const { Verbosity } = require('../../../../src/appsec/iast/telemetry/verbosity') describe('rewriter telemetry', () => { - let iastTelemetry, rewriter, getRewriteFunction + let iastTelemetry, rewriter, getRewriteFunction, incrementTelemetryIfNeeded let instrumentedPropagationInc beforeEach(() => { @@ -17,6 +17,7 @@ describe('rewriter telemetry', () => { '../telemetry': iastTelemetry }) getRewriteFunction = rewriterTelemetry.getRewriteFunction + incrementTelemetryIfNeeded = rewriterTelemetry.incrementTelemetryIfNeeded rewriter = { rewrite: (content) => { return { @@ -69,4 +70,26 @@ describe('rewriter telemetry', () => { expect(instrumentedPropagationInc).to.be.calledOnceWith(undefined, result.metrics.instrumentedPropagation) }) + + describe('incrementTelemetryIfNeeded', () => { + it('should not increment telemetry when verbosity is OFF', () => { + iastTelemetry.verbosity = Verbosity.OFF + const metrics = { + instrumentedPropagation: 2 + } + incrementTelemetryIfNeeded(metrics) + + expect(instrumentedPropagationInc).not.to.be.called + }) + + it('should increment telemetry when verbosity is not OFF', () => { + iastTelemetry.verbosity = Verbosity.DEBUG + const metrics = { + instrumentedPropagation: 2 + } + incrementTelemetryIfNeeded(metrics) + + expect(instrumentedPropagationInc).to.be.calledOnceWith(undefined, metrics.instrumentedPropagation) + }) + }) }) diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter.spec.js index 36dd400afb0..9996bd9028c 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/rewriter.spec.js @@ -2,6 +2,8 @@ const { expect } = require('chai') const proxyquire = require('proxyquire') +const constants = require('../../../../src/appsec/iast/taint-tracking/constants') +const dc = require('dc-polyfill') describe('IAST Rewriter', () => { it('Addon should return a rewritter instance', () => { @@ -13,7 +15,8 @@ describe('IAST Rewriter', () => { }) describe('Enabling rewriter', () => { - let rewriter, iastTelemetry, shimmer + let rewriter, iastTelemetry, shimmer, Module, cacheRewrittenSourceMap, log, rewriterTelemetry + let workerThreads, MessageChannel, port1On, port1Unref class Rewriter { rewrite (content, filename) { @@ -36,28 +39,63 @@ describe('IAST Rewriter', () => { unwrap: sinon.spy() } + Module = { + register: sinon.stub() + } + + cacheRewrittenSourceMap = sinon.stub() + + log = { + error: sinon.stub() + } + const kSymbolPrepareStackTrace = Symbol('kTestSymbolPrepareStackTrace') + rewriterTelemetry = { + incrementTelemetryIfNeeded: sinon.stub() + } + + workerThreads = require('worker_threads') + + MessageChannel = workerThreads.MessageChannel + workerThreads.MessageChannel = function () { + const res = new MessageChannel(...arguments) + port1On = sinon.spy(res.port1, 'on') + port1Unref = sinon.spy(res.port1, 'unref') + + return res + } rewriter = proxyquire('../../../../src/appsec/iast/taint-tracking/rewriter', { '@datadog/native-iast-rewriter': { Rewriter, getPrepareStackTrace: function (fn) { - const testWrap = function testWrappedPrepareStackTrace (_, callsites) { - return fn(_, callsites) + const testWrap = function testWrappedPrepareStackTrace (error, callsites) { + if (typeof fn !== 'function') { + return error.stack + } + + return fn?.(error, callsites) } + Object.defineProperty(testWrap, kSymbolPrepareStackTrace, { value: true }) return testWrap }, - kSymbolPrepareStackTrace + kSymbolPrepareStackTrace, + cacheRewrittenSourceMap }, '../../../../../datadog-shimmer': shimmer, - '../../telemetry': iastTelemetry + '../../telemetry': iastTelemetry, + module: Module, + '../../../log': log, + './rewriter-telemetry': rewriterTelemetry, + worker_threads: workerThreads }) }) afterEach(() => { + workerThreads.MessageChannel = MessageChannel sinon.reset() }) @@ -127,6 +165,171 @@ describe('IAST Rewriter', () => { Error.prepareStackTrace = orig }) + + describe('esm rewriter', () => { + let originalNodeOptions, originalExecArgv + + beforeEach(() => { + originalNodeOptions = process.env.NODE_OPTIONS + originalExecArgv = process.execArgv + process.env.NODE_OPTIONS = '' + process.execArgv = [] + }) + + afterEach(() => { + process.env.NODE_OPTIONS = originalNodeOptions + process.execArgv = originalExecArgv + rewriter.disableRewriter() + }) + + it('Should not enable esm rewriter when ESM is not instrumented', () => { + rewriter.enableRewriter() + + expect(Module.register).not.to.be.called + }) + + it('Should enable esm rewriter when ESM is configured with --loader exec arg', () => { + process.execArgv = ['--loader', 'dd-trace/initialize.mjs'] + + rewriter.enableRewriter() + delete Error.prepareStackTrace + + expect(Module.register).to.be.calledOnce + }) + + it('Should enable esm rewriter when ESM is configured with --experimental-loader exec arg', () => { + process.execArgv = ['--experimental-loader', 'dd-trace/initialize.mjs'] + + rewriter.enableRewriter() + + expect(Module.register).to.be.calledOnce + }) + + it('Should enable esm rewriter when ESM is configured with --loader in NODE_OPTIONS', () => { + process.env.NODE_OPTIONS = '--loader dd-trace/initialize.mjs' + + rewriter.enableRewriter() + + expect(Module.register).to.be.calledOnce + }) + + it('Should enable esm rewriter when ESM is configured with --experimental-loader in NODE_OPTIONS', () => { + process.env.NODE_OPTIONS = '--experimental-loader dd-trace/initialize.mjs' + + rewriter.enableRewriter() + + expect(Module.register).to.be.calledOnce + }) + + describe('thread communication', () => { + let port + + function waitUntilCheckSuccess (check, maxMs = 500) { + setTimeout(() => { + try { + check() + } catch (e) { + if (maxMs > 0) { + waitUntilCheckSuccess(check, maxMs - 10) + return + } + + throw e + } + }, 10) + } + + beforeEach(() => { + process.execArgv = ['--loader', 'dd-trace/initialize.mjs'] + rewriter.enableRewriter() + port = Module.register.args[0][1].data.port + }) + + it('should cache sourceMaps when metrics status is modified', (done) => { + const content = 'file-content' + const data = { + rewritten: { + metrics: { status: 'modified' }, + content + }, + url: 'file://file.js' + } + + port.postMessage({ type: constants.REWRITTEN_MESSAGE, data }) + + waitUntilCheckSuccess(() => { + expect(cacheRewrittenSourceMap).to.be.calledOnceWith('file.js', content) + + done() + }) + }) + + it('should call to increment telemetry', (done) => { + const content = 'file-content' + const metrics = { status: 'modified' } + const data = { + rewritten: { + metrics, + content + }, + url: 'file://file.js' + } + + port.postMessage({ type: constants.REWRITTEN_MESSAGE, data }) + + waitUntilCheckSuccess(() => { + expect(rewriterTelemetry.incrementTelemetryIfNeeded).to.be.calledOnceWith(metrics) + + done() + }) + }) + + it('should publish hardcoded secrets channel with literals', (done) => { + const content = 'file-content' + const metrics = { status: 'modified' } + const literalsResult = ['literal1', 'literal2'] + const data = { + rewritten: { + metrics, + content, + literalsResult + }, + url: 'file://file.js' + } + const hardcodedSecretCh = dc.channel('datadog:secrets:result') + + function onHardcodedSecret (literals) { + expect(literals).to.deep.equal(literalsResult) + + hardcodedSecretCh.unsubscribe(onHardcodedSecret) + done() + } + + hardcodedSecretCh.subscribe(onHardcodedSecret) + + port.postMessage({ type: constants.REWRITTEN_MESSAGE, data }) + }) + + it('should log the message', (done) => { + const messages = ['this is a %s', 'test'] + const data = { + level: 'error', + messages + } + + port.postMessage({ type: constants.LOG_MESSAGE, data }) + + waitUntilCheckSuccess(() => { + expect(log.error).to.be.calledOnceWith(...messages) + done() + }) + }) + + it('should call port1.on before port1.unref', () => { + expect(port1On).to.be.calledBefore(port1Unref) + }) + }) + }) }) describe('getOriginalPathAndLineFromSourceMap', () => { diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.cookie.plugin.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.cookie.plugin.spec.js index 782613e44e4..e6638b28309 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.cookie.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.cookie.plugin.spec.js @@ -16,7 +16,7 @@ describe('Cookies sourcing with cookies', () => { let cookie withVersions('cookie', 'cookie', version => { function app () { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const rawCookies = 'cookie=value' diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.express.plugin.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.express.plugin.spec.js index 8fc32f1c03a..e357004d854 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.express.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.express.plugin.spec.js @@ -50,7 +50,7 @@ describe('URI sourcing with express', () => { const app = express() const pathPattern = semver.intersects(version, '>=5.0.0') ? '/path/*splat' : '/path/*' app.get(pathPattern, (req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const isPathTainted = isTainted(iastContext, req.url) expect(isPathTainted).to.be.true @@ -78,7 +78,7 @@ describe('Path params sourcing with express', () => { withVersions('express', 'express', version => { const checkParamIsTaintedAndNext = (req, res, next, param, name) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const pathParamValue = name ? req.params[name] : req.params @@ -123,7 +123,7 @@ describe('Path params sourcing with express', () => { it('should taint path params', function (done) { const app = express() app.get('/:parameter1/:parameter2', (req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) for (const pathParamName of ['parameter1', 'parameter2']) { @@ -156,7 +156,7 @@ describe('Path params sourcing with express', () => { const nestedRouter = express.Router({ mergeParams: true }) nestedRouter.get('/:parameterChild', (req, res) => { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) for (const pathParamName of ['parameterParent', 'parameterChild']) { diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.headers.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.headers.spec.js index f192db37d7f..bb766b456b0 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.headers.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/sources/taint-tracking.headers.spec.js @@ -11,7 +11,7 @@ const { testInRequest } = require('../../utils') describe('Headers sourcing', () => { function app (req) { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) Object.keys(req.headers).forEach(headerName => { diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-impl.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-impl.spec.js index d356753d607..095574551ba 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-impl.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-impl.spec.js @@ -66,7 +66,7 @@ describe('TaintTracking', () => { commands.forEach((command) => { describe(`with command: '${command}'`, () => { testThatRequestHasVulnerability(function () { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const commandTainted = newTaintedString(iastContext, command, 'param', 'Request') @@ -93,7 +93,7 @@ describe('TaintTracking', () => { describe('using JSON.parse', () => { testThatRequestHasVulnerability(function () { - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const json = '{"command":"ls -la"}' diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js index 68023dc710e..40cbf4196f1 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking-operations.spec.js @@ -44,10 +44,8 @@ describe('IAST TaintTracking Operations', () => { const store = {} - const datadogCore = { - storage: { - getStore: () => store - } + const legacyStorage = { + getStore: () => store } beforeEach(() => { @@ -58,11 +56,11 @@ describe('IAST TaintTracking Operations', () => { taintTrackingImpl = proxyquire('../../../../src/appsec/iast/taint-tracking/taint-tracking-impl', { '@datadog/native-iast-taint-tracking': taintedUtilsMock, './operations-taint-object': operationsTaintObject, - '../../../../../datadog-core': datadogCore + '../../../../../datadog-core': { storage: () => legacyStorage } }) taintTrackingOperations = proxyquire('../../../../src/appsec/iast/taint-tracking/operations', { '@datadog/native-iast-taint-tracking': taintedUtilsMock, - '../../../../../datadog-core': datadogCore, + '../../../../../datadog-core': { storage: () => legacyStorage }, './taint-tracking-impl': taintTrackingImpl, './operations-taint-object': operationsTaintObject, '../telemetry': iastTelemetry @@ -179,7 +177,7 @@ describe('IAST TaintTracking Operations', () => { '../../../log': logSpy }) const taintTrackingOperations = proxyquire('../../../../src/appsec/iast/taint-tracking/operations', { - '../../../../../datadog-core': datadogCore, + '../../../../../datadog-core': { storage: () => legacyStorage }, './taint-tracking-impl': taintTrackingImpl, './operations-taint-object': operationsTaintObject }) @@ -531,8 +529,10 @@ describe('IAST TaintTracking Operations', () => { it('Should not call taintedUtils.trim method if an Error happens', () => { const datadogCoreErr = { - storage: { - getStore: () => { throw new Error() } + storage: () => { + return { + getStore: () => { throw new Error() } + } } } const taintTrackingImpl = proxyquire('../../../../src/appsec/iast/taint-tracking/taint-tracking-impl', { diff --git a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking.lodash.plugin.spec.js b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking.lodash.plugin.spec.js index d92433959ec..8586eccaf8d 100644 --- a/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking.lodash.plugin.spec.js +++ b/packages/dd-trace/test/appsec/iast/taint-tracking/taint-tracking.lodash.plugin.spec.js @@ -53,7 +53,7 @@ describe('TaintTracking lodash', () => { describe(`with command: '${command}'`, () => { testThatRequestHasVulnerability(function () { const _ = require('../../../../../../versions/lodash').get() - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const commandTainted = newTaintedString(iastContext, command, 'param', 'Request') @@ -82,7 +82,7 @@ describe('TaintTracking lodash', () => { describe('lodash method with no taint tracking', () => { it('should return the original result', () => { const _ = require('../../../../../../versions/lodash').get() - const store = storage.getStore() + const store = storage('legacy').getStore() const iastContext = iastContextFunctions.getIastContext(store) const taintedValue = newTaintedString(iastContext, 'tainted', 'param', 'Request') diff --git a/packages/dd-trace/test/appsec/index.spec.js b/packages/dd-trace/test/appsec/index.spec.js index efb98b452e2..70606e44206 100644 --- a/packages/dd-trace/test/appsec/index.spec.js +++ b/packages/dd-trace/test/appsec/index.spec.js @@ -820,7 +820,7 @@ describe('AppSec Index', function () { describe('onPassportVerify', () => { beforeEach(() => { web.root.resetHistory() - sinon.stub(storage, 'getStore').returns({ req }) + sinon.stub(storage('legacy'), 'getStore').returns({ req }) }) it('should block when UserTracking.trackLogin() returns action', () => { @@ -837,7 +837,7 @@ describe('AppSec Index', function () { passportVerify.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(web.root).to.have.been.calledOnceWithExactly(req) expect(UserTracking.trackLogin).to.have.been.calledOnceWithExactly( payload.framework, @@ -864,7 +864,7 @@ describe('AppSec Index', function () { passportVerify.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(web.root).to.have.been.calledOnceWithExactly(req) expect(UserTracking.trackLogin).to.have.been.calledOnceWithExactly( payload.framework, @@ -878,7 +878,7 @@ describe('AppSec Index', function () { }) it('should not block and call log if no rootSpan is found', () => { - storage.getStore.returns(undefined) + storage('legacy').getStore.returns(undefined) const abortController = new AbortController() const payload = { @@ -891,7 +891,7 @@ describe('AppSec Index', function () { passportVerify.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No rootSpan found in onPassportVerify') expect(UserTracking.trackLogin).to.not.have.been.called expect(abortController.signal.aborted).to.be.false @@ -902,7 +902,7 @@ describe('AppSec Index', function () { describe('onPassportDeserializeUser', () => { beforeEach(() => { web.root.resetHistory() - sinon.stub(storage, 'getStore').returns({ req }) + sinon.stub(storage('legacy'), 'getStore').returns({ req }) }) it('should block when UserTracking.trackUser() returns action', () => { @@ -916,7 +916,7 @@ describe('AppSec Index', function () { passportUser.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(web.root).to.have.been.calledOnceWithExactly(req) expect(UserTracking.trackUser).to.have.been.calledOnceWithExactly( payload.user, @@ -937,7 +937,7 @@ describe('AppSec Index', function () { passportUser.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(web.root).to.have.been.calledOnceWithExactly(req) expect(UserTracking.trackUser).to.have.been.calledOnceWithExactly( payload.user, @@ -948,7 +948,7 @@ describe('AppSec Index', function () { }) it('should not block and call log if no rootSpan is found', () => { - storage.getStore.returns(undefined) + storage('legacy').getStore.returns(undefined) const abortController = new AbortController() const payload = { @@ -958,7 +958,7 @@ describe('AppSec Index', function () { passportUser.publish(payload) - expect(storage.getStore).to.have.been.calledOnce + expect(storage('legacy').getStore).to.have.been.calledOnce expect(log.warn).to.have.been.calledOnceWithExactly('[ASM] No rootSpan found in onPassportDeserializeUser') expect(UserTracking.trackUser).to.not.have.been.called expect(abortController.signal.aborted).to.be.false diff --git a/packages/dd-trace/test/appsec/rasp/command_injection.spec.js b/packages/dd-trace/test/appsec/rasp/command_injection.spec.js index bf920940c7a..a4b149e7b05 100644 --- a/packages/dd-trace/test/appsec/rasp/command_injection.spec.js +++ b/packages/dd-trace/test/appsec/rasp/command_injection.spec.js @@ -7,13 +7,11 @@ const { childProcessExecutionTracingChannel } = require('../../../src/appsec/cha const { start } = childProcessExecutionTracingChannel describe('RASP - command_injection.js', () => { - let waf, datadogCore, commandInjection, utils, config + let waf, legacyStorage, commandInjection, utils, config beforeEach(() => { - datadogCore = { - storage: { - getStore: sinon.stub() - } + legacyStorage = { + getStore: sinon.stub() } waf = { @@ -25,7 +23,7 @@ describe('RASP - command_injection.js', () => { } commandInjection = proxyquire('../../../src/appsec/rasp/command_injection', { - '../../../../datadog-core': datadogCore, + '../../../../datadog-core': { storage: () => legacyStorage }, '../waf': waf, './utils': utils }) @@ -55,7 +53,7 @@ describe('RASP - command_injection.js', () => { file: 'cmd' } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -66,7 +64,7 @@ describe('RASP - command_injection.js', () => { const ctx = { file: 'cmd' } - datadogCore.storage.getStore.returns(undefined) + legacyStorage.getStore.returns(undefined) start.publish(ctx) @@ -77,7 +75,7 @@ describe('RASP - command_injection.js', () => { const ctx = { file: 'cmd' } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) start.publish(ctx) @@ -89,7 +87,7 @@ describe('RASP - command_injection.js', () => { fileArgs: ['arg0'] } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -103,7 +101,7 @@ describe('RASP - command_injection.js', () => { shell: true } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -120,7 +118,7 @@ describe('RASP - command_injection.js', () => { shell: true } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -137,7 +135,7 @@ describe('RASP - command_injection.js', () => { const req = { req: 'req' } const res = { res: 'res' } waf.run.returns(wafResult) - datadogCore.storage.getStore.returns({ req, res }) + legacyStorage.getStore.returns({ req, res }) start.publish(ctx) @@ -152,7 +150,7 @@ describe('RASP - command_injection.js', () => { shell: false } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -169,7 +167,7 @@ describe('RASP - command_injection.js', () => { shell: false } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) start.publish(ctx) @@ -186,7 +184,7 @@ describe('RASP - command_injection.js', () => { const req = { req: 'req' } const res = { res: 'res' } waf.run.returns(wafResult) - datadogCore.storage.getStore.returns({ req, res }) + legacyStorage.getStore.returns({ req, res }) start.publish(ctx) diff --git a/packages/dd-trace/test/appsec/rasp/fs-plugin.spec.js b/packages/dd-trace/test/appsec/rasp/fs-plugin.spec.js index 03b2a0acdd0..b87c88c20de 100644 --- a/packages/dd-trace/test/appsec/rasp/fs-plugin.spec.js +++ b/packages/dd-trace/test/appsec/rasp/fs-plugin.spec.js @@ -95,36 +95,36 @@ describe('AppsecFsPlugin', () => { describe('_onFsOperationStart', () => { it('should mark fs root', () => { const origStore = {} - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) appsecFsPlugin._onFsOperationStart() - let store = storage.getStore() + let store = storage('legacy').getStore() assert.property(store, 'fs') assert.propertyVal(store.fs, 'parentStore', origStore) assert.propertyVal(store.fs, 'root', true) appsecFsPlugin._onFsOperationFinishOrRenderEnd() - store = storage.getStore() + store = storage('legacy').getStore() assert.equal(store, origStore) assert.notProperty(store, 'fs') }) it('should mark fs children', () => { const origStore = { orig: true } - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) appsecFsPlugin._onFsOperationStart() - const rootStore = storage.getStore() + const rootStore = storage('legacy').getStore() assert.property(rootStore, 'fs') assert.propertyVal(rootStore.fs, 'parentStore', origStore) assert.propertyVal(rootStore.fs, 'root', true) appsecFsPlugin._onFsOperationStart() - let store = storage.getStore() + let store = storage('legacy').getStore() assert.property(store, 'fs') assert.propertyVal(store.fs, 'parentStore', rootStore) assert.propertyVal(store.fs, 'root', false) @@ -132,11 +132,11 @@ describe('AppsecFsPlugin', () => { appsecFsPlugin._onFsOperationFinishOrRenderEnd() - store = storage.getStore() + store = storage('legacy').getStore() assert.equal(store, rootStore) appsecFsPlugin._onFsOperationFinishOrRenderEnd() - store = storage.getStore() + store = storage('legacy').getStore() assert.equal(store, origStore) }) }) @@ -146,18 +146,18 @@ describe('AppsecFsPlugin', () => { appsecFsPlugin.enable() const origStore = {} - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) appsecFsPlugin._onResponseRenderStart() - let store = storage.getStore() + let store = storage('legacy').getStore() assert.property(store, 'fs') assert.propertyVal(store.fs, 'parentStore', origStore) assert.propertyVal(store.fs, 'opExcluded', true) appsecFsPlugin._onFsOperationFinishOrRenderEnd() - store = storage.getStore() + store = storage('legacy').getStore() assert.equal(store, origStore) assert.notProperty(store, 'fs') }) @@ -176,7 +176,7 @@ describe('AppsecFsPlugin', () => { it('should mark root operations', () => { let count = 0 const onStart = () => { - const store = storage.getStore() + const store = storage('legacy').getStore() assert.isNotNull(store.fs) count++ @@ -185,7 +185,7 @@ describe('AppsecFsPlugin', () => { try { const origStore = {} - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) opStartCh.subscribe(onStart) @@ -200,7 +200,7 @@ describe('AppsecFsPlugin', () => { it('should mark root even if op is excluded', () => { let count = 0 const onStart = () => { - const store = storage.getStore() + const store = storage('legacy').getStore() assert.isNotNull(store.fs) count++ @@ -211,7 +211,7 @@ describe('AppsecFsPlugin', () => { const origStore = { fs: { opExcluded: true } } - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) opStartCh.subscribe(onStart) @@ -226,7 +226,7 @@ describe('AppsecFsPlugin', () => { it('should clean up store when finishing op', () => { let count = 4 const onFinish = () => { - const store = storage.getStore() + const store = storage('legacy').getStore() count-- if (count === 0) { @@ -235,7 +235,7 @@ describe('AppsecFsPlugin', () => { } try { const origStore = {} - storage.enterWith(origStore) + storage('legacy').enterWith(origStore) opFinishCh.subscribe(onFinish) diff --git a/packages/dd-trace/test/appsec/rasp/lfi.spec.js b/packages/dd-trace/test/appsec/rasp/lfi.spec.js index 0a1328e2c52..74f216c3616 100644 --- a/packages/dd-trace/test/appsec/rasp/lfi.spec.js +++ b/packages/dd-trace/test/appsec/rasp/lfi.spec.js @@ -7,13 +7,11 @@ const { FS_OPERATION_PATH } = require('../../../src/appsec/addresses') const { RASP_MODULE } = require('../../../src/appsec/rasp/fs-plugin') describe('RASP - lfi.js', () => { - let waf, datadogCore, lfi, web, blocking, appsecFsPlugin, config + let waf, legacyStorage, lfi, web, blocking, appsecFsPlugin, config beforeEach(() => { - datadogCore = { - storage: { - getStore: sinon.stub() - } + legacyStorage = { + getStore: sinon.stub() } waf = { @@ -34,7 +32,7 @@ describe('RASP - lfi.js', () => { } lfi = proxyquire('../../../src/appsec/rasp/lfi', { - '../../../../datadog-core': datadogCore, + '../../../../datadog-core': { storage: () => legacyStorage }, '../waf': waf, '../../plugins/util/web': web, '../blocking': blocking, @@ -106,7 +104,7 @@ describe('RASP - lfi.js', () => { it('should analyze lfi for root fs operations', () => { const fs = { root: true } - datadogCore.storage.getStore.returns({ req, fs }) + legacyStorage.getStore.returns({ req, fs }) fsOperationStart.publish(ctx) @@ -116,7 +114,7 @@ describe('RASP - lfi.js', () => { it('should NOT analyze lfi for child fs operations', () => { const fs = {} - datadogCore.storage.getStore.returns({ req, fs }) + legacyStorage.getStore.returns({ req, fs }) fsOperationStart.publish(ctx) @@ -125,7 +123,7 @@ describe('RASP - lfi.js', () => { it('should NOT analyze lfi for undefined fs (AppsecFsPlugin disabled)', () => { const fs = undefined - datadogCore.storage.getStore.returns({ req, fs }) + legacyStorage.getStore.returns({ req, fs }) fsOperationStart.publish(ctx) @@ -134,7 +132,7 @@ describe('RASP - lfi.js', () => { it('should NOT analyze lfi for excluded operations', () => { const fs = { opExcluded: true, root: true } - datadogCore.storage.getStore.returns({ req, fs }) + legacyStorage.getStore.returns({ req, fs }) fsOperationStart.publish(ctx) diff --git a/packages/dd-trace/test/appsec/rasp/sql_injection.spec.js b/packages/dd-trace/test/appsec/rasp/sql_injection.spec.js index fe7c9af082d..6dea9f979eb 100644 --- a/packages/dd-trace/test/appsec/rasp/sql_injection.spec.js +++ b/packages/dd-trace/test/appsec/rasp/sql_injection.spec.js @@ -5,13 +5,11 @@ const addresses = require('../../../src/appsec/addresses') const proxyquire = require('proxyquire') describe('RASP - sql_injection', () => { - let waf, datadogCore, sqli + let waf, legacyStorage, sqli beforeEach(() => { - datadogCore = { - storage: { - getStore: sinon.stub() - } + legacyStorage = { + getStore: sinon.stub() } waf = { @@ -19,7 +17,7 @@ describe('RASP - sql_injection', () => { } sqli = proxyquire('../../../src/appsec/rasp/sql_injection', { - '../../../../datadog-core': datadogCore, + '../../../../datadog-core': { storage: () => legacyStorage }, '../waf': waf }) @@ -49,7 +47,7 @@ describe('RASP - sql_injection', () => { } } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) pgQueryStart.publish(ctx) @@ -69,7 +67,7 @@ describe('RASP - sql_injection', () => { } } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) pgQueryStart.publish(ctx) @@ -82,7 +80,7 @@ describe('RASP - sql_injection', () => { text: 'SELECT 1' } } - datadogCore.storage.getStore.returns(undefined) + legacyStorage.getStore.returns(undefined) pgQueryStart.publish(ctx) @@ -95,7 +93,7 @@ describe('RASP - sql_injection', () => { text: 'SELECT 1' } } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) pgQueryStart.publish(ctx) @@ -106,7 +104,7 @@ describe('RASP - sql_injection', () => { const ctx = { query: {} } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) pgQueryStart.publish(ctx) @@ -120,7 +118,7 @@ describe('RASP - sql_injection', () => { sql: 'SELECT 1' } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) mysql2OuterQueryStart.publish(ctx) @@ -138,7 +136,7 @@ describe('RASP - sql_injection', () => { sql: 'SELECT 1' } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) mysql2OuterQueryStart.publish(ctx) @@ -149,7 +147,7 @@ describe('RASP - sql_injection', () => { const ctx = { sql: 'SELECT 1' } - datadogCore.storage.getStore.returns(undefined) + legacyStorage.getStore.returns(undefined) mysql2OuterQueryStart.publish(ctx) @@ -160,7 +158,7 @@ describe('RASP - sql_injection', () => { const ctx = { sql: 'SELECT 1' } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) mysql2OuterQueryStart.publish(ctx) @@ -171,7 +169,7 @@ describe('RASP - sql_injection', () => { const ctx = { sql: 'SELECT 1' } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) mysql2OuterQueryStart.publish(ctx) diff --git a/packages/dd-trace/test/appsec/rasp/ssrf.spec.js b/packages/dd-trace/test/appsec/rasp/ssrf.spec.js index 98d5c8a0104..3cfbaa3ff41 100644 --- a/packages/dd-trace/test/appsec/rasp/ssrf.spec.js +++ b/packages/dd-trace/test/appsec/rasp/ssrf.spec.js @@ -5,13 +5,11 @@ const { httpClientRequestStart } = require('../../../src/appsec/channels') const addresses = require('../../../src/appsec/addresses') describe('RASP - ssrf.js', () => { - let waf, datadogCore, ssrf + let waf, legacyStorage, ssrf beforeEach(() => { - datadogCore = { - storage: { - getStore: sinon.stub() - } + legacyStorage = { + getStore: sinon.stub() } waf = { @@ -19,7 +17,7 @@ describe('RASP - ssrf.js', () => { } ssrf = proxyquire('../../../src/appsec/rasp/ssrf', { - '../../../../datadog-core': datadogCore, + '../../../../datadog-core': { storage: () => legacyStorage }, '../waf': waf }) @@ -49,7 +47,7 @@ describe('RASP - ssrf.js', () => { } } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) httpClientRequestStart.publish(ctx) @@ -65,7 +63,7 @@ describe('RASP - ssrf.js', () => { } } const req = {} - datadogCore.storage.getStore.returns({ req }) + legacyStorage.getStore.returns({ req }) httpClientRequestStart.publish(ctx) @@ -78,7 +76,7 @@ describe('RASP - ssrf.js', () => { uri: 'http://example.com' } } - datadogCore.storage.getStore.returns(undefined) + legacyStorage.getStore.returns(undefined) httpClientRequestStart.publish(ctx) @@ -91,7 +89,7 @@ describe('RASP - ssrf.js', () => { uri: 'http://example.com' } } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) httpClientRequestStart.publish(ctx) @@ -102,7 +100,7 @@ describe('RASP - ssrf.js', () => { const ctx = { args: {} } - datadogCore.storage.getStore.returns({}) + legacyStorage.getStore.returns({}) httpClientRequestStart.publish(ctx) diff --git a/packages/dd-trace/test/appsec/reporter.spec.js b/packages/dd-trace/test/appsec/reporter.spec.js index a38092e728d..08ad31d2fb8 100644 --- a/packages/dd-trace/test/appsec/reporter.spec.js +++ b/packages/dd-trace/test/appsec/reporter.spec.js @@ -141,11 +141,11 @@ describe('reporter', () => { beforeEach(() => { req = {} - storage.enterWith({ req }) + storage('legacy').enterWith({ req }) }) afterEach(() => { - storage.disable() + storage('legacy').disable() }) it('should do nothing when passed incomplete objects', () => { @@ -184,7 +184,7 @@ describe('reporter', () => { it('should call updateWafRequestsMetricTags', () => { const metrics = { rulesVersion: '1.2.3' } - const store = storage.getStore() + const store = storage('legacy').getStore() Reporter.reportMetrics(metrics) @@ -194,7 +194,7 @@ describe('reporter', () => { it('should call updateRaspRequestsMetricTags when raspRule is provided', () => { const metrics = { rulesVersion: '1.2.3' } - const store = storage.getStore() + const store = storage('legacy').getStore() const raspRule = { type: 'rule_type', variant: 'rule_variant' } @@ -218,11 +218,11 @@ describe('reporter', () => { 'user-agent': 'arachni' } } - storage.enterWith({ req }) + storage('legacy').enterWith({ req }) }) afterEach(() => { - storage.disable() + storage('legacy').disable() }) it('should add tags to request span when socket is not there', () => { diff --git a/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js b/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js index 4eba390da27..e43e5ffd972 100644 --- a/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js +++ b/packages/dd-trace/test/appsec/sdk/user_blocking.spec.js @@ -25,7 +25,7 @@ describe('user_blocking', () => { const res = { headersSent: false } const tracer = {} - let rootSpan, getRootSpan, block, storage, log, userBlocking + let rootSpan, getRootSpan, block, legacyStorage, log, userBlocking before(() => { const runStub = sinon.stub(waf, 'run') @@ -44,7 +44,7 @@ describe('user_blocking', () => { block = sinon.stub() - storage = { + legacyStorage = { getStore: sinon.stub().returns({ req, res }) } @@ -55,7 +55,7 @@ describe('user_blocking', () => { userBlocking = proxyquire('../../../src/appsec/sdk/user_blocking', { './utils': { getRootSpan }, '../blocking': { block }, - '../../../../datadog-core': { storage }, + '../../../../datadog-core': { storage: () => legacyStorage }, '../../log': log }) }) @@ -114,16 +114,16 @@ describe('user_blocking', () => { it('should get req and res from local storage when they are not passed', () => { const ret = userBlocking.blockRequest(tracer) expect(ret).to.be.true - expect(storage.getStore).to.have.been.calledOnce + expect(legacyStorage.getStore).to.have.been.calledOnce expect(block).to.be.calledOnceWithExactly(req, res, rootSpan) }) it('should log warning when req or res is not available', () => { - storage.getStore.returns(undefined) + legacyStorage.getStore.returns(undefined) const ret = userBlocking.blockRequest(tracer) expect(ret).to.be.false - expect(storage.getStore).to.have.been.calledOnce + expect(legacyStorage.getStore).to.have.been.calledOnce expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Requests or response object not available in blockRequest') expect(block).to.not.have.been.called diff --git a/packages/dd-trace/test/debugger/devtools_client/state.spec.js b/packages/dd-trace/test/debugger/devtools_client/state.spec.js index 59c971d0f7f..dced50d51e3 100644 --- a/packages/dd-trace/test/debugger/devtools_client/state.spec.js +++ b/packages/dd-trace/test/debugger/devtools_client/state.spec.js @@ -113,14 +113,14 @@ describe('findScriptFromPartialPath', function () { }) }) }) - }) - function testPath (path) { - return function () { - const result = state.findScriptFromPartialPath(path) - expect(result).to.deep.equal([url, scriptId, undefined]) + function testPath (path) { + return function () { + const result = state.findScriptFromPartialPath(path) + expect(result).to.deep.equal([url, scriptId, undefined]) + } } - } + }) } describe('multiple partial matches', function () { diff --git a/packages/dd-trace/test/encode/0.5.spec.js b/packages/dd-trace/test/encode/0.5.spec.js index 6c1fef4de2f..c28ca6fe492 100644 --- a/packages/dd-trace/test/encode/0.5.spec.js +++ b/packages/dd-trace/test/encode/0.5.spec.js @@ -35,7 +35,7 @@ describe('encode 0.5', () => { example: 1 }, start: 123123123123123120, - duration: 456456456456456456, + duration: 4564564564564564, links: [] }] }) diff --git a/packages/dd-trace/test/format.spec.js b/packages/dd-trace/test/format.spec.js index 846a02cd66a..66dbc090f4d 100644 --- a/packages/dd-trace/test/format.spec.js +++ b/packages/dd-trace/test/format.spec.js @@ -60,7 +60,7 @@ describe('format', () => { _service: 'test' }), setTag: sinon.stub(), - _startTime: 1500000000000.123456, + _startTime: 1500000000000.123, _duration: 100 } diff --git a/packages/dd-trace/test/lambda/fixtures/handler.js b/packages/dd-trace/test/lambda/fixtures/handler.js index 2541b0cd1cc..12cf0e8ad08 100644 --- a/packages/dd-trace/test/lambda/fixtures/handler.js +++ b/packages/dd-trace/test/lambda/fixtures/handler.js @@ -23,7 +23,7 @@ const handler = async (_event, _context) => { const callbackHandler = (_event, _context, callback) => { const response = sampleResponse - callback('', response) + callback('', response) // eslint-disable-line n/no-callback-literal } const timeoutHandler = async (...args) => { diff --git a/packages/dd-trace/test/llmobs/sdk/index.spec.js b/packages/dd-trace/test/llmobs/sdk/index.spec.js index e7cfb81a47d..0f6a09bf17e 100644 --- a/packages/dd-trace/test/llmobs/sdk/index.spec.js +++ b/packages/dd-trace/test/llmobs/sdk/index.spec.js @@ -560,7 +560,7 @@ describe('sdk', () => { function myWorkflow (input, cb) { span = llmobs._active() setTimeout(() => { - cb('output', 'ignore') + cb('output', 'ignore') // eslint-disable-line n/no-callback-literal }, 1000) } diff --git a/packages/dd-trace/test/log.spec.js b/packages/dd-trace/test/log.spec.js index cbe5679414b..0221249cda4 100644 --- a/packages/dd-trace/test/log.spec.js +++ b/packages/dd-trace/test/log.spec.js @@ -119,7 +119,7 @@ describe('log', () => { it('should call the logger in a noop context', () => { logger.debug = () => { - expect(storage.getStore()).to.have.property('noop', true) + expect(storage('legacy').getStore()).to.have.property('noop', true) } log.use(logger).debug('debug') diff --git a/packages/dd-trace/test/opentracing/propagation/text_map.spec.js b/packages/dd-trace/test/opentracing/propagation/text_map.spec.js index 3e4f6aed3e8..2c699b107a1 100644 --- a/packages/dd-trace/test/opentracing/propagation/text_map.spec.js +++ b/packages/dd-trace/test/opentracing/propagation/text_map.spec.js @@ -451,7 +451,8 @@ describe('TextMapPropagator', () => { expect(spanContextD._baggageItems).to.deep.equal({}) }) - it('should extract baggage when it is the only propagation style', () => { + // temporary test. On the contrary, it SHOULD extract baggage + it('should not extract baggage when it is the only propagation style', () => { config = new Config({ tracePropagationStyle: { extract: ['baggage'] @@ -462,7 +463,7 @@ describe('TextMapPropagator', () => { baggage: 'foo=bar' } const spanContext = propagator.extract(carrier) - expect(spanContext._baggageItems).to.deep.equal({ foo: 'bar' }) + expect(spanContext).to.be.null }) it('should convert signed IDs to unsigned', () => { diff --git a/packages/dd-trace/test/plugins/agent.js b/packages/dd-trace/test/plugins/agent.js index b365143187e..4eef15fc99f 100644 --- a/packages/dd-trace/test/plugins/agent.js +++ b/packages/dd-trace/test/plugins/agent.js @@ -325,7 +325,7 @@ module.exports = { const emit = server.emit server.emit = function () { - storage.enterWith({ noop: true }) + storage('legacy').enterWith({ noop: true }) return emit.apply(this, arguments) } diff --git a/packages/dd-trace/test/profiling/.eslintrc.json b/packages/dd-trace/test/profiling/.eslintrc.json deleted file mode 100644 index 3f6d8f43424..00000000000 --- a/packages/dd-trace/test/profiling/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": [ - "../.eslintrc.json" - ], - "env": { - "mocha" : true - }, - "rules": { - "no-unused-expressions": 0 - } -} diff --git a/packages/dd-trace/test/setup/mocha.js b/packages/dd-trace/test/setup/mocha.js index 53a2c95897a..950d96bfda4 100644 --- a/packages/dd-trace/test/setup/mocha.js +++ b/packages/dd-trace/test/setup/mocha.js @@ -252,6 +252,6 @@ exports.mochaHooks = { afterEach () { agent.reset() runtimeMetrics.stop() - storage.enterWith(undefined) + storage('legacy').enterWith(undefined) } } diff --git a/packages/dd-trace/test/telemetry/index.spec.js b/packages/dd-trace/test/telemetry/index.spec.js index 0263f395e9f..e7c1fe2a77f 100644 --- a/packages/dd-trace/test/telemetry/index.spec.js +++ b/packages/dd-trace/test/telemetry/index.spec.js @@ -24,7 +24,7 @@ describe('telemetry', () => { // If we don't no-op the server inside it, it will trace it, which will // screw up this test file entirely. -- bengl - storage.run({ noop: true }, () => { + storage('legacy').run({ noop: true }, () => { traceAgent = http.createServer(async (req, res) => { const chunks = [] for await (const chunk of req) { @@ -832,7 +832,7 @@ describe('AVM OSS', () => { before((done) => { clock = sinon.useFakeTimers() - storage.run({ noop: true }, () => { + storage('legacy').run({ noop: true }, () => { traceAgent = http.createServer(async (req, res) => { const chunks = [] for await (const chunk of req) { diff --git a/packages/dd-trace/test/tracer.spec.js b/packages/dd-trace/test/tracer.spec.js index 8591ebe3b8f..a913a1a70e6 100644 --- a/packages/dd-trace/test/tracer.spec.js +++ b/packages/dd-trace/test/tracer.spec.js @@ -3,12 +3,10 @@ require('./setup/tap') const Span = require('../src/opentracing/span') -const { storage } = require('../../datadog-core') const Config = require('../src/config') const tags = require('../../../ext/tags') const { expect } = require('chai') const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants') -const { DD_MAJOR } = require('../../../version') const SPAN_TYPE = tags.SPAN_TYPE const RESOURCE_NAME = tags.RESOURCE_NAME @@ -16,8 +14,6 @@ const SERVICE_NAME = tags.SERVICE_NAME const EXPORT_SERVICE_NAME = 'service' const BASE_SERVICE = tags.BASE_SERVICE -const describeOrphanable = DD_MAJOR < 4 ? describe : describe.skip - describe('Tracer', () => { let Tracer let tracer @@ -283,64 +279,6 @@ describe('Tracer', () => { }) }) }) - - describeOrphanable('when there is no parent span', () => { - it('should not trace if `orphanable: false`', () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', { orphanable: false }, () => {}) - - expect(tracer.startSpan).to.have.not.been.called - }) - - it('should trace if `orphanable: true`', () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', { orhpanable: true }, () => {}) - - expect(tracer.startSpan).to.have.been.called - }) - - it('should trace if `orphanable: undefined`', () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', {}, () => {}) - - expect(tracer.startSpan).to.have.been.called - }) - }) - - describeOrphanable('when there is a parent span', () => { - it('should trace if `orphanable: false`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', { orhpanable: false }, () => {}) - - expect(tracer.startSpan).to.have.been.called - }) - }) - - it('should trace if `orphanable: true`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', { orphanable: true }, () => {}) - - expect(tracer.startSpan).to.have.been.called - }) - }) - - it('should trace if `orphanable: undefined`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - sinon.spy(tracer, 'startSpan') - - tracer.trace('name', {}, () => {}) - - expect(tracer.startSpan).to.have.been.called - }) - }) - }) }) describe('getRumData', () => { @@ -470,87 +408,5 @@ describe('Tracer', () => { tags: { sometag: 'somevalue', invocations: 2 } }) }) - - it('should not trace in a noop context', () => { - const fn = tracer.wrap('name', {}, () => {}) - - sinon.spy(tracer, 'trace') - - storage.enterWith({ noop: true }) - fn() - storage.enterWith(null) - - expect(tracer.trace).to.have.not.been.called - }) - - describeOrphanable('when there is no parent span', () => { - it('should not trace if `orphanable: false`', () => { - const fn = tracer.wrap('name', { orphanable: false }, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.not.been.called - }) - - it('should trace if `orphanable: true`', () => { - const fn = tracer.wrap('name', { orhpanable: true }, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.been.called - }) - - it('should trace if `orphanable: undefined`', () => { - const fn = tracer.wrap('name', {}, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.been.called - }) - }) - - describeOrphanable('when there is a parent span', () => { - it('should trace if `orphanable: false`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - const fn = tracer.wrap('name', { orhpanable: false }, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.been.called - }) - }) - - it('should trace if `orphanable: true`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - const fn = tracer.wrap('name', { orphanable: true }, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.been.called - }) - }) - - it('should trace if `orphanable: undefined`', () => { - tracer.scope().activate(tracer.startSpan('parent'), () => { - const fn = tracer.wrap('name', {}, () => {}) - - sinon.spy(tracer, 'trace') - - fn() - - expect(tracer.trace).to.have.been.called - }) - }) - }) }) }) diff --git a/yarn.lock b/yarn.lock index fc84aba8830..bfd209d3df6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -413,10 +413,10 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.6.1": - version "2.6.1" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.6.1.tgz#5e5393628c73c57dcf08256299c0e8cf71deb14f" - integrity sha512-zv7cr/MzHg560jhAnHcO7f9pLi4qaYrBEcB+Gla0xkVouYSDsp8cGXIGG4fiGdAMHdt7SpDNS6+NcEAqD/v8Ig== +"@datadog/native-iast-rewriter@2.8.0": + version "2.8.0" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.8.0.tgz#8a7eddf5e33266643afcdfb920ff5ccb30e1894a" + integrity sha512-DKmtvlmCld9RIJwDcPKWNkKYWYQyiuOrOtynmBppJiUv/yfCOuZtsQV4Zepj40H33sLiQyi5ct6dbWl53vxqkA== dependencies: lru-cache "^7.14.0" node-gyp-build "^4.5.0" @@ -609,10 +609,10 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== -"@eslint/js@^9.11.1": - version "9.11.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.11.1.tgz#8bcb37436f9854b3d9a561440daf916acd940986" - integrity sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA== +"@eslint/js@^8.57.1": + version "8.57.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== "@graphql-tools/merge@^8.4.1": version "8.4.2"