Skip to content

[Profiling] Add action and vital metadata to profiles#4148

Open
MandragoreVR wants to merge 4 commits intomainfrom
teo.chaillou/RUM-14305-browser-add-action-and-vital-metadata-to-profiles
Open

[Profiling] Add action and vital metadata to profiles#4148
MandragoreVR wants to merge 4 commits intomainfrom
teo.chaillou/RUM-14305-browser-add-action-and-vital-metadata-to-profiles

Conversation

@MandragoreVR
Copy link
Collaborator

@MandragoreVR MandragoreVR commented Feb 6, 2026

Motivation

To enable profiling aggregation on the backend for vitals and actions, we want to add vitals and actions data to the metadata of profiling events.

This PR adds these entries to the profiling events metadata.

Changes

  • Create a vitalHistory next to the profiler that catches vital events from the life cycle and stores them in the history
    • Vital events are currently only sent in the lifecycle when they end. However, one vital event might span over multiple profiles, so the profile where this vital event starts must be tagged with this vital event too.
      • This PR defines the id of duration vitals when they start instead of when they end, and adds a new lifecycle event to broadcast vitals when they start
      • Note: this will not cause issues if the vital doesn't end, because this is only used to tag profile events, so in the worst case, the id of this vital will not be used
  • Same thing for the actions: creation of an actionHistory
    • the id of the action was created on action start, but not returned by the event tracker, so I changed that to make the start method of the event tracker return the stored data
  • Update the build of a profile's attributes to add actions and vitals
    • update profiler's tests to make sure vitals and actions are collected

Test instructions

  • In the file sandbox/react-app/main.tsx, add:
profilingSampleRate: 100,
  site: 'datadoghq.com',
  service: 'sandbox-react-app',
  env: 'development',
  beforeSend: () => false,

to the SDK configuration, and add

  useEffect(() => {
    datadogRum.startDurationVital('test vital')

    const timeout = setTimeout(() => {
      datadogRum.stopDurationVital('test vital')
    }, 1000)

    return () => {
      clearTimeout(timeout)
    }
  }, [])

before the return of the Layout function to have a vital that will be displayed in the collected ones.

  • Run yarn dev and go to localhost:8080/react-app
  • Wait for a request to https://browser-intake-datadoghq.com/api/v2/profile in the network tab (profiles usually last one minute, so this might not come instantly, but you can also edit the constant collectIntervalMs in profiler.ts to make it faster)
  • Look at the payload, that contains two big objects.
    • The first one should contain the fields "action" and "vital", both with an object of the shape { "id": string[], "label": string[] }
    • The second one should contain the fields "action" and "vitals" with the following shape:
image

Checklist

  • Tested locally
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated documentation and/or relevant AGENTS.md file

@MandragoreVR MandragoreVR self-assigned this Feb 6, 2026
@github-actions
Copy link

github-actions bot commented Feb 6, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@cit-pr-commenter-54b7da
Copy link

cit-pr-commenter-54b7da bot commented Feb 6, 2026

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 171.96 KiB 172.07 KiB +110 B +0.06%
Rum Profiler 4.67 KiB 6.17 KiB +1.51 KiB +32.31%
Rum Recorder 24.72 KiB 24.72 KiB 0 B 0.00%
Logs 56.29 KiB 56.29 KiB 0 B 0.00%
Flagging 944 B 944 B 0 B 0.00%
Rum Slim 127.73 KiB 127.84 KiB +112 B +0.09%
Worker 23.63 KiB 23.63 KiB 0 B 0.00%
🚀 CPU Performance
Action Name Base CPU Time (ms) Local CPU Time (ms) 𝚫%
addglobalcontext N/A 0.0042 N/A
addaction N/A 0.0139 N/A
adderror N/A 0.0145 N/A
addtiming N/A 0.0031 N/A
startview N/A 0.0137 N/A
startstopsessionreplayrecording N/A 0.0007 N/A
logmessage N/A 0.016 N/A
🧠 Memory Performance
Action Name Base Memory Consumption Local Memory Consumption 𝚫
addglobalcontext N/A 26.89 KiB N/A
addaction N/A 114.28 KiB N/A
addtiming N/A 26.36 KiB N/A
adderror N/A 119.17 KiB N/A
startstopsessionreplayrecording N/A 26.17 KiB N/A
startview N/A 506.82 KiB N/A
logmessage N/A 46.13 KiB N/A

🔗 RealWorld

@MandragoreVR MandragoreVR force-pushed the teo.chaillou/RUM-14305-browser-add-action-and-vital-metadata-to-profiles branch 2 times, most recently from 59aa5b7 to f709051 Compare February 12, 2026 13:32
@MandragoreVR MandragoreVR marked this pull request as ready for review February 12, 2026 13:33
@MandragoreVR MandragoreVR requested a review from a team as a code owner February 12, 2026 13:33
@datadog-official
Copy link

datadog-official bot commented Feb 12, 2026

⚠️ Tests

Fix all issues with BitsAI or with Cursor

⚠️ Warnings

🧪 3 Tests failed

profiling › send profile events when profiling is enabled › async from profiling.scenario.ts (Datadog) (Fix with Cursor)
profiling.scenario.ts:10:13 async

[chromium] › profiling.scenario.ts:10:13 › profiling › send profile events when profiling is enabled › async 

    Error: expect(received).toEqual(expected) // deep equality

    - Expected  - 0
    + Received  + 2

    @@ -1,6 +1,7 @@
...
profiling › send profile events when profiling is enabled › bundle from profiling.scenario.ts (Datadog) (Fix with Cursor)
profiling.scenario.ts:10:13 bundle

[chromium] › profiling.scenario.ts:10:13 › profiling › send profile events when profiling is enabled › bundle 

    Error: expect(received).toEqual(expected) // deep equality

    - Expected  - 0
    + Received  + 2

    @@ -1,6 +1,7 @@
...
profiling › send profile events when profiling is enabled › npm from profiling.scenario.ts (Datadog) (Fix with Cursor)
profiling.scenario.ts:10:13 npm

[chromium] › profiling.scenario.ts:10:13 › profiling › send profile events when profiling is enabled › npm 

    Error: expect(received).toEqual(expected) // deep equality

    - Expected  - 0
    + Received  + 2

    @@ -1,6 +1,7 @@
...

ℹ️ Info

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 87.88%
Overall Coverage: 77.21% (+0.08%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 84bcf8d | Docs | Datadog PR Page | Was this helpful? Give us feedback!

@MandragoreVR MandragoreVR marked this pull request as draft February 17, 2026 15:51
@MandragoreVR MandragoreVR force-pushed the teo.chaillou/RUM-14305-browser-add-action-and-vital-metadata-to-profiles branch from f709051 to 2d17fef Compare February 17, 2026 22:25
@MandragoreVR MandragoreVR force-pushed the teo.chaillou/RUM-14305-browser-add-action-and-vital-metadata-to-profiles branch from 5059362 to ac62ddd Compare February 18, 2026 17:14
@MandragoreVR MandragoreVR marked this pull request as ready for review February 18, 2026 17:28
Copy link
Collaborator

@thomasbertet thomasbertet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

I believe we could have a more generic history combining all of the profiler's tracked events in one place, it would be slightly less code.

{
id: vitalStart.id,
startClocks: vitalStart.startClocks,
duration: 0 as Duration,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should have another value for "non-stopped" events 🤔
Relying on 0 seems like it could be error prone and the BE that process should be aware 0 means "not stopped".
Maybe just undefined would work instead ? WDYT ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question... could we maybe settle for something like -1, though, to not have to re-do a rum-events-format PR to allow undefined here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but we will need to adjust the logic, I kinda forgot about this when I did the BE logic : https://github.com/DataDog/profiling-backend/pull/7969/changes#diff-fe24f465d52fe19d3a52bfd86ac3eaa5e441e710eca6bb9c26a14cac5ce169e4R339-R346

You can see I'm just using the duration field without taking into account if the duration is 0 or undefined.
Let's have -1 as signal for unfinished events. I'll prepare the BE to support that value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually maybe that's cleaner if that's undefined, even if we have to do another PR for the format, WDYT ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me, I just updated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments