diff --git a/src/frontend/pages/_app.tsx b/src/frontend/pages/_app.tsx index a83d3efe16..15a478ac41 100755 --- a/src/frontend/pages/_app.tsx +++ b/src/frontend/pages/_app.tsx @@ -4,12 +4,10 @@ import '../styles/globals.css'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import App, { AppContext, AppProps } from 'next/app'; -import { getCookie } from 'cookies-next'; import CurrencyProvider from '../providers/Currency.provider'; import CartProvider from '../providers/Cart.provider'; import { ThemeProvider } from 'styled-components'; import Theme from '../styles/Theme'; -import FrontendTracer from '../utils/telemetry/FrontendTracer'; import { init, identify, addSignalAttribute, removeSignalAttribute } from '@dash0/sdk-web'; import { createRandomUser } from '../utils/faker/createRandomUser'; import { createRandomLocation } from '../utils/faker/createRandomLocation'; @@ -23,19 +21,22 @@ declare global { IS_SYNTHETIC_REQUEST?: string; NEXT_PUBLIC_DASH0_WEB_SDK_URL: string; }; + seed?: { + email: string; + location: { + countryCode: string; + continentCode: string; + locality: string; + } + } } } -if (typeof window !== 'undefined') { - const collector = getCookie('otelCollectorUrl')?.toString() || ''; - FrontendTracer(collector); -} - if (typeof window !== 'undefined') { /** * NOTE: This instrumentation is mostly focused on creating random user data and is not how the Dash0 Web SDK should be used. */ - const randomUser = createRandomUser(); + const randomUser = createRandomUser(window.seed?.email); init({ pageViewInstrumentation: { @@ -57,7 +58,7 @@ if (typeof window !== 'undefined') { // So that we can add our own faked one. addSignalAttribute('user_agent.original', randomUser.userAgent); - for (const [key, value] of Object.entries(createRandomLocation())) { + for (const [key, value] of Object.entries(createRandomLocation(window.seed?.location))) { addSignalAttribute(key, value); } } diff --git a/src/frontend/pages/product/[productId]/index.tsx b/src/frontend/pages/product/[productId]/index.tsx index 565c51a939..411839776a 100644 --- a/src/frontend/pages/product/[productId]/index.tsx +++ b/src/frontend/pages/product/[productId]/index.tsx @@ -52,6 +52,7 @@ const ProductDetail: NextPage = () => { const onAddItem = useCallback(async () => { sendEvent('product_added_to_cart', { attributes: { productId, quantity }, + title: `Added ${name} to cart` }); await addItem({ diff --git a/src/frontend/providers/Currency.provider.tsx b/src/frontend/providers/Currency.provider.tsx index 525bc30c64..8fdaba1899 100644 --- a/src/frontend/providers/Currency.provider.tsx +++ b/src/frontend/providers/Currency.provider.tsx @@ -41,7 +41,7 @@ const CurrencyProvider = ({ children }: IProps) => { const onSelectCurrency = useCallback((currencyCode: string) => { setSelectedCurrency(currencyCode); SessionGateway.setSessionValue('currencyCode', currencyCode); - sendEvent('currency_switched', { attributes: { currencyCode } }); + sendEvent('currency_switched', { attributes: { currencyCode }, title: `Switched to currency ${currencyCode}` }); }, []); const currencyCodeList = currencyCodeListUnsorted.sort(); diff --git a/src/frontend/utils/faker/createRandomLocation.ts b/src/frontend/utils/faker/createRandomLocation.ts index c7978c6b3b..b07feb5399 100644 --- a/src/frontend/utils/faker/createRandomLocation.ts +++ b/src/frontend/utils/faker/createRandomLocation.ts @@ -4,7 +4,13 @@ import { faker } from '@faker-js/faker'; import { persistedCall } from './persistedCall'; -export const createRandomLocation = persistedCall('random_location', () => { +type LocationSeed = { + countryCode: string; + continentCode: string; + locality: string +} + +export const createRandomLocation = persistedCall('random_location', (seed?: LocationSeed) => { const continent = faker.location.continent(); // @ts-expect-error we simply don't care. const continentCode = continentCodes[continent] ?? 'EU'; @@ -12,9 +18,9 @@ export const createRandomLocation = persistedCall('random_location', () => { const locality = faker.location.city(); return { - 'geo.continent.code': continentCode, - 'geo.country.iso_code': country, - 'geo.locality.name': locality, + 'geo.continent.code': seed?.continentCode || continentCode, + 'geo.country.iso_code': seed?.countryCode || country, + 'geo.locality.name': seed?.locality || locality, }; }); diff --git a/src/frontend/utils/faker/createRandomUser.ts b/src/frontend/utils/faker/createRandomUser.ts index 81827fea7f..5dd6eb64ce 100644 --- a/src/frontend/utils/faker/createRandomUser.ts +++ b/src/frontend/utils/faker/createRandomUser.ts @@ -4,15 +4,27 @@ import { faker } from '@faker-js/faker'; import { persistedCall } from './persistedCall'; -export const createRandomUser = persistedCall('random_user', () => { - const firstName = faker.person.firstName(); +export const createRandomUser = persistedCall('random_user', (seedEmail?: string) => { + let firstName: string; + if (seedEmail) { + const name = seedEmail.split("@")[0]; + firstName = capitalizeNames(name.replace("_", " ")) + } else { + firstName = faker.person.firstName(); + } const lastName = faker.person.lastName(); return { userId: faker.string.uuid(), username: faker.internet.username(), // before version 9.1.0, use userName() fullName: `${firstName} ${lastName}`, - email: faker.internet.email({ firstName: firstName.toLowerCase(), lastName: lastName.toLowerCase() }), + email: seedEmail || faker.internet.email({ firstName: firstName.toLowerCase(), lastName: lastName.toLowerCase() }), userAgent: faker.internet.userAgent(), }; }); + +function capitalizeNames(name: string) { + return name.split(" ") + .map(part => part.charAt(0).toUpperCase() + part.slice(1)) + .join(" ") +} diff --git a/src/frontend/utils/faker/persistedCall.ts b/src/frontend/utils/faker/persistedCall.ts index fb36ad0e8b..65a911ec16 100644 --- a/src/frontend/utils/faker/persistedCall.ts +++ b/src/frontend/utils/faker/persistedCall.ts @@ -3,8 +3,8 @@ const prefix = 'persisted_call'; -export function persistedCall(key: string, fn: () => T): () => T { - return () => { +export function persistedCall(key: string, fn: (args: P) => T): (args: P) => T { + return (args: P) => { const persistedResult = sessionStorage.getItem(`${prefix}_${key}`); if (persistedResult) { @@ -15,7 +15,7 @@ export function persistedCall(key: string, fn: () => T): () => T { } } - const result = fn(); + const result = fn(args); sessionStorage.setItem(`${prefix}_${key}`, JSON.stringify(result)); return result; }; diff --git a/src/loadgenerator/locustfile.py b/src/loadgenerator/locustfile.py index 913c7deda0..c52abaa051 100644 --- a/src/loadgenerator/locustfile.py +++ b/src/loadgenerator/locustfile.py @@ -146,6 +146,7 @@ async def open_cart_page_and_change_currency(self, page: PageWithRetry): try: page.on("console", lambda msg: print(msg.text)) await page.route('**/*', add_baggage_header) + await seed_person(page) await page.goto("/cart", wait_until="domcontentloaded") await page.select_option('[name="currency_code"]', 'CHF') await page.wait_for_timeout(2000) # giving the browser time to export the traces @@ -158,6 +159,7 @@ async def add_product_to_cart(self, page: PageWithRetry): try: page.on("console", lambda msg: print(msg.text)) await page.route('**/*', add_baggage_header) + await seed_person(page) await page.goto("/", wait_until="domcontentloaded") await page.click('p:has-text("Roof Binoculars")') await page.click('button:has-text("Add To Cart")') @@ -171,17 +173,33 @@ async def browse_shop(self, page: PageWithRetry): try: page.on("console", lambda msg: print(msg.text)) await page.route('**/*', add_baggage_header) + await seed_person(page) async with event(self, 'View shop'): await page.goto("/", wait_until="domcontentloaded") await page.wait_for_timeout(random.randint(2000, 15000)) # emulating user + async with event(self, 'Browse products'): - await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") - await page.wait_for_timeout(random.randint(2000, 15000)) - await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") - await page.wait_for_timeout(random.randint(2000, 15000)) - await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") - await page.wait_for_timeout(random.randint(2000, 15000)) + use_tabs = random.randint(0, 1) == 0 + if use_tabs: + await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")", button="middle") + await page.wait_for_timeout(random.randint(2000, 15000)) + tab1 = await self.browser_context.new_page() + await tab1.route('**/*', add_baggage_header) + await tab1.goto("/" + random.choice(products), wait_until="domcontentloaded") + await page.wait_for_timeout(random.randint(2000, 15000)) + await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") + tab2 = await self.browser_context.new_page() + await tab2.route('**/*', add_baggage_header) + await tab2.goto("/" + random.choice(products), wait_until="domcontentloaded") + await page.wait_for_timeout(random.randint(2000, 15000)) + else: + await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") + await page.wait_for_timeout(random.randint(2000, 15000)) + await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") + await page.wait_for_timeout(random.randint(2000, 15000)) + await page.click(":nth-match([data-cy=product-card], " + str(random.randint(1, 4)) + ")") + await page.wait_for_timeout(random.randint(2000, 15000)) if (random.randint(0, 12) == 0): # Change currency with a chance of 1:12 await page.select_option('[name="currency_code"]', 'CHF') @@ -215,3 +233,16 @@ async def add_baggage_header(route: Route, request: Request): 'baggage': 'synthetic_request=true' } await route.continue_(headers=headers) + +async def seed_person(page: PageWithRetry): + person = random.choice(people) + await page.add_init_script(f""" + window.seed = {{ + email: '{person['email']}', + location: {{ + countryCode: '{person['address']['countryCode']}', + continentCode: '{person['address']['continentCode']}', + locality: '{person['address']['city']}' + }} + }} + """) diff --git a/src/loadgenerator/people.json b/src/loadgenerator/people.json index 5e04a93186..853f48515d 100644 --- a/src/loadgenerator/people.json +++ b/src/loadgenerator/people.json @@ -1,155 +1,173 @@ [ - { - "email": "larry_sergei@example.com", - "address": { - "streetAddress": "1600 Amphitheatre Parkway", - "zipCode": "94043", - "city": "Mountain View", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4432-8015-6152-0454", - "creditCardExpirationMonth": 1, - "creditCardExpirationYear": 2039, - "creditCardCvv": 672 - } + { + "email": "larry_sergei@example.com", + "address": { + "streetAddress": "1600 Amphitheatre Parkway", + "zipCode": "94043", + "city": "Mountain View", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "bill@example.com", - "address": { - "streetAddress": "One Microsoft Way", - "zipCode": "98052", - "city": "Redmond", - "state": "WA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4532-4211-7434-1278", - "creditCardExpirationMonth": 2, - "creditCardExpirationYear": 2039, - "creditCardCvv": 114 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4432-8015-6152-0454", + "creditCardExpirationMonth": 1, + "creditCardExpirationYear": 2039, + "creditCardCvv": 672 + } + }, + { + "email": "bill@example.com", + "address": { + "streetAddress": "One Microsoft Way", + "zipCode": "98052", + "city": "Redmond", + "state": "WA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "steve@example.com", - "address": { - "streetAddress": "One Apple Park Way", - "zipCode": "95014", - "city": "Cupertino", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4532-6178-2799-1951", - "creditCardExpirationMonth": 3, - "creditCardExpirationYear": 2039, - "creditCardCvv": 239 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4532-4211-7434-1278", + "creditCardExpirationMonth": 2, + "creditCardExpirationYear": 2039, + "creditCardCvv": 114 + } + }, + { + "email": "steve@example.com", + "address": { + "streetAddress": "One Apple Park Way", + "zipCode": "95014", + "city": "Cupertino", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "mark@example.com", - "address": { - "streetAddress": "1 Hacker Way", - "zipCode": "94025", - "city": "Menlo Park", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4539-1103-5661-7083", - "creditCardExpirationMonth": 4, - "creditCardExpirationYear": 2039, - "creditCardCvv": 784 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4532-6178-2799-1951", + "creditCardExpirationMonth": 3, + "creditCardExpirationYear": 2039, + "creditCardCvv": 239 + } + }, + { + "email": "mark@example.com", + "address": { + "streetAddress": "1 Hacker Way", + "zipCode": "94025", + "city": "Menlo Park", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "jeff@example.com", - "address": { - "streetAddress": "410 Terry Ave N", - "zipCode": "98109", - "city": "Seattle", - "state": "WA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4916-0816-6217-7968", - "creditCardExpirationMonth": 5, - "creditCardExpirationYear": 2039, - "creditCardCvv": 397 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4539-1103-5661-7083", + "creditCardExpirationMonth": 4, + "creditCardExpirationYear": 2039, + "creditCardCvv": 784 + } + }, + { + "email": "jeff@example.com", + "address": { + "streetAddress": "410 Terry Ave N", + "zipCode": "98109", + "city": "Seattle", + "state": "WA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "reed@example.com", - "address": { - "streetAddress": "100 Winchester Circle", - "zipCode": "95032", - "city": "Los Gatos", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4929-5431-0337-5647", - "creditCardExpirationMonth": 6, - "creditCardExpirationYear": 2039, - "creditCardCvv": 793 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4916-0816-6217-7968", + "creditCardExpirationMonth": 5, + "creditCardExpirationYear": 2039, + "creditCardCvv": 397 + } + }, + { + "email": "reed@example.com", + "address": { + "streetAddress": "100 Winchester Circle", + "zipCode": "95032", + "city": "Los Gatos", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "tobias@example.com", - "address": { - "streetAddress": "150 Elgin St", - "zipCode": "K2P1L4", - "city": "Ottawa", - "state": "ON", - "country": "Canada" - }, - "userCurrency": "CAD", - "creditCard": { - "creditCardNumber": "4763-1844-9699-8031", - "creditCardExpirationMonth": 7, - "creditCardExpirationYear": 2039, - "creditCardCvv": 488 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4929-5431-0337-5647", + "creditCardExpirationMonth": 6, + "creditCardExpirationYear": 2039, + "creditCardCvv": 793 + } + }, + { + "email": "tobias@example.com", + "address": { + "streetAddress": "150 Elgin St", + "zipCode": "K2P1L4", + "city": "Ottawa", + "state": "ON", + "country": "Canada", + "countryCode": "CA", + "continentCode": "NA" + }, + "userCurrency": "CAD", + "creditCard": { + "creditCardNumber": "4763-1844-9699-8031", + "creditCardExpirationMonth": 7, + "creditCardExpirationYear": 2039, + "creditCardCvv": 488 + } + }, + { + "email": "jack@example.com", + "address": { + "streetAddress": "1355 Market St", + "zipCode": "94103", + "city": "San Francisco", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "jack@example.com", - "address": { - "streetAddress": "1355 Market St", - "zipCode": "94103", - "city": "San Francisco", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4929-6495-8333-3657", - "creditCardExpirationMonth": 8, - "creditCardExpirationYear": 2039, - "creditCardCvv": 159 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4929-6495-8333-3657", + "creditCardExpirationMonth": 8, + "creditCardExpirationYear": 2039, + "creditCardCvv": 159 + } + }, + { + "email": "moore@example.com", + "address": { + "streetAddress": "2200 Mission College Blvd", + "zipCode": "95054", + "city": "Santa Clara", + "state": "CA", + "country": "United States", + "countryCode": "US", + "continentCode": "NA" }, - { - "email": "moore@example.com", - "address": { - "streetAddress": "2200 Mission College Blvd", - "zipCode": "95054", - "city": "Santa Clara", - "state": "CA", - "country": "United States" - }, - "userCurrency": "USD", - "creditCard": { - "creditCardNumber": "4485-4803-8707-3547", - "creditCardExpirationMonth": 9, - "creditCardExpirationYear": 2039, - "creditCardCvv": 682 - } + "userCurrency": "USD", + "creditCard": { + "creditCardNumber": "4485-4803-8707-3547", + "creditCardExpirationMonth": 9, + "creditCardExpirationYear": 2039, + "creditCardCvv": 682 } -] \ No newline at end of file + } +]