@zoho_apptics/apptics-js-sdk 1.0.1 → 2.0.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/LICENSE +13 -0
- package/README.md +747 -11
- package/dist/apptics.esm.min.js +3 -0
- package/dist/apptics.esm.min.js.map +1 -0
- package/dist/apptics.min.js +3 -0
- package/dist/apptics.min.js.map +1 -0
- package/dist/chunks/batch-BU_mTpm1.min.js +3 -0
- package/dist/chunks/batch-BU_mTpm1.min.js.map +1 -0
- package/dist/chunks/logs-Bea5zUW_.min.js +3 -0
- package/dist/chunks/logs-Bea5zUW_.min.js.map +1 -0
- package/dist/cjs/auto-init.d.ts +8 -0
- package/dist/cjs/auto-init.js +32 -0
- package/dist/cjs/core/attempts.d.ts +28 -0
- package/dist/cjs/core/attempts.js +113 -0
- package/dist/cjs/core/batch.d.ts +32 -0
- package/dist/cjs/core/batch.js +115 -0
- package/dist/cjs/core/callsite.d.ts +28 -0
- package/dist/cjs/core/callsite.js +93 -0
- package/dist/cjs/core/consent.d.ts +23 -0
- package/dist/cjs/core/consent.js +130 -0
- package/dist/cjs/core/constants.d.ts +212 -0
- package/dist/cjs/core/constants.js +299 -0
- package/dist/cjs/core/db.d.ts +40 -0
- package/dist/cjs/core/db.js +334 -0
- package/dist/cjs/core/debug.d.ts +22 -0
- package/dist/cjs/core/debug.js +88 -0
- package/dist/cjs/core/env.d.ts +28 -0
- package/dist/cjs/core/env.js +267 -0
- package/dist/cjs/core/framework-id.d.ts +1 -0
- package/dist/cjs/core/framework-id.js +9 -0
- package/dist/cjs/core/guard.d.ts +2 -0
- package/dist/cjs/core/guard.js +72 -0
- package/dist/cjs/core/hooks.d.ts +41 -0
- package/dist/cjs/core/hooks.js +23 -0
- package/dist/cjs/core/logger.d.ts +16 -0
- package/dist/cjs/core/logger.js +86 -0
- package/dist/cjs/core/state.d.ts +69 -0
- package/dist/cjs/core/state.js +78 -0
- package/dist/cjs/core/storage.d.ts +46 -0
- package/dist/cjs/core/storage.js +229 -0
- package/dist/cjs/core/transport.d.ts +83 -0
- package/dist/cjs/core/transport.js +441 -0
- package/dist/cjs/core/utils.d.ts +26 -0
- package/dist/cjs/core/utils.js +175 -0
- package/dist/cjs/core/validate.d.ts +18 -0
- package/dist/cjs/core/validate.js +233 -0
- package/dist/cjs/device/appversion.d.ts +20 -0
- package/dist/cjs/device/appversion.js +158 -0
- package/dist/cjs/device/index.d.ts +23 -0
- package/dist/cjs/device/index.js +372 -0
- package/dist/cjs/engagement/api-rules.d.ts +84 -0
- package/dist/cjs/engagement/api-rules.js +219 -0
- package/dist/cjs/engagement/auto-api.d.ts +7 -0
- package/dist/cjs/engagement/auto-api.js +200 -0
- package/dist/cjs/engagement/auto-screen.d.ts +16 -0
- package/dist/cjs/engagement/auto-screen.js +241 -0
- package/dist/cjs/engagement/defined-events.d.ts +23 -0
- package/dist/cjs/engagement/defined-events.js +58 -0
- package/dist/cjs/engagement/send.d.ts +6 -0
- package/dist/cjs/engagement/send.js +99 -0
- package/dist/cjs/engagement/session.d.ts +42 -0
- package/dist/cjs/engagement/session.js +327 -0
- package/dist/cjs/engagement/track.d.ts +56 -0
- package/dist/cjs/engagement/track.js +350 -0
- package/dist/cjs/errors/send.d.ts +6 -0
- package/dist/cjs/errors/send.js +73 -0
- package/dist/cjs/errors/track.d.ts +4 -0
- package/dist/cjs/errors/track.js +127 -0
- package/dist/cjs/feedback/controls.d.ts +31 -0
- package/dist/cjs/feedback/controls.js +286 -0
- package/dist/cjs/feedback/index.d.ts +8 -0
- package/dist/cjs/feedback/index.js +37 -0
- package/dist/cjs/feedback/logs.d.ts +40 -0
- package/dist/cjs/feedback/logs.js +202 -0
- package/dist/cjs/feedback/send.d.ts +25 -0
- package/dist/cjs/feedback/send.js +178 -0
- package/dist/cjs/feedback/template.d.ts +2 -0
- package/dist/cjs/feedback/template.js +162 -0
- package/dist/cjs/feedback/ui.d.ts +55 -0
- package/dist/cjs/feedback/ui.js +631 -0
- package/dist/cjs/heatmap/index.d.ts +16 -0
- package/dist/cjs/heatmap/index.js +22 -0
- package/dist/cjs/heatmap/send.d.ts +13 -0
- package/dist/cjs/heatmap/send.js +82 -0
- package/dist/cjs/heatmap/track.d.ts +4 -0
- package/dist/cjs/heatmap/track.js +377 -0
- package/dist/cjs/index.d.ts +68 -0
- package/dist/cjs/index.js +150 -0
- package/dist/cjs/lifecycle.d.ts +14 -0
- package/dist/cjs/lifecycle.js +538 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/remoteconfig/custom.d.ts +10 -0
- package/dist/cjs/remoteconfig/custom.js +78 -0
- package/dist/cjs/remoteconfig/evaluate.d.ts +24 -0
- package/dist/cjs/remoteconfig/evaluate.js +171 -0
- package/dist/cjs/remoteconfig/fetch.d.ts +24 -0
- package/dist/cjs/remoteconfig/fetch.js +214 -0
- package/dist/cjs/remoteconfig/index.d.ts +13 -0
- package/dist/cjs/remoteconfig/index.js +90 -0
- package/dist/cjs/remoteconfig/store.d.ts +18 -0
- package/dist/cjs/remoteconfig/store.js +98 -0
- package/dist/cjs/remotelog/gate.d.ts +11 -0
- package/dist/cjs/remotelog/gate.js +54 -0
- package/dist/cjs/remotelog/index.d.ts +25 -0
- package/dist/cjs/remotelog/index.js +55 -0
- package/dist/cjs/remotelog/logger.d.ts +28 -0
- package/dist/cjs/remotelog/logger.js +139 -0
- package/dist/cjs/remotelog/send.d.ts +13 -0
- package/dist/cjs/remotelog/send.js +153 -0
- package/dist/cjs/scheduler.d.ts +8 -0
- package/dist/cjs/scheduler.js +78 -0
- package/dist/cjs/types.d.ts +312 -0
- package/dist/cjs/user/index.d.ts +33 -0
- package/dist/cjs/user/index.js +178 -0
- package/dist/esm/auto-init.d.ts +8 -0
- package/dist/esm/auto-init.js +29 -0
- package/dist/esm/core/attempts.d.ts +28 -0
- package/dist/esm/core/attempts.js +106 -0
- package/dist/esm/core/batch.d.ts +32 -0
- package/dist/esm/core/batch.js +108 -0
- package/dist/esm/core/callsite.d.ts +28 -0
- package/dist/esm/core/callsite.js +89 -0
- package/dist/esm/core/consent.d.ts +23 -0
- package/dist/esm/core/consent.js +120 -0
- package/dist/esm/core/constants.d.ts +212 -0
- package/dist/esm/core/constants.js +277 -0
- package/dist/esm/core/db.d.ts +40 -0
- package/dist/esm/core/db.js +324 -0
- package/dist/esm/core/debug.d.ts +22 -0
- package/dist/esm/core/debug.js +81 -0
- package/dist/esm/core/env.d.ts +28 -0
- package/dist/esm/core/env.js +251 -0
- package/dist/esm/core/framework-id.d.ts +1 -0
- package/dist/esm/core/framework-id.js +7 -0
- package/dist/esm/core/guard.d.ts +2 -0
- package/dist/esm/core/guard.js +70 -0
- package/dist/esm/core/hooks.d.ts +41 -0
- package/dist/esm/core/hooks.js +21 -0
- package/dist/esm/core/logger.d.ts +16 -0
- package/dist/esm/core/logger.js +82 -0
- package/dist/esm/core/state.d.ts +69 -0
- package/dist/esm/core/state.js +73 -0
- package/dist/esm/core/storage.d.ts +46 -0
- package/dist/esm/core/storage.js +219 -0
- package/dist/esm/core/transport.d.ts +83 -0
- package/dist/esm/core/transport.js +425 -0
- package/dist/esm/core/utils.d.ts +26 -0
- package/dist/esm/core/utils.js +161 -0
- package/dist/esm/core/validate.d.ts +18 -0
- package/dist/esm/core/validate.js +226 -0
- package/dist/esm/device/appversion.d.ts +20 -0
- package/dist/esm/device/appversion.js +153 -0
- package/dist/esm/device/index.d.ts +23 -0
- package/dist/esm/device/index.js +362 -0
- package/dist/esm/engagement/api-rules.d.ts +84 -0
- package/dist/esm/engagement/api-rules.js +211 -0
- package/dist/esm/engagement/auto-api.d.ts +7 -0
- package/dist/esm/engagement/auto-api.js +198 -0
- package/dist/esm/engagement/auto-screen.d.ts +16 -0
- package/dist/esm/engagement/auto-screen.js +238 -0
- package/dist/esm/engagement/defined-events.d.ts +23 -0
- package/dist/esm/engagement/defined-events.js +55 -0
- package/dist/esm/engagement/send.d.ts +6 -0
- package/dist/esm/engagement/send.js +96 -0
- package/dist/esm/engagement/session.d.ts +42 -0
- package/dist/esm/engagement/session.js +315 -0
- package/dist/esm/engagement/track.d.ts +56 -0
- package/dist/esm/engagement/track.js +340 -0
- package/dist/esm/errors/send.d.ts +6 -0
- package/dist/esm/errors/send.js +70 -0
- package/dist/esm/errors/track.d.ts +4 -0
- package/dist/esm/errors/track.js +123 -0
- package/dist/esm/feedback/controls.d.ts +31 -0
- package/dist/esm/feedback/controls.js +280 -0
- package/dist/esm/feedback/index.d.ts +8 -0
- package/dist/esm/feedback/index.js +30 -0
- package/dist/esm/feedback/logs.d.ts +40 -0
- package/dist/esm/feedback/logs.js +188 -0
- package/dist/esm/feedback/send.d.ts +25 -0
- package/dist/esm/feedback/send.js +175 -0
- package/dist/esm/feedback/template.d.ts +2 -0
- package/dist/esm/feedback/template.js +159 -0
- package/dist/esm/feedback/ui.d.ts +55 -0
- package/dist/esm/feedback/ui.js +626 -0
- package/dist/esm/heatmap/index.d.ts +16 -0
- package/dist/esm/heatmap/index.js +17 -0
- package/dist/esm/heatmap/send.d.ts +13 -0
- package/dist/esm/heatmap/send.js +79 -0
- package/dist/esm/heatmap/track.d.ts +4 -0
- package/dist/esm/heatmap/track.js +374 -0
- package/dist/esm/index.d.ts +68 -0
- package/dist/esm/index.js +122 -0
- package/dist/esm/lifecycle.d.ts +14 -0
- package/dist/esm/lifecycle.js +534 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/remoteconfig/custom.d.ts +10 -0
- package/dist/esm/remoteconfig/custom.js +74 -0
- package/dist/esm/remoteconfig/evaluate.d.ts +24 -0
- package/dist/esm/remoteconfig/evaluate.js +166 -0
- package/dist/esm/remoteconfig/fetch.d.ts +24 -0
- package/dist/esm/remoteconfig/fetch.js +210 -0
- package/dist/esm/remoteconfig/index.d.ts +13 -0
- package/dist/esm/remoteconfig/index.js +85 -0
- package/dist/esm/remoteconfig/store.d.ts +18 -0
- package/dist/esm/remoteconfig/store.js +91 -0
- package/dist/esm/remotelog/gate.d.ts +11 -0
- package/dist/esm/remotelog/gate.js +48 -0
- package/dist/esm/remotelog/index.d.ts +25 -0
- package/dist/esm/remotelog/index.js +51 -0
- package/dist/esm/remotelog/logger.d.ts +28 -0
- package/dist/esm/remotelog/logger.js +136 -0
- package/dist/esm/remotelog/send.d.ts +13 -0
- package/dist/esm/remotelog/send.js +149 -0
- package/dist/esm/scheduler.d.ts +8 -0
- package/dist/esm/scheduler.js +74 -0
- package/dist/esm/types.d.ts +312 -0
- package/dist/esm/user/index.d.ts +33 -0
- package/dist/esm/user/index.js +170 -0
- package/dist/feedback.esm.min.js +3 -0
- package/dist/feedback.esm.min.js.map +1 -0
- package/dist/heatmap.esm.min.js +3 -0
- package/dist/heatmap.esm.min.js.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +124 -7
- package/src/appticssdk.js +0 -3817
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var state = require('../core/state.js');
|
|
5
|
+
var env = require('../core/env.js');
|
|
6
|
+
var consent = require('../core/consent.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The one switch both halves of the remote logger ask: may this line be recorded, and may
|
|
10
|
+
* what is stored be sent? It lives on its own so recording and sending don't import each other.
|
|
11
|
+
*/
|
|
12
|
+
/** The app logger's switch: off until the app calls logger.enable(), as on Android and iOS. */
|
|
13
|
+
let appLoggerOn = false;
|
|
14
|
+
function setAppLogger(on) {
|
|
15
|
+
appLoggerOn = on;
|
|
16
|
+
}
|
|
17
|
+
function appLoggerEnabled() {
|
|
18
|
+
return appLoggerOn;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* What every remote-log line needs, whoever wrote it: a running SDK, a client we send anything
|
|
22
|
+
* for, the server's remote logger switch, and consent.
|
|
23
|
+
*/
|
|
24
|
+
function remoteLoggerReachable() {
|
|
25
|
+
if (!state._ZAP._token || env.is_apptics_disabled()) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
// getsdkconfig module 17: the server can switch the remote logger off on its own
|
|
29
|
+
if (!state._ZAP._remoteLoggerEnabled) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return consent.shouldTrackOrSendData();
|
|
33
|
+
}
|
|
34
|
+
/** The SDK's own diagnostics may be recorded: `remote_log` is on and the logger is reachable. */
|
|
35
|
+
function remoteLogEnabled() {
|
|
36
|
+
return state.getConfig('remote_log') && remoteLoggerReachable(); // no i18n
|
|
37
|
+
}
|
|
38
|
+
/** An app's own log line may be recorded: the app enabled the logger and it is reachable. */
|
|
39
|
+
function appLogEnabled() {
|
|
40
|
+
return appLoggerOn && remoteLoggerReachable();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* What is stored may be sent. Either writer is enough: app logging works with `remote_log`
|
|
44
|
+
* off, since that switch covers only the SDK's own diagnostics.
|
|
45
|
+
*/
|
|
46
|
+
function remoteLogSendable() {
|
|
47
|
+
return (state.getConfig('remote_log') || appLoggerOn) && remoteLoggerReachable(); // no i18n
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.appLogEnabled = appLogEnabled;
|
|
51
|
+
exports.appLoggerEnabled = appLoggerEnabled;
|
|
52
|
+
exports.remoteLogEnabled = remoteLogEnabled;
|
|
53
|
+
exports.remoteLogSendable = remoteLogSendable;
|
|
54
|
+
exports.setAppLogger = setAppLogger;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote logger: the SDK's own diagnostics, sent to console/addlog.
|
|
3
|
+
*
|
|
4
|
+
* This file is not the app-facing logging API — that is logger.ts, which shares this queue and
|
|
5
|
+
* delivery but has its own switch. This file answers "this app reports no data — what is the SDK
|
|
6
|
+
* actually doing on the user's machine?", so what it carries is the SDK's own failures, each
|
|
7
|
+
* tagged with the module that was mid-flight (Session, Screen, Event, API, Properties).
|
|
8
|
+
* App errors belong to exception/error, an app's remote log lines to logger.ts, and lines meant
|
|
9
|
+
* for a feedback report to feedback/logs.ts.
|
|
10
|
+
*
|
|
11
|
+
* This file records lines, send.ts delivers them, and gate.ts holds the switch both ask.
|
|
12
|
+
* Nothing here is exported to apps: the SDK writes these lines itself, through logFailure()
|
|
13
|
+
* in core/logger.ts.
|
|
14
|
+
*/
|
|
15
|
+
import { AP_LOG_MODULE } from '../core/constants.js';
|
|
16
|
+
import { type CallSite } from '../core/callsite.js';
|
|
17
|
+
/** One of console/addlog's `module` values. */
|
|
18
|
+
export type LogModule = (typeof AP_LOG_MODULE)[keyof typeof AP_LOG_MODULE];
|
|
19
|
+
/**
|
|
20
|
+
* Records one line about `module` for console/addlog. Never throws and never blocks the caller:
|
|
21
|
+
* a diagnostics channel that breaks the flow it reports on would be worse than no channel.
|
|
22
|
+
*/
|
|
23
|
+
export declare function remoteLog(module: LogModule, message: unknown, site?: CallSite): void;
|
|
24
|
+
export { remoteLogEnabled } from './gate.js';
|
|
25
|
+
export { forgetStoredLogs, sendStoredLogs } from './send.js';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
require('../core/constants.js');
|
|
5
|
+
var callsite = require('../core/callsite.js');
|
|
6
|
+
var storage = require('../core/storage.js');
|
|
7
|
+
var hooks = require('../core/hooks.js');
|
|
8
|
+
var utils = require('../core/utils.js');
|
|
9
|
+
var gate = require('./gate.js');
|
|
10
|
+
var send = require('./send.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Remote logger: the SDK's own diagnostics, sent to console/addlog.
|
|
14
|
+
*
|
|
15
|
+
* This file is not the app-facing logging API — that is logger.ts, which shares this queue and
|
|
16
|
+
* delivery but has its own switch. This file answers "this app reports no data — what is the SDK
|
|
17
|
+
* actually doing on the user's machine?", so what it carries is the SDK's own failures, each
|
|
18
|
+
* tagged with the module that was mid-flight (Session, Screen, Event, API, Properties).
|
|
19
|
+
* App errors belong to exception/error, an app's remote log lines to logger.ts, and lines meant
|
|
20
|
+
* for a feedback report to feedback/logs.ts.
|
|
21
|
+
*
|
|
22
|
+
* This file records lines, send.ts delivers them, and gate.ts holds the switch both ask.
|
|
23
|
+
* Nothing here is exported to apps: the SDK writes these lines itself, through logFailure()
|
|
24
|
+
* in core/logger.ts.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Records one line about `module` for console/addlog. Never throws and never blocks the caller:
|
|
28
|
+
* a diagnostics channel that breaks the flow it reports on would be worse than no channel.
|
|
29
|
+
*/
|
|
30
|
+
function remoteLog(module, message, site) {
|
|
31
|
+
try {
|
|
32
|
+
if (!gate.remoteLogEnabled()) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
var where = site || callsite.NO_CALL_SITE;
|
|
36
|
+
storage.consolelog_transactions.add({
|
|
37
|
+
module: module,
|
|
38
|
+
happenedat: utils.nowMs(),
|
|
39
|
+
exceptionlog: String(message),
|
|
40
|
+
attempt: 1,
|
|
41
|
+
filename: where.filename,
|
|
42
|
+
linenumber: where.linenumber,
|
|
43
|
+
});
|
|
44
|
+
send.scheduleSend();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
// never let the logger be the thing that fails
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
hooks.hooks.remoteLog = remoteLog;
|
|
51
|
+
|
|
52
|
+
exports.remoteLogEnabled = gate.remoteLogEnabled;
|
|
53
|
+
exports.forgetStoredLogs = send.forgetStoredLogs;
|
|
54
|
+
exports.sendStoredLogs = send.sendStoredLogs;
|
|
55
|
+
exports.remoteLog = remoteLog;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** The level numbers log/add takes and the Remote Logger page names, in the native SDKs' order. */
|
|
2
|
+
export declare const LOG_LEVEL: Readonly<{
|
|
3
|
+
VERBOSE: 1;
|
|
4
|
+
DEBUG: 2;
|
|
5
|
+
INFO: 3;
|
|
6
|
+
WARN: 4;
|
|
7
|
+
ERROR: 5;
|
|
8
|
+
}>;
|
|
9
|
+
export interface AppticsLogger {
|
|
10
|
+
/** Starts recording log lines. Off until called. */
|
|
11
|
+
enable(): void;
|
|
12
|
+
/** Stops recording log lines. */
|
|
13
|
+
disable(): void;
|
|
14
|
+
/** Whether log lines are being recorded. */
|
|
15
|
+
isEnabled(): boolean;
|
|
16
|
+
/** Verbose, level 1. The tag leads the message as `[tag]`. */
|
|
17
|
+
v(tag: string, message: unknown, ...details: unknown[]): void;
|
|
18
|
+
/** Debug, level 2. */
|
|
19
|
+
d(tag: string, message: unknown, ...details: unknown[]): void;
|
|
20
|
+
/** Info, level 3. */
|
|
21
|
+
i(tag: string, message: unknown, ...details: unknown[]): void;
|
|
22
|
+
/** Warning, level 4. */
|
|
23
|
+
w(tag: string, message: unknown, ...details: unknown[]): void;
|
|
24
|
+
/** Error, level 5. */
|
|
25
|
+
e(tag: string, message: unknown, ...details: unknown[]): void;
|
|
26
|
+
}
|
|
27
|
+
/** Android's AppticsLogger: enable, disable, isEnabled and v / d / i / w / e(tag, message). */
|
|
28
|
+
export declare const AppticsLogger: AppticsLogger;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var constants = require('../core/constants.js');
|
|
5
|
+
var callsite = require('../core/callsite.js');
|
|
6
|
+
var storage = require('../core/storage.js');
|
|
7
|
+
var guard = require('../core/guard.js');
|
|
8
|
+
var utils = require('../core/utils.js');
|
|
9
|
+
var state = require('../core/state.js');
|
|
10
|
+
var gate = require('./gate.js');
|
|
11
|
+
var send = require('./send.js');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* AppticsLogger, as on Android: lines the app writes, shown on the console's Remote Logger page.
|
|
15
|
+
*
|
|
16
|
+
* AppticsLogger.enable();
|
|
17
|
+
* AppticsLogger.i('Checkout', 'Payment started');
|
|
18
|
+
* AppticsLogger.e('Checkout', 'Payment failed', err);
|
|
19
|
+
*
|
|
20
|
+
* It mirrors the native SDKs so the page reads the same whatever sent the line: off until
|
|
21
|
+
* enable() (AppticsLogger.enable() on Android, APLog.setShouldLog on iOS), and five levels in
|
|
22
|
+
* the iOS order — verbose, debug, info, warn, error — sent as 1 to 5, which is the scale the
|
|
23
|
+
* Remote Logger page reads back.
|
|
24
|
+
*
|
|
25
|
+
* Lines share the SDK diagnostics' queue and its log/add delivery, so they are stored before
|
|
26
|
+
* they are sent and survive a failed send and a reload. They are a separate switch, though:
|
|
27
|
+
* `remote_log: false` silences the SDK's own failures, not the app's logging.
|
|
28
|
+
*/
|
|
29
|
+
/** The level numbers log/add takes and the Remote Logger page names, in the native SDKs' order. */
|
|
30
|
+
const LOG_LEVEL = Object.freeze({ VERBOSE: 1, DEBUG: 2, INFO: 3, WARN: 4, ERROR: 5 });
|
|
31
|
+
/** What a line's `function` says when the caller had no name to give (an anonymous callback). */
|
|
32
|
+
const ANONYMOUS_CALLER = 'App'; // no i18n
|
|
33
|
+
/**
|
|
34
|
+
* The caller's name as logSDK's `function` accepts it: safe_string refuses angle brackets and an
|
|
35
|
+
* empty value, and the field stops at 100 characters.
|
|
36
|
+
*/
|
|
37
|
+
function functionName(site) {
|
|
38
|
+
var name = String(site.fn || '').replace(/<anonymous>/g, '').replace(/[<>]/g, '').trim(); // no i18n
|
|
39
|
+
if (name === '' || /^(Object|Module|eval)\.?$/.test(name)) {
|
|
40
|
+
return ANONYMOUS_CALLER;
|
|
41
|
+
}
|
|
42
|
+
return name.slice(0, constants.LOG_FUNCTION_MAX);
|
|
43
|
+
}
|
|
44
|
+
/** One detail as text: an Error as its stack (which leads with name and message), JSON otherwise. */
|
|
45
|
+
function describe(value) {
|
|
46
|
+
if (value instanceof Error) {
|
|
47
|
+
var head = value.name + ': ' + value.message; // no i18n
|
|
48
|
+
return value.stack && value.stack.indexOf(value.message) !== -1 ? value.stack : head;
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === 'string') { // no i18n
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
var json = JSON.stringify(value);
|
|
55
|
+
return json === undefined ? String(value) : json;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return String(value);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Stores one line. Reached through guard(), so a line logged before start-up finishes waits for
|
|
63
|
+
* it — which is why the time and call site are taken by the caller, not here.
|
|
64
|
+
*/
|
|
65
|
+
function record(level, message, details, at, site) {
|
|
66
|
+
if (!gate.appLogEnabled()) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
var text = [message].concat(details).map(describe).join(' '); // no i18n
|
|
70
|
+
storage.consolelog_transactions.add({
|
|
71
|
+
module: functionName(site),
|
|
72
|
+
level: level,
|
|
73
|
+
happenedat: at,
|
|
74
|
+
exceptionlog: text,
|
|
75
|
+
attempt: 1,
|
|
76
|
+
filename: site.filename,
|
|
77
|
+
linenumber: site.linenumber,
|
|
78
|
+
});
|
|
79
|
+
send.scheduleSend();
|
|
80
|
+
}
|
|
81
|
+
const recordLine = guard.guard('AppticsLogger', record); // no i18n
|
|
82
|
+
/** The browser console method each level prints with under `show_logs`, as Logcat shows them. */
|
|
83
|
+
const CONSOLE_METHOD = Object.freeze({
|
|
84
|
+
1: 'debug', 2: 'debug', 3: 'info', 4: 'warn', 5: 'error', // no i18n
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* `show_logs`: the line in the browser console too, as Android's showLogs prints to Logcat. For
|
|
88
|
+
* the developer, so it prints whether or not the remote logger is enabled or allowed to record,
|
|
89
|
+
* and the arguments go over untouched so the console can still expand an object or an Error.
|
|
90
|
+
*/
|
|
91
|
+
function show(level, args) {
|
|
92
|
+
if (state.getConfig('show_logs') !== true) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
var method = CONSOLE_METHOD[level] || 'log'; // no i18n
|
|
96
|
+
if (typeof console !== 'undefined' && typeof console[method] === 'function') { // no i18n
|
|
97
|
+
console[method].apply(console, args);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A level's Android-style method, `v/d/i/w/e(tag, message, ...details)`. The tag leads the
|
|
102
|
+
* message as `[tag]`; the function, file and line are still the caller's, as with the long names.
|
|
103
|
+
*/
|
|
104
|
+
function tagged(level) {
|
|
105
|
+
return function (tag, message, ...details) {
|
|
106
|
+
try {
|
|
107
|
+
var label = tag === undefined || tag === null ? '' : String(tag).trim(); // no i18n
|
|
108
|
+
var parts = label === '' ? [message].concat(details) : ['[' + label + ']', message].concat(details); // no i18n
|
|
109
|
+
show(level, parts);
|
|
110
|
+
// skip 1: this function's own frame, so the site is the app's line that logged
|
|
111
|
+
recordLine(level, parts[0], parts.slice(1), utils.nowMs(), callsite.callSite(1));
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
// logging must never be the thing that breaks the app
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Turns the app logger on, or off with `false`. Off by default. */
|
|
119
|
+
function enable(on) {
|
|
120
|
+
gate.setAppLogger(on !== false);
|
|
121
|
+
}
|
|
122
|
+
/** Turns the app logger off, as AppticsLogger.disable() does; the same as enable(false). */
|
|
123
|
+
function disable() {
|
|
124
|
+
gate.setAppLogger(false);
|
|
125
|
+
}
|
|
126
|
+
/** Android's AppticsLogger: enable, disable, isEnabled and v / d / i / w / e(tag, message). */
|
|
127
|
+
const AppticsLogger = {
|
|
128
|
+
enable: guard.guard('AppticsLogger.enable', function () { enable(true); }), // no i18n
|
|
129
|
+
disable: guard.guard('AppticsLogger.disable', disable), // no i18n
|
|
130
|
+
isEnabled: guard.guard('AppticsLogger.isEnabled', gate.appLoggerEnabled), // no i18n
|
|
131
|
+
v: tagged(LOG_LEVEL.VERBOSE),
|
|
132
|
+
d: tagged(LOG_LEVEL.DEBUG),
|
|
133
|
+
i: tagged(LOG_LEVEL.INFO),
|
|
134
|
+
w: tagged(LOG_LEVEL.WARN),
|
|
135
|
+
e: tagged(LOG_LEVEL.ERROR),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
exports.AppticsLogger = AppticsLogger;
|
|
139
|
+
exports.LOG_LEVEL = LOG_LEVEL;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Queues a pass over the stored lines, coalescing a burst into one. */
|
|
2
|
+
export declare function scheduleSend(): void;
|
|
3
|
+
/**
|
|
4
|
+
* Sends the stored lines as one batch. A batch the server refuses for its shape is dropped —
|
|
5
|
+
* retrying it could only fail the same way and would hold every later line behind it.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sendStoredLogs(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Sends what is stored as the page goes away, where a normal request would be cancelled.
|
|
10
|
+
* One keepalive request for the whole batch, which is what the endpoint now accepts. The lines
|
|
11
|
+
* stay stored until the server has confirmed them.
|
|
12
|
+
*/
|
|
13
|
+
export declare function forgetStoredLogs(): Promise<void>;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var constants = require('../core/constants.js');
|
|
5
|
+
var state = require('../core/state.js');
|
|
6
|
+
var logger = require('../core/logger.js');
|
|
7
|
+
var utils = require('../core/utils.js');
|
|
8
|
+
var storage = require('../core/storage.js');
|
|
9
|
+
var transport = require('../core/transport.js');
|
|
10
|
+
var gate = require('./gate.js');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Delivery for the remote logger.
|
|
14
|
+
*
|
|
15
|
+
* v2 replaced console/addlog, which took one line per call and counted retries in an `attempt`
|
|
16
|
+
* param, with log/add, which takes a batch: `{ logs: [...], meta }`. A pass over the queue is now
|
|
17
|
+
* one request however many lines are waiting, so a burst of failures costs one call instead of
|
|
18
|
+
* twenty, and a line no longer has to carry its own retry bookkeeping — the batch either lands or
|
|
19
|
+
* stays for the next pass.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* What the stored lines may take up, as on Android (1 MB): past it the oldest are dropped, so a
|
|
23
|
+
* failing SDK or a chatty app can't fill storage. Measured in size rather than in lines, since one
|
|
24
|
+
* line can be a 10,000-character stack and another a word.
|
|
25
|
+
*/
|
|
26
|
+
const MAX_STORED_BYTES = 1024 * 1024;
|
|
27
|
+
/** Sends are grouped, so one broken flow that logs twice makes one pass over the queue. */
|
|
28
|
+
const SEND_DELAY_MS = 1000;
|
|
29
|
+
/** The endpoint takes a 10 MB body; a batch is capped well inside that. */
|
|
30
|
+
const MAX_PER_BATCH = 50;
|
|
31
|
+
const LABEL = 'remoteLog'; // no i18n
|
|
32
|
+
let sendScheduled = false;
|
|
33
|
+
let sending = false;
|
|
34
|
+
/**
|
|
35
|
+
* One stored line as logSDK wants it.
|
|
36
|
+
*
|
|
37
|
+
* `function` is where the module name goes — it is the only field describing *where* a line came
|
|
38
|
+
* from, and the template caps it at 100. `logmessage` is capped at 10000, so a long stack is
|
|
39
|
+
* trimmed rather than having the whole batch refused for one oversized line.
|
|
40
|
+
*/
|
|
41
|
+
function entryFor(item) {
|
|
42
|
+
var entry = {
|
|
43
|
+
sessionstarttime: state._ZAP._current_session.starttime || item.happenedat || utils.nowMs(),
|
|
44
|
+
logtime: item.happenedat || utils.nowMs(),
|
|
45
|
+
// an app's line carries the level it was logged at; the SDK's own failures carry none
|
|
46
|
+
level: Number(item.level) || constants.REMOTE_LOG_LEVEL,
|
|
47
|
+
logmessage: String(item.exceptionlog).slice(0, constants.CONSOLE_LOG_MAX_BODY),
|
|
48
|
+
function: String(item.module || 'SDK').slice(0, constants.LOG_FUNCTION_MAX), // no i18n
|
|
49
|
+
// the endpoint reads linenumber with getInt(), which throws on a missing key rather than
|
|
50
|
+
// defaulting, so it goes out on every line - 0 where the stack gave us no frame
|
|
51
|
+
linenumber: Number(item.linenumber) || 0,
|
|
52
|
+
};
|
|
53
|
+
// filename is read with optString and validated against file_name, whose pattern needs at
|
|
54
|
+
// least one character: sending '' would have the whole batch refused, so it is left out
|
|
55
|
+
if (!utils.isEmpty(item.filename)) {
|
|
56
|
+
entry.filename = String(item.filename).slice(0, constants.LOG_FILENAME_MAX);
|
|
57
|
+
}
|
|
58
|
+
return entry;
|
|
59
|
+
}
|
|
60
|
+
/** The batch body: `{ logs, meta }`, where meta is metaWebSDKV2 like every other v2 payload. */
|
|
61
|
+
function bodyFor(items) {
|
|
62
|
+
return JSON.stringify({ logs: items.map(entryFor), meta: transport.getMetaObj() }); // no i18n
|
|
63
|
+
}
|
|
64
|
+
/** Queues a pass over the stored lines, coalescing a burst into one. */
|
|
65
|
+
function scheduleSend() {
|
|
66
|
+
if (sendScheduled) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
sendScheduled = true;
|
|
70
|
+
setTimeout(function () {
|
|
71
|
+
sendScheduled = false;
|
|
72
|
+
sendStoredLogs();
|
|
73
|
+
}, SEND_DELAY_MS);
|
|
74
|
+
}
|
|
75
|
+
/** Drops the oldest lines once the queue is over MAX_STORED_BYTES, keeping the newest that fit. */
|
|
76
|
+
function trim(items) {
|
|
77
|
+
var total = 0;
|
|
78
|
+
var keepFrom = items.length;
|
|
79
|
+
// newest first: they are the ones worth keeping
|
|
80
|
+
for (var i = items.length - 1; i >= 0; i--) {
|
|
81
|
+
total += JSON.stringify(items[i]).length;
|
|
82
|
+
if (total > MAX_STORED_BYTES) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
keepFrom = i;
|
|
86
|
+
}
|
|
87
|
+
if (keepFrom === 0) {
|
|
88
|
+
return items;
|
|
89
|
+
}
|
|
90
|
+
storage.consolelog_transactions.remove(items.slice(0, keepFrom));
|
|
91
|
+
return items.slice(keepFrom);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Sends the stored lines as one batch. A batch the server refuses for its shape is dropped —
|
|
95
|
+
* retrying it could only fail the same way and would hold every later line behind it.
|
|
96
|
+
*/
|
|
97
|
+
function sendStoredLogs() {
|
|
98
|
+
if (sending || !gate.remoteLogSendable() || navigator.onLine === false) {
|
|
99
|
+
return Promise.resolve();
|
|
100
|
+
}
|
|
101
|
+
sending = true;
|
|
102
|
+
return storage.consolelog_transactions.all().then(function (stored) {
|
|
103
|
+
var batch = trim(stored).slice(0, MAX_PER_BATCH);
|
|
104
|
+
if (batch.length === 0) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
return transport.postToApptics('consolelog', bodyFor(batch), transport.apiHeaders(), LABEL).then(function () {
|
|
108
|
+
return storage.consolelog_transactions.remove(batch);
|
|
109
|
+
}, function (err) {
|
|
110
|
+
if (transport.isPermanentRefusal(err)) {
|
|
111
|
+
logger.warnAlways('apptics: the server refused these log lines, so they were dropped: ' + String(err && err.message)); // no i18n
|
|
112
|
+
return storage.consolelog_transactions.remove(batch);
|
|
113
|
+
}
|
|
114
|
+
logger.Console.log(LABEL + ': ' + String(err)); // no i18n
|
|
115
|
+
return undefined;
|
|
116
|
+
});
|
|
117
|
+
}).then(function () {
|
|
118
|
+
sending = false;
|
|
119
|
+
}).catch(function () {
|
|
120
|
+
sending = false;
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Sends what is stored as the page goes away, where a normal request would be cancelled.
|
|
125
|
+
* One keepalive request for the whole batch, which is what the endpoint now accepts. The lines
|
|
126
|
+
* stay stored until the server has confirmed them.
|
|
127
|
+
*/
|
|
128
|
+
function forgetStoredLogs() {
|
|
129
|
+
if (!gate.remoteLogSendable()) {
|
|
130
|
+
return Promise.resolve();
|
|
131
|
+
}
|
|
132
|
+
return storage.consolelog_transactions.all().then(function (stored) {
|
|
133
|
+
if (stored.length === 0) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
var batch = stored.slice(0, MAX_PER_BATCH);
|
|
137
|
+
// removed once the server has them; lines whose answer never comes go on the next visit
|
|
138
|
+
transport.postKeepalive('consolelog', bodyFor(batch), transport.apiHeaders(), LABEL).then(function () {
|
|
139
|
+
return storage.consolelog_transactions.remove(batch);
|
|
140
|
+
}, function (err) {
|
|
141
|
+
if (transport.isPermanentRefusal(err)) {
|
|
142
|
+
return storage.consolelog_transactions.remove(batch);
|
|
143
|
+
}
|
|
144
|
+
logger.Console.log(LABEL + ': ' + String(err)); // no i18n
|
|
145
|
+
return undefined;
|
|
146
|
+
});
|
|
147
|
+
return undefined;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
exports.forgetStoredLogs = forgetStoredLogs;
|
|
152
|
+
exports.scheduleSend = scheduleSend;
|
|
153
|
+
exports.sendStoredLogs = sendStoredLogs;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sends everything queued now. With `forget`, the requests are sent without waiting for a
|
|
3
|
+
* response (page hide), so they survive the page going away.
|
|
4
|
+
*/
|
|
5
|
+
export declare function flush(forget?: boolean): Promise<void>;
|
|
6
|
+
/** Starts the flush and getupdates intervals once; later calls do nothing until stopTimers(). */
|
|
7
|
+
export declare function startTimers(): void;
|
|
8
|
+
export declare function stopTimers(): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var state = require('./core/state.js');
|
|
5
|
+
var utils = require('./core/utils.js');
|
|
6
|
+
var logger = require('./core/logger.js');
|
|
7
|
+
var consent = require('./core/consent.js');
|
|
8
|
+
var batch = require('./core/batch.js');
|
|
9
|
+
var send = require('./engagement/send.js');
|
|
10
|
+
var send$1 = require('./errors/send.js');
|
|
11
|
+
var hooks = require('./core/hooks.js');
|
|
12
|
+
var index = require('./device/index.js');
|
|
13
|
+
var debug = require('./core/debug.js');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sends everything queued now. With `forget`, the requests are sent without waiting for a
|
|
17
|
+
* response (page hide), so they survive the page going away.
|
|
18
|
+
*/
|
|
19
|
+
function flush(forget) {
|
|
20
|
+
if (!consent.canTrack('flush')) { // no i18n
|
|
21
|
+
return Promise.resolve();
|
|
22
|
+
}
|
|
23
|
+
state._ZAP._sending = false;
|
|
24
|
+
// one after the other: sending both at once makes the second wait for the 500 ms retry
|
|
25
|
+
return send.sendEngagementData(forget).then(function () {
|
|
26
|
+
return send$1.sendErrorData(forget);
|
|
27
|
+
}).then(function () {
|
|
28
|
+
// no-op unless the heatmap entry was imported, which is what sets the hook
|
|
29
|
+
return hooks.hooks.sendHeatmaps(forget);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
var sendingInterval = null;
|
|
33
|
+
var getUpdatesInterval = null;
|
|
34
|
+
/** Starts the flush and getupdates intervals once; later calls do nothing until stopTimers(). */
|
|
35
|
+
function startTimers() {
|
|
36
|
+
if (sendingInterval === null) {
|
|
37
|
+
sendingInterval = setInterval(function () {
|
|
38
|
+
// the only tick that happens whether or not anything is being tracked, which is
|
|
39
|
+
// exactly the case debug mode has to expire in
|
|
40
|
+
debug.expireDebugIfIdle();
|
|
41
|
+
logger.Console.log('scheduleToSendDataToServer: Scheduling to send engagement data to the server after sometime'); // no i18n
|
|
42
|
+
// one after the other, as flush() does: run together, the second and third find the
|
|
43
|
+
// first still sending and are deferred, and the third's retry replaces the second's
|
|
44
|
+
send.sendEngagementData().then(function () {
|
|
45
|
+
return send$1.sendErrorData();
|
|
46
|
+
}).then(function () {
|
|
47
|
+
return hooks.hooks.sendHeatmaps();
|
|
48
|
+
});
|
|
49
|
+
}, state.getConfig('batch_flush_interval')); // no i18n
|
|
50
|
+
}
|
|
51
|
+
if (getUpdatesInterval === null) {
|
|
52
|
+
// the interval is the floor, not the schedule: getsdkconfig answers with next_check_after,
|
|
53
|
+
// and asking again before then is a call the server has already told us it will not answer
|
|
54
|
+
// differently. The timer still ticks so a server that sends no hint behaves as before.
|
|
55
|
+
getUpdatesInterval = setInterval(function () {
|
|
56
|
+
if (state._ZAP._nextConfigCheck > 0 && utils.nowMs() < state._ZAP._nextConfigCheck) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
logger.Console.log('scheduleToGetUpdatesFromServer: asking the server for its config'); // no i18n
|
|
60
|
+
index.getUpdatesFromServer().catch(function (err) {
|
|
61
|
+
logger.Console.log(err);
|
|
62
|
+
});
|
|
63
|
+
}, state.getConfig('getupdates_interval')); // no i18n
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function stopTimers() {
|
|
67
|
+
if (sendingInterval !== null)
|
|
68
|
+
clearInterval(sendingInterval);
|
|
69
|
+
if (getUpdatesInterval !== null)
|
|
70
|
+
clearInterval(getUpdatesInterval);
|
|
71
|
+
sendingInterval = null;
|
|
72
|
+
getUpdatesInterval = null;
|
|
73
|
+
batch.clearDefer();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
exports.flush = flush;
|
|
77
|
+
exports.startTimers = startTimers;
|
|
78
|
+
exports.stopTimers = stopTimers;
|