light-sentry-sdk/src/plugins/SamplingPlugin.ts

88 lines
2.1 KiB
TypeScript

import type { LightPlugin, LightClient, SentryEvent, LightConfig } from '../types';
import { isObject } from '../utils/helper';
interface SampleRateConfig {
error?: number;
performance?: number;
network?: number;
behavior?: number;
[key: string]: number | undefined;
}
interface SamplingPluginConfig {
rates?: SampleRateConfig;
}
class SamplingPlugin implements LightPlugin {
name = 'sampling';
version = '1.0.0';
private client!: LightClient;
private config: SamplingPluginConfig = {
rates: {
error: 1,
performance: 1,
network: 1,
behavior: 1,
},
};
setup(client: LightClient): void {
this.client = client;
this.loadConfig();
}
private loadConfig(): void {
const clientConfig = this.client.config as LightConfig;
if (clientConfig && isObject(clientConfig.sampling)) {
const samplingConfig = clientConfig.sampling as object;
if ('rates' in samplingConfig && isObject((samplingConfig as { rates?: object }).rates)) {
this.config.rates = { ...this.config.rates, ...((samplingConfig as { rates: object }).rates as object) } as SampleRateConfig;
}
}
}
private shouldSample(event: SentryEvent): boolean {
const globalRate = (this.client.config as LightConfig).sampleRate ?? 1;
if (globalRate <= 0) return false;
const typeRate = this.getTypeRate(event);
if (globalRate >= 1) {
return this.randomCheck(typeRate);
}
return this.randomCheck(globalRate * typeRate);
}
private getTypeRate(event: SentryEvent): number {
const rates = this.config.rates || {};
const type = event.type;
if (type === 'count') {
return 1;
}
const rate = rates[type];
return rate !== undefined ? rate : 1;
}
private randomCheck(rate: number): boolean {
if (rate >= 1) return true;
if (rate <= 0) return false;
return Math.random() < rate;
}
beforeReport(event: SentryEvent): SentryEvent | null {
if (!this.shouldSample(event)) {
return null;
}
return event;
}
destroy(): void {
// nothing to clean up
}
}
export default SamplingPlugin;