Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | /** * Trace Context - Session and Request ID Management * * Provides distributed tracing support for correlating frontend actions * with backend processing in Grafana Loki. * * Session ID: Persists for browser session, correlates all user actions * Request ID: Unique per API call, correlates single request through backend */ const SESSION_ID_KEY = 'mt_session_id'; /** * Generate a short unique ID (8 hex characters) * 8 chars = 4.3 billion combinations, plenty for session/request scope * @returns {string} Short hex ID */ function generateShortId() { // Use crypto.randomUUID if available, take first 8 chars if (typeof crypto !== 'undefined' && crypto.randomUUID) { return crypto.randomUUID().replace(/-/g, '').substring(0, 8); } // Fallback for older browsers return 'xxxxxxxx'.replace(/x/g, () => { return ((Math.random() * 16) | 0).toString(16); }); } /** * Get or create the session ID * Session ID persists across page loads but not browser sessions * * @returns {string} Session ID in format "mt-sess-{8 hex chars}" */ export function getSessionId() { // Check sessionStorage first let sessionId = sessionStorage.getItem(SESSION_ID_KEY); if (!sessionId) { sessionId = `mt-sess-${generateShortId()}`; sessionStorage.setItem(SESSION_ID_KEY, sessionId); // Log session start for debugging console.log('[TraceContext] New session started:', sessionId); } return sessionId; } /** * Generate a unique request ID for an API call * * @returns {string} Request ID in format "mt-req-{8 hex chars}" */ export function generateRequestId() { return `mt-req-${generateShortId()}`; } /** * Get trace headers to include in API requests * * @returns {Object} Headers object with X-Session-ID and X-Request-ID */ export function getTraceHeaders() { return { 'X-Session-ID': getSessionId(), 'X-Request-ID': generateRequestId(), }; } /** * Create a fetch wrapper that automatically includes trace headers * * @param {string} url - Request URL * @param {Object} options - Fetch options * @returns {Promise<Response>} Fetch response */ export async function tracedFetch(url, options = {}) { const traceHeaders = getTraceHeaders(); const mergedOptions = { ...options, headers: { ...traceHeaders, ...options.headers, }, }; return fetch(url, mergedOptions); } /** * Get current trace context for logging * Use this when manually logging events via Faro * * @param {string} [requestId] - Optional specific request ID * @returns {Object} Trace context for logging */ export function getTraceContext(requestId = null) { return { session_id: getSessionId(), request_id: requestId || generateRequestId(), }; } // Initialize session ID on module load // This ensures consistent session tracking from first API call if (typeof window !== 'undefined') { getSessionId(); } |