Skip to content

Commit

Permalink
Merge branch 'main' into congyao/RUM-8295-change-anonymous-id
Browse files Browse the repository at this point in the history
  • Loading branch information
cy-moi authored Feb 6, 2025
2 parents 802d821 + b7fcfcb commit 89ceca7
Show file tree
Hide file tree
Showing 74 changed files with 1,406 additions and 994 deletions.
6 changes: 3 additions & 3 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
variables:
CURRENT_STAGING: staging-05
CURRENT_STAGING: staging-06
APP: 'browser-sdk'
CURRENT_CI_IMAGE: 76
CURRENT_CI_IMAGE: 77
BUILD_STABLE_REGISTRY: 'registry.ddbuild.io'
CI_IMAGE: '$BUILD_STABLE_REGISTRY/ci/$APP:$CURRENT_CI_IMAGE'
GIT_REPOSITORY: '[email protected]:DataDog/browser-sdk.git'
MAIN_BRANCH: 'main'
NEXT_MAJOR_BRANCH: ''
CHROME_PACKAGE_VERSION: 132.0.6834.110-1
CHROME_PACKAGE_VERSION: 133.0.6943.53-1

cache:
key:
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@
---

## v6.2.1

**Public Changes:**

- 🐛 [RUM-7694] - Keep more ReplayStats history to avoid wrongly marking views as having no replay ([#3318](https://github.com/DataDog/browser-sdk/pull/3318)) [RUM]

## v6.2.0

**Public Changes:**

-[RUM-6563] Attribute ressource URL to LCP ([#3154](https://github.com/DataDog/browser-sdk/pull/3154)) [RUM] [RUM-REACT] [RUM-SLIM]
- 🐛 [RUM-8353] Throttle view context update ([#3314](https://github.com/DataDog/browser-sdk/pull/3314)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]
- 🐛 fix document resource duration ([#3307](https://github.com/DataDog/browser-sdk/pull/3307)) [RUM] [RUM-REACT] [RUM-SLIM]

**Internal Changes:**

- ✅ fix failing skipped test ([#3309](https://github.com/DataDog/browser-sdk/pull/3309)) [RUM]
- 🔊 Revert hooks and add missing URL context telemetry ([#3313](https://github.com/DataDog/browser-sdk/pull/3313)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]
- 🔊 Add telemetry on missing URL context ([#3304](https://github.com/DataDog/browser-sdk/pull/3304)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]
- ⚗️Update RC to support new format and URL [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]
- 🚨 enforce consistent type export ([#3302](https://github.com/DataDog/browser-sdk/pull/3302)) [LOGS] [RUM] [RUM-REACT] [RUM-SLIM] [WORKER]
- ♻️ [RUM-8123] Introduce a hook to assemble events ([#3289](https://github.com/DataDog/browser-sdk/pull/3289)) [RUM] [RUM-REACT] [RUM-SLIM]

## v6.1.0

**Public Changes:**
Expand Down
8 changes: 4 additions & 4 deletions developer-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@datadog/browser-sdk-developer-extension",
"version": "6.1.0",
"version": "6.2.1",
"private": true,
"scripts": {
"build": "rm -rf dist && webpack --mode production",
"dev": "webpack --mode development --watch"
},
"devDependencies": {
"@tabler/icons-react": "3.29.0",
"@types/chrome": "0.0.299",
"@types/chrome": "0.0.301",
"@types/react": "18.3.18",
"@types/react-dom": "18.3.5",
"@webextension-toolbox/webpack-webextension-plugin": "3.3.1",
Expand All @@ -22,8 +22,8 @@
"@datadog/browser-core": "workspace:*",
"@datadog/browser-logs": "workspace:*",
"@datadog/browser-rum": "workspace:*",
"@mantine/core": "7.16.1",
"@mantine/hooks": "7.16.1",
"@mantine/core": "7.16.2",
"@mantine/hooks": "7.16.2",
"clsx": "2.1.1",
"react": "18.3.1",
"react-dom": "18.3.1"
Expand Down
10 changes: 9 additions & 1 deletion developer-extension/src/background/domain/syncRules.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { NetRequestRulesOptions } from '../../common/extension.types'
import { DEV_LOGS_URL, DEV_RUM_SLIM_URL, DEV_RUM_URL } from '../../common/packagesUrlConstants'
import {
DEV_LOGS_URL,
DEV_RUM_RECORDER_CHUNK_URL,
DEV_RUM_SLIM_URL,
DEV_RUM_URL,
} from '../../common/packagesUrlConstants'
import { INTAKE_DOMAINS } from '../../common/intakeDomainConstants'
import { createLogger } from '../../common/logger'
import { onDevtoolsDisconnection, onDevtoolsMessage } from '../devtoolsPanelConnection'
Expand Down Expand Up @@ -67,6 +72,9 @@ function buildRules(
url: DEV_RUM_SLIM_URL,
}),
createRedirectRule(/^https:\/\/.*\/datadog-logs(-[\w-]+)?\.js$/, { url: DEV_LOGS_URL }),
createRedirectRule(/^https:\/\/.*\/chunks\/recorder(-[\w-]+)?-datadog-rum.js$/, {
url: DEV_RUM_RECORDER_CHUNK_URL,
}),
createRedirectRule('https://localhost:8443/static/datadog-rum-hotdog.js', { url: devRumUrl })
)
} else if (useRumSlim) {
Expand Down
3 changes: 2 additions & 1 deletion developer-extension/src/common/packagesUrlConstants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const DEV_LOGS_URL = 'http://localhost:8080/datadog-logs.js'
export const DEV_RUM_URL = 'http://localhost:8080/datadog-rum.js'
export const DEV_RUM_RECORDER_CHUNK_URL = 'http://localhost:8080/chunks/recorder-datadog-rum.js'
export const DEV_RUM_SLIM_URL = 'http://localhost:8080/datadog-rum-slim.js'
export const DEV_RUM_URL = 'http://localhost:8080/datadog-rum.js'
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import type { RumActionEvent, RumResourceEvent } from '@datadog/browser-rum'
import { FacetRegistry } from '../../../hooks/useEvents'
import type { FacetValuesFilter } from '../../../hooks/useEvents'
import { FACET_ROOT } from '../../../facets.constants'
import type { Facet } from '../../../facets.constants'
import { computeSelectionState } from './computeFacetState'

const rumResourceXHREvent = {
type: 'resource',
resource: {
type: 'xhr',
url: 'http://example.com',
},
} as RumResourceEvent

const rumResourceBeaconEvent = {
type: 'resource',
resource: {
type: 'beacon',
url: 'http://example.com',
},
} as RumResourceEvent

const rumCustomActionEvent = {
type: 'action',
action: {
type: 'custom',
},
} as RumActionEvent

// test that computeSelectionState returns the correct state
describe('computeSelectionState', () => {
describe('include mode', () => {
it('returns "unselected" when the filter is empty', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'include',
facetValues: {},
}
const facet = {
path: 'resource.type',
label: 'Resource Type',
}

const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
const facetValue = 'xhr'
expect(
computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])
).toBe('unselected')
})
it('returns "selected" when the facet is in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'include',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = {
path: 'resource.type',
label: 'Resource Type',
}

const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
const facetValue = 'xhr'
expect(
computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])
).toBe('selected')
})

it('returns "partial-selected" when some children are in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'include',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = FACET_ROOT.values!.rum?.facets![0] as Facet
const facetValue = 'resource'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumResourceBeaconEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(
'partial-selected'
)
})

it('returns "selected" when all children are in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'include',
facetValues: {
'resource.type': ['xhr', 'beacon'],
},
}
const facet = FACET_ROOT.values!.rum?.facets![0] as Facet
const facetValue = 'resource'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumResourceBeaconEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(
'selected'
)
})

it('returns "unselected" when the facet or children are not in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'include',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = {
path: 'action.type',
label: 'Action Type',
}

const facetValue = 'action'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumCustomActionEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'action'])).toBe(
'unselected'
)
})
})

describe('exclude mode', () => {
it('returns "selected" when the filter is empty', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'exclude',
facetValues: {},
}
const facet = {
path: 'resource.type',
label: 'Resource Type',
}
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
const facetValue = 'xhr'
expect(
computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])
).toBe('selected')
})

it('returns "unselected" when the facet is in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'exclude',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = {
path: 'resource.type',
label: 'Resource Type',
}
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
const facetValue = 'xhr'
expect(
computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource', 'xhr'])
).toBe('unselected')
})
it('returns "partial-selected" when some children are in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'exclude',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = FACET_ROOT.values!.rum?.facets![0] as Facet

const facetValue = 'resource'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumResourceBeaconEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(
'partial-selected'
)
})

it('returns "unelected" when all children are in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'exclude',
facetValues: {
'resource.type': ['xhr', 'beacon'],
},
}
const facet = FACET_ROOT.values!.rum?.facets![0] as Facet
const facetValue = 'resource'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumResourceBeaconEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'resource'])).toBe(
'unselected'
)
})

it('returns "selected" when the facet or children are not in the filter', () => {
const facetValuesFilter: FacetValuesFilter = {
type: 'exclude',
facetValues: {
'resource.type': ['xhr'],
},
}
const facet = {
path: 'action.type',
label: 'Action Type',
}

const facetValue = 'action'
const facetRegistry = new FacetRegistry()
facetRegistry.addEvent(rumResourceXHREvent)
facetRegistry.addEvent(rumCustomActionEvent)
expect(computeSelectionState(facetValuesFilter, facetRegistry, facet, facetValue, ['rum', 'action'])).toBe(
'selected'
)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { FacetRegistry, FacetValuesFilter } from '../../../hooks/useEvents'
import type { Facet, FacetValue } from '../../../facets.constants'
type SelectionState = 'selected' | 'unselected' | 'partial-selected'

function isAllChildrenFiltered(children: string[], filteredFacetValues: string[]) {
return children.every((child: FacetValue) => filteredFacetValues.includes(child))
}

function isAnyChildrenFiltered(children: string[], filteredFacetValues: string[]) {
return children.some((child: FacetValue) => filteredFacetValues.includes(child))
}

// limitation: only populate direct parents
export function computeSelectionState(
facetValuesFilter: FacetValuesFilter,
facetRegistry: FacetRegistry,
facet: Facet,
facetValue: FacetValue,
parentList: string[]
): SelectionState {
const childrenFacets = facet.values?.[facetValue]?.facets

// we cannot know how many children in total there are, so we need to have facetRegistry
const children =
childrenFacets && childrenFacets.flatMap((child: Facet) => facetRegistry.getFacetChildrenValues(child.path))
const filteredFacetValues = Object.values(facetValuesFilter.facetValues).flat()
const isFiltering = !!Object.keys(facetValuesFilter.facetValues)

if (facetValuesFilter.type === 'include') {
if (!isFiltering) {
return 'unselected'
}

for (const parent of parentList) {
if (filteredFacetValues.includes(parent)) {
return 'selected'
}
}

// if all children are in the filter, then it should be selected'
if (children && isAllChildrenFiltered(children, filteredFacetValues)) {
return 'selected'
}
// if any of the direct children of the facet is in the filter, then it should be partial-selected
if (children && isAnyChildrenFiltered(children, filteredFacetValues)) {
return 'partial-selected'
}
} else if (facetValuesFilter.type === 'exclude') {
if (!isFiltering) {
return 'selected'
}
// if facet.value is in facetValueFilter, then it should be unselected
if (filteredFacetValues.includes(facetValue)) {
return 'unselected'
}
// if all children are in the filter, then it should be unselected
if (children && isAllChildrenFiltered(children, filteredFacetValues)) {
return 'unselected'
}
// if any of the children of the facet is in the filter, then it should be partial-selected
if (children && isAnyChildrenFiltered(children, filteredFacetValues)) {
return 'partial-selected'
}
return 'selected'
}

return 'unselected'
}
Loading

0 comments on commit 89ceca7

Please sign in to comment.