Skip to content

feat: collect-and-flush-analytics-evaluation-events#377

Open
Zaimwa9 wants to merge 17 commits intomainfrom
feat/send-evaluation-data-to-analytics-pipeline
Open

feat: collect-and-flush-analytics-evaluation-events#377
Zaimwa9 wants to merge 17 commits intomainfrom
feat/send-evaluation-data-to-analytics-pipeline

Conversation

@Zaimwa9
Copy link
Contributor

@Zaimwa9 Zaimwa9 commented Mar 3, 2026

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to 6636

  • Add evaluation analytics pipeline integration: buffer individual flag evaluation events and flush them to a configurable pipeline endpoint (evaluationAnalyticsConfig)
  • Record event data per evaluation, as of now: flag key, value, enabled state, identity, traits at evaluation time, and timestamp
  • Re-queue events on flush failure with buffer cap

Usage

// JS
flagsmith.init({
      environmentID: 'your_environment_key',
      evaluationAnalyticsConfig: {
          analyticsServerUrl: 'https://analytics.flagsmith.com/',
          maxBuffer: 500,
          flushInterval: 5000,
      },
  });
  
  // React
    <FlagsmithProvider
    flagsmith={flagsmith}
    options={{
      environmentID: 'your_environment_key',
      evaluationAnalyticsConfig: {
        analyticsServerUrl: 'https://analytics.flagsmith.com/',
      },
    }}
  >
    {children}
  </FlagsmithProvider>

Bonus

  • Added the pull request template

Improvements for V2

  • Retry with exponential backoff: currently re-queues on failure but retries at the same interval
  • Flush on session end use visibilitychange / beforeunload + navigator.sendBeacon() to flush buffered events before tab close (the size of the payload might be too heavy versus the simple count of previous analytics to be stored in localStorage)
  • Persist unflushed events: persist buffer to so events survive page refreshes
  • Extract PipelineAnalytics class: isolate analytics logic (buffer, flush, intervals) from the core to gain in flexibility without sacrificing maintainability
  • destroy() method (cf openFeature): proper teardown to prevent memory leaks in SSR/Next.js (pre-existing gap in all interval-based feature in SDK atm)

How did you test this code?

  • Added dedicated tests

@Zaimwa9 Zaimwa9 requested a review from a team as a code owner March 3, 2026 08:13
@Zaimwa9 Zaimwa9 requested review from talissoncosta and removed request for a team March 3, 2026 08:13
Comment on lines +79 to +82
if (url.includes('v1/analytics/batch')) {
return {status: 202, text: () => Promise.resolve('')}
}
if (url.includes('analytics/flags')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that 'v1/analytics/batch' and 'analytics/flags' appear multiple times. Would be better to add it as const ?

Not blocking, just a suggestion

talissoncosta
talissoncosta previously approved these changes Mar 5, 2026
Copy link
Contributor

@talissoncosta talissoncosta left a comment

Choose a reason for hiding this comment

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

Great work @Zaimwa9

expect(valueEvent.event_type).toBe('flag_evaluation');
expect(valueEvent.value).toBe(16);
expect(valueEvent.enabled).toBe(true);
expect(valueEvent.identity_identifier).toBe('');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is temporary to allow testing without redeploying the rust service. Will be reverted to null once made optional there

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