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

[FullStory] Limit number of pageVars #159725

Merged
merged 2 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ describe('FullStoryShipper', () => {
expect(fullStoryApiMock.setVars).toHaveBeenCalledWith('page', {
// eslint-disable-next-line @typescript-eslint/naming-convention
cloudId_str: 'test-es-org-id',
org_id_str: 'test-es-org-id',
});
});

Expand All @@ -94,19 +93,19 @@ describe('FullStoryShipper', () => {
expect(fullStoryApiMock.setVars).toHaveBeenCalledWith('page', {
// eslint-disable-next-line @typescript-eslint/naming-convention
cloudId_str: 'test-es-org-id',
org_id_str: 'test-es-org-id',
version_str: '1.2.3',
version_major_int: 1,
version_minor_int: 2,
version_patch_int: 3,
});
});

test('adds the rest of the context to `setVars`', () => {
test('adds the rest of the context to `setVars` (only if they match one of the valid keys)', () => {
const context = {
userId: 'test-user-id',
version: '1.2.3',
cloudId: 'test-es-org-id',
labels: { serverless: 'test' },
foo: 'bar',
};
fullstoryShipper.extendContext(context);
Expand All @@ -117,8 +116,7 @@ describe('FullStoryShipper', () => {
version_patch_int: 3,
// eslint-disable-next-line @typescript-eslint/naming-convention
cloudId_str: 'test-es-org-id',
org_id_str: 'test-es-org-id',
foo_str: 'bar',
labels: { serverless_str: 'test' },
});
});
});
Expand Down
82 changes: 61 additions & 21 deletions packages/analytics/shippers/fullstory/src/fullstory_shipper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,39 @@ import type {
Event,
IShipper,
} from '@kbn/analytics-client';
import { get, has } from 'lodash';
import { set } from '@kbn/safer-lodash-set';
import type { FullStoryApi } from './types';
import type { FullStorySnippetConfig } from './load_snippet';
import { formatPayload } from './format_payload';
import { loadSnippet } from './load_snippet';
import { getParsedVersion } from './get_parsed_version';

const PAGE_VARS_KEYS = [
// Page-specific keys
'pageName',
'page',
'entityId',
'applicationId',

// Deployment-specific keys
'version', // x4, split to version_major, version_minor, version_patch for easier filtering
'buildNum', // May be useful for Serverless
'cloudId',
'deploymentId',
'cluster_name',
'cluster_uuid',
'cluster_version',
'labels.serverless',
'license_id',
'license_status',
'license_type',

// Session-specific
'session_id',
'preferred_languages',
] as const;

/**
* FullStory shipper configuration.
*/
Expand Down Expand Up @@ -62,7 +89,13 @@ export class FullStoryShipper implements IShipper {
this.initContext.logger.debug(`Received context ${JSON.stringify(newContext)}`);

// FullStory requires different APIs for different type of contexts.
const { userId, isElasticCloudUser, ...nonUserContext } = newContext;
const {
userId,
isElasticCloudUser,
cloudIsElasticStaffOwned,
cloudTrialEndDate,
...nonUserContext
} = newContext;

// Call it only when the userId changes
if (userId && userId !== this.lastUserId) {
Expand All @@ -73,30 +106,37 @@ export class FullStoryShipper implements IShipper {
}

// User-level context
if (typeof isElasticCloudUser === 'boolean') {
this.initContext.logger.debug(
`Calling FS.setUserVars with isElasticCloudUser ${isElasticCloudUser}`
);
this.fullStoryApi.setUserVars(
formatPayload({
isElasticCloudUser,
})
);
if (
typeof isElasticCloudUser === 'boolean' ||
typeof cloudIsElasticStaffOwned === 'boolean' ||
cloudTrialEndDate
) {
Comment on lines +109 to +113
Copy link
Member Author

Choose a reason for hiding this comment

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

we promoted cloudIsElasticStaffOwned and cloudTrialEndDate to the user level because they are account-related.

const userVars = {
isElasticCloudUser,
cloudIsElasticStaffOwned,
cloudTrialEndDate,
};
this.initContext.logger.debug(`Calling FS.setUserVars with ${JSON.stringify(userVars)}`);
this.fullStoryApi.setUserVars(formatPayload(userVars));
}

// Cherry-picking fields because FS limits the number of fields that can be sent.
// > Note: You can capture up to 20 unique page properties (exclusive of pageName) for any given page
// > and up to 500 unique page properties across all pages.
// https://help.fullstory.com/hc/en-us/articles/1500004101581-FS-setVars-API-Sending-custom-page-data-to-FullStory
const pageVars = PAGE_VARS_KEYS.reduce((acc, key) => {
if (has(nonUserContext, key)) {
set(acc, key, get(nonUserContext, key));
}
return acc;
}, {} as Partial<Pick<EventContext, typeof PAGE_VARS_KEYS[number]>> & Record<string, unknown>);

// Event-level context. At the moment, only the scope `page` is supported by FullStory for webapps.
if (Object.keys(nonUserContext).length) {
// Keeping these fields for backwards compatibility.
if (nonUserContext.applicationId) nonUserContext.app_id = nonUserContext.applicationId;
if (nonUserContext.entityId) nonUserContext.ent_id = nonUserContext.entityId;
if (nonUserContext.cloudId) nonUserContext.org_id = nonUserContext.cloudId;
Comment on lines -89 to -92
Copy link
Member Author

Choose a reason for hiding this comment

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

Since we are mostly interested in trial users, most reports don't care about BWC.
Also, we've had these for a few minors, so there should be enough overlap of both to compare with previous versions.


this.initContext.logger.debug(
`Calling FS.setVars with context ${JSON.stringify(nonUserContext)}`
);
if (Object.keys(pageVars).length) {
this.initContext.logger.debug(`Calling FS.setVars with context ${JSON.stringify(pageVars)}`);
this.fullStoryApi.setVars('page', {
...formatPayload(nonUserContext),
...(nonUserContext.version ? getParsedVersion(nonUserContext.version) : {}),
...formatPayload(pageVars),
...(pageVars.version ? getParsedVersion(pageVars.version) : {}),
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/analytics/shippers/fullstory/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
],
"kbn_references": [
"@kbn/analytics-client",
"@kbn/logging-mocks"
"@kbn/logging-mocks",
"@kbn/safer-lodash-set"
],
"exclude": [
"target/**/*",
Expand Down