-
Notifications
You must be signed in to change notification settings - Fork 4k
[Refactor] Metrics Provider Transition #9729
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
Conversation
cf785db to
7ed2180
Compare
7ed2180 to
1780fac
Compare
**Metrics Migration Part 1**: This PR extends the `host_config` endpoint
to add a `metricsUrl`, which will serve as the destination URL for
metrics data.
`metricsUrl` for `host_config` endpoint will handle 4 options:
* **`"off"`**: Turns off metrics collection
* **`"<url>"`**: Sends metrics events to the passed URL
* _The logic to build/send event with necessary fields will be added in
a separate PR_
* **`"postMessage"`**: Sends metrics events via `postMessage` API
* _This logic will be added in a separate PR_
* **`" "`**: Default (OS) - telemetry destination url will be fetched
Should no url be received from the BE, the FE will attempt to fetch the
telemetry url from `data.streamlit.io/metrics.json`, caching it in
localStorage if successful. If there is no `metricsUrl`, no telemetry is
sent.
**Metrics Migration Part 2:** This PR adds a `MetricsEvent` proto for a single source of truth for event fields, as well as the infrastructure necessary to send event data to the testing Fivetran webhook in parallel with Segment. This includes building the `anonymousId` & `context` data fields for FW that we received by default from Segment.
**Metrics Migration Part 3:** As a follow up to the metrics options in hostConfig endpoint (PR #9611), this PR adds the ability to send metrics events to the host via postMessage API using our existing Host <-> Guest communication.
1780fac to
e2e8415
Compare
a1b7b97 to
3589805
Compare
3589805 to
306af1d
Compare
lukasmasuch
left a comment
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 think the requestDefaultMetricsConfig might need to be awaited. Otherwise, LGTM 👍
| */ | ||
|
|
||
| // Timestamp when the Streamlit execution started for GUEST_READY message | ||
| const streamlitExecutionStartedAt = Date.now() |
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'm a bit on the fence if we should pass this through our app stack as a prop since its a global variable that does not change after initialization. The two alternatives are: 1) Put this variable into the context for this prop, see WindowDimensions as an example
2) Put it into a global window variable, e.g. window.streamlitExecutionStartedAt and read it out when the GUEST_READY message is send.
But this could easily be discussed and implemented as a follow-up after cut off. The way it's implemented right now is fine.
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.
FWIW I also preferred window variable to passing as prop, though Pat & Benny leaned toward prop (discussion here). Now at least votes are tied 😂
frontend/app/src/MetricsManager.ts
Outdated
| public initialize({ | ||
| gatherUsageStats, | ||
| sendMessageToHost, | ||
| }: { | ||
| gatherUsageStats: boolean | ||
| sendMessageToHost: (message: IGuestToHostMessage) => void | ||
| }): void { | ||
| this.initialized = true | ||
| this.sendMessageToHost = sendMessageToHost | ||
| // Handle if the user or the host has disabled metrics | ||
| this.actuallySendMetrics = gatherUsageStats && this.metricsUrl !== "off" | ||
| this.getAnonymousId() | ||
|
|
||
| // Trigger fallback to fetch default metrics config if not provided by host | ||
| if (this.actuallySendMetrics && !this.metricsUrl) { | ||
| this.requestDefaultMetricsConfig() | ||
|
|
||
| // If metricsUrl still undefined, deactivate metrics | ||
| if (!this.metricsUrl) { | ||
| logError("Undefined metrics config - deactivating metrics tracking.") | ||
| this.actuallySendMetrics = false | ||
| } | ||
| } | ||
|
|
||
| if (this.actuallySendMetrics) { | ||
| // Segment will not initialize if this is rendered with SSR | ||
| initializeSegment() | ||
| this.sendPendingEvents() | ||
| } | ||
|
|
||
| logAlways("Gather usage stats: ", this.actuallySendMetrics) | ||
| } |
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 think the initialize needs to be async and await the requestDefaultMetricsConfig method. Otherwise, the metrics gathering might be deactivated because the async function has not yet finished execution. And it would probably be good to move the this.initialized = true to the end, so that it can initialize async and collect pending events at the same time.
public async initialize({
gatherUsageStats,
sendMessageToHost,
}: {
gatherUsageStats: boolean
sendMessageToHost: (message: IGuestToHostMessage) => void
}): Promise<void> {
this.sendMessageToHost = sendMessageToHost
// Handle if the user or the host has disabled metrics
this.actuallySendMetrics = gatherUsageStats && this.metricsUrl !== "off"
this.getAnonymousId()
// Trigger fallback to fetch default metrics config if not provided by host
if (this.actuallySendMetrics && !this.metricsUrl) {
await this.requestDefaultMetricsConfig()
// If metricsUrl still undefined, deactivate metrics
if (!this.metricsUrl) {
logError("Undefined metrics config - deactivating metrics tracking.")
this.actuallySendMetrics = false
}
}
if (this.actuallySendMetrics) {
// Segment will not initialize if this is rendered with SSR
initializeSegment()
this.sendPendingEvents()
}
logAlways("Gather usage stats: ", this.actuallySendMetrics)
this.initialized = true
}Final feature PR to execute the (soft) transition of our metrics provider
Describe your changes
Final feature PR to execute the (soft) transition our metrics provider. We plan to use both systems for one release, allowing us to test/compare/adjust based on metrics at scale through the 1.40 release. We will then remove legacy provider code & switch to the production webhook after validating the new system is working as expected.
This PR consolidates the following logic from PRs into this branch:
SegmentMetricsManager#9610host_configendpoint withmetricsUrlconfiguration #9611GUEST_READYmessage #9702MetricsEventproto & Fivetran infrastructure #9695postMessagemetrics #9704Outside these PRs:
anonymousIds between the two systems by manually setting theanonymousIdfor SegmentanonymousIdwas set in the cookie from localStorage to address an issue in Community Cloud where "%22" was showing up as part of theanonymousIdTesting Plan