11import { pino , Logger } from 'pino' ;
22import { Fetch } from "./types.js" ;
3+ import { Flags } from "./models.js" ;
34
4- const ANALYTICS_ENDPOINT = 'analytics/flags/' ;
5+ export const ANALYTICS_ENDPOINT = './ analytics/flags/' ;
56
6- // Used to control how often we send data(in seconds)
7+ /** Duration in seconds to wait before trying to flush collected data after { @link trackFeature} is called. **/
78const ANALYTICS_TIMER = 10 ;
89
10+ const DEFAULT_REQUEST_TIMEOUT_MS = 3000
11+
12+ export interface AnalyticsProcessorOptions {
13+ /** URL of the Flagsmith analytics events API endpoint
14+ * @example https://flagsmith.example.com/api/v1/analytics
15+ */
16+ analyticsUrl ?: string ;
17+ /** Client-side key of the environment that analytics will be recorded for. **/
18+ environmentKey : string ;
19+ /** Duration in milliseconds to wait for API requests to complete before timing out. Defaults to {@link DEFAULT_REQUEST_TIMEOUT_MS}. **/
20+ requestTimeoutMs ?: number ;
21+ logger ?: Logger ;
22+ /** Custom {@link fetch} implementation to use for API requests. **/
23+ fetch ?: Fetch
24+
25+ /** @deprecated Use {@link analyticsUrl} instead. **/
26+ baseApiUrl ?: string ;
27+ }
28+
29+ /**
30+ * Tracks how often individual features are evaluated whenever {@link trackFeature} is called.
31+ *
32+ * Analytics data is posted after {@link trackFeature} is called and at least {@link ANALYTICS_TIMER} seconds have
33+ * passed since the previous analytics API request was made (if any), or by calling {@link flush}.
34+ *
35+ * Data will stay in memory indefinitely until it can be successfully posted to the API.
36+ * @see https://docs.flagsmith.com/advanced-use/flag-analytics.
37+ */
938export class AnalyticsProcessor {
10- private analyticsEndpoint : string ;
39+ private analyticsUrl : string ;
1140 private environmentKey : string ;
1241 private lastFlushed : number ;
1342 analyticsData : { [ key : string ] : any } ;
14- private requestTimeoutMs : number = 3000 ;
43+ private requestTimeoutMs : number = DEFAULT_REQUEST_TIMEOUT_MS ;
1544 private logger : Logger ;
1645 private currentFlush : ReturnType < typeof fetch > | undefined ;
1746 private customFetch : Fetch ;
1847
19- /**
20- * AnalyticsProcessor is used to track how often individual Flags are evaluated within
21- * the Flagsmith SDK. Docs: https://docs.flagsmith.com/advanced-use/flag-analytics.
22- *
23- * @param data.environmentKey environment key obtained from the Flagsmith UI
24- * @param data.baseApiUrl base api url to override when using self hosted version
25- * @param data.requestTimeoutMs used to tell requests to stop waiting for a response after a
26- given number of milliseconds
27- */
28- constructor ( data : { environmentKey : string ; baseApiUrl : string ; requestTimeoutMs ?: number , logger ?: Logger , fetch ?: Fetch } ) {
29- this . analyticsEndpoint = data . baseApiUrl + ANALYTICS_ENDPOINT ;
48+ constructor ( data : AnalyticsProcessorOptions ) {
49+ this . analyticsUrl = data . analyticsUrl || data . baseApiUrl + ANALYTICS_ENDPOINT ;
3050 this . environmentKey = data . environmentKey ;
3151 this . lastFlushed = Date . now ( ) ;
3252 this . analyticsData = { } ;
@@ -35,15 +55,15 @@ export class AnalyticsProcessor {
3555 this . customFetch = data . fetch ?? fetch ;
3656 }
3757 /**
38- * Sends all the collected data to the api asynchronously and resets the timer
58+ * Try to flush pending collected data to the Flagsmith analytics API.
3959 */
4060 async flush ( ) {
4161 if ( this . currentFlush || ! Object . keys ( this . analyticsData ) . length ) {
4262 return ;
4363 }
4464
4565 try {
46- this . currentFlush = this . customFetch ( this . analyticsEndpoint , {
66+ this . currentFlush = this . customFetch ( this . analyticsUrl , {
4767 method : 'POST' ,
4868 body : JSON . stringify ( this . analyticsData ) ,
4969 signal : AbortSignal . timeout ( this . requestTimeoutMs ) ,
@@ -66,6 +86,11 @@ export class AnalyticsProcessor {
6686 this . lastFlushed = Date . now ( ) ;
6787 }
6888
89+ /**
90+ * Track a single evaluation event for a feature.
91+ *
92+ * This method is called whenever {@link Flags.isFeatureEnabled}, {@link Flags.getFeatureValue} or {@link Flags.getFlag} are called.
93+ */
6994 trackFeature ( featureName : string ) {
7095 this . analyticsData [ featureName ] = ( this . analyticsData [ featureName ] || 0 ) + 1 ;
7196 if ( Date . now ( ) - this . lastFlushed > ANALYTICS_TIMER * 1000 ) {
0 commit comments