mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-06-10 18:17:08 +00:00
151 lines
4.1 KiB
JavaScript
151 lines
4.1 KiB
JavaScript
const { getRumProxyClientUrl, isEnabled, isRumProxyEnabled } = require('@librechat/api');
|
|
const { logger } = require('@librechat/data-schemas');
|
|
|
|
const DEFAULT_RUM_SERVICE_NAME = 'librechat-web';
|
|
|
|
function parseBooleanEnv(value, defaultValue = false) {
|
|
if (value == null || value === '') {
|
|
return defaultValue;
|
|
}
|
|
|
|
return isEnabled(value);
|
|
}
|
|
|
|
function parseNumberEnv(value) {
|
|
if (value == null || value === '') {
|
|
return undefined;
|
|
}
|
|
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : undefined;
|
|
}
|
|
|
|
function parseCsvEnv(value) {
|
|
if (!value) {
|
|
return [];
|
|
}
|
|
|
|
return value
|
|
.split(',')
|
|
.map((item) => item.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function parseUrl(value) {
|
|
try {
|
|
return new URL(value);
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
function isLocalhost(url) {
|
|
return url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]';
|
|
}
|
|
|
|
function isSafeRumUrl(url) {
|
|
if (url.username || url.password) {
|
|
return false;
|
|
}
|
|
|
|
if (url.protocol === 'https:') {
|
|
return true;
|
|
}
|
|
|
|
return url.protocol === 'http:' && isLocalhost(url);
|
|
}
|
|
|
|
function isSafeTraceTarget(target) {
|
|
if (target.includes('*')) {
|
|
return false;
|
|
}
|
|
|
|
const url = parseUrl(target);
|
|
if (!url || url.protocol !== 'https:') {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function getRumConfig() {
|
|
if (!parseBooleanEnv(process.env.RUM_ENABLED)) {
|
|
return undefined;
|
|
}
|
|
|
|
const provider = process.env.RUM_PROVIDER || 'hyperdx';
|
|
if (provider !== 'hyperdx') {
|
|
logger.warn(`[config] Unsupported RUM provider "${provider}", disabling RUM`);
|
|
return undefined;
|
|
}
|
|
|
|
const authMode = process.env.RUM_AUTH_MODE || 'publicToken';
|
|
if (authMode !== 'publicToken' && authMode !== 'proxy') {
|
|
logger.warn(`[config] Unsupported RUM auth mode "${authMode}", disabling RUM`);
|
|
return undefined;
|
|
}
|
|
|
|
let rumUrl;
|
|
if (authMode === 'proxy') {
|
|
rumUrl = getRumProxyClientUrl();
|
|
|
|
if (!isRumProxyEnabled()) {
|
|
logger.warn('[config] RUM proxy mode requires RUM_PROXY_TARGET_URL, disabling RUM');
|
|
return undefined;
|
|
}
|
|
} else {
|
|
rumUrl = process.env.RUM_URL;
|
|
const parsedUrl = rumUrl ? parseUrl(rumUrl) : undefined;
|
|
|
|
if (!parsedUrl || !isSafeRumUrl(parsedUrl)) {
|
|
logger.warn('[config] Invalid RUM_URL, disabling RUM');
|
|
return undefined;
|
|
}
|
|
|
|
if (!process.env.RUM_PUBLIC_TOKEN) {
|
|
logger.warn('[config] RUM publicToken mode requires RUM_PUBLIC_TOKEN, disabling RUM');
|
|
return undefined;
|
|
}
|
|
|
|
rumUrl = parsedUrl.href.replace(/\/$/, '');
|
|
}
|
|
|
|
const rawTracePropagationTargets = parseCsvEnv(process.env.RUM_TRACE_PROPAGATION_TARGETS);
|
|
const tracePropagationTargets = rawTracePropagationTargets.filter(isSafeTraceTarget);
|
|
if (rawTracePropagationTargets.length !== tracePropagationTargets.length) {
|
|
logger.info('[config] Ignored unsafe RUM trace propagation targets');
|
|
}
|
|
|
|
const configuredSampleRate = parseNumberEnv(process.env.RUM_SAMPLE_RATE);
|
|
const sampleRate =
|
|
configuredSampleRate != null && configuredSampleRate >= 0 && configuredSampleRate <= 1
|
|
? configuredSampleRate
|
|
: undefined;
|
|
const consoleCapture = parseBooleanEnv(process.env.RUM_CONSOLE_CAPTURE);
|
|
const advancedNetworkCapture = parseBooleanEnv(process.env.RUM_ADVANCED_NETWORK_CAPTURE);
|
|
|
|
if (consoleCapture) {
|
|
logger.warn('[config] RUM console capture is enabled and may collect sensitive browser logs');
|
|
}
|
|
|
|
if (advancedNetworkCapture) {
|
|
logger.warn('[config] RUM advanced network capture is enabled and may collect payload data');
|
|
}
|
|
|
|
return {
|
|
provider: 'hyperdx',
|
|
enabled: true,
|
|
url: rumUrl,
|
|
serviceName: process.env.RUM_SERVICE_NAME || DEFAULT_RUM_SERVICE_NAME,
|
|
authMode,
|
|
...(authMode === 'publicToken' ? { publicToken: process.env.RUM_PUBLIC_TOKEN } : {}),
|
|
...(tracePropagationTargets.length > 0 ? { tracePropagationTargets } : {}),
|
|
consoleCapture,
|
|
disableReplay: parseBooleanEnv(process.env.RUM_DISABLE_REPLAY, true),
|
|
advancedNetworkCapture,
|
|
...(sampleRate != null ? { sampleRate } : {}),
|
|
...(process.env.RUM_ENVIRONMENT ? { environment: process.env.RUM_ENVIRONMENT } : {}),
|
|
};
|
|
}
|
|
|
|
module.exports = { getRumConfig };
|