Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Custom sanitizer for Context Manager #3290

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

nulrich
Copy link
Contributor

@nulrich nulrich commented Jan 17, 2025

Motivation

When using Context Manager in our Public API, we manually call the sanitazition functions at multiple places before setting the context.

setUserProperty: monitor((key, property) => {
  const sanitizedProperty = sanitizeUser({ [key]: property })[key]
  userContextManager.setContextProperty(key, sanitizedProperty)
}),

This could be done automatically by the Context Manager itself and just write

setUserProperty: monitor((key, property) => {
  userContextManager.setContextProperty(key, property)
}),

Changes

Now we can pass the sanization configuration to createContextManager. It will be applied whenever we update the internal context.

const userContextManager = createContextManager('user', {
  customerDataTracker: customerDataTrackerManager.getOrCreateTracker(CustomerDataType.User),
  propertiesConfig: {
    id: { type: 'string' },
    name: { type: 'string' },
    email: { type: 'string' },
  },
})

Also the configuration can also warn the user if a required property is missing:

const userContextManager = createContextManager('test', {
  customerDataTracker: customerDataTrackerManager.getOrCreateTracker(CustomerDataType.User),
  propertiesConfig: { id: { required: true } },
})
manager.setContext({ foo: 'bar' })
// warn: The property id of test context is required; context will not be sent to the intake.

Testing

  • Local
  • Staging
  • Unit
  • End to end

I have gone over the contributing documentation.

@datadog-datadog-prod-us1
Copy link

Datadog Report

Branch report: nicolas.ulrich/context-manager-sanitizer
Commit report: fb395cc
Test service: browser-sdk

❌ 16 Failed (0 Known Flaky), 17071 Passed, 345 Skipped, 1m 38.34s Total Time

❌ Failed Tests (16)

This report shows up to 5 failed tests.

  • report observable should compute stack for intervention - Chrome 63.0.3239.84 (Windows 10) - Details

    Expand for error
     TypeError: Cannot read property 'unsubscribe' of undefined
         at UserContext.afterEach (webpack:///packages/core/src/domain/report/reportObservable.spec.ts:27:25 <- reportObservable.spec.3761986749.js:1311:29)
         at <Jasmine>
    
  • report observable should notify csp_violation - Chrome 63.0.3239.84 (Windows 10) - Details

    Expand for error
     TypeError: Cannot read property 'unsubscribe' of undefined
         at UserContext.afterEach (webpack:///packages/core/src/domain/report/reportObservable.spec.ts:27:25 <- reportObservable.spec.3761986749.js:1311:29)
         at <Jasmine>
    
  • report observable should notify deprecation reports - Chrome 63.0.3239.84 (Windows 10) - Details

    Expand for error
     TypeError: Cannot read property 'unsubscribe' of undefined
         at UserContext.afterEach (webpack:///packages/core/src/domain/report/reportObservable.spec.ts:27:25 <- reportObservable.spec.3761986749.js:1311:29)
         at <Jasmine>
    
  • report observable should notify intervention reports - Chrome 63.0.3239.84 (Windows 10) - Details

    Expand for error
     TypeError: Cannot read property 'unsubscribe' of undefined
         at UserContext.afterEach (webpack:///packages/core/src/domain/report/reportObservable.spec.ts:27:25 <- reportObservable.spec.3761986749.js:1311:29)
         at <Jasmine>
    
  • report observable should compute stack for intervention - Firefox 67.0 (Windows 10) - Details

    Expand for error
     TypeError: consoleSubscription is undefined in reportObservable.spec.3761986749.js (line 1311)
     @webpack:///packages/core/src/domain/report/reportObservable.spec.ts:27:5 <- reportObservable.spec.3761986749.js:1311:9
     <Jasmine>
    

@nulrich nulrich marked this pull request as ready for review January 17, 2025 13:01
@nulrich nulrich requested a review from a team as a code owner January 17, 2025 13:01
@nulrich nulrich changed the title Custom sanitizer for Context Manager ♻️ Custom sanitizer for Context Manager Jan 17, 2025
@codecov-commenter
Copy link

codecov-commenter commented Jan 22, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 93.67%. Comparing base (9fbe626) to head (c354a1c).
Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3290      +/-   ##
==========================================
- Coverage   93.68%   93.67%   -0.02%     
==========================================
  Files         288      288              
  Lines        7617     7619       +2     
  Branches     1739     1743       +4     
==========================================
+ Hits         7136     7137       +1     
- Misses        481      482       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

cit-pr-commenter bot commented Jan 22, 2025

Bundles Sizes Evolution

📦 Bundle Name Base Size Local Size 𝚫 𝚫% Status
Rum 145.66 KiB 146.00 KiB 348 B +0.23%
Logs 51.09 KiB 51.45 KiB 375 B +0.72%
Rum Slim 104.45 KiB 104.79 KiB 345 B +0.32%
Worker 24.50 KiB 24.50 KiB 0 B 0.00%
🚀 CPU Performance
Action Name Base Average Cpu Time (ms) Local Average Cpu Time (ms) 𝚫
addglobalcontext 0.002 0.002 0.000
addaction 0.035 0.042 0.008
addtiming 0.001 0.001 0.000
adderror 0.044 0.049 0.005
startstopsessionreplayrecording 0.007 0.010 0.003
startview 0.462 0.447 -0.015
logmessage 0.020 0.025 0.005
🧠 Memory Performance
Action Name Base Consumption Memory (bytes) Local Consumption Memory (bytes) 𝚫 (bytes)
addglobalcontext 27.57 KiB 27.31 KiB -272 B
addaction 56.55 KiB 55.29 KiB -1287 B
addtiming 25.51 KiB 25.68 KiB 171 B
adderror 59.36 KiB 57.54 KiB -1857 B
startstopsessionreplayrecording 26.77 KiB 25.11 KiB -1695 B
startview 416.06 KiB 422.05 KiB 6.00 KiB
logmessage 63.47 KiB 61.27 KiB -2258 B

🔗 RealWorld

Comment on lines 11 to 36
export type PropertiesConfig = {
[key: string]: {
required?: boolean
type?: 'string'
}
}

function enforceTypeProperties(context: Context, propertiesConfig: PropertiesConfig) {
const newContext = { ...context }
for (const [key, { type }] of Object.entries(propertiesConfig)) {
if (type === 'string' && key in newContext) {
/* eslint-disable @typescript-eslint/no-base-to-string */
newContext[key] = String(newContext[key])
}
}

return newContext
}

function checkRequiredProperties(context: Context, propertiesConfig: PropertiesConfig, name: string) {
for (const [key, { required }] of Object.entries(propertiesConfig)) {
if (required && !(key in context)) {
display.warn(`The property ${key} of ${name} context is required; context will not be sent to the intake.`)
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 suggestion: ‏I think it could be beneficial to include these as part part of the sanitize module.

sanitize(context, {
  ensureProperty: {
    id: ' { type: 'string', required: true },
    name:  { type: 'string' },
    email:  { type: 'string' },
  }
});

Also you could merge enforceTypeProperties and checkRequiredProperties into a single function. This would allow iterating over propertiesConfig only once

function ensureProperties(context, propertiesConfig) {
...
}

Copy link
Contributor Author

@nulrich nulrich Jan 23, 2025

Choose a reason for hiding this comment

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

I merged the functions 👍

Concerning moving the code into sanitize module, I found that the type enforcement and requirement are specific to context management and do not help to sanitize the content.

The type enforcement is more for controlling the content for the intake than preventing illegal data, and property requirement is not really sanitization work.

Also sanitize is checking all properties recursively so we would need to pass the path of properties we want to check and not only supporting the first level.

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.

4 participants