Skip to content

feat(session-replay): add configurable font-family transform#1016

Open
nottmey wants to merge 1 commit intoDataDog:developfrom
nottmey:feat/smart-font-family-handling
Open

feat(session-replay): add configurable font-family transform#1016
nottmey wants to merge 1 commit intoDataDog:developfrom
nottmey:feat/smart-font-family-handling

Conversation

@nottmey
Copy link
Copy Markdown

@nottmey nottmey commented Apr 30, 2026

What and why?

Add FontFamilyStrategy and FontFamilyTransformConfig to rewrite text wireframe font families in the processor isolate. Smart mode normalizes Flutter-specific names for web replay; default strategy is none to preserve prior behavior.

How?

Review checklist

  • This pull request has appropriate unit and / or integration tests
  • This pull request references a Github or JIRA issue

Add FontFamilyStrategy and FontFamilyTransformConfig to rewrite text
wireframe font families in the processor isolate. Smart mode normalizes
Flutter-specific names for web replay; default strategy is none to
preserve prior behavior. Document in CHANGELOG.

Made-with: Cursor
@nottmey nottmey requested a review from a team as a code owner April 30, 2026 10:44
@nottmey nottmey changed the title feat(session_replay): add configurable font-family transform feat(session-replay): add configurable font-family transform Apr 30, 2026
Copy link
Copy Markdown
Member

@fuzzybinary fuzzybinary left a comment

Choose a reason for hiding this comment

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

Minor suggestions if you want to take care of them.

I'm going to actually ask @gonzalezreal to review as I think he has familiarity with how iOS handles this and will be able to give me more insight on whether or not we need separate iOS / Android fallback values.

Comment on lines +84 to +90
if (lower == 'blinkmacsystemfont') {
return 'BlinkMacSystemFont';
}
if (lower == '-apple-system') {
return '-apple-system';
}
return lower;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: You could use pattern matching for this:

return switch (lower) {
  'blinkmacsystemfont' => 'BlinkMacSystemFont',
  '-apple-system' => '-apple-system',
  _ => lower,
};

which I find very slightly cleaner.

Comment on lines +130 to +131
case FontFamilyStrategy.fallback:
return kIosParityFontStack;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this only needed on iOS? Is there an Android fallback we should be using as well?

}
}

SRTextWireframe rewrite(SRTextWireframe wireframe) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it makes sense for this method to be called apply and to potentially change the name of the String transform method. I can see a situation where we might need multiple of these Transforms in the future, and having them all implement a method called apply makes sense to me, whereas rewrite doesn't quite seem like the right term for generalized application of a transform.

I'll leave it to your discretion if you want to change it though.

Comment on lines +187 to +189
if (stripped.isEmpty) {
continue;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be above the check in _flutterFontSentinels?


import 'dart:isolate';

import '../../datadog_session_replay.dart';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be below the package imports... I'm surprised the linter didn't complain about that....

import 'dart:async';
import 'dart:convert';

import '../../datadog_session_replay.dart';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here, this should move down to be with the other relative imports.

Comment on lines +52 to +53
/// wireframes in a background isolate, which cannot serialize Dart closures—use
/// [FontFamilyTransformConfig.rules] instead.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// wireframes in a background isolate, which cannot serialize Dart closures—use
/// [FontFamilyTransformConfig.rules] instead.
/// wireframes in a background isolate, which cannot serialize Dart closures
/// use [FontFamilyTransformConfig.rules] instead.

Comment on lines +66 to +71
/// Always emits the single hardcoded CSS stack
/// `-apple-system, BlinkMacSystemFont, Roboto, sans-serif`,
/// regardless of the captured family. Matches the current iOS SDK
/// behavior and is the safest choice if you do not want any
/// Flutter font names leaving the device.
fallback,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does it make sense to check the current Platform and supply an Android fallback as well?

Comment on lines +3 to +6
## Unreleased

* Add `DatadogSessionReplayConfiguration.fontFamilyTransform` (`FontFamilyStrategy` / `FontFamilyTransformConfig`) so captured font families can be rewritten to web-compatible CSS stacks in the processor isolate before upload (default `FontFamilyStrategy.none` for backwards compatibility; opt into `FontFamilyStrategy.smart` for normalization). In smart mode, `FontFamilyTransformConfig.rules['']` sets the stack when the captured family is empty or ends up empty after sentinel stripping.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We pull CHANGELOG items from the commit message now. I can add in the extra details during the release.

@fuzzybinary
Copy link
Copy Markdown
Member

If you want, we could actually setup a golden test for this as well. Since goldens can only render one specific font, you could take any of the tests that render text and setup the transformer to make the switch.

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.

3 participants