1
1
import { pino , Logger } from 'pino' ;
2
2
import { Fetch } from "./types.js" ;
3
+ import { Flags } from "./models.js" ;
3
4
4
- const ANALYTICS_ENDPOINT = 'analytics/flags/' ;
5
+ export const ANALYTICS_ENDPOINT = './ analytics/flags/' ;
5
6
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. **/
7
8
const ANALYTICS_TIMER = 10 ;
8
9
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
+ */
9
38
export class AnalyticsProcessor {
10
- private analyticsEndpoint : string ;
39
+ private analyticsUrl : string ;
11
40
private environmentKey : string ;
12
41
private lastFlushed : number ;
13
42
analyticsData : { [ key : string ] : any } ;
14
- private requestTimeoutMs : number = 3000 ;
43
+ private requestTimeoutMs : number = DEFAULT_REQUEST_TIMEOUT_MS ;
15
44
private logger : Logger ;
16
45
private currentFlush : ReturnType < typeof fetch > | undefined ;
17
46
private customFetch : Fetch ;
18
47
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 ;
30
50
this . environmentKey = data . environmentKey ;
31
51
this . lastFlushed = Date . now ( ) ;
32
52
this . analyticsData = { } ;
@@ -35,15 +55,15 @@ export class AnalyticsProcessor {
35
55
this . customFetch = data . fetch ?? fetch ;
36
56
}
37
57
/**
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.
39
59
*/
40
60
async flush ( ) {
41
61
if ( this . currentFlush || ! Object . keys ( this . analyticsData ) . length ) {
42
62
return ;
43
63
}
44
64
45
65
try {
46
- this . currentFlush = this . customFetch ( this . analyticsEndpoint , {
66
+ this . currentFlush = this . customFetch ( this . analyticsUrl , {
47
67
method : 'POST' ,
48
68
body : JSON . stringify ( this . analyticsData ) ,
49
69
signal : AbortSignal . timeout ( this . requestTimeoutMs ) ,
@@ -66,6 +86,11 @@ export class AnalyticsProcessor {
66
86
this . lastFlushed = Date . now ( ) ;
67
87
}
68
88
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
+ */
69
94
trackFeature ( featureName : string ) {
70
95
this . analyticsData [ featureName ] = ( this . analyticsData [ featureName ] || 0 ) + 1 ;
71
96
if ( Date . now ( ) - this . lastFlushed > ANALYTICS_TIMER * 1000 ) {
0 commit comments