@log-drop/web 1.0.0-alpha2 → 1.0.0-alpha4
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/README.md +1 -3
- package/dist/index.cjs +334 -23
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js +334 -23
- package/dist/index.js.map +3 -3
- package/dist/logdrop-sw.js +2 -2
- package/dist/logdrop.min.js +2 -2
- package/dist/logdrop.min.js.map +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,6 @@ import { LogDrop } from "@log-drop/web";
|
|
|
13
13
|
|
|
14
14
|
LogDrop.init({
|
|
15
15
|
appId: "your-app-id",
|
|
16
|
-
apiKey: "your-api-key",
|
|
17
16
|
release: "1.0.0",
|
|
18
17
|
});
|
|
19
18
|
```
|
|
@@ -25,7 +24,7 @@ Load a pinned stable SDK version from the LogDrop CDN:
|
|
|
25
24
|
```html
|
|
26
25
|
<script src="https://cdn.logdrop.io/PUBLIC_FILES/logdrop-web-sdk/release/1.0.0/logdrop.min.js"></script>
|
|
27
26
|
<script>
|
|
28
|
-
LogDrop.init({ appId: "your-app-id"
|
|
27
|
+
LogDrop.init({ appId: "your-app-id" });
|
|
29
28
|
</script>
|
|
30
29
|
```
|
|
31
30
|
|
|
@@ -36,7 +35,6 @@ Copy the exported `logdrop-sw.js` file to the website's own public directory, th
|
|
|
36
35
|
```js
|
|
37
36
|
LogDrop.init({
|
|
38
37
|
appId: "your-app-id",
|
|
39
|
-
apiKey: "your-api-key",
|
|
40
38
|
serviceWorkerUrl: "/logdrop-sw.js",
|
|
41
39
|
serviceWorkerScope: "/",
|
|
42
40
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,7 @@ LogDropConstants.DEFAULT_BASE_URL = "https://server.logdrop.io";
|
|
|
38
38
|
LogDropConstants.DEFAULT_WEB_SECRET_KEY = "xuM9w0BAQEFx";
|
|
39
39
|
LogDropConstants.FILE_EXPORT_INTERVAL_MS = 3e5;
|
|
40
40
|
LogDropConstants.DEVICE_INFO_INTERVAL_MS = 1e4;
|
|
41
|
-
LogDropConstants.SDK_VERSION = true ? "1.0.0-
|
|
41
|
+
LogDropConstants.SDK_VERSION = true ? "1.0.0-alpha4" : "1.0.0";
|
|
42
42
|
LogDropConstants.STORAGE_CHECK_INTERVAL_MS = 12e4;
|
|
43
43
|
LogDropConstants.MAX_LOCAL_STORAGE_SIZE = 5242880;
|
|
44
44
|
LogDropConstants.DATABASE_MAX_STORAGE_LIMIT = 16e6;
|
|
@@ -540,6 +540,168 @@ var NetworkInstrumentation = class {
|
|
|
540
540
|
}
|
|
541
541
|
};
|
|
542
542
|
|
|
543
|
+
// src/instrumentation/httpCapturePolicy.js
|
|
544
|
+
var ALWAYS_MASKED_HEADERS = /* @__PURE__ */ new Set([
|
|
545
|
+
"authorization",
|
|
546
|
+
"proxy-authorization",
|
|
547
|
+
"x-auth-token",
|
|
548
|
+
"x-api-key",
|
|
549
|
+
"x-session-token",
|
|
550
|
+
"cookie",
|
|
551
|
+
"set-cookie"
|
|
552
|
+
]);
|
|
553
|
+
var MASK = "***";
|
|
554
|
+
var MAX_PATTERN_LENGTH = 500;
|
|
555
|
+
var DANGEROUS_PATTERN = /(a\+)\+|\(\.\*\)\+|\(\.\+\)\+/;
|
|
556
|
+
function normalizeHost(value) {
|
|
557
|
+
const host = String(value ?? "").trim().replace(/\.+$/, "").toLowerCase();
|
|
558
|
+
if (!host || /[/:?#@]/.test(host) || host.length > 253) return null;
|
|
559
|
+
return host;
|
|
560
|
+
}
|
|
561
|
+
function normalizePath(value) {
|
|
562
|
+
const trimmed = String(value ?? "").trim();
|
|
563
|
+
if (!trimmed) return "/";
|
|
564
|
+
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
565
|
+
return withSlash.length > 1 ? withSlash.replace(/\/+$/, "") : withSlash;
|
|
566
|
+
}
|
|
567
|
+
function domainMatches(host, ruleHost) {
|
|
568
|
+
return host === ruleHost || host.endsWith(`.${ruleHost}`);
|
|
569
|
+
}
|
|
570
|
+
function pathMatches(path, rulePath, matchType) {
|
|
571
|
+
if (matchType === "EXACT") return path === rulePath;
|
|
572
|
+
if (matchType === "PREFIX") return rulePath === "/" || path === rulePath || path.startsWith(`${rulePath}/`);
|
|
573
|
+
return false;
|
|
574
|
+
}
|
|
575
|
+
function parseUrl(url) {
|
|
576
|
+
try {
|
|
577
|
+
const parsed = new URL(String(url ?? ""));
|
|
578
|
+
const host = normalizeHost(parsed.hostname);
|
|
579
|
+
return host ? { host, path: normalizePath(parsed.pathname) } : null;
|
|
580
|
+
} catch {
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
function compileSensitivePatterns(filters) {
|
|
585
|
+
const patterns = [];
|
|
586
|
+
for (const filter of Array.isArray(filters) ? filters : []) {
|
|
587
|
+
const source = String(filter ?? "");
|
|
588
|
+
if (!source || source.length > MAX_PATTERN_LENGTH) continue;
|
|
589
|
+
const parts = source.match(/^\/(.+)\/([gimsuy]*)$/);
|
|
590
|
+
const body = parts ? parts[1] : source;
|
|
591
|
+
if (DANGEROUS_PATTERN.test(body)) continue;
|
|
592
|
+
let flags = parts ? parts[2] : "";
|
|
593
|
+
if (!flags.includes("g")) flags += "g";
|
|
594
|
+
if (!flags.includes("i")) flags += "i";
|
|
595
|
+
try {
|
|
596
|
+
patterns.push(new RegExp(body, flags));
|
|
597
|
+
} catch {
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return patterns;
|
|
601
|
+
}
|
|
602
|
+
function hashString(text) {
|
|
603
|
+
let hash = 2166136261;
|
|
604
|
+
for (let i = 0; i < text.length; i++) {
|
|
605
|
+
hash ^= text.charCodeAt(i);
|
|
606
|
+
hash = Math.imul(hash, 16777619);
|
|
607
|
+
}
|
|
608
|
+
return (hash >>> 0).toString(16);
|
|
609
|
+
}
|
|
610
|
+
function buildHttpCapturePolicy(config) {
|
|
611
|
+
const policy = {
|
|
612
|
+
domainBlacklist: (config?.httpDomainBlackList ?? []).map(normalizeHost).filter(Boolean),
|
|
613
|
+
pathBlacklist: Array.isArray(config?.httpPathBlackList) ? config.httpPathBlackList : [],
|
|
614
|
+
captureConfig: config?.httpPayloadCaptureConfig ?? null,
|
|
615
|
+
sensitivePatterns: compileSensitivePatterns(config?.sensitiveInfoFilter)
|
|
616
|
+
};
|
|
617
|
+
policy.fingerprint = hashString(JSON.stringify([
|
|
618
|
+
policy.domainBlacklist,
|
|
619
|
+
policy.pathBlacklist,
|
|
620
|
+
policy.captureConfig,
|
|
621
|
+
policy.sensitivePatterns.map((pattern) => `${pattern.source}/${pattern.flags}`)
|
|
622
|
+
]));
|
|
623
|
+
return policy;
|
|
624
|
+
}
|
|
625
|
+
function shouldIgnoreHttpUrl(url, policy) {
|
|
626
|
+
const target = parseUrl(url);
|
|
627
|
+
if (!target || !policy) return false;
|
|
628
|
+
if (policy.domainBlacklist.some((domain) => domainMatches(target.host, domain))) return true;
|
|
629
|
+
return policy.pathBlacklist.some((rule) => {
|
|
630
|
+
const ruleHost = normalizeHost(rule?.host);
|
|
631
|
+
if (!ruleHost || !domainMatches(target.host, ruleHost)) return false;
|
|
632
|
+
return pathMatches(target.path, normalizePath(rule.path), rule.matchType);
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
function resolveDisabledPayloadFields(url, captureConfig) {
|
|
636
|
+
const disabled = {
|
|
637
|
+
requestHeaders: captureConfig?.disableRequestHeaders === true,
|
|
638
|
+
requestBody: captureConfig?.disableRequestBody === true,
|
|
639
|
+
responseHeaders: captureConfig?.disableResponseHeaders === true,
|
|
640
|
+
responseBody: captureConfig?.disableResponseBody === true
|
|
641
|
+
};
|
|
642
|
+
const target = parseUrl(url);
|
|
643
|
+
if (!captureConfig || !target) return disabled;
|
|
644
|
+
for (const rule of captureConfig.rules ?? []) {
|
|
645
|
+
const ruleHost = normalizeHost(rule?.host);
|
|
646
|
+
if (!ruleHost || !domainMatches(target.host, ruleHost)) continue;
|
|
647
|
+
if (rule.path && String(rule.path).trim() && !pathMatches(target.path, normalizePath(rule.path), rule.matchType)) {
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
disabled.requestHeaders || (disabled.requestHeaders = rule.disableRequestHeaders === true);
|
|
651
|
+
disabled.requestBody || (disabled.requestBody = rule.disableRequestBody === true);
|
|
652
|
+
disabled.responseHeaders || (disabled.responseHeaders = rule.disableResponseHeaders === true);
|
|
653
|
+
disabled.responseBody || (disabled.responseBody = rule.disableResponseBody === true);
|
|
654
|
+
}
|
|
655
|
+
return disabled;
|
|
656
|
+
}
|
|
657
|
+
function maskSensitive(text, patterns) {
|
|
658
|
+
if (typeof text !== "string" || !patterns?.length) return text;
|
|
659
|
+
let output = text;
|
|
660
|
+
for (const regex of patterns) {
|
|
661
|
+
regex.lastIndex = 0;
|
|
662
|
+
output = output.replace(regex, (...args) => {
|
|
663
|
+
const groups = args.slice(1, -2).filter((group) => typeof group === "string" || group === void 0);
|
|
664
|
+
const present = groups.filter((group) => group !== void 0 && group !== "");
|
|
665
|
+
if (present.length === 3) return `${groups[0]}${MASK}${groups[2]}`;
|
|
666
|
+
if (present.length === 2) return `${groups[0]}${MASK}`;
|
|
667
|
+
return MASK;
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
return output;
|
|
671
|
+
}
|
|
672
|
+
function maskStructured(value, patterns) {
|
|
673
|
+
if (value == null || !patterns.length) return value;
|
|
674
|
+
if (typeof value === "string") return maskSensitive(value, patterns);
|
|
675
|
+
try {
|
|
676
|
+
return JSON.parse(maskSensitive(JSON.stringify(value), patterns));
|
|
677
|
+
} catch {
|
|
678
|
+
return value;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
function maskCredentialHeaders(headers) {
|
|
682
|
+
if (!headers || typeof headers !== "object") return {};
|
|
683
|
+
const out = {};
|
|
684
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
685
|
+
out[key] = ALWAYS_MASKED_HEADERS.has(String(key).toLowerCase()) ? MASK : value;
|
|
686
|
+
}
|
|
687
|
+
return out;
|
|
688
|
+
}
|
|
689
|
+
function applyHttpCapturePolicy(payload, policy) {
|
|
690
|
+
if (!payload) return null;
|
|
691
|
+
const effective = policy ?? buildHttpCapturePolicy(null);
|
|
692
|
+
if (shouldIgnoreHttpUrl(payload.url, effective)) return null;
|
|
693
|
+
const disabled = resolveDisabledPayloadFields(payload.url, effective.captureConfig);
|
|
694
|
+
const patterns = effective.sensitivePatterns;
|
|
695
|
+
return {
|
|
696
|
+
...payload,
|
|
697
|
+
url: maskSensitive(String(payload.url ?? ""), patterns),
|
|
698
|
+
requestHeaders: disabled.requestHeaders ? {} : maskStructured(maskCredentialHeaders(payload.requestHeaders), patterns),
|
|
699
|
+
requestBody: disabled.requestBody ? null : maskStructured(payload.requestBody ?? null, patterns),
|
|
700
|
+
responseHeaders: disabled.responseHeaders ? {} : maskStructured(maskCredentialHeaders(payload.responseHeaders), patterns),
|
|
701
|
+
responseBody: disabled.responseBody ? null : maskStructured(payload.responseBody ?? null, patterns)
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
|
|
543
705
|
// src/push/pushModule.js
|
|
544
706
|
function hasWindow2() {
|
|
545
707
|
return typeof window !== "undefined";
|
|
@@ -569,7 +731,7 @@ var PushModule = class {
|
|
|
569
731
|
* serviceWorkerRegistration?: ServiceWorkerRegistration | null,
|
|
570
732
|
* isPushEnabled?: boolean,
|
|
571
733
|
* onRemoteMessageReceived?: ((payload: any) => void) | null,
|
|
572
|
-
*
|
|
734
|
+
* appId?: string,
|
|
573
735
|
* apiBase?: string,
|
|
574
736
|
* deviceId?: string,
|
|
575
737
|
* getSessionToken?: (() => string | null) | null,
|
|
@@ -587,7 +749,7 @@ var PushModule = class {
|
|
|
587
749
|
this.serviceWorkerRegistration = cfg.serviceWorkerRegistration ?? null;
|
|
588
750
|
this.isPushEnabled = cfg.isPushEnabled !== false;
|
|
589
751
|
this.onRemoteMessageReceived = typeof cfg.onRemoteMessageReceived === "function" ? cfg.onRemoteMessageReceived : null;
|
|
590
|
-
this.
|
|
752
|
+
this.appId = cfg.appId ?? null;
|
|
591
753
|
this.apiBase = cfg.apiBase ?? "";
|
|
592
754
|
this.deviceId = cfg.deviceId ?? null;
|
|
593
755
|
this.getSessionToken = typeof cfg.getSessionToken === "function" ? cfg.getSessionToken : null;
|
|
@@ -909,7 +1071,7 @@ var PushModule = class {
|
|
|
909
1071
|
config: {
|
|
910
1072
|
vapidPublicKey: this.vapidPublicKey,
|
|
911
1073
|
apiBase: this.apiBase,
|
|
912
|
-
|
|
1074
|
+
appId: this.appId,
|
|
913
1075
|
sessionToken: this.getSessionToken ? this.getSessionToken() : null,
|
|
914
1076
|
deviceUuid: this.deviceId
|
|
915
1077
|
}
|
|
@@ -1725,6 +1887,105 @@ function decodeWebPushConfig(buf) {
|
|
|
1725
1887
|
}
|
|
1726
1888
|
return result;
|
|
1727
1889
|
}
|
|
1890
|
+
var HTTP_PATH_MATCH_TYPES = ["EXACT", "PREFIX"];
|
|
1891
|
+
function decodeHttpPathMatchType(value) {
|
|
1892
|
+
return HTTP_PATH_MATCH_TYPES[value] ?? null;
|
|
1893
|
+
}
|
|
1894
|
+
function decodeHttpPathBlacklistRule(buf) {
|
|
1895
|
+
const r = new ProtoReader(buf);
|
|
1896
|
+
const result = { host: "", path: "", matchType: "EXACT" };
|
|
1897
|
+
while (r.hasMore()) {
|
|
1898
|
+
const tag = r.readTag();
|
|
1899
|
+
switch (tag.fieldNumber) {
|
|
1900
|
+
case 1:
|
|
1901
|
+
result.host = r.readString();
|
|
1902
|
+
break;
|
|
1903
|
+
case 2:
|
|
1904
|
+
result.path = r.readString();
|
|
1905
|
+
break;
|
|
1906
|
+
case 3:
|
|
1907
|
+
result.matchType = decodeHttpPathMatchType(r.readVarint());
|
|
1908
|
+
break;
|
|
1909
|
+
default:
|
|
1910
|
+
r.skip(tag.wireType);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
return result;
|
|
1914
|
+
}
|
|
1915
|
+
function decodeHttpPayloadCaptureRule(buf) {
|
|
1916
|
+
const r = new ProtoReader(buf);
|
|
1917
|
+
const result = {
|
|
1918
|
+
host: "",
|
|
1919
|
+
path: null,
|
|
1920
|
+
matchType: "EXACT",
|
|
1921
|
+
disableRequestHeaders: false,
|
|
1922
|
+
disableRequestBody: false,
|
|
1923
|
+
disableResponseHeaders: false,
|
|
1924
|
+
disableResponseBody: false
|
|
1925
|
+
};
|
|
1926
|
+
while (r.hasMore()) {
|
|
1927
|
+
const tag = r.readTag();
|
|
1928
|
+
switch (tag.fieldNumber) {
|
|
1929
|
+
case 1:
|
|
1930
|
+
result.host = r.readString();
|
|
1931
|
+
break;
|
|
1932
|
+
case 2:
|
|
1933
|
+
result.path = r.readString();
|
|
1934
|
+
break;
|
|
1935
|
+
case 3:
|
|
1936
|
+
result.matchType = decodeHttpPathMatchType(r.readVarint());
|
|
1937
|
+
break;
|
|
1938
|
+
case 4:
|
|
1939
|
+
result.disableRequestHeaders = r.readBool();
|
|
1940
|
+
break;
|
|
1941
|
+
case 5:
|
|
1942
|
+
result.disableRequestBody = r.readBool();
|
|
1943
|
+
break;
|
|
1944
|
+
case 6:
|
|
1945
|
+
result.disableResponseHeaders = r.readBool();
|
|
1946
|
+
break;
|
|
1947
|
+
case 7:
|
|
1948
|
+
result.disableResponseBody = r.readBool();
|
|
1949
|
+
break;
|
|
1950
|
+
default:
|
|
1951
|
+
r.skip(tag.wireType);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
return result;
|
|
1955
|
+
}
|
|
1956
|
+
function decodeHttpPayloadCaptureConfig(buf) {
|
|
1957
|
+
const r = new ProtoReader(buf);
|
|
1958
|
+
const result = {
|
|
1959
|
+
disableRequestHeaders: false,
|
|
1960
|
+
disableRequestBody: false,
|
|
1961
|
+
disableResponseHeaders: false,
|
|
1962
|
+
disableResponseBody: false,
|
|
1963
|
+
rules: []
|
|
1964
|
+
};
|
|
1965
|
+
while (r.hasMore()) {
|
|
1966
|
+
const tag = r.readTag();
|
|
1967
|
+
switch (tag.fieldNumber) {
|
|
1968
|
+
case 1:
|
|
1969
|
+
result.disableRequestHeaders = r.readBool();
|
|
1970
|
+
break;
|
|
1971
|
+
case 2:
|
|
1972
|
+
result.disableRequestBody = r.readBool();
|
|
1973
|
+
break;
|
|
1974
|
+
case 3:
|
|
1975
|
+
result.disableResponseHeaders = r.readBool();
|
|
1976
|
+
break;
|
|
1977
|
+
case 4:
|
|
1978
|
+
result.disableResponseBody = r.readBool();
|
|
1979
|
+
break;
|
|
1980
|
+
case 5:
|
|
1981
|
+
result.rules.push(decodeHttpPayloadCaptureRule(r.readBytes()));
|
|
1982
|
+
break;
|
|
1983
|
+
default:
|
|
1984
|
+
r.skip(tag.wireType);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
return result;
|
|
1988
|
+
}
|
|
1728
1989
|
function decodeSdkRiskConfig(buf) {
|
|
1729
1990
|
const r = new ProtoReader(buf);
|
|
1730
1991
|
const result = {
|
|
@@ -1761,6 +2022,8 @@ function decodeConfigResponse(buf) {
|
|
|
1761
2022
|
isCrashTrackingEnabled: false,
|
|
1762
2023
|
isEventTrackingEnabled: false,
|
|
1763
2024
|
httpDomainBlackList: [],
|
|
2025
|
+
httpPathBlackList: [],
|
|
2026
|
+
httpPayloadCaptureConfig: null,
|
|
1764
2027
|
sensitiveInfoFilter: [],
|
|
1765
2028
|
sslPinning: null,
|
|
1766
2029
|
accessToken: "",
|
|
@@ -1821,6 +2084,12 @@ function decodeConfigResponse(buf) {
|
|
|
1821
2084
|
case 15:
|
|
1822
2085
|
result.isEventTrackingEnabled = r.readBool();
|
|
1823
2086
|
break;
|
|
2087
|
+
case 16:
|
|
2088
|
+
result.httpPathBlackList.push(decodeHttpPathBlacklistRule(r.readBytes()));
|
|
2089
|
+
break;
|
|
2090
|
+
case 17:
|
|
2091
|
+
result.httpPayloadCaptureConfig = decodeHttpPayloadCaptureConfig(r.readBytes());
|
|
2092
|
+
break;
|
|
1824
2093
|
case 18:
|
|
1825
2094
|
result.webPushConfig = decodeWebPushConfig(r.readBytes());
|
|
1826
2095
|
break;
|
|
@@ -1990,7 +2259,7 @@ var EventModule = class {
|
|
|
1990
2259
|
* getSessionId: () => string,
|
|
1991
2260
|
* getUserUuid: () => string|null,
|
|
1992
2261
|
* release: string|undefined,
|
|
1993
|
-
*
|
|
2262
|
+
* appId: string,
|
|
1994
2263
|
* apiBase: string,
|
|
1995
2264
|
* isEventTrackingEnabled: boolean,
|
|
1996
2265
|
* isFirstVisit: boolean,
|
|
@@ -2007,7 +2276,7 @@ var EventModule = class {
|
|
|
2007
2276
|
this._logEvent = typeof cfg.logEvent === "function" ? cfg.logEvent : null;
|
|
2008
2277
|
this._getSessionToken = typeof cfg.getSessionToken === "function" ? cfg.getSessionToken : null;
|
|
2009
2278
|
this._release = cfg.release ?? void 0;
|
|
2010
|
-
this.
|
|
2279
|
+
this._appId = cfg.appId ?? "";
|
|
2011
2280
|
this._apiBase = cfg.apiBase ?? "";
|
|
2012
2281
|
this._isEventTrackingEnabled = cfg.isEventTrackingEnabled === true;
|
|
2013
2282
|
this._isFirstVisit = cfg.isFirstVisit === true;
|
|
@@ -2311,7 +2580,7 @@ var EventModule = class {
|
|
|
2311
2580
|
headers: {
|
|
2312
2581
|
"Content-Type": "application/x-protobuf",
|
|
2313
2582
|
"Accept": "application/x-protobuf",
|
|
2314
|
-
"x-api-key": this.
|
|
2583
|
+
"x-api-key": this._appId,
|
|
2315
2584
|
"x-session-token": sessionToken
|
|
2316
2585
|
},
|
|
2317
2586
|
body: new Blob([protoBytes], { type: "application/x-protobuf" })
|
|
@@ -3504,6 +3773,7 @@ var LogDropClient = class {
|
|
|
3504
3773
|
};
|
|
3505
3774
|
this._activeIpReputationAction = this._loadStoredIpReputationAction();
|
|
3506
3775
|
this._ipReputationExpiryTimer = null;
|
|
3776
|
+
this._httpCapturePolicy = null;
|
|
3507
3777
|
this._loadCachedServerConfig();
|
|
3508
3778
|
this._user = this._loadPersistedExternalUser();
|
|
3509
3779
|
this._errorHandlersInstalled = false;
|
|
@@ -4060,9 +4330,9 @@ var LogDropClient = class {
|
|
|
4060
4330
|
const fetchFn = hasWindow5() ? window.fetch : typeof fetch !== "undefined" ? fetch : null;
|
|
4061
4331
|
if (typeof fetchFn !== "function") return false;
|
|
4062
4332
|
const osInfo = this._getOsInfo();
|
|
4063
|
-
const last = this._lastSentUserUpdate?.
|
|
4333
|
+
const last = this._lastSentUserUpdate?.appId === config.appId ? this._lastSentUserUpdate : null;
|
|
4064
4334
|
const runtime = {
|
|
4065
|
-
|
|
4335
|
+
appId: config.appId,
|
|
4066
4336
|
userUuid: task.userUuid,
|
|
4067
4337
|
osName: osInfo.osName,
|
|
4068
4338
|
osVersion: osInfo.osVersion,
|
|
@@ -4092,7 +4362,7 @@ var LogDropClient = class {
|
|
|
4092
4362
|
const headers = {
|
|
4093
4363
|
"content-type": "application/x-protobuf",
|
|
4094
4364
|
"accept": "application/x-protobuf",
|
|
4095
|
-
"x-api-key": config.
|
|
4365
|
+
"x-api-key": config.appId
|
|
4096
4366
|
};
|
|
4097
4367
|
let usedSignatureAuth = false;
|
|
4098
4368
|
if (sessionToken) {
|
|
@@ -4330,6 +4600,7 @@ var LogDropClient = class {
|
|
|
4330
4600
|
if (typeof parsed.data.isSDKDisabled === "boolean") {
|
|
4331
4601
|
this._serverConfig.isSDKDisabled = parsed.data.isSDKDisabled;
|
|
4332
4602
|
}
|
|
4603
|
+
this._httpCapturePolicy = buildHttpCapturePolicy(parsed.data);
|
|
4333
4604
|
}
|
|
4334
4605
|
}
|
|
4335
4606
|
} catch {
|
|
@@ -4351,6 +4622,9 @@ var LogDropClient = class {
|
|
|
4351
4622
|
if (typeof data.isHttpLoggingEnabled === "boolean") {
|
|
4352
4623
|
this._serverConfig.isHttpLoggingEnabled = data.isHttpLoggingEnabled;
|
|
4353
4624
|
}
|
|
4625
|
+
if ("httpDomainBlackList" in data || "httpPayloadCaptureConfig" in data || "sensitiveInfoFilter" in data) {
|
|
4626
|
+
this._httpCapturePolicy = buildHttpCapturePolicy(data);
|
|
4627
|
+
}
|
|
4354
4628
|
if (typeof data.isCrashTrackingEnabled === "boolean" && this._crashTrackingOverride === null) {
|
|
4355
4629
|
this._serverConfig.isCrashTrackingEnabled = data.isCrashTrackingEnabled;
|
|
4356
4630
|
}
|
|
@@ -4410,7 +4684,7 @@ var LogDropClient = class {
|
|
|
4410
4684
|
onEvent: (eventName, payload) => {
|
|
4411
4685
|
if (eventName !== "network_activity") return;
|
|
4412
4686
|
if (!this._serverConfig.isHttpLoggingEnabled || !this._config?.network?.enabled) return;
|
|
4413
|
-
this.
|
|
4687
|
+
this._recordNetworkActivity(payload);
|
|
4414
4688
|
},
|
|
4415
4689
|
getBaseHref,
|
|
4416
4690
|
excludeUrls: this._config.network.excludeUrls,
|
|
@@ -4429,6 +4703,31 @@ var LogDropClient = class {
|
|
|
4429
4703
|
});
|
|
4430
4704
|
this._net.install();
|
|
4431
4705
|
}
|
|
4706
|
+
_recordNetworkActivity(payload) {
|
|
4707
|
+
const recorded = applyHttpCapturePolicy(payload, this._httpCapturePolicy);
|
|
4708
|
+
if (!recorded) return;
|
|
4709
|
+
this._enqueue(LogLevel.NETWORK_ACTIVITY, recorded, new LogFlow("NetworkActivity", recorded.uuid));
|
|
4710
|
+
}
|
|
4711
|
+
// Logs captured before the init response, or under rules that have changed
|
|
4712
|
+
// since, are filtered again with the current policy before upload; logs
|
|
4713
|
+
// stored under the same rules are sent as they are. Returns null when the
|
|
4714
|
+
// log must be dropped.
|
|
4715
|
+
_applyHttpCapturePolicyToStoredLog(log) {
|
|
4716
|
+
const policy = this._httpCapturePolicy;
|
|
4717
|
+
if (!policy || log.level === LogLevel.DEVICEINFO) return log.message;
|
|
4718
|
+
if (log.httpPolicyFingerprint === policy.fingerprint) return log.message;
|
|
4719
|
+
if (log.level !== LogLevel.NETWORK_ACTIVITY) {
|
|
4720
|
+
return maskSensitive(log.message, policy.sensitivePatterns);
|
|
4721
|
+
}
|
|
4722
|
+
let parsed;
|
|
4723
|
+
try {
|
|
4724
|
+
parsed = JSON.parse(log.message);
|
|
4725
|
+
} catch {
|
|
4726
|
+
return maskSensitive(log.message, policy.sensitivePatterns);
|
|
4727
|
+
}
|
|
4728
|
+
const recorded = applyHttpCapturePolicy(parsed, policy);
|
|
4729
|
+
return recorded ? safeStringify(recorded) : null;
|
|
4730
|
+
}
|
|
4432
4731
|
_uninstallNetworkInstrumentation() {
|
|
4433
4732
|
if (this._net) {
|
|
4434
4733
|
this._net.uninstall();
|
|
@@ -4643,9 +4942,8 @@ var LogDropClient = class {
|
|
|
4643
4942
|
this._warnInternal("[LogDrop] SDK is disabled by server configuration");
|
|
4644
4943
|
return;
|
|
4645
4944
|
}
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
if (!apiKey) throw new Error("LogDrop.init requires config.apiKey");
|
|
4945
|
+
const appId = String(config?.appId || "").trim();
|
|
4946
|
+
if (!appId) throw new Error("LogDrop.init requires config.appId");
|
|
4649
4947
|
const defaultWebSecretKey = config.webSecretKey == null ? LogDropConstants.DEFAULT_WEB_SECRET_KEY : config.webSecretKey;
|
|
4650
4948
|
const webSecretKey = String(defaultWebSecretKey || "").trim() || null;
|
|
4651
4949
|
const baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
@@ -4672,8 +4970,7 @@ var LogDropClient = class {
|
|
|
4672
4970
|
]
|
|
4673
4971
|
};
|
|
4674
4972
|
this._config = {
|
|
4675
|
-
appId
|
|
4676
|
-
apiKey,
|
|
4973
|
+
appId,
|
|
4677
4974
|
webSecretKey,
|
|
4678
4975
|
baseUrl,
|
|
4679
4976
|
endpoint,
|
|
@@ -4716,7 +5013,7 @@ var LogDropClient = class {
|
|
|
4716
5013
|
isPushEnabled: true,
|
|
4717
5014
|
// default; overridden by server config in _applyServerConfig
|
|
4718
5015
|
onRemoteMessageReceived: this._config.onRemoteMessageReceived,
|
|
4719
|
-
|
|
5016
|
+
appId: this._config.appId,
|
|
4720
5017
|
apiBase: this._config.baseUrl,
|
|
4721
5018
|
deviceId: this._deviceId,
|
|
4722
5019
|
getSessionToken: () => this._getAccessToken(),
|
|
@@ -4750,7 +5047,7 @@ var LogDropClient = class {
|
|
|
4750
5047
|
// Mirror every successfully sent event into the log stream at EVENT level.
|
|
4751
5048
|
logEvent: (eventLog) => this._enqueue(LogLevel.EVENT, eventLog),
|
|
4752
5049
|
release: this._config.release,
|
|
4753
|
-
|
|
5050
|
+
appId: this._config.appId,
|
|
4754
5051
|
apiBase: this._config.baseUrl,
|
|
4755
5052
|
isEventTrackingEnabled: this._serverConfig.isEventTrackingEnabled,
|
|
4756
5053
|
isFirstVisit: this._isNewDevice,
|
|
@@ -5046,6 +5343,13 @@ var LogDropClient = class {
|
|
|
5046
5343
|
// IMPORTANT: if message object convert => JSON string
|
|
5047
5344
|
message: typeof message === "string" ? message : safeStringify(message)
|
|
5048
5345
|
};
|
|
5346
|
+
const policy = this._httpCapturePolicy;
|
|
5347
|
+
if (policy && level !== LogLevel.DEVICEINFO) {
|
|
5348
|
+
if (level !== LogLevel.NETWORK_ACTIVITY) {
|
|
5349
|
+
entry.message = maskSensitive(entry.message, policy.sensitivePatterns);
|
|
5350
|
+
}
|
|
5351
|
+
entry.httpPolicyFingerprint = policy.fingerprint;
|
|
5352
|
+
}
|
|
5049
5353
|
if (tag) {
|
|
5050
5354
|
entry.tag = tag;
|
|
5051
5355
|
}
|
|
@@ -5131,6 +5435,7 @@ var LogDropClient = class {
|
|
|
5131
5435
|
message: entry.message
|
|
5132
5436
|
};
|
|
5133
5437
|
if (entry.tag) logRecord.tag = entry.tag;
|
|
5438
|
+
if (entry.httpPolicyFingerprint) logRecord.httpPolicyFingerprint = entry.httpPolicyFingerprint;
|
|
5134
5439
|
if (logFlow && logFlow instanceof LogFlow) {
|
|
5135
5440
|
logRecord.flowId = logFlow.id;
|
|
5136
5441
|
logRecord.flowName = logFlow.name;
|
|
@@ -5432,11 +5737,16 @@ var LogDropClient = class {
|
|
|
5432
5737
|
for (const [sessionId, logs] of Object.entries(sessionGroups)) {
|
|
5433
5738
|
const sessionLogs = [];
|
|
5434
5739
|
for (const log of logs) {
|
|
5740
|
+
const message = this._applyHttpCapturePolicyToStoredLog(log);
|
|
5741
|
+
if (message === null) {
|
|
5742
|
+
chunk.droppedLogIds.push(log.id);
|
|
5743
|
+
continue;
|
|
5744
|
+
}
|
|
5435
5745
|
const logEntry = {
|
|
5436
5746
|
id: log.id,
|
|
5437
5747
|
ts: log.ts,
|
|
5438
5748
|
level: log.level,
|
|
5439
|
-
message
|
|
5749
|
+
message,
|
|
5440
5750
|
flowId: log.flowId,
|
|
5441
5751
|
flowName: log.flowName,
|
|
5442
5752
|
flowAttributes: log.flowAttributes
|
|
@@ -5509,7 +5819,7 @@ var LogDropClient = class {
|
|
|
5509
5819
|
headers: {
|
|
5510
5820
|
"content-type": "application/x-protobuf",
|
|
5511
5821
|
"accept": "application/x-protobuf",
|
|
5512
|
-
"x-api-key": this._config.
|
|
5822
|
+
"x-api-key": this._config.appId,
|
|
5513
5823
|
"x-session-token": sessionToken
|
|
5514
5824
|
},
|
|
5515
5825
|
body: new Blob([protoBytes], { type: "application/x-protobuf" })
|
|
@@ -5555,7 +5865,7 @@ var LogDropClient = class {
|
|
|
5555
5865
|
headers: {
|
|
5556
5866
|
"content-type": "application/x-protobuf",
|
|
5557
5867
|
"accept": "application/x-protobuf",
|
|
5558
|
-
"x-api-key": this._config.
|
|
5868
|
+
"x-api-key": this._config.appId,
|
|
5559
5869
|
"x-session-token": sessionToken
|
|
5560
5870
|
},
|
|
5561
5871
|
body: new Blob([protoBytes], { type: "application/x-protobuf" })
|
|
@@ -5654,7 +5964,8 @@ var LogDropClient = class {
|
|
|
5654
5964
|
if (!this._dbPromise) return false;
|
|
5655
5965
|
this._fileFlushInProgress = true;
|
|
5656
5966
|
try {
|
|
5657
|
-
const
|
|
5967
|
+
const storedLogs = await this._readAllLogs();
|
|
5968
|
+
const allLogs = this._httpCapturePolicy ? storedLogs : storedLogs.filter((log) => log.level !== LogLevel.NETWORK_ACTIVITY);
|
|
5658
5969
|
if (this._isInternalLoggingEnabled()) {
|
|
5659
5970
|
this._logInternal(`[LogDrop DEBUG] _flushLogs called. DB log count: ${allLogs.length}`);
|
|
5660
5971
|
}
|
|
@@ -5780,7 +6091,7 @@ var LogDropClient = class {
|
|
|
5780
6091
|
const headers = {
|
|
5781
6092
|
"content-type": "application/x-protobuf",
|
|
5782
6093
|
"accept": "application/x-protobuf",
|
|
5783
|
-
"x-api-key": this._config.
|
|
6094
|
+
"x-api-key": this._config.appId
|
|
5784
6095
|
};
|
|
5785
6096
|
const sessionToken = this._getAccessToken();
|
|
5786
6097
|
const refreshToken = this._getRefreshToken();
|