diff --git a/.changeset/curly-swans-agree.md b/.changeset/curly-swans-agree.md new file mode 100644 index 0000000..cf73a2b --- /dev/null +++ b/.changeset/curly-swans-agree.md @@ -0,0 +1,5 @@ +--- +'@envyjs/nextjs': patch +--- + +Fix bug where the nextjs sender could be registered multiple times, causing traces to show duplicates diff --git a/examples/next/app/api/swapi/route.ts b/examples/next/app/api/swapi/route.ts new file mode 100644 index 0000000..9166760 --- /dev/null +++ b/examples/next/app/api/swapi/route.ts @@ -0,0 +1,10 @@ +import axios from 'axios'; +import { NextResponse } from 'next/server'; + +const SWAPI_URL = 'https://swapi.dev/api/people/1'; + +export async function GET() { + // Look - just one call to the SWAPI endpoint! + const { data } = await axios.get(SWAPI_URL); + return NextResponse.json(data); +} diff --git a/examples/next/app/next13app/call-api-route/ApiRouteExample.tsx b/examples/next/app/next13app/call-api-route/ApiRouteExample.tsx new file mode 100644 index 0000000..2cb2b26 --- /dev/null +++ b/examples/next/app/next13app/call-api-route/ApiRouteExample.tsx @@ -0,0 +1,34 @@ +'use client'; + +const API_ROUTE_URL = 'http://localhost:3000/api/swapi'; +const SWAPI_URL = 'https://swapi.dev/api/people/1'; + +export default function ApiRouteExample() { + async function makeSwapiCall() { + await fetch(API_ROUTE_URL); + } + + const swapiUrl = {SWAPI_URL}; + const apiRouteUrl = ( + {API_ROUTE_URL} + ); + + const button = ( + + ); + + return ( +
+
+

Calling an API route which makes an upstream request

+

Click the button to make a call to an API route from this page.

+

+ This will call {apiRouteUrl}, where that API route will call {swapiUrl} +

+
+
{button}
+
+ ); +} diff --git a/examples/next/app/next13app/call-api-route/page.tsx b/examples/next/app/next13app/call-api-route/page.tsx new file mode 100644 index 0000000..3e8ed6f --- /dev/null +++ b/examples/next/app/next13app/call-api-route/page.tsx @@ -0,0 +1,5 @@ +import ApiRouteExample from './ApiRouteExample'; + +export default function Home() { + return ; +} diff --git a/examples/next/package.json b/examples/next/package.json index 4d93115..8bf3f01 100644 --- a/examples/next/package.json +++ b/examples/next/package.json @@ -12,6 +12,7 @@ "@types/react": "18.2.21", "@types/react-dom": "18.2.7", "autoprefixer": "10.4.15", + "axios": "1.6.5", "eslint": "8.49.0", "eslint-config-next": "13.4.19", "next": "13.4.19", diff --git a/packages/nextjs/src/tracing.ts b/packages/nextjs/src/tracing.ts index 1c7c0d8..b5c94d4 100644 --- a/packages/nextjs/src/tracing.ts +++ b/packages/nextjs/src/tracing.ts @@ -3,13 +3,12 @@ import { TracingOptions, enableTracing as nodeTracing } from '@envyjs/node'; import { Routes } from './route'; +type GlobalWithFlag = { __nextjsTracingInitialized: boolean }; +const globalWithFlag: GlobalWithFlag = global as unknown as GlobalWithFlag; + // eslint-disable-next-line @typescript-eslint/ban-types export type NextjsTracingOptions = TracingOptions & {}; -// nextjs dev mode can run this multiple times -// prevent multiple registrations with a flag -let initialized = false; - export function enableTracing(options: NextjsTracingOptions) { const nextjsOptions: NextjsTracingOptions = { ...options, @@ -30,8 +29,8 @@ export function enableTracing(options: NextjsTracingOptions) { return true; }; - if (!initialized) { - initialized = true; + if (!globalWithFlag.__nextjsTracingInitialized) { + globalWithFlag.__nextjsTracingInitialized = true; return nodeTracing({ ...nextjsOptions, plugins: [...(options.plugins || []), Routes], diff --git a/yarn.lock b/yarn.lock index 5770cdd..1dc4dd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5199,6 +5199,15 @@ axe-core@^4.6.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.1.tgz#6948854183ee7e7eae336b9877c5bafa027998ea" integrity sha512-9l850jDDPnKq48nbad8SiEelCv4OrUWrKab/cPj0GScVg6cb6NbCCt/Ulk26QEq5jP9NnGr04Bit1BHyV6r5CQ== +axios@1.6.5: + version "1.6.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" + integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axios@^0.27.2: version "0.27.2" resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" @@ -7515,6 +7524,11 @@ follow-redirects@^1.14.9, follow-redirects@^1.15.2: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.15.4: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -10765,7 +10779,7 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-from-env@^1.0.0: +proxy-from-env@^1.0.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==