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

[EBT] Add Shipper "FullStory" #129927

Merged
merged 9 commits into from
Apr 13, 2022
Merged

Conversation

afharo
Copy link
Member

@afharo afharo commented Apr 11, 2022

Summary

Resolves #125692.

It moves the FullStory implementation from the cloud plugin to the @elastic/analytics package.

It also changes the way the cloud plugin sets the context of the events. We'll move some of them to where they actually belong in #125690.

It also adds the logic in the telemetry/public to call the optIn API with the isOptedIn value.

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@afharo afharo added release_note:skip Skip the PR/issue when compiling release notes backport:skip This commit does not require backporting v8.3.0 labels Apr 11, 2022
@afharo afharo requested a review from a team as a code owner April 11, 2022 17:57
@afharo afharo force-pushed the ebt/add-fullstory-shipper branch 2 times, most recently from 6637a0a to c411fe8 Compare April 11, 2022 18:44
Comment on lines 32 to 46
/**
* The current page.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
page?: string;
/**
* The current application ID.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
app_id?: string;
/**
* The current entity ID.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
ent_id?: string;
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we define a good set of names for these fields and add a backwards-compatible layer in the FullStory shipper?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd say so, yes. shipper-specific mappings aren't an issue, but I'd put that in the shipper implementation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated types to full names and shipper to maintain bwc

return res.ok({ body: stats.slice(-takeNumberOfCounters) });
return res.ok({
body: stats
.filter((counter) => counter.event_type === eventType)
Copy link
Member Author

Choose a reason for hiding this comment

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

I had to add this filter to this FTR plugin because new events may affect the tests otherwise.

context$: from(loadUserId({ getCurrentUser: security.authc.getCurrentUser })).pipe(
filter((userId): userId is string => Boolean(userId)),
exhaustMap(async (userId) => {
const { sha256 } = await import('js-sha256');
Copy link
Member Author

Choose a reason for hiding this comment

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

Import the hashing library only if we got a userId.

Copy link
Member

Choose a reason for hiding this comment

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

We can use the browser native digest function here:
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest

Though it only works on https which might be an OK tradeoff?

Alternatively, wouldn't t be better to send a request to a custom route on the kibana server to get this in a GET/POST request instead of loading an external library?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point! I created #130147 to look for alternatives. I'll keep it for now because we already had this dependency before.

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

Overall LGTM. A few remarks and questions

Comment on lines 32 to 46
/**
* The current page.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
page?: string;
/**
* The current application ID.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
app_id?: string;
/**
* The current entity ID.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
ent_id?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd say so, yes. shipper-specific mappings aren't an issue, but I'd put that in the shipper implementation.

* The current page.
* @remarks We need to keep this for backwards compatibility because it was provided by previous implementations of FullStory.
*/
page?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Outside of the scope of this PR, but this makes me wonder: for the v3 telemetry shipper, will we have a specific field to dissociate events sent from the client and from the server?

Copy link
Member Author

@afharo afharo Apr 12, 2022

Choose a reason for hiding this comment

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

That's a good question! I haven't thought about it. If we want to, we can define different channel names when shipping the data to V3. I'll ask the Platform Analytics team in our next meeting today.

}

function isDate(value: unknown): value is Date {
return value instanceof Date || moment.isMoment(value);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit scary to know that we may have moment instances used for dates instead of plain Dates or timestamp. Do we really want to support that?

Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove this. Technically, anything is possible. We are accepting unknown. And nothing is really stopping folks from setting a field to a moment instance. But let's remove it for now 👍

* Side Public License, v 1.
*/

import type { FullStoryApi } from './types';
Copy link
Contributor

Choose a reason for hiding this comment

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

Naming convention: fullstory_shipper.test.mocks.ts

version_minor_int: number;
version_patch_int: number;
} {
const [major, minor, patch] = version.split('.');
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional: Could use Semver.parse

Copy link
Member Author

Choose a reason for hiding this comment

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

yes! I thought so: but I wanted to avoid the additional dependency. Bear in mind that this shipper runs on the UI.

}

// Keep this import async so that we do not load any FullStory code into the browser when it is disabled.
const { FullStoryShipper } = await import('@elastic/analytics');
Copy link
Contributor

Choose a reason for hiding this comment

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

Given we know that the @elastic/analytics will at least always be imported by core, should we move it to the shared libs?

Copy link
Member Author

@afharo afharo Apr 12, 2022

Choose a reason for hiding this comment

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

I can create a follow-up PR to test what's the gain in bundle size 👍

#130027

Comment on lines 325 to 332
const executionContext = await executionContextPromise;
analytics.registerContextProvider({
name: 'execution_context',
context$: executionContext.context$.pipe(
// Update the current context every time it changes
map(({ name, page, id }) => ({
pageName: `${compact([name, page]).join(':')}`,
app_id: name ?? 'unknown',
Copy link
Contributor

Choose a reason for hiding this comment

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

If it make sense to have the cloud plugin register the orgId/userId providers, I wonder if that's the best owner for the EC and version providers?

Copy link
Member Author

Choose a reason for hiding this comment

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

I totally agree! I just used this PR to "convert" the FS calls to the new analytics client's API. The plan is to use #125690 to move them where they actually belong :)

@@ -36,6 +36,7 @@ NPM_MODULE_EXTRA_FILES = [
# "@npm//name-of-package"
# eg. "@npm//lodash"
RUNTIME_DEPS = [
"@npm//moment",
Copy link
Member

Choose a reason for hiding this comment

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

+1 for removing moment from the package and using plain old unix timestamps or Date objects

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 need moment to validate the ISO string. We could replace it with a regex, but I worry we might leave out some formats depending on the TZ.

@kibana-ci
Copy link
Collaborator

kibana-ci commented Apr 13, 2022

💚 Build Succeeded

Test Failures

  • [job] [logs] Jest Tests #4 / useActiveCursor should trigger cursor pointer update (chart type: datatable - time based, event type: time)

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
cloud 19 32 +13
core 346 352 +6
total +19

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@elastic/analytics 11 23 +12

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cloud 15.1KB 26.5KB +11.5KB
core 132.3KB 132.3KB +29.0B
total +11.5KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
cloud 8.8KB 10.0KB +1.2KB
core 320.0KB 324.7KB +4.7KB
telemetry 27.6KB 27.7KB +150.0B
total +6.1KB
Unknown metric groups

API count

id before after diff
@elastic/analytics 82 106 +24
core 2499 2511 +12
total +36

async chunk count

id before after diff
cloud 2 3 +1

ESLint disabled in files

id before after diff
@elastic/analytics 0 1 +1
cloud 2 1 -1
total -0

ESLint disabled line counts

id before after diff
cloud 7 6 -1

Total ESLint disabled count

id before after diff
@elastic/analytics 16 17 +1
cloud 9 7 -2
total -1

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Contributor

@pgayvallet pgayvallet left a comment

Choose a reason for hiding this comment

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

second pass - LGTM

@afharo afharo merged commit bed793a into elastic:main Apr 13, 2022
@afharo afharo deleted the ebt/add-fullstory-shipper branch April 13, 2022 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:skip Skip the PR/issue when compiling release notes v8.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[EBT][UI] Fullstory shipper
4 participants