import { context } from '@/common/context'; import { logger, getApiHost } from '@jolibox/common'; import { IDevice, IPage, IEventPackage, IEvent, EProject, serializeEventPackage } from '@jolibox/common'; interface ISamplesConfig { samples: { [sampleRate: number]: string[]; }; cluster: number; } /** * Base class for event tracker, all the event tracker should inherit from this class * Send event to oss reporter * @abstract */ export abstract class EventTracker { deviceInfo: IDevice | null = null; abstract doReport(event: unknown[]): void; abstract doReport>(event: unknown[], extra: T): void; abstract doReport>(event: unknown[], extra?: T): void; private samplesConfig: ISamplesConfig | null = null; constructor(readonly apiHost: string) { this.fetchSamplesConfig(); } private async fetchSamplesConfig() { const host = this.apiHost; const path = `${host}/api/fe-configs/js-sdk/samples-config`; const samplesConfig = (await (await fetch(path)).json()) as ISamplesConfig; this.samplesConfig = samplesConfig; } private checkIsSampled(event: IEvent) { if (!this.samplesConfig) { return false; } const { samples } = this.samplesConfig; for (const [sampleRate, events] of Object.entries(samples)) { if (events.includes(event.name)) { return Math.floor(Math.random() * 101) < parseFloat(sampleRate); } } return false; } getDevice(): IDevice { const { nativeSDKVersion, jssdkVersion } = context.sdkInfo; return { platform: 1000, os: context.deviceInfo.platform, appVersion: nativeSDKVersion ?? jssdkVersion ?? '1.0.0', // mock appId: context.hostInfo?.aid ?? '1', model: context.deviceInfo.model ?? 'UnknownModel', brand: context.deviceInfo.brand ?? 'UnknownBrand', uuid: context.deviceInfo.did, jsSdkVersion: jssdkVersion, // mock extra: {} }; } getLocation(): IPage { const urlParams = new URLSearchParams(window.location.search); const params: Record = {}; urlParams.forEach((value, key) => { params[key] = value; }); return { name: 'GamePage', params }; } async trackEvent(event: IEvent, project: EProject, extraInfo?: Record) { // check if the event is sampled if (this.checkIsSampled(event)) { return; } const location = event.location ? event.location : await this.getLocation(); const target = event.target || null; const extra = event.extra || null; const { hostUserInfo } = context; if (!this.deviceInfo) { this.deviceInfo = await this.getDevice(); } const device = this.deviceInfo; const events: IEvent[] = [ { ...event, location, target, extra, timestamp: Date.now(), userId: hostUserInfo?.uid ?? null } ]; const eventPackage: IEventPackage = { protocolVersion: '1.0.0', events, device, project }; try { extraInfo ? await this.doReport(serializeEventPackage(eventPackage), extraInfo) : await this.doReport(serializeEventPackage(eventPackage)); } catch (e) { logger.log('[Jolibox SDK] report API error', e); } } }