Home Reference Source

src/tracking.js

/* @flow */

import { noop, stringifyError, stringifyErrorMessage, isIEIntranet, getResourceLoadTime, waitForWindowReady, ATTRIBUTES } from '@krakenjs/belter/src';
import { ZalgoPromise } from '@krakenjs/zalgo-promise/src';
import { FPTI_KEY, FPTI_FEED, FPTI_DATA_SOURCE, FPTI_SDK_NAME, FPTI_USER_ACTION } from '@paypal/sdk-constants/src';

import { getEnv, getVersion, getCorrelationID } from './global';
import { getPartnerAttributionID, getClientID, getMerchantID, getCommit, getLocale, getSDKScript, getSDKIntegrationSource, getPageType } from './script';
import { getSessionID } from './session';
import { getLogger } from './logger';
import { isPayPalDomain } from './domains';

let sdkInitTime;

export function getSDKInitTime() : number {
    if (typeof sdkInitTime === 'undefined') {
        throw new TypeError(`SDK not initialized`);
    }

    return sdkInitTime;
}

export function setupLogger() {
    const logger = getLogger();

    sdkInitTime = Date.now();
    
    logger.addPayloadBuilder(() => {
        return {
            referer: window.location.host,
            uid:     getSessionID(),
            env:     getEnv()
        };
    });

    logger.addTrackingBuilder(() => {
        const { lang, country } = getLocale();
        const mID = getMerchantID();

        return {
            [FPTI_KEY.FEED]:                   FPTI_FEED.PAYMENTS_SDK,
            [FPTI_KEY.DATA_SOURCE]:            FPTI_DATA_SOURCE.PAYMENTS_SDK,
            [FPTI_KEY.CLIENT_ID]:              getClientID(),
            [FPTI_KEY.SELLER_ID]:              mID && mID.toString(),
            [FPTI_KEY.SESSION_UID]:            getSessionID(),
            [FPTI_KEY.REFERER]:                window.location.host,
            [FPTI_KEY.LOCALE]:                 `${ lang }_${ country }`,
            [FPTI_KEY.INTEGRATION_IDENTIFIER]: getClientID(),
            [FPTI_KEY.PARTNER_ATTRIBUTION_ID]: getPartnerAttributionID(),
            [FPTI_KEY.PAGE_TYPE]:              getPageType(),
            [FPTI_KEY.SDK_NAME]:               FPTI_SDK_NAME.PAYMENTS_SDK,
            [FPTI_KEY.SDK_VERSION]:            getVersion(),
            [FPTI_KEY.USER_AGENT]:             window.navigator && window.navigator.userAgent,
            [FPTI_KEY.USER_ACTION]:            getCommit() ? FPTI_USER_ACTION.COMMIT : FPTI_USER_ACTION.CONTINUE,
            [FPTI_KEY.CONTEXT_CORRID]:         getCorrelationID(),
            [FPTI_KEY.SDK_INTEGRATION_SOURCE]: getSDKIntegrationSource()
        };
    });

    ZalgoPromise.onPossiblyUnhandledException(err => {

        logger.track({
            [FPTI_KEY.ERROR_CODE]: 'payments_sdk_error',
            [FPTI_KEY.ERROR_DESC]: stringifyErrorMessage(err)
        });

        logger.error('unhandled_error', {
            err: stringifyError(err)
        });

        // eslint-disable-next-line promise/no-promise-in-callback
        logger.flush().catch(noop);
    });

    waitForWindowReady().then(() => {
        const sdkScript = getSDKScript();
        const loadTime = getResourceLoadTime(sdkScript.src);
        let cache;
    
        if (loadTime === 0) {
            cache = 'sdk_client_cache_hit';
        } else if (typeof loadTime === 'number') {
            cache = 'sdk_client_cache_miss';
        } else {
            cache = 'sdk_client_cache_unknown';
        }

        // Exclude apps that use the JS SDK and are hosted directly on www.paypal.com. Ex:
        // https://www.paypal.com/buttons/smart
        // https://www.paypal.com/us/gifts/
        const isLoadedInFrame = isPayPalDomain() && window.xprops;

        logger
            .info(`setup_${ getEnv() }`)
            .info(`setup_${ getEnv() }_${ getVersion().replace(/\./g, '_') }`)
            .info(`sdk_${ isLoadedInFrame ? 'paypal' : 'non_paypal' }_domain_script_uid_${ sdkScript.hasAttribute(ATTRIBUTES.UID) ? 'present' : 'missing' }`)
            .info(cache)
            .track({
                [FPTI_KEY.TRANSITION]:    'process_js_sdk_init_client',
                [FPTI_KEY.SDK_LOAD_TIME]: (typeof loadTime === 'number') ? loadTime.toString() : undefined,
                [FPTI_KEY.SDK_CACHE]:     cache
            }).flush();

        if (isIEIntranet()) {
            logger.warn('ie_intranet_mode');
        }
    });
}