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

Signals sampling #1166

Merged
merged 23 commits into from
Oct 29, 2024
Merged

Signals sampling #1166

merged 23 commits into from
Oct 29, 2024

Conversation

danieljackins
Copy link
Contributor

  • I've included a changeset (psst. run yarn changeset. Read about changesets here).

Copy link

changeset-bot bot commented Oct 8, 2024

🦋 Changeset detected

Latest commit: b8c6586

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@segment/analytics-next Minor
@segment/analytics-signals Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@danieljackins
Copy link
Contributor Author

@silesky does this method of cancelling signals make sense? Should the plugin be deregistered too?

@@ -83,6 +83,12 @@ export class Signals implements ISignals {
* - Registers custom signal generators.
*/
async start(analytics: AnyAnalytics): Promise<void> {
if (
Copy link
Contributor

@silesky silesky Oct 8, 2024

Choose a reason for hiding this comment

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

Nit: This stuff would be better suited toAnalyticsService. i.e. have an analyticsService.signalsDisabled() ?

The analyticsService class is a mean to be a facade to abstract away cdnSettings or analytics instance related logic, exposing that to our domain -- for testing, and to keep this initialization stuff tidier.

if (
!analytics.settings.cdnSettings.autoInstrumentationSettings ||
Math.random() >
analytics.settings.cdnSettings.autoInstrumentationSettings.sampleRate
Copy link
Contributor

Choose a reason for hiding this comment

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

Hey, I don't understand this Math.random() thing, maybe you could explain? I assumed we would just do:
analytics.settings.cdnSettings.autoInstrumentationSettings.sampleRate === 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a sample rate from [0,1] that we "roll against" to see if we should send signals or not (not just a boolean in the settings)

Copy link
Contributor

@silesky silesky Oct 8, 2024

Choose a reason for hiding this comment

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

  • If the sample rate is 0, we just want to stop from sending signals to Segment, right? We don't want to stop processing them. This early return will abort the entire signals initialization, so we don't send signals but we also won't process (create events) from them.
  • The disabling of Signals completely (i.e. analytics.settings.cdnSettings.autoInstrumentationSetting) should probably not be in scope? Seems like a seperate scenario potentially?

* A sample rate to determine what percentage of sessions should send signals, from [0,1]
*/
sampleRate: number
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We'd need a changeset for both signals and analytics =)

@silesky
Copy link
Contributor

silesky commented Oct 8, 2024

@danieljackins can we have a test / maybe an integration test for this?

this.setSignalIngestion(initialValue)
}

// setting ?segment_signals_debug=true will disable redaction, and set a key in local storage
Copy link
Contributor

Choose a reason for hiding this comment

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

Can probably delete this comment?

// this setting will persist across page loads (even if there is no query string)
// in order to clear the setting, user must set ?segment_signals_debug=false
const debugModeInQs = parseDebugModeQueryString()
logger.debug('debugMode is set to true via query string')
Copy link
Contributor

Choose a reason for hiding this comment

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

don't need need to log this twice ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah sorry I'm going to refactor the whole debug part still

constructor(settings: SignalsIngestSettingsConfig) {
this.flushAt = settings.flushAt ?? 5
this.apiHost = settings.apiHost ?? 'signals.segment.io/v1'
this.flushInterval = settings.flushInterval ?? 2000
this.shouldDisableSignalRedaction =
settings.shouldDisableSignalRedaction ?? (() => false)
this.signalIngestion = settings.signalIngestion ?? (() => false)
this.sampleRate = settings.sampleRate ?? 0
Copy link
Contributor

@silesky silesky Oct 10, 2024

Choose a reason for hiding this comment

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

Hey, I don't think we want to expose sampleRate publicly, as it's strictly an implementation detail -- IMO, you shouldn't be able to customize the sample rate as a setting. Can we abstract this way completely as part of this.signalsIngestion? the sampleRate should be used to completely disable signals ingestion for a current user -- so it's basically about whether or not to send signals at all for a given session -- not something we recalculate everytime a new event comes through.

@@ -69,10 +75,25 @@ export class SignalsIngestClient {
return analytics
}

private shouldIngestSignals(): boolean {
Copy link
Contributor

@silesky silesky Oct 10, 2024

Choose a reason for hiding this comment

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

I don't think we don't want to calculate this on a per event basis -- see comment above.

@seg-atlantis-prod
Copy link

Plan Error

running git merge -q --no-ff -m atlantis-merge FETCH_HEAD: Auto-merging packages/signals/signals-integration-tests/src/helpers/base-page-object.ts
CONFLICT (content): Merge conflict in packages/signals/signals-integration-tests/src/helpers/base-page-object.ts
Auto-merging packages/signals/signals/src/core/client/__tests__/client.test.ts
Auto-merging packages/signals/signals/src/core/client/index.ts
Automatic merge failed; fix conflicts and then commit the result.
: exit status 1

@@ -79,58 +93,80 @@ export class SignalGlobalSettings {
* Add new URLs to the disallow list
*/
disallowListURLs: (string | undefined)[]
/**
* Sample rate to determine sending signals
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this | undefined / optional, so update can be used atomically (one day?)

])

await waitForCondition(
() => indexPage.signalsAPI.getEvents('interaction').length > 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is and everything below it is needed -- as long as signals api has flushed, test is good!

@danieljackins danieljackins merged commit 9e6db28 into master Oct 29, 2024
7 checks passed
@danieljackins danieljackins deleted the signals-sampling branch October 29, 2024 16:39
@github-actions github-actions bot mentioned this pull request Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants