mirror of
https://github.com/umami-software/umami.git
synced 2026-05-30 06:47:25 +00:00
Fetch recorder settings from website config endpoint
This commit is contained in:
@@ -16,6 +16,8 @@ export default {
|
||||
replace({
|
||||
__COLLECT_API_HOST__: process.env.COLLECT_API_HOST || '',
|
||||
__COLLECT_REPLAY_ENDPOINT__: process.env.COLLECT_REPLAY_ENDPOINT || '/api/record',
|
||||
__RECORDER_CONFIG_ENDPOINT__:
|
||||
process.env.RECORDER_CONFIG_ENDPOINT || '/api/websites/{websiteId}/recorder',
|
||||
delimiters: ['', ''],
|
||||
preventAssignment: true,
|
||||
}),
|
||||
|
||||
@@ -42,9 +42,7 @@ export function WebsiteReplaySettings({ websiteId }: { websiteId: string }) {
|
||||
? `${process.env.cloudUrl}/${RECORDER_NAME}`
|
||||
: `${window?.location?.origin || ''}${process.env.basePath || ''}/${RECORDER_NAME}`;
|
||||
|
||||
let recorderAttrs = `data-website-id="${websiteId}" data-sample-rate="${sampleRate}" data-mask-level="${maskLevel}" data-max-duration="${parseInt(maxDuration, 10) || 300000}"`;
|
||||
if (blockSelector) recorderAttrs += ` data-block-selector="${blockSelector}"`;
|
||||
const recorderCode = `<script defer src="${recorderUrl}" ${recorderAttrs}></script>`;
|
||||
const recorderCode = `<script defer src="${recorderUrl}" data-website-id="${websiteId}"></script>`;
|
||||
|
||||
const handleToggle = async (value: boolean) => {
|
||||
const previous = enabled;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { json } from '@/lib/response';
|
||||
import { getWebsite } from '@/queries/prisma';
|
||||
|
||||
interface ReplayConfig {
|
||||
sampleRate?: number;
|
||||
maskLevel?: string;
|
||||
maxDuration?: number;
|
||||
blockSelector?: string;
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ websiteId: string }> },
|
||||
) {
|
||||
const { error } = await parseRequest(request, null, { skipAuth: true });
|
||||
|
||||
if (error) {
|
||||
return error();
|
||||
}
|
||||
|
||||
const { websiteId } = await params;
|
||||
const website = await getWebsite(websiteId);
|
||||
|
||||
const headers = {
|
||||
'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',
|
||||
};
|
||||
|
||||
if (!website || !website.replayEnabled) {
|
||||
return Response.json({ enabled: false }, { headers });
|
||||
}
|
||||
|
||||
const config = (website.replayConfig as ReplayConfig) || {};
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
enabled: true,
|
||||
sampleRate: config.sampleRate ?? 0.15,
|
||||
maskLevel: config.maskLevel ?? 'moderate',
|
||||
maxDuration: config.maxDuration ?? 300000,
|
||||
blockSelector: config.blockSelector ?? '',
|
||||
},
|
||||
{ headers },
|
||||
);
|
||||
}
|
||||
+40
-15
@@ -11,23 +11,26 @@ import { record } from 'rrweb';
|
||||
|
||||
const website = config(`website-id`);
|
||||
const hostUrl = config(`host-url`);
|
||||
const sampleRate = parseFloat(config(`sample-rate`) || '0.15');
|
||||
const maskLevel = config(`mask-level`) || 'moderate';
|
||||
const maxDuration = parseInt(config(`max-duration`) || '300000', 10);
|
||||
const blockSelector = config(`block-selector`) || '';
|
||||
|
||||
if (!website) return;
|
||||
|
||||
// Sample rate check
|
||||
if (sampleRate < 1 && Math.random() > sampleRate) return;
|
||||
|
||||
const host =
|
||||
hostUrl || '__COLLECT_API_HOST__' || currentScript.src.split('/').slice(0, -1).join('/');
|
||||
const endpoint = `${host.replace(/\/$/, '')}__COLLECT_REPLAY_ENDPOINT__`;
|
||||
const hostBase = host.replace(/\/$/, '');
|
||||
const endpoint = `${hostBase}__COLLECT_REPLAY_ENDPOINT__`;
|
||||
const configEndpoint = `${hostBase}__RECORDER_CONFIG_ENDPOINT__`.replace(
|
||||
'{websiteId}',
|
||||
website,
|
||||
);
|
||||
|
||||
const FLUSH_EVENT_COUNT = 100;
|
||||
const FLUSH_INTERVAL = 10000;
|
||||
|
||||
let sampleRate = 0.15;
|
||||
let maskLevel = 'moderate';
|
||||
let maxDuration = 300000;
|
||||
let blockSelector = '';
|
||||
|
||||
let eventBuffer = [];
|
||||
let stopFn = null;
|
||||
let flushTimer = null;
|
||||
@@ -265,11 +268,33 @@ import { record } from 'rrweb';
|
||||
});
|
||||
};
|
||||
|
||||
if (document.readyState === 'complete') {
|
||||
waitForSession();
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (document.readyState === 'complete') waitForSession();
|
||||
});
|
||||
}
|
||||
const bootstrap = async () => {
|
||||
try {
|
||||
const response = await fetch(configEndpoint, { credentials: 'omit' });
|
||||
if (!response.ok) return;
|
||||
|
||||
const data = await response.json();
|
||||
if (!data?.enabled) return;
|
||||
|
||||
if (typeof data.sampleRate === 'number') sampleRate = data.sampleRate;
|
||||
if (typeof data.maskLevel === 'string') maskLevel = data.maskLevel;
|
||||
if (typeof data.maxDuration === 'number') maxDuration = data.maxDuration;
|
||||
if (typeof data.blockSelector === 'string') blockSelector = data.blockSelector;
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sample rate check
|
||||
if (sampleRate < 1 && Math.random() > sampleRate) return;
|
||||
|
||||
if (document.readyState === 'complete') {
|
||||
waitForSession();
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (document.readyState === 'complete') waitForSession();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
bootstrap();
|
||||
})(window);
|
||||
|
||||
Reference in New Issue
Block a user