Skip to content

Commit

Permalink
[FullStory] Limit number of pageVars (#159725)
Browse files Browse the repository at this point in the history
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
afharo and kibanamachine authored Jun 15, 2023
1 parent 3f55d18 commit a13ac77
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 27 deletions.
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
) {
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;

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

0 comments on commit a13ac77

Please sign in to comment.