-
Notifications
You must be signed in to change notification settings - Fork 8.1k
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
[EBT] Add Shipper "FullStory" #129927
Conversation
62a51d3
to
41877f9
Compare
6637a0a
to
c411fe8
Compare
c411fe8
to
76786bb
Compare
/** | ||
* 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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this 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
packages/elastic-analytics/src/analytics_client/analytics_client.test.ts
Show resolved
Hide resolved
/** | ||
* 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; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
packages/elastic-analytics/src/shippers/fullstory/format_payload.ts
Outdated
Show resolved
Hide resolved
} | ||
|
||
function isDate(value: unknown): value is Date { | ||
return value instanceof Date || moment.isMoment(value); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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('.'); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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'); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 👍
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', |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
💚 Build SucceededTest Failures
Metrics [docs]Module Count
Public APIs missing comments
Async chunks
Page load bundle
Unknown metric groupsAPI count
async chunk count
ESLint disabled in files
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
second pass - LGTM
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 theoptIn
API with theisOptedIn
value.Checklist
Delete any items that are not applicable to this PR.
For maintainers