diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 084410981aa..6c9e1961e25 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -48,7 +48,7 @@ updates: - "eslint*" - package-ecosystem: "npm" - directory: "/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp" + directory: "/test/instrumentation/azure-functions/fixtures/azfunc3" schedule: interval: "weekly" open-pull-requests-limit: 5 @@ -56,7 +56,7 @@ updates: - "elastic/apm-agent-node-js" - package-ecosystem: "npm" - directory: "/test/instrumentation/modules/next/a-nextjs-app" + directory: "/test/instrumentation/azure-functions/fixtures/azfunc4" schedule: interval: "weekly" open-pull-requests-limit: 5 diff --git a/.github/workflows/addToProject.yml b/.github/workflows/addToProject.yml index 52611a9b9d9..3bdfd0a8959 100644 --- a/.github/workflows/addToProject.yml +++ b/.github/workflows/addToProject.yml @@ -9,7 +9,7 @@ permissions: jobs: add_to_project: if: github.event.issue && github.event.issue.milestone - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Get token id: get_token diff --git a/.github/workflows/edge.yml b/.github/workflows/edge.yml index 14c9b4e0bd7..207cf01b3f4 100644 --- a/.github/workflows/edge.yml +++ b/.github/workflows/edge.yml @@ -27,7 +27,7 @@ jobs: # made, these will stop and there will be no value in testing v17 nightlies. # test-nightly: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 30 strategy: fail-fast: false @@ -44,7 +44,7 @@ jobs: # The node.js project *sometimes* produces "rc" builds leading up to a new # release. They get uploaded to: https://nodejs.org/download/rc/ test-rc: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 30 strategy: fail-fast: false diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index dc563904df7..b1e3607c70e 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -13,7 +13,7 @@ permissions: jobs: triage: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Get token id: get_token @@ -33,7 +33,10 @@ jobs: github-token: ${{ steps.get_token.outputs.token }} - name: Add community and triage labels - if: contains(steps.is_elastic_member.outputs.result, 'false') && github.actor != 'dependabot[bot]' && github.actor != 'elastic-observability-automation[bot]' + if: contains(steps.is_elastic_member.outputs.result, 'false') && + github.actor != 'dependabot[bot]' && + github.actor != 'elastic-renovate-prod[bot]' && + github.actor != 'elastic-observability-automation[bot]' uses: actions/github-script@v7 with: script: | diff --git a/.github/workflows/microbenchmark.yml b/.github/workflows/microbenchmark.yml index 09d525ea12e..3e63af3025f 100644 --- a/.github/workflows/microbenchmark.yml +++ b/.github/workflows/microbenchmark.yml @@ -17,7 +17,7 @@ permissions: jobs: microbenchmark: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 5 steps: - name: Run microbenchmark diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 157641c53a1..47c0046160a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ permissions: jobs: release: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 env: DOCKER_IMAGE_NAME: docker.elastic.co/observability/apm-agent-nodejs steps: @@ -63,7 +63,7 @@ jobs: - name: Build and Push Docker Image id: docker-push - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 with: context: . platforms: linux/amd64,linux/arm64 @@ -97,7 +97,7 @@ jobs: - name: Build and Push Docker Image (wolfi) id: docker-push-wolfi - uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 + uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6.12.0 with: context: . platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/slack.yml b/.github/workflows/slack.yml new file mode 100644 index 00000000000..3de28511cba --- /dev/null +++ b/.github/workflows/slack.yml @@ -0,0 +1,126 @@ +# Post a slack message something like the following for issue and PR actions: +# <$url|$title> +# | $repo#$num · issue opened by $user +# +# Configuration: +# 1. Set `SLACK_CHANNEL`. +# 2. Add a `SLACK_BOT_TOKEN` secret to your repo. This is the "Bot User OAuth +# Token" from the "OAuth & Permissions" section of your Slack App +# (https://api.slack.com/apps). The token must have the `chat:write` +# permission. +# 3. Optionally tweak the `if:` and `on:` sections below to control which issue +# and PR events are skipped. + +name: slack + +env: + SLACK_CHANNEL: "#apm-agent-node" + +on: + issues: + types: [opened, reopened, closed] + pull_request: + types: [opened, ready_for_review, reopened, closed] + +jobs: + slack: + # Skip notification if: + # - dependabot or renovate PRs, too noisy + # - draft PRs + if: ${{ !( + (github.event.action == 'opened' && github.event.pull_request.draft) || + github.event.pull_request.user.login == 'dependabot[bot]' || + github.event.pull_request.user.login == 'elastic-renovate-prod[bot]' + ) }} + runs-on: ubuntu-24.04 + steps: + - name: Prepare Slack message + id: prepare + shell: python + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: | + import os + from pprint import pprint + import json + + CLOSED_RED = '#cb2431' + GITHUB_BLACK = '#24292f' + MERGED_PURPLE = '#6f42c1' + OPEN_GREEN = '#36a64f' + DRAFT_GRAY = '#6a737d' + + ctx = json.loads(os.environ["GITHUB_CONTEXT"]) + # pprint(ctx) # for dev/debugging + event = ctx["event"] + action = event["action"] + if "issue" in event: + title = event["issue"]["title"] + url = event["issue"]["html_url"] + num = event["issue"]["number"] + action_str = f"issue {action}" + color = { + "opened": OPEN_GREEN, + "reopened": OPEN_GREEN, + "closed": CLOSED_RED, + }.get(action, "#ffffff") + elif "pull_request" in event: + title = event["pull_request"]["title"] + url = event["pull_request"]["html_url"] + num = event["pull_request"]["number"] + if action == "closed": + if event["pull_request"]["merged"]: + action_str = "PR merged" + color = MERGED_PURPLE + else: + action_str = "PR closed" + color = CLOSED_RED + elif event["pull_request"]["draft"]: + action_str = "PR in draft" + color = DRAFT_GRAY + elif action == "ready_for_review": + action_str = "PR ready for review" + color = OPEN_GREEN + else: + action_str = "PR opened" + color = OPEN_GREEN + else: + pprint(ctx) + raise ValueError('unexpected event: not an issue or PR event') + + payload = { + "channel": os.environ["SLACK_CHANNEL"], + + # Note: Omitting the "text" field is intentional, so that it is not + # rendered by default. Guidelines on accessibility in: + # https://api.slack.com/methods/chat.postMessage#text-blocks-attachments + # are unclear for "attachments" usage. This competes with: + # https://api.slack.com/reference/messaging/attachments#guidelines__message-attachments-as-objects + # guidelines to group all object data inside the attachment. + # The downside is that the `chatMessage` below results in warnings + # from the Slack API about not including the top-level "text". + #"text": title, + + # Intentionally *not* using Slack's newer blocks, + # https://api.slack.com/messaging/attachments-to-blocks + # because styling with the older syntax is slightly nicer, IMHO. + "attachments": [ + { + "color": color, + "title": title, + "title_link": url, + "footer": f"{ctx['repository']}#{num} · *{action_str}* by {event['sender']['login']}", + "footer_icon": "https://github.githubassets.com/favicon.ico" + } + ] + } + + with open(os.environ.get("GITHUB_OUTPUT"), "a") as f: + f.write("payload={}".format(json.dumps(payload))) + + - name: Post Slack message + uses: slackapi/slack-github-action@v2.0.0 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: ${{ steps.prepare.outputs.payload }} diff --git a/.github/workflows/tav-command.yml b/.github/workflows/tav-command.yml index ea6fb43adb7..68d44316ba9 100644 --- a/.github/workflows/tav-command.yml +++ b/.github/workflows/tav-command.yml @@ -14,7 +14,7 @@ permissions: jobs: command-validation: if: startsWith(github.event.review.body, '/test tav') - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 5 permissions: pull-requests: write @@ -132,7 +132,7 @@ jobs: test-tav: needs: command-validation - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 40 strategy: max-parallel: 15 diff --git a/.github/workflows/tav.yml b/.github/workflows/tav.yml index 0bcb52399df..a0dcdeb9451 100644 --- a/.github/workflows/tav.yml +++ b/.github/workflows/tav.yml @@ -21,7 +21,7 @@ permissions: jobs: prepare-matrix: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 5 outputs: permutations: ${{ steps.transform.outputs.permutations }} @@ -59,7 +59,7 @@ jobs: test-tav: needs: prepare-matrix - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 40 strategy: max-parallel: 15 diff --git a/.github/workflows/test-docs.yml b/.github/workflows/test-docs.yml index ee10f943fe8..2b99309092c 100644 --- a/.github/workflows/test-docs.yml +++ b/.github/workflows/test-docs.yml @@ -17,6 +17,6 @@ permissions: jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - run: echo "No build required" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 600b93a3593..af8212411e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,7 @@ permissions: jobs: lint: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -164,7 +164,7 @@ jobs: - '16.0' - '14' - '14.17' - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -197,7 +197,7 @@ jobs: # failure if at least one job listed "needs" is not successful. test: if: always() - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: - lint - test-vers diff --git a/.github/workflows/updatecli.yml b/.github/workflows/updatecli.yml index e2d67bd22e3..92d28867d9e 100644 --- a/.github/workflows/updatecli.yml +++ b/.github/workflows/updatecli.yml @@ -10,7 +10,7 @@ permissions: jobs: compose: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 permissions: contents: read packages: read diff --git a/.tav.yml b/.tav.yml index 1098cec29dc..fcca1426fa3 100644 --- a/.tav.yml +++ b/.tav.yml @@ -467,14 +467,20 @@ aws-sdk: - node test/instrumentation/modules/aws-sdk/dynamodb.test.js '@aws-sdk/client-s3': - versions: - # - 3.377.0 was a bad release (https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1828#issuecomment-1834276719) - mode: max-7 - include: '>=3.15.0 <4' - exclude: '3.377.0' - commands: - - node test/instrumentation/modules/@aws-sdk/client-s3.test.js - node: '>=14' + - versions: + # - 3.377.0 was a bad release (https://github.com/open-telemetry/opentelemetry-js-contrib/issues/1828#issuecomment-1834276719) + mode: max-5 + include: '>=3.15.0 <3.723.0' + exclude: '3.377.0' + node: '>=14' + commands: + - node test/instrumentation/modules/@aws-sdk/client-s3.test.js + - versions: + mode: max-5 + include: '>=3.723.0 <4' + node: '>=18' + commands: + - node test/instrumentation/modules/@aws-sdk/client-s3.test.js '@aws-sdk/client-dynamodb': versions: @@ -485,20 +491,32 @@ aws-sdk: node: '>=14' '@aws-sdk/client-sns': - versions: - mode: max-7 - include: '>=3.15.0 <4' - commands: - - node test/instrumentation/modules/@aws-sdk/client-sns.test.js - node: '>=14' + - versions: + mode: max-7 + include: '>=3.15.0 <3.723.0' + node: '>=14' + commands: + - node test/instrumentation/modules/@aws-sdk/client-sns.test.js + - versions: + mode: max-5 + include: '>=3.723.0 <4' + node: '>=18' + commands: + - node test/instrumentation/modules/@aws-sdk/client-sns.test.js '@aws-sdk/client-sqs': - versions: - mode: max-7 - include: '>=3.15.0 <4' - commands: - - node test/instrumentation/modules/@aws-sdk/client-sqs.test.js - node: '>=14' + - versions: + mode: max-7 + include: '>=3.15.0 <3.723.0' + node: '>=14' + commands: + - node test/instrumentation/modules/@aws-sdk/client-sqs.test.js + - versions: + mode: max-5 + include: '>=3.723.0 <4' + node: '>=18' + commands: + - node test/instrumentation/modules/@aws-sdk/client-sqs.test.js # - undici@4.7.0 added its diagnostics_channel support. # - In undici@4.7.1 the `request.origin` property was added, which we need diff --git a/.tool-versions b/.tool-versions index 433f827ca91..e9de826baa2 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -updatecli v0.89.0 \ No newline at end of file +updatecli v0.92.0 \ No newline at end of file diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 93a5792dad4..6d415e6393c 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -33,6 +33,23 @@ Notes: See the <> guide. +[[release-notes-4.11.0]] +==== 4.11.0 - 2025/01/20 + +[float] +===== Features + +* Support instrumentation of Azure Functions using the https://learn.microsoft.com/en-ca/azure/azure-functions/functions-node-upgrade-v4[v4 Node.js programming model]. + ({pull}4426[#4426]) + +[float] +===== Bug fixes + +* Fix instrumentation of `@aws-sdk/client-s3`, `@aws-sdk/client-sqs`, and + `@aws-sdk/client-sns` for versions 3.723.0 and later. Internally the AWS SDK + clients updated to `@smithy/smithy-client@4`. ({pull}4398[#4398]) + + [[release-notes-4.10.0]] ==== 4.10.0 - 2024/12/24 diff --git a/Dockerfile.wolfi b/Dockerfile.wolfi index cd835ed09e5..460860cec5b 100644 --- a/Dockerfile.wolfi +++ b/Dockerfile.wolfi @@ -1,3 +1,3 @@ -FROM docker.elastic.co/wolfi/chainguard-base:latest@sha256:bfdeddb33330a281950c2a54adef991dbbe6a42832bc505d13b11beaf50ae73f +FROM docker.elastic.co/wolfi/chainguard-base:latest@sha256:ea157dd3d70787c6b6dc9e14dda1ff103c781d4c3f9a544393ff4583dd80c9d0 ARG AGENT_DIR COPY ${AGENT_DIR} /opt/nodejs \ No newline at end of file diff --git a/dev-utils/update-4x-branch.sh b/dev-utils/update-4x-branch.sh index b82932e26fc..9564901162a 100755 --- a/dev-utils/update-4x-branch.sh +++ b/dev-utils/update-4x-branch.sh @@ -4,6 +4,8 @@ # just-tagged release. The 4.x branch needs to be updated for the current docs # build. # +# Usage: +# ./dev-utils/update-4x-branch.sh [TARGTAG [LASTTAG]] if [ "$TRACE" != "" ]; then export PS4='${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' @@ -27,24 +29,37 @@ cd $WRKDIR git clone git@github.com:elastic/apm-agent-nodejs.git cd apm-agent-nodejs -TARGTAG=$(git tag --points-at HEAD) +# Allow passing in target tag (first arg), in case the latest commit is no +# longer the tagged release commit. +TARGTAG="$1" +if [[ -z "$TARGTAG" ]]; then + TARGTAG=$(git tag --points-at HEAD) +fi if [[ ! ("$TARGTAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]$) ]]; then - fatal "the tag on HEAD, '${TARGTAG}', does not look like a release tag" + fatal "the target tag, '${TARGTAG}', does not look like a release tag" fi # echo "TARGTAG=$TARGTAG" -readonly NUM_COMMITS_SANITY_GUARD=200 -LASTTAG=$( - git log --pretty=format:%h -$NUM_COMMITS_SANITY_GUARD | tail -n +2 | while read sha; do - possible=$(git tag --points-at $sha) - if [[ "$possible" =~ ^v[0-9]+\.[0-9]+\.[0-9]$ ]]; then - echo $possible - break - fi - done -) +# Allow passing in last tag (second arg), in case the 4.x branch wasn't updated +# for some previous releases. +LASTTAG="$2" if [[ -z "$LASTTAG" ]]; then - fatal "could not find previous release tag in last $NUM_COMMITS_SANITY_GUARD commits" + readonly NUM_COMMITS_SANITY_GUARD=200 + LASTTAG=$( + git log --pretty=format:%h -$NUM_COMMITS_SANITY_GUARD | tail -n +2 | while read sha; do + possible=$(git tag --points-at $sha) + if [[ "$possible" =~ ^v[0-9]+\.[0-9]+\.[0-9]$ ]]; then + echo $possible + break + fi + done + ) + if [[ -z "$LASTTAG" ]]; then + fatal "could not find previous release tag in last $NUM_COMMITS_SANITY_GUARD commits" + fi +fi +if [[ ! ("$LASTTAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]$) ]]; then + fatal "the last tag, '${LASTTAG}', does not look like a release tag" fi # echo "LASTTAG=$LASTTAG" diff --git a/docs/azure-functions.asciidoc b/docs/azure-functions.asciidoc index 08aa0884e24..cb91dfd6697 100644 --- a/docs/azure-functions.asciidoc +++ b/docs/azure-functions.asciidoc @@ -9,7 +9,7 @@ endif::[] === Monitoring Node.js Azure Functions -The Node.js APM Agent can trace function invocations in an https://learn.microsoft.com/en-us/azure/azure-functions/[Azure Functions] app. +The Node.js APM Agent can trace function invocations in an https://learn.microsoft.com/en-us/azure/azure-functions/[Azure Functions] app, using either v3 or https://learn.microsoft.com/en-us/azure/azure-functions/functions-node-upgrade-v4[v4 of the Node.js programming model]. [float] @@ -36,7 +36,7 @@ will result in unreasonably large deployments that will be very slow to publish and will run your Azure Function app VM out of disk space. ==== -You can also take a look at and use this https://github.com/elastic/apm-agent-nodejs/tree/main/examples/an-azure-function-app/[Azure Functions example app with Elastic APM already integrated]. +You can also take a look at and use this https://github.com/elastic/apm-agent-nodejs/tree/main/examples/azure-function-app/[Azure Functions example app with Elastic APM already integrated]. [float] [[azure-functions-setup]] @@ -69,17 +69,14 @@ require('elastic-apm-node').start({ ---- <1> Optional <> can be added here. -2. Add a "main" entry to your package.json pointing to the app init file. +2. Change the "main" entry in your "package.json" to point to the initapm.js file. + [source,json] ---- ... - "main": "initapm.js", + "main": "{initapm.js,src/functions/*.js}", ... ---- -+ -If your application already has a "main" init file, you can instead add the -`require('elastic-apm-node').start()` to top of that file. [float] @@ -103,7 +100,7 @@ For example: image::./images/azure-functions-configuration.png[Configuring the APM Agent in the Azure Portal] -For local testing via `func start` you can set these environment variables in +For local testing via `func start`, you can set these environment variables in your terminal, or in the "local.settings.json" file. See the <> for full details on supported configuration variables. @@ -127,13 +124,11 @@ of time, so allow a minute or so for data to appear. [[azure-functions-limitations]] ==== Limitations -This instrumentation does not send an APM transaction or error to APM server when -a handler has an `uncaughtException` or `unhandledRejection`. -The Azure Functions Node.js reference https://learn.microsoft.com/en-ca/azure/azure-functions/functions-reference-node#use-async-and-await[has a section] with best practices for avoiding these cases. +Distributed tracing for incoming HTTP requests to Azure Functions (using v4 of the programming model) does *not* work, because of a issue with Azure's handling of trace-context. See https://github.com/elastic/apm-agent-nodejs/pull/4426#issuecomment-2596922653[this] for details. + +Azure Functions instrumentation currently does _not_ collect system metrics in the background because of a concern with unintentionally increasing Azure Functions costs (for Consumption plans). -Azure Functions instrumentation currently does _not_ collect system metrics in -the background because of a concern with unintentionally increasing Azure -Functions costs (for Consumption plans). +Elastic APM's <> is not supported for Azure Functions. [float] diff --git a/docs/esm.asciidoc b/docs/esm.asciidoc index d984b3881e2..32ca0c8f362 100644 --- a/docs/esm.asciidoc +++ b/docs/esm.asciidoc @@ -36,7 +36,7 @@ when invoked as follows: export ELASTIC_APM_SERVER_URL='https://...apm...cloud.es.io:443' export ELASTIC_APM_SECRET_TOKEN='...' node -r elastic-apm-node/start.js \ - --experimental-loader=elastic-apm-node/loader.mjs' \ + --experimental-loader=elastic-apm-node/loader.mjs \ node server.mjs ---- diff --git a/docs/supported-technologies.asciidoc b/docs/supported-technologies.asciidoc index 979465fb4c2..db517480352 100644 --- a/docs/supported-technologies.asciidoc +++ b/docs/supported-technologies.asciidoc @@ -63,7 +63,7 @@ These are the frameworks that we officially support: |======================================================================= | Framework | Version | Note | <> | N/A | -| <> | ~4 | See https://learn.microsoft.com/en-ca/azure/azure-functions/set-runtime-version[the guide on Azure Functions runtime versions]. +| <> | v3, v4 | https://learn.microsoft.com/en-us/azure/azure-functions/functions-node-upgrade-v4[Node.js programming model v3 and v4] | <> | ^4.0.0 | | <> | >=1.0.0 | See also https://www.fastify.io/docs/latest/Reference/LTS/[Fastify's own LTS documentation] | <> | >=17.9.0 <22.0.0 | diff --git a/eslint.config.js b/eslint.config.js index c05b5de444d..ecadd738cff 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -30,7 +30,7 @@ module.exports = [ 'examples/esbuild/dist/**', 'examples/typescript/dist/**', - 'examples/an-azure-function-app/**', + 'examples/azure-function-app/**', 'lib/opentelemetry-bridge/opentelemetry-core-mini/**', 'test/babel/out.js', 'test/lambda/fixtures/esbuild-bundled-handler/hello.js', diff --git a/examples/an-azure-function-app/Bye/index.js b/examples/an-azure-function-app/Bye/index.js deleted file mode 100644 index f0d0364ce0a..00000000000 --- a/examples/an-azure-function-app/Bye/index.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = async function (context, _req) { - const body = JSON.stringify({ good: 'bye' }) - context.res = { - status: 200, - headers: { - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(body) - }, - body - } -} diff --git a/examples/an-azure-function-app/Hi/function.json b/examples/an-azure-function-app/Hi/function.json deleted file mode 100644 index 91052aaf8a0..00000000000 --- a/examples/an-azure-function-app/Hi/function.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "bindings": [ - { - "authLevel": "Anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "req", - "methods": [ - "get", - "post" - ] - }, - { - "type": "http", - "direction": "out", - "name": "res" - } - ] -} \ No newline at end of file diff --git a/examples/an-azure-function-app/Hi/index.js b/examples/an-azure-function-app/Hi/index.js deleted file mode 100644 index 2a50aa6ac08..00000000000 --- a/examples/an-azure-function-app/Hi/index.js +++ /dev/null @@ -1,28 +0,0 @@ -const http = require('http') -const https = require('https') - -module.exports = async function (context, req) { - return new Promise((resolve, reject) => { - // Call the 'Bye' Function in this same Function App... - const url = new URL(req.url) - url.pathname = '/api/Bye' - const proto = (url.protocol === 'https:' ? https : http) - proto.get(url, res => { - res.resume() - res.on('error', reject) - res.on('end', () => { - // ... then respond. - const body = JSON.stringify({ hi: 'there' }) - context.res = { - status: 200, - headers: { - 'Content-Type': 'application/json', - 'Content-Length': Buffer.byteLength(body) - }, - body - } - resolve() - }) - }) - }) -} diff --git a/examples/an-azure-function-app/initapm.js b/examples/an-azure-function-app/initapm.js deleted file mode 100644 index 482b0b1be46..00000000000 --- a/examples/an-azure-function-app/initapm.js +++ /dev/null @@ -1,3 +0,0 @@ -require('elastic-apm-node').start({ - // ... -}) diff --git a/examples/an-azure-function-app/package.json b/examples/an-azure-function-app/package.json deleted file mode 100644 index 275269bd469..00000000000 --- a/examples/an-azure-function-app/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "an-azure-function-app", - "version": "1.0.0", - "description": "An example Azure Function app showing Elastic APM integration for tracing/monitoring", - "private": true, - "main": "initapm.js", - "scripts": { - "start": "func start" - }, - "dependencies": { - "elastic-apm-node": "^3.42.0" - } -} diff --git a/examples/an-azure-function-app/.gitignore b/examples/azure-function-app/.gitignore similarity index 100% rename from examples/an-azure-function-app/.gitignore rename to examples/azure-function-app/.gitignore diff --git a/examples/an-azure-function-app/.npmrc b/examples/azure-function-app/.npmrc similarity index 100% rename from examples/an-azure-function-app/.npmrc rename to examples/azure-function-app/.npmrc diff --git a/examples/azure-function-app/Makefile b/examples/azure-function-app/Makefile new file mode 100644 index 00000000000..cb7b5530b95 --- /dev/null +++ b/examples/azure-function-app/Makefile @@ -0,0 +1,15 @@ +APP_NAME=$(USER)-example-azure-function-app + +.PHONY: print-app-name +print-app-name: + @echo "APP_NAME: $(APP_NAME)" + +.PHONY: publish +publish: + func azure functionapp publish "$(APP_NAME)" + +# Note that the Azure Functions log stream is extremely flaky. Don't expect it +# to reliably be able to show logs from the deployed function app. +.PHONY: logstream +logstream: + func azure functionapp logstream "$(APP_NAME)" diff --git a/examples/an-azure-function-app/README.md b/examples/azure-function-app/README.md similarity index 63% rename from examples/an-azure-function-app/README.md rename to examples/azure-function-app/README.md index e34bd852a7b..f6dafbca622 100644 --- a/examples/an-azure-function-app/README.md +++ b/examples/azure-function-app/README.md @@ -1,10 +1,10 @@ -This directory holds a very small Azure Function App implemented in Node.js -and setup to be traced by the Elastic APM agent. The App has two "functions": - -1. `Hi` - an HTTP-triggered function that will call the `Bye` function, then - respond with `{"hi":"there"}`. -2. `Bye` - an HTTP-triggered function that will respond with `{"good":"bye"}`. +This directory holds a simple Azure Function (using v4 of the Node.js +programming model) implemented in Node.js and setup to be traced by the Elastic +APM agent. The App has a single function: +- `Hello`: an HTTP-triggered function that will call worldtimeapi.org to get + the current time in Vancouver and respond with + `{"hello": "world", "current time in Vancouver": "..."}` # Testing locally @@ -13,14 +13,7 @@ and setup to be traced by the Elastic APM agent. The App has two "functions": 2. Install the [Azure Functions Core Tools](https://github.com/Azure/azure-functions-core-tools), which provide a `func` CLI tool for running Azure Functions locally for - development, and for publishing an Function App to Azure. One way to - install is via: - - npm install -g azure-functions-core-tools@4 - - It is recommended that you **not** install it in the local `./node_modules` - folder, because its large install size will get in the way of publishing to - Azure. + development, and for publishing an Function App to Azure. 3. Set environment variable to configure the APM agent, for example: @@ -29,12 +22,12 @@ and setup to be traced by the Elastic APM agent. The App has two "functions": export ELASTIC_APM_SECRET_TOKEN=... ``` -4. `npm start` +4. `npm start` (This calls `func start` to run the Azure Function app locally.) 5. In a separate terminal, call the Azure Function via: ``` - curl -i http://localhost:7071/api/Hi + curl -i http://localhost:7071/api/Hello ``` @@ -52,7 +45,7 @@ and setup to be traced by the Elastic APM agent. The App has two "functions": 4. Call your functions: ``` - curl -i https://.azurewebsites.net/api/hi + curl -i https://.azurewebsites.net/api/hello ``` The result (after a minute for data to propagate) should be a `` service diff --git a/examples/azure-function-app/host.json b/examples/azure-function-app/host.json new file mode 100644 index 00000000000..06d01bdaa95 --- /dev/null +++ b/examples/azure-function-app/host.json @@ -0,0 +1,15 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + }, + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[4.*, 5.0.0)" + } +} diff --git a/examples/azure-function-app/initapm.js b/examples/azure-function-app/initapm.js new file mode 100644 index 00000000000..00a368a32ea --- /dev/null +++ b/examples/azure-function-app/initapm.js @@ -0,0 +1 @@ +require('elastic-apm-node').start() diff --git a/examples/an-azure-function-app/local.settings.json b/examples/azure-function-app/local.settings.json similarity index 79% rename from examples/an-azure-function-app/local.settings.json rename to examples/azure-function-app/local.settings.json index 9dcd935ef0c..8638bc7ec71 100644 --- a/examples/an-azure-function-app/local.settings.json +++ b/examples/azure-function-app/local.settings.json @@ -5,7 +5,7 @@ "AzureWebJobsStorage": "", "REGION_NAME": "test-region-name", - "WEBSITE_SITE_NAME": "an-azure-function-app", + "WEBSITE_SITE_NAME": "example-azure-function-app", "WEBSITE_INSTANCE_ID": "test-website-instance-id" } } diff --git a/examples/azure-function-app/package.json b/examples/azure-function-app/package.json new file mode 100644 index 00000000000..bd09f8c86d6 --- /dev/null +++ b/examples/azure-function-app/package.json @@ -0,0 +1,18 @@ +{ + "name": "example-azure-function-app", + "version": "2.0.0", + "description": "An example Azure Function app showing Elastic APM integration for tracing/monitoring", + "private": true, + "main": "{initapm.js,src/functions/*.js}", + "engines": { + "node": ">=20" + }, + "scripts": { + "start": "func start", + "dev:sync-local-apm-agent-changes": "rsync -av ../../lib/ ./node_modules/elastic-apm-node/lib/" + }, + "dependencies": { + "@azure/functions": "^4.0.0", + "elastic-apm-node": "^4.11.0" + } +} diff --git a/examples/azure-function-app/src/functions/Hello.js b/examples/azure-function-app/src/functions/Hello.js new file mode 100644 index 00000000000..5d2bc432f4a --- /dev/null +++ b/examples/azure-function-app/src/functions/Hello.js @@ -0,0 +1,24 @@ +const { app } = require('@azure/functions'); + +app.http('Hello', { + methods: ['GET'], + authLevel: 'anonymous', + handler: async (_request, _context) => { + const url = new URL('http://worldtimeapi.org/api/timezone/America/Vancouver'); + const timeRes = await fetch(url, { signal: AbortSignal.timeout(5000) }); + const timeBody = await timeRes.json(); + + const body = JSON.stringify({ + hello: 'world', + 'current time in Vancouver': timeBody.datetime + }); + return { + status: 200, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(body) + }, + body + }; + }, +}); diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 39744d2409f..669926d343a 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "elastic-apm-node": "elastic/apm-agent-nodejs#main", - "next": "14.2.10", + "next": "14.2.21", "react": "18.2.0", "react-dom": "18.2.0" }, diff --git a/lib/instrumentation/azure-functions.js b/lib/instrumentation/azure-functions.js index ea1247bae06..d158a1b8b6e 100644 --- a/lib/instrumentation/azure-functions.js +++ b/lib/instrumentation/azure-functions.js @@ -363,30 +363,55 @@ function instrument(agent) { isFirstRun = false; } + // In programming model v3 the InvocationContext includes + // `bindingDefinitions` and `executionContext`. In v4 the structure is a + // little different. + let bindingDefinitions = context.bindingDefinitions; + if (!bindingDefinitions) { + bindingDefinitions = []; + // Input bindings + bindingDefinitions.push({ + name: context?.options?.trigger?.name, + type: context?.options?.trigger?.type, + direction: context?.options?.trigger?.direction, + }); + // Output bindings + bindingDefinitions.push(context?.options?.return); + } + let executionContext = context.executionContext; + if (!executionContext) { + executionContext = { + functionDirectory: '', + functionName: context.functionName, + }; + } + const funcInfo = (hookCtx.hookData.funcInfo = new FunctionInfo( - context.bindingDefinitions, - context.executionContext, + bindingDefinitions, + executionContext, log, )); const triggerType = funcInfo.triggerType; - // Handle trace-context. - // Note: We ignore the `context.traceContext`. By default it is W3C - // trace-context that continues the given traceparent in headers. However, - // we do not injest that span, so would get a broken distributed trace if - // we included it. + // `InvocationContext.traceContext` is broken: it results in sampled=false + // (i.e. traces are discarded) and/or broken traces because it creates an + // internal Span ID in the trace that cannot be ingested. + // See this for full explanation: + // https://github.com/elastic/apm-agent-nodejs/pull/4426#issuecomment-2596922653 let traceparent; let tracestate; - if (triggerType === TRIGGER_HTTP && context.req && context.req.headers) { - traceparent = - context.req.headers.traceparent || - context.req.headers['elastic-apm-traceparent']; + if (triggerType === TRIGGER_HTTP && context?.req?.headers?.traceparent) { + traceparent = context.req.headers.traceparent; tracestate = context.req.headers.tracestate; + log.trace( + { traceparent, tracestate }, + 'azure-functions: get trace-context from HTTP trigger request headers', + ); } const trans = (hookCtx.hookData.trans = ins.startTransaction( // This is the default name. Trigger-specific values are added below. - context.executionContext.functionName, + executionContext.functionName, TRANS_TYPE_FROM_TRIGGER_TYPE[triggerType], { childOf: traceparent, @@ -399,7 +424,7 @@ function instrument(agent) { const accountId = getAzureAccountId(); const resourceGroup = process.env.WEBSITE_RESOURCE_GROUP; const fnAppName = process.env.WEBSITE_SITE_NAME; - const fnName = context.executionContext.functionName; + const fnName = executionContext.functionName; const faasData = { trigger: { type: FAAS_TRIGGER_TYPE_FROM_TRIGGER_TYPE[triggerType], diff --git a/lib/instrumentation/modules/@smithy/smithy-client.js b/lib/instrumentation/modules/@smithy/smithy-client.js index e20eb767c62..fb128e53a9d 100644 --- a/lib/instrumentation/modules/@smithy/smithy-client.js +++ b/lib/instrumentation/modules/@smithy/smithy-client.js @@ -110,7 +110,7 @@ module.exports = function (mod, agent, { name, version, enabled }) { // `@smithy/` npm org. if ( name === '@smithy/smithy-client' && - !semver.satisfies(version, '>=1 <4') + !semver.satisfies(version, '>=1 <5') ) { agent.logger.debug( 'cannot instrument @aws-sdk/client-*: @smithy/smithy-client version %s not supported', diff --git a/lib/instrumentation/transaction.js b/lib/instrumentation/transaction.js index 5280bee3220..feb9d469df3 100644 --- a/lib/instrumentation/transaction.js +++ b/lib/instrumentation/transaction.js @@ -91,6 +91,7 @@ function Transaction(agent, name, ...args) { sampled: this.sampled, name: this.name, type: this.type, + traceparent: this.traceparent, }); this._defaultName = name || ''; diff --git a/package-lock.json b/package-lock.json index da95bb10680..f33942b7ce1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "elastic-apm-node", - "version": "4.10.0", + "version": "4.11.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "elastic-apm-node", - "version": "4.10.0", + "version": "4.11.0", "license": "BSD-2-Clause", "dependencies": { "@elastic/ecs-pino-format": "^1.5.0", @@ -27,7 +27,7 @@ "fast-safe-stringify": "^2.0.7", "fast-stream-to-buffer": "^1.0.0", "http-headers": "^3.0.2", - "import-in-the-middle": "1.11.3", + "import-in-the-middle": "1.12.0", "json-bigint": "^1.0.0", "lru-cache": "10.2.0", "measured-reporting": "^1.51.1", @@ -117,7 +117,6 @@ "prettier": "^3.0.0", "pug": "^3.0.1", "redis": "^4.3.0", - "request": "^2.88.2", "restify": "^11.0.0", "rimraf": "^3.0.2", "tape": "^5.0.0", @@ -199,15 +198,15 @@ "dev": true }, "node_modules/@apollo/server": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.2.tgz", - "integrity": "sha512-WUTHY7DDek8xAMn4Woa9Bl8duQUDzRYQkosX/d1DtCsBWESZyApR7ndnI5d6+W4KSTtqBHhJFkusEI7CWuIJXg==", + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.3.tgz", + "integrity": "sha512-mW8idE2q0/BN14mimfJU5DAnoPHZRrAWgwsVLBEdACds+mxapIYxIbI6AH4AsOpxfrpvHts3PCYDbopy1XPW1g==", "dev": true, "dependencies": { "@apollo/cache-control-types": "^1.0.3", "@apollo/server-gateway-interface": "^1.1.1", "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.createhash": "^2.0.0", + "@apollo/utils.createhash": "^2.0.2", "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.isnodelike": "^2.0.0", "@apollo/utils.keyvaluecache": "^2.1.0", @@ -490,12 +489,12 @@ } }, "node_modules/@apollo/utils.createhash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.0.tgz", - "integrity": "sha512-9GhGGD3J0HJF/VC+odwYpKi3Cg1NWrsO8GQvyGwDS5v/78I3154Hn8s4tpW+nqoaQ/lAvxdQQr3HM1b5HLM6Ww==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.2.tgz", + "integrity": "sha512-UkS3xqnVFLZ3JFpEmU/2cM2iKJotQXMoSTgxXsfQgXLC5gR1WaepoXagmYnPSA7Q/2cmnyTYK5OgAgoC4RULPg==", "dev": true, "dependencies": { - "@apollo/utils.isnodelike": "^2.0.0", + "@apollo/utils.isnodelike": "^2.0.1", "sha.js": "^2.4.11" }, "engines": { @@ -524,9 +523,9 @@ } }, "node_modules/@apollo/utils.isnodelike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.0.tgz", - "integrity": "sha512-77CiAM2qDXn0haQYrgX0UgrboQykb+bOHaz5p3KKItMwUZ/EFphzuB2vqHvubneIc9dxJcTx2L7MFDswRw/JAQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.1.tgz", + "integrity": "sha512-w41XyepR+jBEuVpoRM715N2ZD0xMD413UiJx8w5xnAZD2ZkSJnMJBoIzauK83kJpSgNuR6ywbV29jG9NmxjK0Q==", "dev": true, "engines": { "node": ">=14" @@ -4135,10 +4134,13 @@ } }, "node_modules/@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -4201,9 +4203,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", - "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4219,11 +4221,12 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "dependencies": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" }, "engines": { @@ -4257,15 +4260,31 @@ } }, "node_modules/@fastify/formbody": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.1.tgz", - "integrity": "sha512-LPrcadSIK8TrQk510Zdj56fnw7cyHq0/PW0YHGGM8ycGL4X7XAex+FKcwpzB4i5lF9eykc71a4EtcO9AEoByqw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.2.tgz", + "integrity": "sha512-84v5J2KrkXzjgBpYnaNRPqwgMsmY7ZDjuj0YVuMR3NXCJRCgKEZy/taSP1wUYGn0onfxJpLyRGDLa+NMaDJtnA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "dependencies": { "fast-querystring": "^1.1.2", "fastify-plugin": "^5.0.0" } }, + "node_modules/@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "dev": true + }, "node_modules/@fastify/merge-json-schemas": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", @@ -4275,6 +4294,25 @@ "fast-deep-equal": "^3.1.3" } }, + "node_modules/@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "dev": true, + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + } + }, + "node_modules/@fastify/proxy-addr/node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@graphql-tools/merge": { "version": "8.2.10", "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.10.tgz", @@ -5114,9 +5152,9 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, @@ -5128,11 +5166,11 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", - "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "dependencies": { - "@opentelemetry/core": "1.29.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -5143,12 +5181,12 @@ } }, "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz", - "integrity": "sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", + "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", "dependencies": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" }, "engines": { "node": ">=14" @@ -6415,9 +6453,9 @@ } }, "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "dependencies": { "humanize-ms": "^1.2.1" }, @@ -7035,15 +7073,6 @@ "node": ">=4.0" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/aws-ssl-profiles": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz", @@ -7053,16 +7082,10 @@ "node": ">= 6.0.0" } }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -7071,9 +7094,9 @@ } }, "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -7581,12 +7604,6 @@ } ] }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "node_modules/cassandra-driver": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.7.2.tgz", @@ -8907,18 +8924,18 @@ } }, "node_modules/eslint": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", - "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", + "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.17.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.18.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -9132,9 +9149,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.0.tgz", - "integrity": "sha512-xF3zJkOfLlFOm5TvmqmsnA9/fO+/z2pYs0dkuKXKN/ymS6UB1yEcaoIkqxLKQ9Dw/WmLX/Tdh6/5ZS5azVixFQ==", + "version": "17.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.1.tgz", + "integrity": "sha512-KFw7x02hZZkBdbZEFQduRGH4VkIH4MW97ClsbAM4Y4E6KguBJWGfWG1P4HEIpZk2bkoWf0bojpnjNAhYQP8beA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.1", @@ -9685,12 +9702,6 @@ "node": ">= 0.8" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -9826,9 +9837,9 @@ } }, "node_modules/fastify": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.2.0.tgz", - "integrity": "sha512-3s+Qt5S14Eq5dCpnE0FxTp3z4xKChI83ZnMv+k0FwX+VUoZrgCFoLAxpfdi/vT4y6Mk+g7aAMt9pgXDoZmkefQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.2.1.tgz", + "integrity": "sha512-rslrNBF67eg8/Gyn7P2URV8/6pz8kSAscFL4EThZJ8JBMaXacVdVE4hmUcnPNKERl5o/xTiBSLfdowBRhVF1WA==", "dev": true, "funding": [ { @@ -9844,6 +9855,7 @@ "@fastify/ajv-compiler": "^4.0.0", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", @@ -9851,7 +9863,6 @@ "light-my-request": "^6.0.0", "pino": "^9.0.0", "process-warning": "^4.0.0", - "proxy-addr": "^2.0.7", "rfdc": "^1.3.1", "secure-json-parse": "^3.0.1", "semver": "^7.6.0", @@ -10105,29 +10116,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/formidable": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", @@ -10502,51 +10490,6 @@ "node": ">=0.10.0" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -10782,21 +10725,6 @@ "node": ">= 14" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -10885,9 +10813,9 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.3.tgz", - "integrity": "sha512-tNpKEb4AjZrCyrxi+Eyu43h5ig0O8ZRFSXPHh/00/o+4P4pKzVEW/m5lsVtsAT7fCIgmQOAPjdqecGDsBXRxsw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -10951,9 +10879,9 @@ } }, "node_modules/ioredis": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", - "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz", + "integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==", "dev": true, "dependencies": { "@ioredis/commands": "^1.1.1", @@ -11369,12 +11297,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -11456,12 +11378,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "node_modules/jackpot": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/jackpot/-/jackpot-0.0.6.tgz", @@ -11685,21 +11601,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -12000,23 +11901,33 @@ } }, "node_modules/light-my-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.0.0.tgz", - "integrity": "sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.5.1.tgz", + "integrity": "sha512-0q82RyxIextuDtkA0UDofhPHIiQ2kmpa7fwElCSlm/8nQl36cDU1Cw+CAO90Es0lReH2HChClKL84I86Nc52hg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "dependencies": { - "cookie": "^0.6.0", + "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } }, "node_modules/light-my-request/node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=18" } }, "node_modules/lodash": { @@ -12609,9 +12520,9 @@ } }, "node_modules/mysql2": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.5.tgz", - "integrity": "sha512-0XFu8rUmFN9vC0ME36iBvCUObftiMHItrYFhlCRvFWbLgpNqtC4Br/NmZX1HNCszxT0GGy5QtP+k3Q3eCJPaYA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.12.0.tgz", + "integrity": "sha512-C8fWhVysZoH63tJbX8d10IAoYCyXy4fdRFz2Ihrt9jtPILYynFEKUUzpp1U7qxzDc3tMbotvaBH+sl6bFnGZiw==", "dev": true, "dependencies": { "aws-ssl-profiles": "^1.1.1", @@ -12879,15 +12790,6 @@ "node": "*" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -13236,12 +13138,6 @@ "node": ">=8" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, "node_modules/pg": { "version": "8.13.1", "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", @@ -13680,10 +13576,21 @@ "dev": true }, "node_modules/process-warning": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", - "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==", - "dev": true + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, "node_modules/promise": { "version": "7.3.1", @@ -13713,12 +13620,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, "node_modules/pug": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", @@ -14164,57 +14065,6 @@ "resolved": "https://registry.npmjs.org/relative-microtime/-/relative-microtime-2.0.0.tgz", "integrity": "sha512-l18ha6HEZc+No/uK4GyAnNxgKW7nvEe35IaeN54sShMojtqik2a6GbTyuiezkjpPaqP874Z3lW5ysBo5irz4NA==" }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/require_optional": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", @@ -15657,19 +15507,6 @@ "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", "dev": true }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", @@ -15732,18 +15569,6 @@ "node": ">=0.6.x" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -15845,9 +15670,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -15903,9 +15728,9 @@ } }, "node_modules/undici": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.1.0.tgz", - "integrity": "sha512-3+mdX2R31khuLCm2mKExSlMdJsfol7bJkIMH80tdXA74W34rT1jKemUTlYR7WY3TqsV4wfOgpatWmmB2Jl1+5g==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.3.tgz", + "integrity": "sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==", "dev": true, "engines": { "node": ">=20.18.1" @@ -16141,12 +15966,12 @@ } }, "node_modules/wait-on": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.1.tgz", - "integrity": "sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.2.tgz", + "integrity": "sha512-qHlU6AawrgAIHlueGQHQ+ETcPLAauXbnoTKl3RKq20W0T8x0DKVAo5xWIYjHSyvHxQlcYbFdR0jp4T9bDVITFA==", "dev": true, "dependencies": { - "axios": "^1.7.7", + "axios": "^1.7.9", "joi": "^17.13.3", "lodash": "^4.17.21", "minimist": "^1.2.8", @@ -16468,15 +16293,15 @@ } }, "@apollo/server": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.2.tgz", - "integrity": "sha512-WUTHY7DDek8xAMn4Woa9Bl8duQUDzRYQkosX/d1DtCsBWESZyApR7ndnI5d6+W4KSTtqBHhJFkusEI7CWuIJXg==", + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.3.tgz", + "integrity": "sha512-mW8idE2q0/BN14mimfJU5DAnoPHZRrAWgwsVLBEdACds+mxapIYxIbI6AH4AsOpxfrpvHts3PCYDbopy1XPW1g==", "dev": true, "requires": { "@apollo/cache-control-types": "^1.0.3", "@apollo/server-gateway-interface": "^1.1.1", "@apollo/usage-reporting-protobuf": "^4.1.1", - "@apollo/utils.createhash": "^2.0.0", + "@apollo/utils.createhash": "^2.0.2", "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.isnodelike": "^2.0.0", "@apollo/utils.keyvaluecache": "^2.1.0", @@ -16682,12 +16507,12 @@ } }, "@apollo/utils.createhash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.0.tgz", - "integrity": "sha512-9GhGGD3J0HJF/VC+odwYpKi3Cg1NWrsO8GQvyGwDS5v/78I3154Hn8s4tpW+nqoaQ/lAvxdQQr3HM1b5HLM6Ww==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.2.tgz", + "integrity": "sha512-UkS3xqnVFLZ3JFpEmU/2cM2iKJotQXMoSTgxXsfQgXLC5gR1WaepoXagmYnPSA7Q/2cmnyTYK5OgAgoC4RULPg==", "dev": true, "requires": { - "@apollo/utils.isnodelike": "^2.0.0", + "@apollo/utils.isnodelike": "^2.0.1", "sha.js": "^2.4.11" } }, @@ -16704,9 +16529,9 @@ "dev": true }, "@apollo/utils.isnodelike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.0.tgz", - "integrity": "sha512-77CiAM2qDXn0haQYrgX0UgrboQykb+bOHaz5p3KKItMwUZ/EFphzuB2vqHvubneIc9dxJcTx2L7MFDswRw/JAQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.1.tgz", + "integrity": "sha512-w41XyepR+jBEuVpoRM715N2ZD0xMD413UiJx8w5xnAZD2ZkSJnMJBoIzauK83kJpSgNuR6ywbV29jG9NmxjK0Q==", "dev": true }, "@apollo/utils.keyvaluecache": { @@ -19507,10 +19332,13 @@ } }, "@eslint/core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", - "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", - "dev": true + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", + "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.15" + } }, "@eslint/eslintrc": { "version": "3.2.0", @@ -19556,9 +19384,9 @@ } }, "@eslint/js": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", - "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", + "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "dev": true }, "@eslint/object-schema": { @@ -19568,11 +19396,12 @@ "dev": true }, "@eslint/plugin-kit": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", - "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", + "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", "dev": true, "requires": { + "@eslint/core": "^0.10.0", "levn": "^0.4.1" } }, @@ -19603,15 +19432,21 @@ } }, "@fastify/formbody": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.1.tgz", - "integrity": "sha512-LPrcadSIK8TrQk510Zdj56fnw7cyHq0/PW0YHGGM8ycGL4X7XAex+FKcwpzB4i5lF9eykc71a4EtcO9AEoByqw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.2.tgz", + "integrity": "sha512-84v5J2KrkXzjgBpYnaNRPqwgMsmY7ZDjuj0YVuMR3NXCJRCgKEZy/taSP1wUYGn0onfxJpLyRGDLa+NMaDJtnA==", "dev": true, "requires": { "fast-querystring": "^1.1.2", "fastify-plugin": "^5.0.0" } }, + "@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "dev": true + }, "@fastify/merge-json-schemas": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", @@ -19621,6 +19456,24 @@ "fast-deep-equal": "^3.1.3" } }, + "@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "dev": true, + "requires": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true + } + } + }, "@graphql-tools/merge": { "version": "8.2.10", "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.10.tgz", @@ -20422,29 +20275,29 @@ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, "@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "requires": { "@opentelemetry/semantic-conventions": "1.28.0" } }, "@opentelemetry/resources": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", - "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "requires": { - "@opentelemetry/core": "1.29.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" } }, "@opentelemetry/sdk-metrics": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz", - "integrity": "sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", + "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", "requires": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" } }, "@opentelemetry/semantic-conventions": { @@ -21518,9 +21371,9 @@ } }, "agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "requires": { "humanize-ms": "^1.2.1" } @@ -21991,28 +21844,16 @@ } } }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, "aws-ssl-profiles": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz", "integrity": "sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==", "dev": true }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, "axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "requires": { "follow-redirects": "^1.15.6", @@ -22021,9 +21862,9 @@ }, "dependencies": { "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -22387,12 +22228,6 @@ "integrity": "sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "cassandra-driver": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.7.2.tgz", @@ -23423,18 +23258,18 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "eslint": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", - "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", + "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.9.0", + "@eslint/core": "^0.10.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.17.0", - "@eslint/plugin-kit": "^0.2.3", + "@eslint/js": "9.18.0", + "@eslint/plugin-kit": "^0.2.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.1", @@ -23661,9 +23496,9 @@ } }, "eslint-plugin-n": { - "version": "17.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.0.tgz", - "integrity": "sha512-xF3zJkOfLlFOm5TvmqmsnA9/fO+/z2pYs0dkuKXKN/ymS6UB1yEcaoIkqxLKQ9Dw/WmLX/Tdh6/5ZS5azVixFQ==", + "version": "17.15.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.15.1.tgz", + "integrity": "sha512-KFw7x02hZZkBdbZEFQduRGH4VkIH4MW97ClsbAM4Y4E6KguBJWGfWG1P4HEIpZk2bkoWf0bojpnjNAhYQP8beA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.1", @@ -23987,12 +23822,6 @@ "mini-queue": "0.0.14" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -24108,14 +23937,15 @@ } }, "fastify": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.2.0.tgz", - "integrity": "sha512-3s+Qt5S14Eq5dCpnE0FxTp3z4xKChI83ZnMv+k0FwX+VUoZrgCFoLAxpfdi/vT4y6Mk+g7aAMt9pgXDoZmkefQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.2.1.tgz", + "integrity": "sha512-rslrNBF67eg8/Gyn7P2URV8/6pz8kSAscFL4EThZJ8JBMaXacVdVE4hmUcnPNKERl5o/xTiBSLfdowBRhVF1WA==", "dev": true, "requires": { "@fastify/ajv-compiler": "^4.0.0", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", @@ -24123,7 +23953,6 @@ "light-my-request": "^6.0.0", "pino": "^9.0.0", "process-warning": "^4.0.0", - "proxy-addr": "^2.0.7", "rfdc": "^1.3.1", "secure-json-parse": "^3.0.1", "semver": "^7.6.0", @@ -24334,23 +24163,6 @@ "is-callable": "^1.1.3" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "formidable": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", @@ -24614,42 +24426,6 @@ } } }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -24835,17 +24611,6 @@ "debug": "^4.3.4" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -24915,9 +24680,9 @@ } }, "import-in-the-middle": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.3.tgz", - "integrity": "sha512-tNpKEb4AjZrCyrxi+Eyu43h5ig0O8ZRFSXPHh/00/o+4P4pKzVEW/m5lsVtsAT7fCIgmQOAPjdqecGDsBXRxsw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", "requires": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -24969,9 +24734,9 @@ "dev": true }, "ioredis": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", - "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz", + "integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==", "dev": true, "requires": { "@ioredis/commands": "^1.1.1", @@ -25235,12 +25000,6 @@ "which-typed-array": "^1.1.14" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -25301,12 +25060,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "jackpot": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/jackpot/-/jackpot-0.0.6.tgz", @@ -25502,18 +25255,6 @@ } } }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -25745,20 +25486,20 @@ } }, "light-my-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.0.0.tgz", - "integrity": "sha512-kFkFXrmKCL0EEeOmJybMH5amWFd+AFvlvMlvFTRxCUwbhfapZqDmeLMPoWihntnYY6JpoQDE9k+vOzObF1fDqg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.5.1.tgz", + "integrity": "sha512-0q82RyxIextuDtkA0UDofhPHIiQ2kmpa7fwElCSlm/8nQl36cDU1Cw+CAO90Es0lReH2HChClKL84I86Nc52hg==", "dev": true, "requires": { - "cookie": "^0.6.0", + "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" }, "dependencies": { "cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", "dev": true } } @@ -26219,9 +25960,9 @@ } }, "mysql2": { - "version": "3.11.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.5.tgz", - "integrity": "sha512-0XFu8rUmFN9vC0ME36iBvCUObftiMHItrYFhlCRvFWbLgpNqtC4Br/NmZX1HNCszxT0GGy5QtP+k3Q3eCJPaYA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.12.0.tgz", + "integrity": "sha512-C8fWhVysZoH63tJbX8d10IAoYCyXy4fdRFz2Ihrt9jtPILYynFEKUUzpp1U7qxzDc3tMbotvaBH+sl6bFnGZiw==", "dev": true, "requires": { "aws-ssl-profiles": "^1.1.1", @@ -26443,12 +26184,6 @@ "integrity": "sha1-StCAk21EPCVhrtnyGX7//iX05QY=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -26707,12 +26442,6 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, "pg": { "version": "8.13.1", "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", @@ -27024,9 +26753,9 @@ "dev": true }, "process-warning": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.0.tgz", - "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", "dev": true }, "promise": { @@ -27054,12 +26783,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, "pug": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", @@ -27426,48 +27149,6 @@ "resolved": "https://registry.npmjs.org/relative-microtime/-/relative-microtime-2.0.0.tgz", "integrity": "sha512-l18ha6HEZc+No/uK4GyAnNxgKW7nvEe35IaeN54sShMojtqik2a6GbTyuiezkjpPaqP874Z3lW5ysBo5irz4NA==" }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, "require_optional": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", @@ -28621,16 +28302,6 @@ "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", "dev": true }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, "tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", @@ -28686,15 +28357,6 @@ "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -28769,9 +28431,9 @@ } }, "typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true }, "typical": { @@ -28805,9 +28467,9 @@ "dev": true }, "undici": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.1.0.tgz", - "integrity": "sha512-3+mdX2R31khuLCm2mKExSlMdJsfol7bJkIMH80tdXA74W34rT1jKemUTlYR7WY3TqsV4wfOgpatWmmB2Jl1+5g==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.3.tgz", + "integrity": "sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==", "dev": true }, "undici-types": { @@ -28988,12 +28650,12 @@ "dev": true }, "wait-on": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.1.tgz", - "integrity": "sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.2.tgz", + "integrity": "sha512-qHlU6AawrgAIHlueGQHQ+ETcPLAauXbnoTKl3RKq20W0T8x0DKVAo5xWIYjHSyvHxQlcYbFdR0jp4T9bDVITFA==", "dev": true, "requires": { - "axios": "^1.7.7", + "axios": "^1.7.9", "joi": "^17.13.3", "lodash": "^4.17.21", "minimist": "^1.2.8", diff --git a/package.json b/package.json index 16c75daf9c5..794fefe389a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elastic-apm-node", - "version": "4.10.0", + "version": "4.11.0", "description": "The official Elastic APM agent for Node.js", "type": "commonjs", "main": "index.js", @@ -106,7 +106,7 @@ "fast-safe-stringify": "^2.0.7", "fast-stream-to-buffer": "^1.0.0", "http-headers": "^3.0.2", - "import-in-the-middle": "1.11.3", + "import-in-the-middle": "1.12.0", "json-bigint": "^1.0.0", "lru-cache": "10.2.0", "measured-reporting": "^1.51.1", @@ -196,7 +196,6 @@ "prettier": "^3.0.0", "pug": "^3.0.1", "redis": "^4.3.0", - "request": "^2.88.2", "restify": "^11.0.0", "rimraf": "^3.0.2", "tape": "^5.0.0", diff --git a/test/cloud-metadata/test-server.test.js b/test/cloud-metadata/test-server.test.js index 279813cfd45..dd2859b5e84 100644 --- a/test/cloud-metadata/test-server.test.js +++ b/test/cloud-metadata/test-server.test.js @@ -5,9 +5,9 @@ */ 'use strict'; +const http = require('http'); const { createTestServer } = require('./_lib'); const tape = require('tape'); -const request = require('request'); tape.test('test the test server: valid', function (t) { const serverAws = createTestServer('aws', 'default aws fixture'); @@ -32,14 +32,17 @@ tape.test('basic metadata request: aws', function (t) { const url = `http://127.0.0.1:${ listener.address().port }/latest/dynamic/instance-identity/document`; - request(url, function (error, response, rawBody) { - if (error) { - throw error; - } - const body = JSON.parse(rawBody); - t.ok(body.version, 'version set'); - listener.close(); - t.end(); + http.get(url, (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = JSON.parse(Buffer.concat(chunks)); + t.ok(body.version, 'version set'); + listener.close(); + t.end(); + }); }); }); }); @@ -47,92 +50,112 @@ tape.test('basic metadata request: aws', function (t) { tape.test('basic metadata request: gcp', function (t) { const serverGcp = createTestServer('gcp', 'default gcp fixture'); const listener = serverGcp.listen(0, function () { - const url = `http://127.0.0.1:${ - listener.address().port - }/computeMetadata/v1/?recursive=true`; - const options = { - url, - headers: { - 'Metadata-Flavor': 'Google', + http.get( + { + hostname: '127.0.0.1', + port: listener.address().port, + path: '/computeMetadata/v1/?recursive=true', + headers: { + 'Metadata-Flavor': 'Google', + }, }, - }; - request(options, function (error, response, rawBody) { - if (error) { - throw error; - } - const body = JSON.parse(rawBody); - t.ok(body.instance.id, 'id set'); - listener.close(); - t.end(); - }); + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = JSON.parse(Buffer.concat(chunks)); + t.ok(body.instance.id, 'id set'); + listener.close(); + t.end(); + }); + }, + ); }); }); tape.test('basic metadata request: azure', function (t) { const serverAzure = createTestServer('azure', 'default azure fixture'); const listener = serverAzure.listen(0, function () { - const url = `http://127.0.0.1:${ - listener.address().port - }/metadata/instance?api-version=2020-09-01`; - const options = { - url, - headers: { - Metadata: 'true', + http.get( + { + hostname: '127.0.0.1', + port: listener.address().port, + path: '/metadata/instance?api-version=2020-09-01', + headers: { + Metadata: 'true', + }, }, - }; - request(options, function (error, response, rawBody) { - if (error) { - throw error; - } - const body = JSON.parse(rawBody); - t.ok(body.compute.vmId, 'vmId set'); - listener.close(); - t.end(); - }); + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = JSON.parse(Buffer.concat(chunks)); + t.ok(body.compute.vmId, 'vmId set'); + listener.close(); + t.end(); + }); + }, + ); }); }); tape.test('IMDSv2 token fetching: aws', function (t) { const serverAws = createTestServer('aws-IMDSv2', 'default aws fixture'); const listener = serverAws.listen(0, function () { - const urlToken = `http://127.0.0.1:${ - listener.address().port - }/latest/api/token`; - const optionsToken = { - url: urlToken, - headers: { - 'X-aws-ec2-metadata-token-ttl-seconds': '300', + // First request to get API token. + const req = http.request( + { + method: 'PUT', + hostname: '127.0.0.1', + port: listener.address().port, + path: '/latest/api/token', + headers: { + 'X-aws-ec2-metadata-token-ttl-seconds': '300', + }, }, - }; - request.put( - optionsToken, - function (errorToken, responseToken, rawBodyToken) { - // token request succeded, now make real request - t.equals( - rawBodyToken, - 'AQAAAOaONNcThIsIsAfAkEtOkEn_b94UPLuLYRThIsIsAfAkEtOkEn==', - 'returns correct fake token', - ); - const url = `http://127.0.0.1:${ - listener.address().port - }/latest/dynamic/instance-identity/document`; - const options = { - url, - headers: { - 'X-aws-ec2-metadata-token': rawBodyToken, - }, - }; - request(options, function (error, response, rawBody) { - if (error) { - throw error; - } + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const rawBodyToken = Buffer.concat(chunks).toString('utf8'); + t.equals( + rawBodyToken, + 'AQAAAOaONNcThIsIsAfAkEtOkEn_b94UPLuLYRThIsIsAfAkEtOkEn==', + 'returns correct fake token', + ); - const body = JSON.parse(rawBody); - t.ok(body.version, 'version set'); - listener.close(); - t.end(); + // Second request to get metadata, using that token. + http.get( + { + hostname: '127.0.0.1', + port: listener.address().port, + path: '/latest/dynamic/instance-identity/document', + headers: { + 'X-aws-ec2-metadata-token': rawBodyToken, + }, + }, + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = JSON.parse(Buffer.concat(chunks)); + t.ok(body.version, 'version set'); + listener.close(); + t.end(); + }); + }, + ); }); }, ); + req.end(); }); }); diff --git a/test/instrumentation/azure-functions/azfunctestutils.js b/test/instrumentation/azure-functions/azfunctestutils.js new file mode 100644 index 00000000000..910cf2c7a68 --- /dev/null +++ b/test/instrumentation/azure-functions/azfunctestutils.js @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and other contributors where applicable. + * Licensed under the BSD 2-Clause License; you may not use this file except in + * compliance with the BSD 2-Clause License. + */ + +'use strict'; + +const http = require('http'); + +/** + * Wait for the test "func start" to be ready. + * + * This polls the admin endpoint until + * it gets a 200 response, assuming the server is ready by then. + * It times out after ~60s -- so long because startup on Windows CI has been + * found to take a long time (it is downloading 250MB+ in "ExtensionBundle"s). + * + * @param {Test} t - This is only used to `t.comment(...)` with progress. + * @param {Function} cb - Calls `cb(err)` if there was a timeout, `cb()` on + * success. + */ +function waitForServerReady(t, cb) { + let sentinel = 30; + const INTERVAL_MS = 2000; + + const pollForServerReady = () => { + const req = http.get( + 'http://127.0.0.1:7071/admin/functions', + { + agent: false, + timeout: 500, + }, + (res) => { + res.resume(); + res.on('end', () => { + if (res.statusCode !== 200) { + scheduleNextPoll(`statusCode=${res.statusCode}`); + } else { + cb(); + } + }); + }, + ); + req.on('error', (err) => { + scheduleNextPoll(err.message); + }); + }; + + const scheduleNextPoll = (msg) => { + t.comment( + `[sentinel=${sentinel} ${new Date().toISOString()}] wait another 2s for server ready: ${msg}`, + ); + sentinel--; + if (sentinel <= 0) { + cb(new Error('timed out')); + } else { + setTimeout(pollForServerReady, INTERVAL_MS); + } + }; + + pollForServerReady(); +} + +async function makeTestRequest(t, testReq) { + return new Promise((resolve, reject) => { + const reqOpts = testReq.reqOpts; + const url = `http://127.0.0.1:7071${reqOpts.path}`; + t.comment( + `makeTestRequest: "${testReq.testName}" (${reqOpts.method} ${url})`, + ); + const req = http.request( + url, + { + method: reqOpts.method, + }, + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = Buffer.concat(chunks); + if (testReq.expectedRes.statusCode) { + t.equal( + res.statusCode, + testReq.expectedRes.statusCode, + `res.statusCode === ${testReq.expectedRes.statusCode}`, + ); + } + if (testReq.expectedRes.headers) { + for (const [k, v] of Object.entries(testReq.expectedRes.headers)) { + if (v instanceof RegExp) { + t.ok( + v.test(res.headers[k]), + `res.headers[${JSON.stringify(k)}] =~ ${v}`, + ); + } else { + t.equal( + res.headers[k], + v, + `res.headers[${JSON.stringify(k)}] === ${JSON.stringify(v)}`, + ); + } + } + } + if (testReq.expectedRes.body) { + if (testReq.expectedRes.body instanceof RegExp) { + t.ok( + testReq.expectedRes.body.test(body), + `body =~ ${testReq.expectedRes.body}`, + ); + } else if (typeof testReq.expectedRes.body === 'string') { + t.equal(body.toString(), testReq.expectedRes.body, 'body'); + } else { + t.fail( + `unsupported type for TEST_REQUESTS[].expectedRes.body: ${typeof testReq + .expectedRes.body}`, + ); + } + } + resolve(); + }); + }, + ); + req.on('error', reject); + req.end(); + }); +} + +function getEventField(e, fieldName) { + return (e.transaction || e.error || e.span)[fieldName]; +} + +module.exports = { + getEventField, + makeTestRequest, + waitForServerReady, +}; diff --git a/test/instrumentation/azure-functions/azure-functions.test.js b/test/instrumentation/azure-functions/azure-functions-v3.test.js similarity index 78% rename from test/instrumentation/azure-functions/azure-functions.test.js rename to test/instrumentation/azure-functions/azure-functions-v3.test.js index 758435bc2d9..9c368cade91 100644 --- a/test/instrumentation/azure-functions/azure-functions.test.js +++ b/test/instrumentation/azure-functions/azure-functions-v3.test.js @@ -6,10 +6,11 @@ 'use strict'; +// Test Azure Functions programming model v3. + const assert = require('assert'); const { exec, spawn } = require('child_process'); const fs = require('fs'); -const http = require('http'); const os = require('os'); const path = require('path'); @@ -19,13 +20,20 @@ const treekill = require('tree-kill'); const { MockAPMServer } = require('../../_mock_apm_server'); const { formatForTComment } = require('../../_utils'); - -if (!semver.satisfies(process.version, '>=14.1.0 <19')) { - // The "14.1.0" version is selected to skip testing on Node.js v14.0.0 - // because of the issue described here: - // https://github.com/elastic/apm-agent-nodejs/issues/3279#issuecomment-1532084620 +const { + getEventField, + makeTestRequest, + waitForServerReady, +} = require('./azfunctestutils'); + +// Azure Functions programming model v3 supports node 14.x-20.x: +// https://learn.microsoft.com/en-ca/azure/azure-functions/functions-reference-node?tabs=javascript%2Cwindows%2Cazure-cli&pivots=nodejs-model-v4#supported-versions +// However, let's only test with node 18.x for now. The testing involves +// installing the ridiculously large "azure-functions-core-tools" dep, so it +// isn't worth testing all versions. +if (!semver.satisfies(process.version, '^18.0.1')) { console.log( - `# SKIP Azure Functions runtime ~4 does not support node ${process.version} (https://aka.ms/functions-node-versions)`, + '# SKIP Azure Functions v3 tests, only testing with Node.js v18.latest', ); process.exit(); } else if (os.platform() === 'win32') { @@ -35,130 +43,6 @@ if (!semver.satisfies(process.version, '>=14.1.0 <19')) { process.exit(); } -/** - * Wait for the test "func start" to be ready. - * - * This polls the admin endpoint until - * it gets a 200 response, assuming the server is ready by then. - * It times out after ~60s -- so long because startup on Windows CI has been - * found to take a long time (it is downloading 250MB+ in "ExtensionBundle"s). - * - * @param {Test} t - This is only used to `t.comment(...)` with progress. - * @param {Function} cb - Calls `cb(err)` if there was a timeout, `cb()` on - * success. - */ -function waitForServerReady(t, cb) { - let sentinel = 30; - const INTERVAL_MS = 2000; - - const pollForServerReady = () => { - const req = http.get( - 'http://127.0.0.1:7071/admin/functions', - { - agent: false, - timeout: 500, - }, - (res) => { - res.resume(); - res.on('end', () => { - if (res.statusCode !== 200) { - scheduleNextPoll(`statusCode=${res.statusCode}`); - } else { - cb(); - } - }); - }, - ); - req.on('error', (err) => { - scheduleNextPoll(err.message); - }); - }; - - const scheduleNextPoll = (msg) => { - t.comment( - `[sentinel=${sentinel} ${new Date().toISOString()}] wait another 2s for server ready: ${msg}`, - ); - sentinel--; - if (sentinel <= 0) { - cb(new Error('timed out')); - } else { - setTimeout(pollForServerReady, INTERVAL_MS); - } - }; - - pollForServerReady(); -} - -async function makeTestRequest(t, testReq) { - return new Promise((resolve, reject) => { - const reqOpts = testReq.reqOpts; - const url = `http://127.0.0.1:7071${reqOpts.path}`; - t.comment( - `makeTestRequest: "${testReq.testName}" (${reqOpts.method} ${url})`, - ); - const req = http.request( - url, - { - method: reqOpts.method, - }, - (res) => { - const chunks = []; - res.on('data', (chunk) => { - chunks.push(chunk); - }); - res.on('end', () => { - const body = Buffer.concat(chunks); - if (testReq.expectedRes.statusCode) { - t.equal( - res.statusCode, - testReq.expectedRes.statusCode, - `res.statusCode === ${testReq.expectedRes.statusCode}`, - ); - } - if (testReq.expectedRes.headers) { - for (const [k, v] of Object.entries(testReq.expectedRes.headers)) { - if (v instanceof RegExp) { - t.ok( - v.test(res.headers[k]), - `res.headers[${JSON.stringify(k)}] =~ ${v}`, - ); - } else { - t.equal( - res.headers[k], - v, - `res.headers[${JSON.stringify(k)}] === ${JSON.stringify(v)}`, - ); - } - } - } - if (testReq.expectedRes.body) { - if (testReq.expectedRes.body instanceof RegExp) { - t.ok( - testReq.expectedRes.body.test(body), - `body =~ ${testReq.expectedRes.body}`, - ); - } else if (typeof testReq.expectedRes.body === 'string') { - t.equal(body.toString(), testReq.expectedRes.body, 'body'); - } else { - t.fail( - `unsupported type for TEST_REQUESTS[].expectedRes.body: ${typeof testReq - .expectedRes.body}`, - ); - } - } - resolve(); - }); - }, - ); - req.on('error', reject); - req.end(); - }); -} - -function getEventField(e, fieldName) { - return (e.transaction || e.error || e.span)[fieldName]; -} - /** * Assert that the given `apmEvents` (events that the mock APM server received) * match all the expected APM events in `TEST_REQUESTS`. @@ -168,7 +52,7 @@ function checkExpectedApmEvents(t, apmEvents) { if (apmEvents.length > 0) { const metadata = apmEvents.shift().metadata; t.ok(metadata, 'metadata is first event'); - t.equal(metadata.service.name, 'AJsAzureFnApp', 'metadata.service.name'); + t.equal(metadata.service.name, 'azfunc3', 'metadata.service.name'); t.equal( metadata.service.framework.name, 'Azure Functions', @@ -196,7 +80,7 @@ function checkExpectedApmEvents(t, apmEvents) { ); t.equal( metadata.cloud.instance.name, - 'AJsAzureFnApp', + 'azfunc3', 'metadata.cloud.instance.name', ); t.equal( @@ -256,7 +140,7 @@ function checkExpectedApmEvents(t, apmEvents) { const UUID_RE = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i; -const fnAppDir = path.join(__dirname, 'fixtures', 'AJsAzureFnApp'); +const fnAppDir = path.join(__dirname, 'fixtures', 'azfunc3'); const funcExe = path.resolve(fnAppDir, 'node_modules/.bin/func') + (os.platform() === 'win32' ? '.cmd' : ''); @@ -277,14 +161,10 @@ var TEST_REQUESTS = [ t.equal(trans.type, 'request', 'transaction.type'); t.equal(trans.outcome, 'success', 'transaction.outcome'); t.equal(trans.result, 'HTTP 2xx', 'transaction.result'); - t.equal( - trans.faas.name, - 'AJsAzureFnApp/HttpFn1', - 'transaction.faas.name', - ); + t.equal(trans.faas.name, 'azfunc3/HttpFn1', 'transaction.faas.name'); t.equal( trans.faas.id, - '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/AJsAzureFnApp/functions/HttpFn1', + '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/azfunc3/functions/HttpFn1', 'transaction.faas.id', ); t.equal(trans.faas.trigger.type, 'http', 'transaction.faas.trigger.type'); @@ -332,11 +212,7 @@ var TEST_REQUESTS = [ t.equal(trans.name, 'GET /api/HttpFnError', 'transaction.name'); t.equal(trans.outcome, 'failure', 'transaction.outcome'); t.equal(trans.result, 'HTTP 5xx', 'transaction.result'); - t.equal( - trans.faas.name, - 'AJsAzureFnApp/HttpFnError', - 'transaction.faas.name', - ); + t.equal(trans.faas.name, 'azfunc3/HttpFnError', 'transaction.faas.name'); t.equal(trans.faas.coldstart, false, 'transaction.faas.coldstart'); t.equal( trans.context.request.method, @@ -538,14 +414,10 @@ var TEST_REQUESTS = [ const trans = apmEventsForReq[0].transaction; t.equal(trans.name, 'GET /api/HttpFn1', 'transaction.name'); t.equal(trans.result, 'HTTP 2xx', 'transaction.result'); - t.equal( - trans.faas.name, - 'AJsAzureFnApp/HttpFn1', - 'transaction.faas.name', - ); + t.equal(trans.faas.name, 'azfunc3/HttpFn1', 'transaction.faas.name'); t.equal( trans.faas.id, - '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/AJsAzureFnApp/functions/HttpFn1', + '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/azfunc3/functions/HttpFn1', 'transaction.faas.id', ); t.equal( @@ -574,12 +446,12 @@ var TEST_REQUESTS = [ t.equal(trans.result, 'HTTP 2xx', 'transaction.result'); t.equal( trans.faas.name, - 'AJsAzureFnApp/HttpFnRouteTemplate', + 'azfunc3/HttpFnRouteTemplate', 'transaction.faas.name', ); t.equal( trans.faas.id, - '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/AJsAzureFnApp/functions/HttpFnRouteTemplate', + '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/azfunc3/functions/HttpFnRouteTemplate', 'transaction.faas.id', ); t.equal( @@ -605,7 +477,7 @@ var TEST_REQUESTS = [ t.equal(apmEventsForReq.length, 4); const t1 = apmEventsForReq[0].transaction; t.equal(t1.name, 'GET /api/HttpFnDistTraceA', 't1.name'); - t.equal(t1.faas.name, 'AJsAzureFnApp/HttpFnDistTraceA', 't1.faas.name'); + t.equal(t1.faas.name, 'azfunc3/HttpFnDistTraceA', 't1.faas.name'); const s1 = apmEventsForReq[1].span; t.equal(s1.name, 'spanA', 's1.name'); t.equal(s1.parent_id, t1.id, 's1 is a child of t1'); @@ -615,7 +487,7 @@ var TEST_REQUESTS = [ t.equal(s2.parent_id, s1.id, 's2 is a child of s1'); const t2 = apmEventsForReq[3].transaction; t.equal(t2.name, 'GET /api/HttpFnDistTraceB', 't2.name'); - t.equal(t2.faas.name, 'AJsAzureFnApp/HttpFnDistTraceB', 't2.faas.name'); + t.equal(t2.faas.name, 'azfunc3/HttpFnDistTraceB', 't2.faas.name'); t.equal(t2.parent_id, s2.id, 't2 is a child of s2'); t.equal( t2.context.request.headers.traceparent, @@ -659,7 +531,7 @@ tape.test( }, ); -tape.test('azure functions', function (suite) { +tape.test('azure functions v3', function (suite) { let apmServer; let apmServerUrl; @@ -673,7 +545,7 @@ tape.test('azure functions', function (suite) { }); let fnAppProc; - suite.test('setup: "func start" for AJsAzureFnApp fixture', (t) => { + suite.test('setup: "func start" for azfunc3 fixture', (t) => { fnAppProc = spawn(funcExe, ['start'], { cwd: fnAppDir, env: Object.assign({}, process.env, { @@ -698,11 +570,11 @@ tape.test('azure functions', function (suite) { // binaries to "$fnAppDir/node_modules/azure-functions-core-tools/...", // which means a local test run on macOS followed by an attempted test run // in Docker will result in a crash: - // node_tests_1 | # ["func start" stderr] /app/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/node_modules/azure-functions-core-tools/bin/func: 1: Syntax error: "(" unexpected + // node_tests_1 | # ["func start" stderr] /app/test/instrumentation/azure-functions/fixtures/azfunc3/node_modules/azure-functions-core-tools/bin/func: 1: Syntax error: "(" unexpected // node_tests_1 | not ok 2 "func start" failed early: code=2 // For now the workaround is to manually clean that tree before running // tests on a separate OS: - // rm -rf test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/node_modules + // rm -rf test/instrumentation/azure-functions/fixtures/azfunc3/node_modules t.fail(`"func start" failed early: code=${code}`); fnAppProc = null; clearTimeout(earlyCloseTimer); diff --git a/test/instrumentation/azure-functions/azure-functions-v4.test.js b/test/instrumentation/azure-functions/azure-functions-v4.test.js new file mode 100644 index 00000000000..80977f25059 --- /dev/null +++ b/test/instrumentation/azure-functions/azure-functions-v4.test.js @@ -0,0 +1,341 @@ +/* + * Copyright Elasticsearch B.V. and other contributors where applicable. + * Licensed under the BSD 2-Clause License; you may not use this file except in + * compliance with the BSD 2-Clause License. + */ + +'use strict'; + +// Test Azure Functions programming model v4. + +const assert = require('assert'); +const { exec, spawn } = require('child_process'); +const fs = require('fs'); +const os = require('os'); +const path = require('path'); + +const semver = require('semver'); +const tape = require('tape'); +const treekill = require('tree-kill'); + +const { MockAPMServer } = require('../../_mock_apm_server'); +const { formatForTComment } = require('../../_utils'); +const { + getEventField, + makeTestRequest, + waitForServerReady, +} = require('./azfunctestutils'); + +// Azure Functions programming model v4 supports node 18.x-20.x: +// https://learn.microsoft.com/en-ca/azure/azure-functions/functions-reference-node?tabs=javascript%2Cwindows%2Cazure-cli&pivots=nodejs-model-v4#supported-versions +// However, let's only test with node 20.x for now. The testing involves +// installing the ridiculously large "azure-functions-core-tools" dep, so it +// isn't worth testing all versions. +if (!semver.satisfies(process.version, '^20.0.1')) { + console.log( + '# SKIP Azure Functions v4 tests, only testing with Node.js v20.latest', + ); + process.exit(); +} else if (os.platform() === 'win32') { + console.log( + '# SKIP Azure Functions tests on Windows because of flaky azure-functions-core-tools install (see https://github.com/elastic/apm-agent-nodejs/issues/3107)', + ); + process.exit(); +} + +/** + * Assert that the given `apmEvents` (events that the mock APM server received) + * match all the expected APM events in `TEST_REQUESTS`. + */ +function checkExpectedApmEvents(t, apmEvents) { + // metadata + if (apmEvents.length > 0) { + const metadata = apmEvents.shift().metadata; + t.ok(metadata, 'metadata is first event'); + t.equal(metadata.service.name, 'azfunc4', 'metadata.service.name'); + t.equal( + metadata.service.framework.name, + 'Azure Functions', + 'metadata.service.framework.name', + ); + t.equal( + metadata.service.framework.version, + '~4', + 'metadata.service.framework.version', + ); + t.equal( + metadata.service.runtime.name, + 'node', + 'metadata.service.runtime.name', + ); + t.equal( + metadata.service.node.configured_name, + 'test-website-instance-id', + 'metadata.service.node.configured_name', + ); + t.equal( + metadata.cloud.account.id, + '2491fc8e-f7c1-4020-b9c6-78509919fd16', + 'metadata.cloud.account.id', + ); + t.equal( + metadata.cloud.instance.name, + 'azfunc4', + 'metadata.cloud.instance.name', + ); + t.equal( + metadata.cloud.project.name, + 'my-resource-group', + 'metadata.cloud.project.name', + ); + t.equal(metadata.cloud.provider, 'azure', 'metadata.cloud.provider'); + t.equal(metadata.cloud.region, 'test-region-name', 'metadata.cloud.region'); + t.equal( + metadata.cloud.service.name, + 'functions', + 'metadata.cloud.service.name', + ); + } + + // Filter out any metadata from separate requests, and metricsets which we + // aren't testing. + apmEvents = apmEvents.filter((e) => !e.metadata).filter((e) => !e.metricset); + + // Sort all the remaining APM events and check expectations from TEST_REQUESTS. + apmEvents = apmEvents.sort((a, b) => { + return getEventField(a, 'timestamp') < getEventField(b, 'timestamp') + ? -1 + : 1; + }); + TEST_REQUESTS.forEach((testReq) => { + t.comment(`check APM events for "${testReq.testName}"`); + // Collect all events for this transaction's trace_id, and pass that to + // the `checkApmEvents` function for this request. + let apmEventsForReq = []; + if (apmEvents.length > 0) { + assert( + apmEvents[0].transaction, + `next APM event is a transaction: ${JSON.stringify(apmEvents[0])}`, + ); + const traceId = apmEvents[0].transaction.trace_id; + apmEventsForReq = apmEvents.filter( + (e) => getEventField(e, 'trace_id') === traceId, + ); + apmEvents = apmEvents.filter( + (e) => getEventField(e, 'trace_id') !== traceId, + ); + } + testReq.checkApmEvents(t, apmEventsForReq); + }); + + t.equal( + apmEvents.length, + 0, + 'no additional unexpected APM server events: ' + JSON.stringify(apmEvents), + ); +} + +// ---- tests + +const UUID_RE = + /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i; + +const fnAppDir = path.join(__dirname, 'fixtures', 'azfunc4'); +const funcExe = + path.resolve(fnAppDir, 'node_modules/.bin/func') + + (os.platform() === 'win32' ? '.cmd' : ''); + +var TEST_REQUESTS = [ + { + testName: 'HttpExample', + reqOpts: { method: 'GET', path: '/api/HttpExample' }, + expectedRes: { + statusCode: 200, // the Azure Functions default + headers: { myheadername: 'MyHeaderValue' }, + body: 'HttpExample body', + }, + checkApmEvents: (t, apmEventsForReq) => { + t.equal(apmEventsForReq.length, 1); + const trans = apmEventsForReq[0].transaction; + t.equal(trans.name, 'GET /api/HttpExample', 'transaction.name'); + t.equal(trans.type, 'request', 'transaction.type'); + t.equal(trans.outcome, 'success', 'transaction.outcome'); + t.equal(trans.result, 'HTTP 2xx', 'transaction.result'); + t.equal(trans.faas.name, 'azfunc4/HttpExample', 'transaction.faas.name'); + t.equal( + trans.faas.id, + '/subscriptions/2491fc8e-f7c1-4020-b9c6-78509919fd16/resourceGroups/my-resource-group/providers/Microsoft.Web/sites/azfunc4/functions/HttpExample', + 'transaction.faas.id', + ); + t.equal(trans.faas.trigger.type, 'http', 'transaction.faas.trigger.type'); + t.ok( + UUID_RE.test(trans.faas.execution), + 'transaction.faas.execution ' + trans.faas.execution, + ); + t.equal(trans.faas.coldstart, true, 'transaction.faas.coldstart'); + t.equal( + trans.context.request.method, + 'GET', + 'transaction.context.request.method', + ); + t.equal( + trans.context.request.url.full, + 'http://127.0.0.1:7071/api/HttpExample', + 'transaction.context.request.url.full', + ); + t.ok( + trans.context.request.headers, + 'transaction.context.request.headers', + ); + t.equal( + trans.context.response.status_code, + 200, + 'transaction.context.response.status_code', + ); + t.equal( + trans.context.response.headers.MyHeaderName, + 'MyHeaderValue', + 'transaction.context.response.headers.MyHeaderName', + ); + }, + }, + // TODO: test more of the cases that are covered in azure-functions-v3.test.js +]; + +// We need to `npm ci` for a first test run. +tape.test( + `setup: npm ci (in ${fnAppDir})`, + { skip: fs.existsSync(funcExe) }, + (t) => { + const startTime = Date.now(); + exec( + 'npm ci', + { + cwd: fnAppDir, + }, + function (err, stdout, stderr) { + t.error( + err, + `"npm ci" succeeded (took ${(Date.now() - startTime) / 1000}s)`, + ); + if (err) { + t.comment( + `$ npm ci\n-- stdout --\n${stdout}\n-- stderr --\n${stderr}\n--`, + ); + } + t.end(); + }, + ); + }, +); + +tape.test('azure functions v4', function (suite) { + let apmServer; + let apmServerUrl; + + suite.test('setup', function (t) { + apmServer = new MockAPMServer(); + apmServer.start(function (serverUrl) { + apmServerUrl = serverUrl; + t.comment('mock APM apmServerUrl: ' + apmServerUrl); + t.end(); + }); + }); + + let fnAppProc; + suite.test('setup: "func start" for azfunc4 fixture', (t) => { + fnAppProc = spawn(funcExe, ['start'], { + cwd: fnAppDir, + env: Object.assign({}, process.env, { + ELASTIC_APM_SERVER_URL: apmServerUrl, + ELASTIC_APM_API_REQUEST_TIME: '2s', + }), + }); + fnAppProc.on('error', (err) => { + t.error(err, 'no error from "func start"'); + }); + fnAppProc.stdout.on('data', (data) => { + t.comment(`["func start" stdout] ${formatForTComment(data)}`); + }); + fnAppProc.stderr.on('data', (data) => { + t.comment(`["func start" stderr] ${formatForTComment(data)}`); + }); + + // Allow some time for an early fail of `func start`, e.g. if there is + // already a user of port 7071... + const onEarlyClose = (code) => { + // Warning/Limitation: The 'npm ci' above installs platform-specific + // binaries to "$fnAppDir/node_modules/azure-functions-core-tools/...", + // which means a local test run on macOS followed by an attempted test run + // in Docker will result in a crash: + // node_tests_1 | # ["func start" stderr] /app/test/instrumentation/azure-functions/fixtures/azfunc3/node_modules/azure-functions-core-tools/bin/func: 1: Syntax error: "(" unexpected + // node_tests_1 | not ok 2 "func start" failed early: code=2 + // For now the workaround is to manually clean that tree before running + // tests on a separate OS: + // rm -rf test/instrumentation/azure-functions/fixtures/azfunc3/node_modules + t.fail(`"func start" failed early: code=${code}`); + fnAppProc = null; + clearTimeout(earlyCloseTimer); + t.end(); + }; + fnAppProc.on('close', onEarlyClose); + const earlyCloseTimer = setTimeout(() => { + fnAppProc.removeListener('close', onEarlyClose); + + // ... then wait for the server to be ready. + waitForServerReady(t, (waitErr) => { + if (waitErr) { + t.fail( + `error waiting for "func start" to be ready: ${waitErr.message}`, + ); + treekill(fnAppProc.pid, 'SIGKILL'); + fnAppProc = null; + } else { + t.comment('"func start" is ready'); + } + t.end(); + }); + }, 1000); + }); + + suite.test('make requests', async (t) => { + if (!fnAppProc) { + t.skip('there is no fnAppProc'); + t.end(); + return; + } + + apmServer.clear(); + for (let i = 0; i < TEST_REQUESTS.length; i++) { + await makeTestRequest(t, TEST_REQUESTS[i]); + } + + t.end(); + }); + + suite.test('check all APM events', (t) => { + if (!fnAppProc) { + t.skip('there is no fnAppProc'); + t.end(); + return; + } + + // To ensure we get all the trace data from the instrumented function app + // server, we wait 2x the `apiRequestTime` (set above) before stopping it. + fnAppProc.on('close', (_code) => { + checkExpectedApmEvents(t, apmServer.events); + t.end(); + }); + t.comment('wait 4s for trace data to be sent before closing "func start"'); + setTimeout(() => { + treekill(fnAppProc.pid, 'SIGKILL'); + }, 4000); // 2x ELASTIC_APM_API_REQUEST_TIME set above + }); + + suite.test('teardown', function (t) { + apmServer.close(); + t.end(); + }); + + suite.end(); +}); diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnError/function.json b/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnError/function.json deleted file mode 100644 index 91052aaf8a0..00000000000 --- a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnError/function.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "bindings": [ - { - "authLevel": "Anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "req", - "methods": [ - "get", - "post" - ] - }, - { - "type": "http", - "direction": "out", - "name": "res" - } - ] -} \ No newline at end of file diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/README.md b/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/README.md deleted file mode 100644 index e9264594afb..00000000000 --- a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/README.md +++ /dev/null @@ -1,12 +0,0 @@ -A Node.js JavaScript Azure function app to be used for testing of -elastic-apm-node. - -# Notes on how this was created - -- `func init AJsAzureFnApp` -- Remove "azure-functions-core-tools" devDep and move to top-level to share - between possibly many fixtures. -- An HTTP-triggered function: `func new --name HttpFn1 --template "HTTP trigger" --authlevel "anonymous"` -- ... - - diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/.gitignore b/test/instrumentation/azure-functions/fixtures/azfunc3/.gitignore similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/.gitignore rename to test/instrumentation/azure-functions/fixtures/azfunc3/.gitignore diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFn1/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFn1/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFn1/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFn1/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFn1/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFn1/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFn1/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFn1/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnBindingsRes/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnBindingsRes/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnBindingsRes/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnBindingsRes/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnBindingsRes/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnBindingsRes/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnBindingsRes/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnBindingsRes/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnContextDone/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnContextDone/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnContextDone/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnContextDone/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnContextDone/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnContextDone/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnContextDone/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnContextDone/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceA/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceA/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceA/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceA/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceA/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceA/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceA/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceA/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceB/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceB/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceB/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceB/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceB/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceB/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnDistTraceB/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnDistTraceB/index.js diff --git a/examples/an-azure-function-app/Bye/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnError/function.json similarity index 100% rename from examples/an-azure-function-app/Bye/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnError/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnError/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnError/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnError/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnError/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnContext/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnContext/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnContext/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnContext/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnContext/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnContext/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnContext/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnContext/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnObject/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnObject/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnObject/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnObject/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnObject/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnObject/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnObject/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnObject/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnResponseData/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnResponseData/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnResponseData/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnResponseData/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnResponseData/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnResponseData/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnResponseData/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnResponseData/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnString/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnString/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnString/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnString/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnString/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnString/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnReturnString/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnReturnString/index.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnRouteTemplate/function.json b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnRouteTemplate/function.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnRouteTemplate/function.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnRouteTemplate/function.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnRouteTemplate/index.js b/test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnRouteTemplate/index.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/HttpFnRouteTemplate/index.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/HttpFnRouteTemplate/index.js diff --git a/test/instrumentation/azure-functions/fixtures/azfunc3/README.md b/test/instrumentation/azure-functions/fixtures/azfunc3/README.md new file mode 100644 index 00000000000..9e3ea2e8ed6 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc3/README.md @@ -0,0 +1,3 @@ +A Node.js Azure Functions app, using **version 3** of the Node.js +programming model. See: +https://learn.microsoft.com/en-ca/azure/azure-functions/functions-node-upgrade-v4 diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/host.json b/test/instrumentation/azure-functions/fixtures/azfunc3/host.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/host.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/host.json diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/initapm.js b/test/instrumentation/azure-functions/fixtures/azfunc3/initapm.js similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/initapm.js rename to test/instrumentation/azure-functions/fixtures/azfunc3/initapm.js diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/local.settings.json b/test/instrumentation/azure-functions/fixtures/azfunc3/local.settings.json similarity index 92% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/local.settings.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/local.settings.json index 51058f07a53..8910ca349e0 100644 --- a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/local.settings.json +++ b/test/instrumentation/azure-functions/fixtures/azfunc3/local.settings.json @@ -7,7 +7,7 @@ "WEBSITE_NODE_DEFAULT_VERSION": "~16", "FUNCTIONS_EXTENSION_VERSION": "~4", - "WEBSITE_SITE_NAME": "AJsAzureFnApp", + "WEBSITE_SITE_NAME": "azfunc3", "WEBSITE_OWNER_NAME": "2491fc8e-f7c1-4020-b9c6-78509919fd16+my-resource-group-ARegionShortNamewebspace", "WEBSITE_RESOURCE_GROUP": "my-resource-group", "WEBSITE_INSTANCE_ID": "test-website-instance-id", diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/package-lock.json b/test/instrumentation/azure-functions/fixtures/azfunc3/package-lock.json similarity index 99% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/package-lock.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/package-lock.json index c2b5968f996..786aa2cee4a 100644 --- a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/package-lock.json +++ b/test/instrumentation/azure-functions/fixtures/azfunc3/package-lock.json @@ -1,5 +1,5 @@ { - "name": "AJsAzureFnApp", + "name": "azfunc3", "version": "1.0.0", "lockfileVersion": 2, "requires": true, diff --git a/test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/package.json b/test/instrumentation/azure-functions/fixtures/azfunc3/package.json similarity index 100% rename from test/instrumentation/azure-functions/fixtures/AJsAzureFnApp/package.json rename to test/instrumentation/azure-functions/fixtures/azfunc3/package.json diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/.funcignore b/test/instrumentation/azure-functions/fixtures/azfunc4/.funcignore new file mode 100644 index 00000000000..17bd0f697c2 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/.funcignore @@ -0,0 +1,10 @@ +*.js.map +*.ts +.git* +.vscode +local.settings.json +test +getting_started.md +node_modules/@types/ +node_modules/azure-functions-core-tools/ +node_modules/typescript/ \ No newline at end of file diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/.npmrc b/test/instrumentation/azure-functions/fixtures/azfunc4/.npmrc new file mode 100644 index 00000000000..4eae7876ff1 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/.npmrc @@ -0,0 +1 @@ +lockfile-version=3 diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/README.md b/test/instrumentation/azure-functions/fixtures/azfunc4/README.md new file mode 100644 index 00000000000..1da6020a3af --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/README.md @@ -0,0 +1,3 @@ +A Node.js Azure Functions app, using **version 4** of the Node.js +programming model. See: +https://learn.microsoft.com/en-ca/azure/azure-functions/functions-node-upgrade-v4 diff --git a/examples/an-azure-function-app/host.json b/test/instrumentation/azure-functions/fixtures/azfunc4/host.json similarity index 89% rename from examples/an-azure-function-app/host.json rename to test/instrumentation/azure-functions/fixtures/azfunc4/host.json index fd4bee790b9..9df913614d9 100644 --- a/examples/an-azure-function-app/host.json +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/host.json @@ -10,6 +10,6 @@ }, "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[3.*, 4.0.0)" + "version": "[4.*, 5.0.0)" } } \ No newline at end of file diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/initapm.js b/test/instrumentation/azure-functions/fixtures/azfunc4/initapm.js new file mode 100644 index 00000000000..db2f85666c6 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/initapm.js @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and other contributors where applicable. + * Licensed under the BSD 2-Clause License; you may not use this file except in + * compliance with the BSD 2-Clause License. + */ + +// For the normal use case an "initapm.js" would look like: +// module.exports = require('elastic-apm-node').start(/* { ... } */) + +module.exports = require('../../../../../').start(); diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/local.settings.json b/test/instrumentation/azure-functions/fixtures/azfunc4/local.settings.json new file mode 100644 index 00000000000..574eb480636 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/local.settings.json @@ -0,0 +1,14 @@ +{ + "IsEncrypted": false, + "Values": { + "FUNCTIONS_WORKER_RUNTIME": "node", + "AzureWebJobsStorage": "", + + "FUNCTIONS_EXTENSION_VERSION": "~4", + "WEBSITE_SITE_NAME": "azfunc4", + "WEBSITE_OWNER_NAME": "2491fc8e-f7c1-4020-b9c6-78509919fd16+my-resource-group-ARegionShortNamewebspace", + "WEBSITE_RESOURCE_GROUP": "my-resource-group", + "WEBSITE_INSTANCE_ID": "test-website-instance-id", + "REGION_NAME": "test-region-name" + } +} diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/package-lock.json b/test/instrumentation/azure-functions/fixtures/azfunc4/package-lock.json new file mode 100644 index 00000000000..e78727a8d2b --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/package-lock.json @@ -0,0 +1,426 @@ +{ + "name": "azfunc4", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "dependencies": { + "@azure/functions": "^4.0.0", + "azure-functions-core-tools": "^4.0.6821" + } + }, + "node_modules/@azure/functions": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@azure/functions/-/functions-4.6.0.tgz", + "integrity": "sha512-vGq9jXlgrJ3KaI8bepgfpk26zVY8vFZsQukF85qjjKTAR90eFOOBNaa+mc/0ViDY2lcdrU2fL/o1pQyZUtTDsw==", + "dependencies": { + "cookie": "^0.7.0", + "long": "^4.0.0", + "undici": "^5.13.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/azure-functions-core-tools": { + "version": "4.0.6821", + "resolved": "https://registry.npmjs.org/azure-functions-core-tools/-/azure-functions-core-tools-4.0.6821.tgz", + "integrity": "sha512-D+VcQKPk+aVk9WRO56zlkq9xmeO+kxixDIMEIH2tG9OSSSxmioNOdjkpEnZuUEUdv6PPFn9vybcLhGCXL4Xftg==", + "hasInstallScript": true, + "hasShrinkwrap": true, + "os": [ + "win32", + "darwin", + "linux" + ], + "dependencies": { + "chalk": "3.0.0", + "extract-zip": "^2.0.1", + "https-proxy-agent": "5.0.1", + "progress": "2.0.3", + "rimraf": "4.4.1" + }, + "bin": { + "azfun": "lib/main.js", + "azurefunctions": "lib/main.js", + "func": "lib/main.js" + }, + "engines": { + "node": ">=6.9.1" + } + }, + "node_modules/azure-functions-core-tools/node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "node_modules/azure-functions-core-tools/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "optional": true + }, + "node_modules/azure-functions-core-tools/node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/azure-functions-core-tools/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/ansi-styles": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz", + "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==", + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-functions-core-tools/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/azure-functions-core-tools/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/azure-functions-core-tools/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-functions-core-tools/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/azure-functions-core-tools/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/azure-functions-core-tools/node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/azure-functions-core-tools/node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/azure-functions-core-tools/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/azure-functions-core-tools/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/azure-functions-core-tools/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-functions-core-tools/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/azure-functions-core-tools/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/azure-functions-core-tools/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/azure-functions-core-tools/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-functions-core-tools/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/azure-functions-core-tools/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/azure-functions-core-tools/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/azure-functions-core-tools/node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/azure-functions-core-tools/node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/azure-functions-core-tools/node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/azure-functions-core-tools/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/azure-functions-core-tools/node_modules/rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "license": "ISC", + "dependencies": { + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/azure-functions-core-tools/node_modules/supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-functions-core-tools/node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/azure-functions-core-tools/node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + } + } +} diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/package.json b/test/instrumentation/azure-functions/fixtures/azfunc4/package.json new file mode 100644 index 00000000000..4f755c02b79 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/package.json @@ -0,0 +1,13 @@ +{ + "name": "", + "version": "1.0.0", + "description": "", + "main": "{initapm.js,src/functions/*.js}", + "scripts": { + "start": "func start" + }, + "dependencies": { + "@azure/functions": "^4.0.0", + "azure-functions-core-tools": "^4.0.6821" + } +} diff --git a/test/instrumentation/azure-functions/fixtures/azfunc4/src/functions/HttpExample.js b/test/instrumentation/azure-functions/fixtures/azfunc4/src/functions/HttpExample.js new file mode 100644 index 00000000000..4b85e0f3f37 --- /dev/null +++ b/test/instrumentation/azure-functions/fixtures/azfunc4/src/functions/HttpExample.js @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and other contributors where applicable. + * Licensed under the BSD 2-Clause License; you may not use this file except in + * compliance with the BSD 2-Clause License. + */ + +const { app } = require('@azure/functions'); + +app.http('HttpExample', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + handler: async (_request, _context) => { + return { + body: 'HttpExample body', + headers: { + MyHeaderName: 'MyHeaderValue', + }, + }; + }, +}); diff --git a/test/instrumentation/modules/http/request.test.js b/test/instrumentation/modules/http/request.test.js index f77967de2b6..0ce44a492fb 100644 --- a/test/instrumentation/modules/http/request.test.js +++ b/test/instrumentation/modules/http/request.test.js @@ -20,7 +20,6 @@ var http = require('http'); var test = require('tape'); var express = require('express'); -var request = require('request'); var mockClient = require('../../../_mock_http_client'); var findObjInArray = require('../../../_utils').findObjInArray; @@ -52,7 +51,9 @@ test('request', function (t) { }); app.get('/', (req, res) => { - request(`http://localhost:${req.socket.localPort}/test`).pipe(res); + http.get(`http://localhost:${req.socket.localPort}/test`, (cres) => { + cres.pipe(res); + }); }); sendRequest(server); @@ -83,7 +84,10 @@ test('Outcome', function (t) { }); app.get('/', (req, res) => { - request(`http://localhost:${req.socket.localPort}/test`).pipe(res); + http.get(`http://localhost:${req.socket.localPort}/test`, (cres) => { + res.statusCode = cres.statusCode; + cres.pipe(res); + }); }); sendRequest(server); diff --git a/test/integration/api-schema/apm-server-schema/span.json b/test/integration/api-schema/apm-server-schema/span.json index e86da9a69cd..14eea1b15b8 100644 --- a/test/integration/api-schema/apm-server-schema/span.json +++ b/test/integration/api-schema/apm-server-schema/span.json @@ -188,6 +188,9 @@ "object" ], "properties": { + "body": { + "description": "The http request body usually as a string, but may be a dictionary for multipart/form-data content" + }, "id": { "description": "ID holds the unique identifier for the http request.", "type": [ diff --git a/test/opentelemetry-metrics/fixtures/package-lock.json b/test/opentelemetry-metrics/fixtures/package-lock.json index 8770cd00cca..e8e5dbb855b 100644 --- a/test/opentelemetry-metrics/fixtures/package-lock.json +++ b/test/opentelemetry-metrics/fixtures/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-prometheus": ">=0.41.2 <2", - "@opentelemetry/sdk-metrics": "^1.27.0" + "@opentelemetry/sdk-metrics": "^1.30.0" } }, "node_modules/@opentelemetry/api": { @@ -22,9 +22,9 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, @@ -36,13 +36,13 @@ } }, "node_modules/@opentelemetry/exporter-prometheus": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.56.0.tgz", - "integrity": "sha512-5kFcTumUveNREskg6n4aaXx2o3ADc9YxDkArGCIegzErlc3zfzreO4Y7HDc/fYBnV9aIhJUk5P8yotyVCuymkQ==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.57.1.tgz", + "integrity": "sha512-lwwOQzyvhzioGCYmIh7mXo+RLSoEVhuO0dFzWeEiQhFkjSUOPgKQKNTgYtl2KO1L7XIbHp5LIgn4nZrYx191Rg==", "dependencies": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0", - "@opentelemetry/sdk-metrics": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/sdk-metrics": "1.30.1" }, "engines": { "node": ">=14" @@ -52,11 +52,11 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", - "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "dependencies": { - "@opentelemetry/core": "1.29.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -67,12 +67,12 @@ } }, "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz", - "integrity": "sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", + "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", "dependencies": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" }, "engines": { "node": ">=14" @@ -97,39 +97,39 @@ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, "@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "requires": { "@opentelemetry/semantic-conventions": "1.28.0" } }, "@opentelemetry/exporter-prometheus": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.56.0.tgz", - "integrity": "sha512-5kFcTumUveNREskg6n4aaXx2o3ADc9YxDkArGCIegzErlc3zfzreO4Y7HDc/fYBnV9aIhJUk5P8yotyVCuymkQ==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.57.1.tgz", + "integrity": "sha512-lwwOQzyvhzioGCYmIh7mXo+RLSoEVhuO0dFzWeEiQhFkjSUOPgKQKNTgYtl2KO1L7XIbHp5LIgn4nZrYx191Rg==", "requires": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0", - "@opentelemetry/sdk-metrics": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/sdk-metrics": "1.30.1" } }, "@opentelemetry/resources": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", - "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "requires": { - "@opentelemetry/core": "1.29.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" } }, "@opentelemetry/sdk-metrics": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz", - "integrity": "sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", + "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", "requires": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0" + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" } }, "@opentelemetry/semantic-conventions": { diff --git a/test/opentelemetry-metrics/fixtures/package.json b/test/opentelemetry-metrics/fixtures/package.json index 33d1b1ee7eb..8c101297701 100644 --- a/test/opentelemetry-metrics/fixtures/package.json +++ b/test/opentelemetry-metrics/fixtures/package.json @@ -5,6 +5,6 @@ "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/exporter-prometheus": ">=0.41.2 <2", - "@opentelemetry/sdk-metrics": "^1.27.0" + "@opentelemetry/sdk-metrics": "^1.30.0" } } diff --git a/test/sanitize-field-names/_shared.js b/test/sanitize-field-names/_shared.js index 21fde0c9bff..b20aff1c6dc 100644 --- a/test/sanitize-field-names/_shared.js +++ b/test/sanitize-field-names/_shared.js @@ -5,6 +5,8 @@ */ 'use strict'; + +const http = require('http'); const querystring = require('querystring'); const mockClient = require('../_mock_http_client'); @@ -114,9 +116,42 @@ function getBodyAsObject(string) { } } +/** + * Convenience function to make an form-encoded HTTP POST request and callback + * with the body, `cb(null, res, body)`. + */ +function requestPost(url, headers, form, cb) { + const u = new URL(url); + const req = http.request( + { + method: 'POST', + hostname: u.hostname, + port: u.port, + path: u.pathname + u.search, + headers: Object.assign( + { 'content-type': 'application/x-www-form-urlencoded' }, + headers, + ), + }, + (res) => { + const chunks = []; + res.on('data', (chunk) => { + chunks.push(chunk); + }); + res.on('end', () => { + const body = Buffer.concat(chunks).toString('utf8'); + cb(null, res, body); + }); + }, + ); + req.write(querystring.encode(form)); + req.end(); +} + module.exports = { createAgentConfig, getBodyAsObject, + requestPost, resetAgent, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, diff --git a/test/sanitize-field-names/express.test.js b/test/sanitize-field-names/express.test.js index d276963b328..ae4a136ac04 100644 --- a/test/sanitize-field-names/express.test.js +++ b/test/sanitize-field-names/express.test.js @@ -8,6 +8,7 @@ const { createAgentConfig } = require('./_shared'); const agent = require('../..').start(createAgentConfig()); const { + requestPost, resetAgent, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, @@ -15,7 +16,6 @@ const { } = require('./_shared'); const test = require('tape'); -const request = require('request'); const express = require('express'); const bodyParser = require('body-parser'); const fixtures = require('./_fixtures'); @@ -52,21 +52,13 @@ function runTest( }); const server = app.listen(0, '0.0.0.0', () => { - const url = `http://${server.address().address}:${ - server.address().port - }/test`; - request.post( - url, - { - form: formFields, - headers: requestHeaders, - }, - function (error, response, body) { - t.error(error); - t.ok(body, 'received response'); - t.end(); - }, - ); + const addr = server.address(); + const url = `http://${addr.address}:${addr.port}/test`; + requestPost(url, requestHeaders, formFields, (err, _res, body) => { + t.error(err); + t.ok(body, 'received response'); + t.end(); + }); }); const done = () => { diff --git a/test/sanitize-field-names/fastify.test.js b/test/sanitize-field-names/fastify.test.js index f284704d2b6..1136faef678 100644 --- a/test/sanitize-field-names/fastify.test.js +++ b/test/sanitize-field-names/fastify.test.js @@ -15,13 +15,13 @@ if (isFastifyIncompat) { } const { + requestPost, resetAgent, assertFormsWithFixture, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, } = require('./_shared'); const test = require('tape'); -const request = require('request'); const fastify = require('fastify'); const fastifyFormbody = require('@fastify/formbody'); const fixtures = require('./_fixtures'); @@ -64,20 +64,13 @@ function runTest( throw err; } const url = `${address}/test`; - request.post( - url, - { - form: formFields, - headers: requestHeaders, - }, - function (error, response, body) { - if (error) { - t.fail(error); - } - t.ok(body, 'received response'); - t.end(); - }, - ); + requestPost(url, requestHeaders, formFields, (err, _res, body) => { + if (err) { + t.fail(err); + } + t.ok(body, 'received response'); + t.end(); + }); }); const done = () => { diff --git a/test/sanitize-field-names/hapi.test.js b/test/sanitize-field-names/hapi.test.js index 937f5d46677..76362b445c8 100644 --- a/test/sanitize-field-names/hapi.test.js +++ b/test/sanitize-field-names/hapi.test.js @@ -7,6 +7,7 @@ 'use strict'; const { + requestPost, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, assertFormsWithFixture, @@ -22,7 +23,6 @@ if (isHapiIncompat()) { } const test = require('tape'); -const request = require('request'); const Hapi = require('@hapi/hapi'); const fixtures = require('./_fixtures'); @@ -96,18 +96,11 @@ async function runTest( await server.start(); const url = server.info.uri + '/test'; - request.post( - url, - { - form: formFields, - headers: requestHeaders, - }, - function (error, response, body) { - if (error) { - t.fail(error); - } - t.ok(body, 'received response'); - t.end(); - }, - ); + requestPost(url, requestHeaders, formFields, (err, _res, body) => { + if (err) { + t.fail(err); + } + t.ok(body, 'received response'); + t.end(); + }); } diff --git a/test/sanitize-field-names/koa.test.js b/test/sanitize-field-names/koa.test.js index 0e7d2fb9b1b..eba2bc54b13 100644 --- a/test/sanitize-field-names/koa.test.js +++ b/test/sanitize-field-names/koa.test.js @@ -8,12 +8,12 @@ const { createAgentConfig } = require('./_shared'); const agent = require('../..').start(createAgentConfig()); const { + requestPost, resetAgent, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, } = require('./_shared'); const test = require('tape'); -const request = require('request'); const Koa = require('koa'); const koaBodyparser = require('koa-bodyparser'); const fixtures = require('./_fixtures'); @@ -83,19 +83,12 @@ function runTest( const url = `http://${server.address().address}:${ server.address().port }/test`; - request.post( - url, - { - form: formFields, - headers: requestHeaders, - }, - function (error, response, body) { - if (error) { - t.fail(error); - } - t.ok(body, 'received response'); - t.end(); - }, - ); + requestPost(url, requestHeaders, formFields, (err, _res, body) => { + if (err) { + t.fail(err); + } + t.ok(body, 'received response'); + t.end(); + }); }); } diff --git a/test/sanitize-field-names/restify.test.js b/test/sanitize-field-names/restify.test.js index d9120f38b77..43191bd35e2 100644 --- a/test/sanitize-field-names/restify.test.js +++ b/test/sanitize-field-names/restify.test.js @@ -15,13 +15,13 @@ if (isRestifyIncompat) { const { createAgentConfig } = require('./_shared'); const agent = require('../..').start(createAgentConfig()); const { + requestPost, resetAgent, assertRequestHeadersWithFixture, assertResponseHeadersWithFixture, assertFormsWithFixture, } = require('./_shared'); const test = require('tape'); -const request = require('request'); const restify = require('restify'); const fixtures = require('./_fixtures'); @@ -93,19 +93,12 @@ function runTest( server.listen(0, '0.0.0.0', () => { const url = `${server.url}/test`; - request.post( - url, - { - form: formFields, - headers: requestHeaders, - }, - function (error, response, body) { - if (error) { - t.fail(error); - } - t.ok(body, 'received response'); - t.end(); - }, - ); + requestPost(url, requestHeaders, formFields, (err, _res, body) => { + if (err) { + t.fail(err); + } + t.ok(body, 'received response'); + t.end(); + }); }); }