Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/frontend/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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: {
Expand All @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/frontend/pages/product/[productId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/providers/Currency.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
14 changes: 10 additions & 4 deletions src/frontend/utils/faker/createRandomLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@
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';
const country = faker.location.countryCode();
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,
};
});

Expand Down
18 changes: 15 additions & 3 deletions src/frontend/utils/faker/createRandomUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(" ")
}
6 changes: 3 additions & 3 deletions src/frontend/utils/faker/persistedCall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

const prefix = 'persisted_call';

export function persistedCall<T>(key: string, fn: () => T): () => T {
return () => {
export function persistedCall<P, T>(key: string, fn: (args: P) => T): (args: P) => T {
return (args: P) => {
const persistedResult = sessionStorage.getItem(`${prefix}_${key}`);

if (persistedResult) {
Expand All @@ -15,7 +15,7 @@ export function persistedCall<T>(key: string, fn: () => T): () => T {
}
}

const result = fn();
const result = fn(args);
sessionStorage.setItem(`${prefix}_${key}`, JSON.stringify(result));
return result;
};
Expand Down
43 changes: 37 additions & 6 deletions src/loadgenerator/locustfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")')
Expand All @@ -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')
Expand Down Expand Up @@ -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']}'
}}
}}
""")
Loading
Loading