Skip to content

Commit bc40ce5

Browse files
committed
improve example app
1 parent cee7395 commit bc40ce5

File tree

2 files changed

+188
-58
lines changed

2 files changed

+188
-58
lines changed

examples/web/examples/navigation/index.html

Lines changed: 110 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,28 @@
33

44
<head>
55
<meta charset="utf-8">
6-
<title>Browser Navigation Plugin Example</title>
6+
<title>Browser Navigation Instrumentation Example</title>
77
<base href="/">
8-
9-
<!--
10-
https://www.w3.org/TR/trace-context/
11-
Set the `traceparent` in the server's HTML template code. It should be
12-
dynamically generated server side to have the server's request trace Id,
13-
a parent span Id that was set on the server's request span, and the trace
14-
flags to indicate the server's sampling decision
15-
(01 = sampled, 00 = notsampled).
16-
'{version}-{traceId}-{spanId}-{sampleDecision}'
17-
-->
18-
<!-- <meta name="traceparent" content="00-ab42124a3c573678d4d8b21ba52df3bf-d21f7bc17caa5aba-01">-->
19-
208
<meta name="viewport" content="width=device-width, initial-scale=1">
219
</head>
2210

2311
<body>
24-
Example of using Browser Navigation Instrumentation with console exporter and collector exporter
12+
<h1>🧭 Browser Navigation Instrumentation Example</h1>
13+
<p>This example demonstrates the <strong>Browser Navigation Instrumentation</strong> package with enhanced Navigation API support, custom log record data, and comprehensive event tracking.</p>
14+
15+
<div class="info-panel">
16+
<h3>📊 Features Demonstrated:</h3>
17+
<ul>
18+
<li><strong>Navigation API Support:</strong> Modern browser navigation events</li>
19+
<li><strong>History API Tracking:</strong> pushState, replaceState, popstate events</li>
20+
<li><strong>Hash Change Detection:</strong> Fragment navigation tracking</li>
21+
<li><strong>Custom Log Attributes:</strong> App metadata, viewport info, user agent</li>
22+
<li><strong>URL Sanitization:</strong> Automatic credential and sensitive data redaction</li>
23+
<li><strong>Same-Document Navigation:</strong> SPA-style navigation detection</li>
24+
</ul>
25+
</div>
26+
2527
<script type="text/javascript" src="/navigation.js"></script>
26-
<br/>
2728
<nav>
2829
<a href="/navigation/route1" data-link>Route 1</a>
2930
<a href="/navigation/route2" data-link>Route 2</a>
@@ -40,6 +41,100 @@
4041
<!-- Hash content will be displayed here -->
4142
</div>
4243

44+
<div id="nav-api-content">
45+
<!-- Navigation API content will be displayed here -->
46+
</div>
47+
48+
<style>
49+
.nav-result {
50+
margin: 10px 0;
51+
padding: 15px;
52+
border-radius: 8px;
53+
border-left: 4px solid #007acc;
54+
background-color: #f8f9fa;
55+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
56+
}
57+
.nav-result.error {
58+
border-left-color: #dc3545;
59+
background-color: #f8d7da;
60+
}
61+
.nav-result.fallback {
62+
border-left-color: #ffc107;
63+
background-color: #fff3cd;
64+
}
65+
.nav-result h4 {
66+
margin: 0 0 10px 0;
67+
color: #333;
68+
}
69+
.nav-result code {
70+
background-color: #e9ecef;
71+
padding: 2px 6px;
72+
border-radius: 4px;
73+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
74+
}
75+
.nav-result ul {
76+
margin: 10px 0;
77+
padding-left: 20px;
78+
}
79+
.nav-result li {
80+
margin: 5px 0;
81+
}
82+
.console-note {
83+
font-style: italic;
84+
color: #6c757d;
85+
margin-top: 10px;
86+
}
87+
.info-panel {
88+
margin: 20px 0;
89+
padding: 15px;
90+
background-color: #e8f4fd;
91+
border-radius: 8px;
92+
border-left: 4px solid #007acc;
93+
}
94+
.info-panel h3 {
95+
margin-top: 0;
96+
color: #007acc;
97+
}
98+
.info-panel ul {
99+
margin: 10px 0;
100+
padding-left: 20px;
101+
}
102+
.info-panel li {
103+
margin: 8px 0;
104+
}
105+
nav {
106+
margin: 20px 0;
107+
padding: 15px;
108+
background-color: #f1f3f4;
109+
border-radius: 8px;
110+
}
111+
nav a, nav button {
112+
margin: 5px 10px 5px 0;
113+
padding: 8px 16px;
114+
text-decoration: none;
115+
background-color: #007acc;
116+
color: white;
117+
border: none;
118+
border-radius: 4px;
119+
cursor: pointer;
120+
font-size: 14px;
121+
}
122+
nav a:hover, nav button:hover {
123+
background-color: #005a9e;
124+
}
125+
body {
126+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
127+
line-height: 1.6;
128+
margin: 20px;
129+
color: #333;
130+
}
131+
h1 {
132+
color: #007acc;
133+
border-bottom: 2px solid #007acc;
134+
padding-bottom: 10px;
135+
}
136+
</style>
137+
43138
</body>
44139

45140
</html>

examples/web/examples/navigation/index.js

Lines changed: 78 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,15 @@ logs.setGlobalLoggerProvider(loggerProvider);
4040
registerInstrumentations({
4141
instrumentations: [new BrowserNavigationInstrumentation({
4242
enabled: true,
43-
useNavigationApiIfAvailable: true
43+
useNavigationApiIfAvailable: true,
44+
applyCustomLogRecordData: (logRecord) => {
45+
// Add custom attributes to navigation log records
46+
if (!logRecord.attributes) {
47+
logRecord.attributes = {};
48+
}
49+
logRecord.attributes['app.name'] = 'navigation-example';
50+
logRecord.attributes['app.version'] = '1.0.0';
51+
}
4452
})],
4553
});
4654

@@ -85,16 +93,53 @@ function testHashChange() {
8593
hashCounter++;
8694
const newHash = `section-${hashCounter}`;
8795
location.hash = newHash;
96+
8897
document.getElementById('hash-content').innerHTML =
89-
`<p>Hash changed to: #${newHash}</p><p>Check console for navigation events!</p>`;
98+
`<div class="nav-result">
99+
<h4>🔗 Hash Navigation</h4>
100+
<p><strong>New Hash:</strong> <code>#${newHash}</code></p>
101+
<p><strong>Method:</strong> location.hash assignment</p>
102+
<p><strong>Expected Instrumentation:</strong></p>
103+
<ul>
104+
<li>✓ same_document: true</li>
105+
<li>✓ hash_change: true</li>
106+
<li>✓ type: traverse or push</li>
107+
</ul>
108+
<p class="console-note">📊 Check console for navigation events!</p>
109+
</div>`;
90110
}
91111

92112
// Back button functionality
93113
function goBack() {
94114
if (window.history.length > 1) {
115+
95116
window.history.back();
117+
118+
// Update content to show back navigation happened
119+
setTimeout(() => {
120+
const contentDiv = document.getElementById('content') || document.body;
121+
const backIndicator = document.createElement('div');
122+
backIndicator.className = 'nav-result';
123+
backIndicator.innerHTML =
124+
`<div class="nav-result">
125+
<h4>⬅️ Back Navigation</h4>
126+
<p><strong>Method:</strong> history.back()</p>
127+
<p><strong>Current URL:</strong> <code>${location.href}</code></p>
128+
<p><strong>Expected Instrumentation:</strong></p>
129+
<ul>
130+
<li>✓ same_document: true</li>
131+
<li>✓ hash_change: depends on URL change</li>
132+
<li>✓ type: traverse</li>
133+
</ul>
134+
<p class="console-note">📊 Check console for navigation events!</p>
135+
</div>`;
136+
contentDiv.appendChild(backIndicator);
137+
138+
// Remove the indicator after 5 seconds
139+
setTimeout(() => backIndicator.remove(), 5000);
140+
}, 100);
96141
} else {
97-
console.log('No history to go back to');
142+
alert('No history to go back to!');
98143
}
99144
}
100145

@@ -112,53 +157,46 @@ function testNavigationApiHash() {
112157
function testNavigationApiRoute(route, navigationType) {
113158
if ('navigation' in window) {
114159
try {
115-
// Add a navigate event listener to debug the event properties
116-
const debugHandler = (event) => {
117-
console.log(`${navigationType} - Navigation API event details:`, {
118-
destination: event.destination,
119-
sameDocument: event.destination?.sameDocument,
120-
hashChange: event.hashChange,
121-
url: event.destination?.url,
122-
canIntercept: event.canIntercept,
123-
userInitiated: event.userInitiated
124-
});
125-
126-
// Don't prevent the navigation - let it proceed
127-
// event.preventDefault(); // DON'T do this
128-
};
129-
window.navigation.addEventListener('navigate', debugHandler, { once: true });
160+
130161

131162
// Use Navigation API navigate method
132163
window.navigation.navigate(route);
133164

134-
// Update content to show Navigation API usage
165+
// Update content after navigation
135166
setTimeout(() => {
136-
document.getElementById('content').innerHTML =
137-
`<h2>${navigationType} Test</h2>
138-
<p>Used navigation.navigate() to navigate to: <code>${route}</code></p>
139-
<p>Current URL: <code>${window.location.href}</code></p>
140-
<p>Check console for navigation events and sameDocument property!</p>`;
167+
document.getElementById('nav-api-content').innerHTML =
168+
`<div class="nav-result">
169+
<h4>✅ ${navigationType} Completed</h4>
170+
<p><strong>Target:</strong> <code>${route}</code></p>
171+
<p><strong>Current URL:</strong> <code>${window.location.href}</code></p>
172+
<p><strong>Navigation API:</strong> Supported ✓</p>
173+
<p class="console-note">📊 Check console for detailed navigation events and instrumentation data!</p>
174+
</div>`;
141175
}, 100);
142-
176+
143177
} catch (error) {
144-
console.error(`Navigation API ${navigationType} failed:`, error);
178+
console.error(`Navigation API error for ${navigationType}:`, error);
145179
// Fallback to history API
146-
const fallbackRoute = `/navigation/fallback-${navApiCounter}`;
147-
navigateTo(fallbackRoute);
148-
document.getElementById('content').innerHTML =
149-
`<h2>${navigationType} Fallback</h2>
150-
<p>Navigation API not supported, used history.pushState() instead</p>
151-
<p>Navigated to: <code>${fallbackRoute}</code></p>`;
180+
const fallbackRoute = route.startsWith('#') ? route : `?fallback=${Date.now()}`;
181+
history.pushState({}, '', fallbackRoute);
182+
document.getElementById('nav-api-content').innerHTML =
183+
`<div class="nav-result error">
184+
<h4>⚠️ Navigation API Failed</h4>
185+
<p><strong>Fallback used:</strong> <code>${fallbackRoute}</code></p>
186+
<p><strong>Error:</strong> ${error.message}</p>
187+
</div>`;
152188
}
153189
} else {
154-
console.log(`Navigation API not supported - ${navigationType}`);
155-
// Fallback to history API
156-
const fallbackRoute = `/navigation/no-nav-api-${navApiCounter}`;
157-
navigateTo(fallbackRoute);
158-
document.getElementById('content').innerHTML =
159-
`<h2>No Navigation API Support - ${navigationType}</h2>
160-
<p>Navigation API not available, used history.pushState() instead</p>
161-
<p>Navigated to: <code>${fallbackRoute}</code></p>`;
190+
// Fallback for browsers without Navigation API
191+
const fallbackRoute = route.startsWith('#') ? route : `?fallback=${Date.now()}`;
192+
history.pushState({}, '', fallbackRoute);
193+
document.getElementById('nav-api-content').innerHTML =
194+
`<div class="nav-result fallback">
195+
<h4>📱 Navigation API Not Available</h4>
196+
<p><strong>Fallback used:</strong> <code>${fallbackRoute}</code></p>
197+
<p><strong>Method:</strong> history.pushState()</p>
198+
<p class="console-note">📊 Check console for instrumentation data!</p>
199+
</div>`;
162200
}
163201
}
164202

@@ -171,8 +209,5 @@ const loadTimeSetup = () => {
171209
document.getElementById('hashChangeBtn').addEventListener('click', testHashChange);
172210
document.getElementById('backBtn').addEventListener('click', goBack);
173211
document.getElementById('navApiHashBtn').addEventListener('click', testNavigationApiHash);
174-
175-
console.log('Browser Navigation Instrumentation Example loaded!');
176-
console.log('Try clicking the buttons to see navigation events in the console.');
177212
};
178213
window.addEventListener('load', loadTimeSetup);

0 commit comments

Comments
 (0)