# Core Web Vitals Scenario Script
* load via `kclocal`, and run!
## Before starting check
* `ls /root`: If it has `discounts-requirements.txt`, try refreshing the browser (there's been a race condition).
## Fire drill if false start
* `docker ps`
* `grab the id of the discounts service`
* `docker exec -it <id> sh`
* `apt update && apt install -y vim`
* `vim requirements.txt`
* Update ddtrace version to `0.50.2`
* add `Flask-Cors==3.0.10`
* Save file, and run `pip install -r requirements.txt`
* `exit`, and continue with course.
## 👉 Core Web Vitals: Resolution 👈
You can see here that no rum events occurred for 3 seconds, which means that the hold up must have been from the back end because nothing happened or was reported yet by rum. so let’s go take a look at our back end traces and see if we spot any anomalies there
————
* Ads-service (top nav): `sleep` in ads.py
We can see there’s a sleep here, sure, but notice that: if this were done on the front end via XHR it wouldn’t have affected the core web vitals because the page would’ve been able to load without having to wait for the ads service.
If it was loaded after the page load, all you most valuable content would've loaded already and your scores would be high, but because this was done on the backend – it makes the front end wait
# RUM & Synthetics in CI Script
# WebSound Demo
👉 Show/Describe WebSound: npm start `websound-worklet`
* Have Ryan jump on with you (via shared ngrok url), tell them what you’re doing (use `127.0.0.1:9090`)
* **Play together**: looks super fun right?
* Kill `websound-worklet` process, navigate to `websound` dir, `npm start`
* Play for a moment, then hold up keyboard and show the delay
* This is not so fun, is it?
* Kill process
# << CONTINUE SCRIPT >>
# Step 1: Add Datadog RUM
1. Make a new RUM Application: Observability-Spotlight-Workshop
2. `npm install @datadog/browser-rum`
3. Share an instance (ngrok URL) with Ryan, and we'll make some noise with our phones and via desktop browsers, to capture some unique session data, actions, etc.
4. Now we can verify the app's installation of Datadog RUM
5. Commit `spotlight-workshop-add-dd-rum`
# Step 2: Fix the App
## Take A Look around for Potential Issues
1. Look at Conduit in the RUM Explorer, note the initial load time (eg. 2000ms).
2. Notice that there are big delays when fetching the articles and tags, adding significant latency to the experience – especially for mobile users.
3. Walk through `src/agent.js` and note how the tags and articles are being fetched.
* Then show that the articles are being fetched every time the page is loaded in `src/components/Home/MainView.js`: using **`agent.Articles.all()`**
4. Talk about some different approaches
1. We could definitely call the fetch once, instead of every time the component is loaded – and then periodically poll for new updates and prepend those to the list at a set interval (kind of like how twitter.com does it).
2. OR, we could set up a workflow for a Github Action (like a regularly scheduled task) that prefetches the articles from the production API at a set interval, and then updates an ‘articles’ module that’s a dependency of Conduit.
On Conduit’s side, it might asynchronously poll the articles list – and then update this local articles cache if new ones have been published.
3. Today for the sake of time, instead of setting up a Github Action & it's workflow – we’ll simulate the outcome of having the articles in a local cache, and act as if we had already been prefetching them.
So let's dig in.
## Caching
> Note: I've already got the articles and tags cached locally in `src/comonents/cache`
### src/components/Home/MainView.js
1
```javascript
// Line 6
import * as articles from '../cache/articles.json';
```
2
```javascript
// Line 8
const allArticles = articles.articles
```
3
```javascript
// Line 33
// Change from agent.Articles.all() to allArticles
props.onTabClick('all', agent.Articles.all, allArticles)
```
4
```jsx
// Line 90: Conditionally render articles
{ props.tab === 'feed'
? <ArticleList
pager={props.pager}
articles={props.articles}
loading={props.loading}
articlesCount={props.articlesCount}
currentPage={props.currentPage} />
: <ArticleList
pager={props.pager}
articles={allArticles}
loading={props.loading}
articlesCount={articles.articlesCount}
currentPage={props.currentPage} />
}
```
### src/components/Home/index.js
1
```javascript
// Line 13
import * as tags from '../cache/tags.json'
```
2
```javascript
// Line 39
// agent.Tags.getAll() => tags
Promise.all([tags, articlesPromise()])
```
3
```javascript
// line 62:
tags={tags}
```
4
```javascript
// line 12: Comment out filtered tags block
```
5
```javascript
// line 21: Change filteredTags to tags
```
### src/components/Home/Tags.js
1
```javascript
// Line 5/6, change to:
const tags = props.tags.tags;
```
2
```javascript
// Line 12: Comment out filteredTags logic
```
3
```javascript
// Line 21: Change `filteredTags` to `tags`
```
* Check out our changes here in RUM, verify the perf increase is substantial
* Here in RUM they don't show up because they're not network requests.
* If you want more runtime detail (regarding your real users), using tracers from Datadog's APM tool could be a good fit.
* To test this out quickly in the lab though, let's do a quick profile in the dev tools, check out the main thread and timings section, and see when the components are being updated (eg. React tree reconciliation)

* Commit `jsnation-use-cache`
**There’s still more we can do now though, this local articles list is just _huge_. So, for this it's LazyLoading to the rescue! (Explain what it is: ‘if you’re not familiar’)**
Let's make it happen.
## Step 3: Lazy Loading
> This codebase is currently using `React 16.3`, and the`React.Lazy` function didn't arrive until version `16.6` –– that’s how I’d do this if I were implementing Lazy Loading on a newer version of React since it's native to the framework.
👉 In this case, I'm going to grab a module that lazy loads React components beautifully, it's called `react-lazyload`.
* `npm install react-lazyload`
### src/components/ArticlePreview.js
1
```javascript
// Line 6:
import LazyLoad from 'react-lazyload';
```
2
👉 Here we'll lazy load each article on the preview list. Splitting this up will help us break down latency to be *on demand*, rather than inconveniently all at once for the user.
```jsx
// Line 42: LazyLoad needs a no-op type of prop to be rendered to the DOM
<LazyLoad height={200} once >
// line 82:
</LazyLoad>
```
* Now let's go back to the articles list, and visibly see it be smooth.
* If I had traces set up, I could view more of this in Datadog, but for now let's take a quick look in the dev tools and see that the lazy loading is working (timings, main thread).
* Commit `jsnation-lazy-load-articles`
## Step 5: Let's feel the difference for ourselves (again)
* Switch to Discovery page branch: `bpm/discovery-component`
* Demo walking through loading the articles list on the home page, then again through the discovery page –– you can literally feel the difference.
# << CONTINUE SCRIPT >>
## Step 6: Adding KPI or Business Oriented Metrics
### Tracking Signups
#### src/components/Register.js
```javascript
// Line 6:
import { datadogRum } from '@datadog/browser-rum';
// line 39: Add to onSubmit form
datadogRum.addAction('signup', {
'userName': username,
'newUser': username,
'email': email
})
```
👉 Verify custom signup actions in the RUM explorer
### Tracking Logins
#### src/components/Login.js
```javascript
// Line 11:
import { datadogRum } from '@datadog/browser-rum';
// Line 34: Add to onSubmit form
datadogRum.addAction('login', {
'userLogin': email,
'userEmail': email
})
```
👉 Verify custom login actions in the RUM explorer
### Tracking the Number of Published Articles
#### src/components/Editor.js
```javascript
// Line 13:
import { datadogRum } from '@datadog/browser-rum';
// Line 72: add to the this.submit form
datadogRum.addAction('newpost', {
'article': article,
'slug': slug
});
```
👉 Verify custom _article post_ actions in the RUM explorer
* Commit: `jsnation-add-KPIs`
### Making a Custom Dashboard
* Now that we've got our custom KPI metrics aggregating to Datadog, we can add them to custom dashboards to continuously monitor their health.
So let's do that.
* Talk about the dashboard
Total Signups (action.name:signup)

Total Logins (action.name:login)

Total Posts (action.name:newpost)

* This is great, but maybe you'd just like to be alerted when a performance metric like your average loading time goes above a bad threshold.
👉 Navigate to Performance Dashboard and create monitor for this.
* Well, even though there's always more to cover, we'll end here for now.
* I hope this workshop was helpful in your journey of understanding the power of observability.
* If there's anything I hope you took away from this, it's that:
* Observability practices like Real User Monitoring (which help you understand the experience of your actual users) are a very necessary compliment to synthetically auditing your Web App's general performance with great lab tools like Lighthouse and the dev tools profiler.
* I hope that getting a little insight into how to use tools that help you fashion a delightful experience for your current users will foster success and longevity for your ongoing projects and especially your craft in the front end.
* Now let's move on to setting up synthetic monitoring in a CI/CD pipeline!
# << CONTINUE SCRIPT >>
## Step 7: Synthetics in CI/CD Workshop
* Load via `kclocal` and run!
# << CONTINUE SCRIPT >>