@microsoft/power-apps-native-common 0.3.0 → 0.3.2
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/lib/NOTICE.txt +26 -0
- package/lib/commonjs/index.js +24 -0
- package/lib/commonjs/telemetry/AnonymousTelemetry.js +25 -0
- package/lib/commonjs/telemetry/OneDsTelemetryProvider.js +47 -5
- package/lib/commonjs/telemetry/TelemetrySanitizer.js +25 -4
- package/lib/commonjs/telemetry/resolveTelemetryLocation.js +29 -3
- package/lib/commonjs/telemetry/stringifyError.js +7 -15
- package/lib/commonjs/utils/DeviceIdUtils.js +9 -28
- package/lib/module/index.js +2 -2
- package/lib/module/telemetry/AnonymousTelemetry.js +21 -0
- package/lib/module/telemetry/OneDsTelemetryProvider.js +47 -5
- package/lib/module/telemetry/TelemetrySanitizer.js +25 -4
- package/lib/module/telemetry/resolveTelemetryLocation.js +26 -3
- package/lib/module/telemetry/stringifyError.js +7 -16
- package/lib/module/utils/DeviceIdUtils.js +8 -28
- package/lib/typescript/commonjs/index.d.ts +2 -2
- package/lib/typescript/commonjs/telemetry/AnonymousTelemetry.d.ts +4 -0
- package/lib/typescript/commonjs/telemetry/OneDsTelemetryProvider.d.ts +8 -1
- package/lib/typescript/commonjs/telemetry/TelemetryTypes.d.ts +7 -0
- package/lib/typescript/commonjs/telemetry/resolveTelemetryLocation.d.ts +8 -1
- package/lib/typescript/commonjs/telemetry/stringifyError.d.ts +3 -3
- package/lib/typescript/commonjs/utils/DeviceIdUtils.d.ts +5 -12
- package/lib/typescript/module/index.d.ts +2 -2
- package/lib/typescript/module/telemetry/AnonymousTelemetry.d.ts +4 -0
- package/lib/typescript/module/telemetry/OneDsTelemetryProvider.d.ts +8 -1
- package/lib/typescript/module/telemetry/TelemetryTypes.d.ts +7 -0
- package/lib/typescript/module/telemetry/resolveTelemetryLocation.d.ts +8 -1
- package/lib/typescript/module/telemetry/stringifyError.d.ts +3 -3
- package/lib/typescript/module/utils/DeviceIdUtils.d.ts +5 -12
- package/package.json +3 -2
package/lib/NOTICE.txt
CHANGED
|
@@ -30,6 +30,32 @@ SOFTWARE.
|
|
|
30
30
|
|
|
31
31
|
========================================================================
|
|
32
32
|
|
|
33
|
+
@microsoft/applicationinsights-channel-js 3.4.3
|
|
34
|
+
--
|
|
35
|
+
The MIT License (MIT)
|
|
36
|
+
|
|
37
|
+
Copyright (c) Microsoft Corporation
|
|
38
|
+
|
|
39
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
40
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
41
|
+
in the Software without restriction, including without limitation the rights
|
|
42
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
43
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
44
|
+
furnished to do so, subject to the following conditions:
|
|
45
|
+
|
|
46
|
+
The above copyright notice and this permission notice shall be included in all
|
|
47
|
+
copies or substantial portions of the Software.
|
|
48
|
+
|
|
49
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
50
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
51
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
52
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
53
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
54
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
55
|
+
SOFTWARE.
|
|
56
|
+
|
|
57
|
+
========================================================================
|
|
58
|
+
|
|
33
59
|
@microsoft/applicationinsights-core-js 3.4.3
|
|
34
60
|
--
|
|
35
61
|
The MIT License (MIT)
|
package/lib/commonjs/index.js
CHANGED
|
@@ -87,6 +87,12 @@ Object.defineProperty(exports, "regionToClusterCategory", {
|
|
|
87
87
|
return _ClusterCategory.regionToClusterCategory;
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
|
+
Object.defineProperty(exports, "resetDeviceId", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _DeviceIdUtils.resetDeviceId;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
90
96
|
Object.defineProperty(exports, "resolveDeviceId", {
|
|
91
97
|
enumerable: true,
|
|
92
98
|
get: function () {
|
|
@@ -99,6 +105,12 @@ Object.defineProperty(exports, "resolveTelemetryLocation", {
|
|
|
99
105
|
return _resolveTelemetryLocation.resolveTelemetryLocation;
|
|
100
106
|
}
|
|
101
107
|
});
|
|
108
|
+
Object.defineProperty(exports, "resolveTelemetryLocationFromDataverseRegion", {
|
|
109
|
+
enumerable: true,
|
|
110
|
+
get: function () {
|
|
111
|
+
return _resolveTelemetryLocation.resolveTelemetryLocationFromDataverseRegion;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
102
114
|
Object.defineProperty(exports, "sanitizeErrorString", {
|
|
103
115
|
enumerable: true,
|
|
104
116
|
get: function () {
|
|
@@ -129,6 +141,18 @@ Object.defineProperty(exports, "suppressKnownWarnings", {
|
|
|
129
141
|
return _suppressKnownWarnings.suppressKnownWarnings;
|
|
130
142
|
}
|
|
131
143
|
});
|
|
144
|
+
Object.defineProperty(exports, "tryResolveTelemetryLocationFromDataverseRegion", {
|
|
145
|
+
enumerable: true,
|
|
146
|
+
get: function () {
|
|
147
|
+
return _resolveTelemetryLocation.tryResolveTelemetryLocationFromDataverseRegion;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
Object.defineProperty(exports, "tryResolveTelemetryLocationFromEnvironment", {
|
|
151
|
+
enumerable: true,
|
|
152
|
+
get: function () {
|
|
153
|
+
return _resolveTelemetryLocation.tryResolveTelemetryLocationFromEnvironment;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
132
156
|
var _ConsoleAdapter = require("./telemetry/ConsoleAdapter.js");
|
|
133
157
|
var _Logger = require("./telemetry/Logger.js");
|
|
134
158
|
var _OneDsTelemetryProvider = require("./telemetry/OneDsTelemetryProvider.js");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buildAnonymousTelemetryData = buildAnonymousTelemetryData;
|
|
7
|
+
function buildAnonymousTelemetryData(event, appName, clusterCategory) {
|
|
8
|
+
const operationName = typeof event.properties.operationName === 'string' ? event.properties.operationName : undefined;
|
|
9
|
+
return {
|
|
10
|
+
app_Name: appName,
|
|
11
|
+
clusterCategory,
|
|
12
|
+
event_Name: event.eventName,
|
|
13
|
+
severity: event.severity,
|
|
14
|
+
timestamp: event.timestamp,
|
|
15
|
+
...(event.duration !== undefined ? {
|
|
16
|
+
duration: event.duration
|
|
17
|
+
} : {}),
|
|
18
|
+
...(operationName ? {
|
|
19
|
+
operation_Name: operationName
|
|
20
|
+
} : {}),
|
|
21
|
+
customDimensions: JSON.stringify(operationName ? {
|
|
22
|
+
operationName
|
|
23
|
+
} : {})
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -8,6 +8,7 @@ var _applicationinsightsCoreJs = require("@microsoft/applicationinsights-core-js
|
|
|
8
8
|
var _dsPostJs = require("@microsoft/1ds-post-js");
|
|
9
9
|
var _GuidUtils = require("../utils/GuidUtils.js");
|
|
10
10
|
var _PlatformInfoUtils = require("../utils/PlatformInfoUtils.js");
|
|
11
|
+
var _AnonymousTelemetry = require("./AnonymousTelemetry.js");
|
|
11
12
|
/*!
|
|
12
13
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
13
14
|
*/
|
|
@@ -97,11 +98,14 @@ class OneDsTelemetryProvider {
|
|
|
97
98
|
defaultProperties = {};
|
|
98
99
|
constructor(config) {
|
|
99
100
|
this._sessionId = (0, _GuidUtils.generateGuid)();
|
|
101
|
+
this.anonymous = config.anonymous ?? false;
|
|
102
|
+
this.telemetryLocation = config.telemetryLocation ?? 'global';
|
|
100
103
|
this.appName = resolveAppName(config.clusterCategory);
|
|
101
104
|
this.appVersion = config.appVersion ?? '';
|
|
102
105
|
this.clientType = config.clientType;
|
|
103
106
|
this.clusterCategory = config.clusterCategory;
|
|
104
107
|
this.deviceId = config.deviceId ?? 'react-native';
|
|
108
|
+
this.includeUserIdentity = config.includeUserIdentity ?? false;
|
|
105
109
|
this.minSeverity = config.minSeverity ?? 'info';
|
|
106
110
|
const {
|
|
107
111
|
osName,
|
|
@@ -128,15 +132,15 @@ class OneDsTelemetryProvider {
|
|
|
128
132
|
if (config.commonProperties) {
|
|
129
133
|
Object.assign(this.defaultProperties, config.commonProperties);
|
|
130
134
|
}
|
|
131
|
-
|
|
135
|
+
this.postChannel = new _dsPostJs.PostChannel();
|
|
132
136
|
const instrumentationKey = config.instrumentationKey ?? resolveInstrumentationKey(config.clusterCategory);
|
|
133
|
-
const collectorUrl = resolveCollectorUrl(config.clusterCategory,
|
|
137
|
+
const collectorUrl = resolveCollectorUrl(config.clusterCategory, this.telemetryLocation);
|
|
134
138
|
const coreConfig = {
|
|
135
139
|
instrumentationKey,
|
|
136
|
-
channels: [[postChannel]]
|
|
140
|
+
channels: [[this.postChannel]]
|
|
137
141
|
};
|
|
138
142
|
coreConfig.extensionConfig = {
|
|
139
|
-
[postChannel.identifier]: {
|
|
143
|
+
[this.postChannel.identifier]: {
|
|
140
144
|
// Override endpoint explicitly — PostChannel reads overrideEndpointUrl
|
|
141
145
|
// from its own extensionConfig, not from coreConfig.endpointUrl.
|
|
142
146
|
overrideEndpointUrl: collectorUrl,
|
|
@@ -168,6 +172,7 @@ class OneDsTelemetryProvider {
|
|
|
168
172
|
const ext = envelope.ext = envelope.ext ?? {};
|
|
169
173
|
const utc = ext['utc'] = ext['utc'] ?? {};
|
|
170
174
|
utc['eventFlags'] = (utc['eventFlags'] || 0) | 0x100000;
|
|
175
|
+
if (this.anonymous) return;
|
|
171
176
|
const app = ext['app'] = ext['app'] ?? {};
|
|
172
177
|
app['sesId'] = this._sessionId;
|
|
173
178
|
if (this.appVersion) app['ver'] = this.appVersion; // → AppInfo_Version
|
|
@@ -193,6 +198,15 @@ class OneDsTelemetryProvider {
|
|
|
193
198
|
this.core.addTelemetryInitializer(initializer);
|
|
194
199
|
}
|
|
195
200
|
track(event) {
|
|
201
|
+
if (this.anonymous) {
|
|
202
|
+
this.core.track({
|
|
203
|
+
name: 'event',
|
|
204
|
+
time: event.timestamp,
|
|
205
|
+
baseType: 'custom',
|
|
206
|
+
data: (0, _AnonymousTelemetry.buildAnonymousTelemetryData)(event, this.appName, this.clusterCategory)
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
196
210
|
const allProperties = {
|
|
197
211
|
...this.defaultProperties,
|
|
198
212
|
...event.properties
|
|
@@ -218,7 +232,7 @@ class OneDsTelemetryProvider {
|
|
|
218
232
|
};
|
|
219
233
|
|
|
220
234
|
// User identity promoted to top-level columns directly
|
|
221
|
-
if (this.userIdentity) {
|
|
235
|
+
if (this.includeUserIdentity && this.userIdentity) {
|
|
222
236
|
data.objectId = this.userIdentity.objectId;
|
|
223
237
|
data.tenantId = this.userIdentity.tenantId;
|
|
224
238
|
}
|
|
@@ -246,6 +260,34 @@ class OneDsTelemetryProvider {
|
|
|
246
260
|
};
|
|
247
261
|
this.core.track(item);
|
|
248
262
|
}
|
|
263
|
+
async resolveTelemetryLocation(telemetryLocation) {
|
|
264
|
+
if (!this.anonymous && telemetryLocation === this.telemetryLocation) return;
|
|
265
|
+
const previousResolution = this.locationResolution ?? Promise.resolve();
|
|
266
|
+
const currentResolution = previousResolution.catch(() => undefined).then(() => this.applyTelemetryLocation(telemetryLocation));
|
|
267
|
+
this.locationResolution = currentResolution;
|
|
268
|
+
try {
|
|
269
|
+
await currentResolution;
|
|
270
|
+
} finally {
|
|
271
|
+
if (this.locationResolution === currentResolution) {
|
|
272
|
+
this.locationResolution = undefined;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async applyTelemetryLocation(telemetryLocation) {
|
|
277
|
+
if (!this.anonymous && telemetryLocation === this.telemetryLocation) return;
|
|
278
|
+
if (telemetryLocation !== this.telemetryLocation) {
|
|
279
|
+
await this.flush();
|
|
280
|
+
this.core.updateCfg({
|
|
281
|
+
extensionConfig: {
|
|
282
|
+
[this.postChannel.identifier]: {
|
|
283
|
+
overrideEndpointUrl: resolveCollectorUrl(this.clusterCategory, telemetryLocation)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
this.telemetryLocation = telemetryLocation;
|
|
288
|
+
}
|
|
289
|
+
this.anonymous = false;
|
|
290
|
+
}
|
|
249
291
|
flush() {
|
|
250
292
|
return new Promise(resolve => {
|
|
251
293
|
this.core.flush(true, () => {
|
|
@@ -56,6 +56,13 @@ const SAS_KEY_SIG_RE = /(?:dsas_secret|sig)=[^#)\(<>\r\n\s'",\\_&]{8}[^#)\(<>\r\
|
|
|
56
56
|
*/
|
|
57
57
|
const SYMM_KEY_256_RE = /[a-z0-9/+]{43}=/gi;
|
|
58
58
|
|
|
59
|
+
/** Bearer credentials and compact JWTs embedded in otherwise arbitrary text. */
|
|
60
|
+
const BEARER_CREDENTIAL_RE = /\bbearer\s+[a-z0-9._~+\/-]+=*/gi;
|
|
61
|
+
const JWT_RE = /\beyJ[a-z0-9_-]+\.[a-z0-9_-]+\.[a-z0-9_-]+\b/gi;
|
|
62
|
+
|
|
63
|
+
/** Query strings and fragments on absolute URLs commonly carry user context. */
|
|
64
|
+
const URL_QUERY_OR_FRAGMENT_RE = /(https?:\/\/[^\s?#'"<>]+)[?#][^\s'"<>]*/gi;
|
|
65
|
+
|
|
59
66
|
/**
|
|
60
67
|
* Property key patterns that must never appear as telemetry values.
|
|
61
68
|
* Checked case-insensitively against the full key name.
|
|
@@ -67,7 +74,7 @@ const SENSITIVE_KEY_RE = /password|secret|token|credential|auth(?:orization)?|be
|
|
|
67
74
|
* Safe to use on error messages, URL paths, and arbitrary text.
|
|
68
75
|
*/
|
|
69
76
|
function sanitizeErrorString(raw) {
|
|
70
|
-
return raw.replace(EMAIL_RE, '<upn>').replace(PRIVATE_IPV4_RE, (_, port) => port ? `<private-ip>${port}` : '<private-ip>').replace(GOOGLE_API_KEY_RE, '<credential>').replace(SAS_KEY_SIG_RE, '<credential>').replace(SYMM_KEY_256_RE, '<credential>');
|
|
77
|
+
return raw.replace(URL_QUERY_OR_FRAGMENT_RE, '$1').replace(EMAIL_RE, '<upn>').replace(PRIVATE_IPV4_RE, (_, port) => port ? `<private-ip>${port}` : '<private-ip>').replace(GOOGLE_API_KEY_RE, '<credential>').replace(SAS_KEY_SIG_RE, '<credential>').replace(SYMM_KEY_256_RE, '<credential>').replace(BEARER_CREDENTIAL_RE, 'Bearer <credential>').replace(JWT_RE, '<credential>');
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
/**
|
|
@@ -86,15 +93,29 @@ function sanitizeUrl(url) {
|
|
|
86
93
|
* - Non-string primitives passed through unchanged
|
|
87
94
|
*/
|
|
88
95
|
function sanitizeProperties(props) {
|
|
96
|
+
return sanitizeRecord(props, new WeakSet(), 0);
|
|
97
|
+
}
|
|
98
|
+
const MAX_SANITIZE_DEPTH = 5;
|
|
99
|
+
function sanitizeRecord(props, seen, depth) {
|
|
100
|
+
if (seen.has(props) || depth > MAX_SANITIZE_DEPTH) return {};
|
|
101
|
+
seen.add(props);
|
|
89
102
|
const result = {};
|
|
90
103
|
for (const [key, value] of Object.entries(props)) {
|
|
91
104
|
if (SENSITIVE_KEY_RE.test(key)) {
|
|
92
105
|
result[key] = '<redacted>';
|
|
93
|
-
} else if (typeof value === 'string') {
|
|
94
|
-
result[key] = sanitizeErrorString(value);
|
|
95
106
|
} else {
|
|
96
|
-
result[key] = value;
|
|
107
|
+
result[key] = sanitizeValue(value, seen, depth + 1);
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
return result;
|
|
111
|
+
}
|
|
112
|
+
function sanitizeValue(value, seen, depth) {
|
|
113
|
+
if (typeof value === 'string') return sanitizeErrorString(value);
|
|
114
|
+
if (value === null || typeof value !== 'object') return value;
|
|
115
|
+
if (depth > MAX_SANITIZE_DEPTH || seen.has(value)) return '<redacted>';
|
|
116
|
+
if (Array.isArray(value)) {
|
|
117
|
+
seen.add(value);
|
|
118
|
+
return value.map(item => sanitizeValue(item, seen, depth + 1));
|
|
119
|
+
}
|
|
120
|
+
return sanitizeRecord(value, seen, depth);
|
|
100
121
|
}
|
|
@@ -4,6 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.resolveTelemetryLocation = resolveTelemetryLocation;
|
|
7
|
+
exports.resolveTelemetryLocationFromDataverseRegion = resolveTelemetryLocationFromDataverseRegion;
|
|
8
|
+
exports.tryResolveTelemetryLocationFromDataverseRegion = tryResolveTelemetryLocationFromDataverseRegion;
|
|
9
|
+
exports.tryResolveTelemetryLocationFromEnvironment = tryResolveTelemetryLocationFromEnvironment;
|
|
7
10
|
/*!
|
|
8
11
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
9
12
|
*/
|
|
@@ -15,13 +18,23 @@ exports.resolveTelemetryLocation = resolveTelemetryLocation;
|
|
|
15
18
|
* Source: `metadata.properties.location` in the BAP Get Environments API response.
|
|
16
19
|
*/
|
|
17
20
|
const EU_BAP_LOCATIONS = new Set(['europe', 'france', 'germany', 'italy', 'poland', 'norway', 'sweden', 'switzerland', 'unitedkingdom']);
|
|
21
|
+
const NON_EU_BAP_LOCATIONS = new Set(['asia', 'australia', 'brazil', 'canada', 'india', 'japan', 'korea', 'southafrica', 'southamerica', 'unitedarabemirates', 'unitedstates']);
|
|
22
|
+
const EU_DATAVERSE_REGIONS = new Set(['che', 'emea', 'eur', 'fra', 'gbr', 'ger', 'ita', 'nor', 'pol', 'swe']);
|
|
23
|
+
const NON_EU_DATAVERSE_REGIONS = new Set(['apac', 'aus', 'can', 'ind', 'jpn', 'kor', 'latam', 'nam', 'na', 'oce', 'sam', 'sgp', 'uae', 'usa']);
|
|
24
|
+
function resolveKnownLocation(input, euValues, nonEuValues) {
|
|
25
|
+
const value = input?.trim().toLowerCase();
|
|
26
|
+
if (value && euValues.has(value)) return 'eu';
|
|
27
|
+
if (value && nonEuValues.has(value)) return 'global';
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
18
30
|
|
|
19
31
|
/**
|
|
20
32
|
* Resolve the 1DS telemetry collector location from a Power Platform BAP
|
|
21
33
|
* environment `location` string (`environment.properties.location`).
|
|
22
34
|
* Returns `'eu'` when the location maps to the EU data boundary, routing
|
|
23
35
|
* telemetry to `eu-mobile.events.data.microsoft.com` instead of the global
|
|
24
|
-
* US collector.
|
|
36
|
+
* US collector. Missing or blank locations fail closed to the EU collector so
|
|
37
|
+
* telemetry emitted before the environment is known does not leave the EUDB.
|
|
25
38
|
*
|
|
26
39
|
* Mirrors the CLI's detection in `CliLogger.ts`:
|
|
27
40
|
* ```
|
|
@@ -35,8 +48,21 @@ const EU_BAP_LOCATIONS = new Set(['europe', 'france', 'germany', 'italy', 'polan
|
|
|
35
48
|
* resolveTelemetryLocation('unitedkingdom') // → 'eu'
|
|
36
49
|
* resolveTelemetryLocation('italy') // → 'eu'
|
|
37
50
|
* resolveTelemetryLocation('unitedstates') // → 'global'
|
|
51
|
+
* resolveTelemetryLocation() // → 'eu'
|
|
38
52
|
*/
|
|
39
53
|
function resolveTelemetryLocation(input) {
|
|
40
|
-
|
|
41
|
-
|
|
54
|
+
return resolveKnownLocation(input, EU_BAP_LOCATIONS, NON_EU_BAP_LOCATIONS) ?? 'eu';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Resolve a Dataverse Global Discovery `Instance.Region` code. */
|
|
58
|
+
function resolveTelemetryLocationFromDataverseRegion(input) {
|
|
59
|
+
return tryResolveTelemetryLocationFromDataverseRegion(input) ?? 'eu';
|
|
60
|
+
}
|
|
61
|
+
function tryResolveTelemetryLocationFromDataverseRegion(input) {
|
|
62
|
+
return resolveKnownLocation(input, EU_DATAVERSE_REGIONS, NON_EU_DATAVERSE_REGIONS);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Resolve launch metadata, falling back from BAP location to cluster geography. */
|
|
66
|
+
function tryResolveTelemetryLocationFromEnvironment(location, clusterGeoShortName) {
|
|
67
|
+
return resolveKnownLocation(location, EU_BAP_LOCATIONS, NON_EU_BAP_LOCATIONS) ?? tryResolveTelemetryLocationFromDataverseRegion(clusterGeoShortName);
|
|
42
68
|
}
|
|
@@ -4,28 +4,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.stringifyError = stringifyError;
|
|
7
|
-
var _TelemetrySanitizer = require("./TelemetrySanitizer.js");
|
|
8
7
|
/*!
|
|
9
8
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* Classifies an unknown thrown value without exporting its message, stack, or
|
|
13
|
+
* serialized contents. Error prose is not a safe telemetry contract because
|
|
14
|
+
* upstream services may include customer data or credentials in it.
|
|
16
15
|
*/
|
|
17
16
|
function stringifyError(error) {
|
|
18
|
-
let raw;
|
|
19
17
|
if (error instanceof Error) {
|
|
20
|
-
|
|
21
|
-
} else if (typeof error === 'string') {
|
|
22
|
-
raw = error;
|
|
23
|
-
} else {
|
|
24
|
-
try {
|
|
25
|
-
raw = JSON.stringify(error);
|
|
26
|
-
} catch {
|
|
27
|
-
raw = String(error);
|
|
28
|
-
}
|
|
18
|
+
return error.name || error.constructor.name || 'Error';
|
|
29
19
|
}
|
|
30
|
-
|
|
20
|
+
if (typeof error === 'string') return 'StringError';
|
|
21
|
+
if (error && typeof error === 'object') return error.constructor?.name || 'ObjectError';
|
|
22
|
+
return `${typeof error}Error`;
|
|
31
23
|
}
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.resetDeviceId = resetDeviceId;
|
|
6
7
|
exports.resolveDeviceId = resolveDeviceId;
|
|
7
|
-
var Application = _interopRequireWildcard(require("expo-application"));
|
|
8
8
|
var SecureStore = _interopRequireWildcard(require("expo-secure-store"));
|
|
9
|
-
var _reactNative = require("react-native");
|
|
10
9
|
var _GuidUtils = require("./GuidUtils.js");
|
|
11
10
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
12
11
|
/*!
|
|
@@ -18,18 +17,9 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
18
17
|
const DEVICE_ID_FALLBACK_KEY = 'microsoft.power-apps-native-common.device_id';
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
|
-
* Returns a
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* - **iOS**: `getIosIdForVendorAsync()` (IDFV) — stable while ≥1 app from the
|
|
25
|
-
* same vendor bundle prefix is installed. Resets only when ALL vendor apps
|
|
26
|
-
* are removed.
|
|
27
|
-
* - **Android**: `getAndroidId()` (SSAID) — scoped to the app signing key on
|
|
28
|
-
* Android 8+; survives reinstalls as long as the signing key is unchanged.
|
|
29
|
-
*
|
|
30
|
-
* If the platform API returns null (rare edge cases: first boot, some emulators)
|
|
31
|
-
* the function falls back to a UUID persisted in `expo-secure-store`, which on
|
|
32
|
-
* iOS survives reinstalls via the Keychain and on Android is per-install only.
|
|
20
|
+
* Returns a random app-scoped telemetry identifier. It does not use IDFV,
|
|
21
|
+
* SSAID, or another platform device identifier, and can be rotated with
|
|
22
|
+
* `resetDeviceId()` for deletion and opt-out workflows.
|
|
33
23
|
*
|
|
34
24
|
* Pass the resolved value to `OneDsTelemetryProviderConfig.deviceId` at startup.
|
|
35
25
|
*
|
|
@@ -42,20 +32,6 @@ const DEVICE_ID_FALLBACK_KEY = 'microsoft.power-apps-native-common.device_id';
|
|
|
42
32
|
* ```
|
|
43
33
|
*/
|
|
44
34
|
async function resolveDeviceId() {
|
|
45
|
-
if (_reactNative.Platform.OS === 'ios') {
|
|
46
|
-
const idfv = await Application.getIosIdForVendorAsync();
|
|
47
|
-
if (idfv) {
|
|
48
|
-
return idfv;
|
|
49
|
-
}
|
|
50
|
-
} else if (_reactNative.Platform.OS === 'android') {
|
|
51
|
-
const androidId = Application.getAndroidId();
|
|
52
|
-
if (androidId) {
|
|
53
|
-
return androidId;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Fallback: stable UUID in SecureStore (iOS: survives reinstall via Keychain;
|
|
58
|
-
// Android: per-install only, but only reached when SSAID is unavailable).
|
|
59
35
|
const existing = await SecureStore.getItemAsync(DEVICE_ID_FALLBACK_KEY);
|
|
60
36
|
if (existing) {
|
|
61
37
|
return existing;
|
|
@@ -63,4 +39,9 @@ async function resolveDeviceId() {
|
|
|
63
39
|
const id = (0, _GuidUtils.generateGuid)();
|
|
64
40
|
await SecureStore.setItemAsync(DEVICE_ID_FALLBACK_KEY, id);
|
|
65
41
|
return id;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Deletes the app-scoped telemetry identifier so the next resolution rotates it. */
|
|
45
|
+
async function resetDeviceId() {
|
|
46
|
+
await SecureStore.deleteItemAsync(DEVICE_ID_FALLBACK_KEY);
|
|
66
47
|
}
|
package/lib/module/index.js
CHANGED
|
@@ -9,12 +9,12 @@ export { ConsoleAdapter } from "./telemetry/ConsoleAdapter.js";
|
|
|
9
9
|
export { Logger } from "./telemetry/Logger.js";
|
|
10
10
|
export { OneDsTelemetryProvider } from "./telemetry/OneDsTelemetryProvider.js";
|
|
11
11
|
export { ApplicationInsightsTelemetryProvider } from "./telemetry/ApplicationInsightsTelemetryProvider.js";
|
|
12
|
-
export { resolveTelemetryLocation } from "./telemetry/resolveTelemetryLocation.js";
|
|
12
|
+
export { resolveTelemetryLocation, resolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromEnvironment } from "./telemetry/resolveTelemetryLocation.js";
|
|
13
13
|
export { stringifyError } from "./telemetry/stringifyError.js";
|
|
14
14
|
export { sanitizeErrorString, sanitizeUrl, sanitizeProperties } from "./telemetry/TelemetrySanitizer.js";
|
|
15
15
|
export { suppressKnownWarnings } from "./telemetry/suppressKnownWarnings.js";
|
|
16
16
|
export { HttpClient, getHttpCorrelationProperties } from "./http/HttpClient.js";
|
|
17
|
-
export { resolveDeviceId } from "./utils/DeviceIdUtils.js";
|
|
17
|
+
export { resetDeviceId, resolveDeviceId } from "./utils/DeviceIdUtils.js";
|
|
18
18
|
export { configureAppLogger, getAppLogger } from "./telemetry/AppLogger.js";
|
|
19
19
|
export { configureCustomEventsLogger, getCustomEventsLogger } from "./telemetry/CustomEventsLogger.js";
|
|
20
20
|
export { ScenarioResults, TelemetryEventNames } from "./telemetry/TelemetryTypes.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export function buildAnonymousTelemetryData(event, appName, clusterCategory) {
|
|
4
|
+
const operationName = typeof event.properties.operationName === 'string' ? event.properties.operationName : undefined;
|
|
5
|
+
return {
|
|
6
|
+
app_Name: appName,
|
|
7
|
+
clusterCategory,
|
|
8
|
+
event_Name: event.eventName,
|
|
9
|
+
severity: event.severity,
|
|
10
|
+
timestamp: event.timestamp,
|
|
11
|
+
...(event.duration !== undefined ? {
|
|
12
|
+
duration: event.duration
|
|
13
|
+
} : {}),
|
|
14
|
+
...(operationName ? {
|
|
15
|
+
operation_Name: operationName
|
|
16
|
+
} : {}),
|
|
17
|
+
customDimensions: JSON.stringify(operationName ? {
|
|
18
|
+
operationName
|
|
19
|
+
} : {})
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -8,6 +8,7 @@ import { AppInsightsCore } from '@microsoft/applicationinsights-core-js';
|
|
|
8
8
|
import { PostChannel } from '@microsoft/1ds-post-js';
|
|
9
9
|
import { generateGuid } from "../utils/GuidUtils.js";
|
|
10
10
|
import { resolvePlatformInfo } from "../utils/PlatformInfoUtils.js";
|
|
11
|
+
import { buildAnonymousTelemetryData } from "./AnonymousTelemetry.js";
|
|
11
12
|
/** 1DS Aria project IDs shared by the webplayer and CLI. */
|
|
12
13
|
const AriaProjectIds = {
|
|
13
14
|
Production: '5c3a61f48d7c4522912765ae7465ab5c-fb3d6606-fe59-4d6b-9bb1-5e993d889672-7138',
|
|
@@ -93,11 +94,14 @@ export class OneDsTelemetryProvider {
|
|
|
93
94
|
defaultProperties = {};
|
|
94
95
|
constructor(config) {
|
|
95
96
|
this._sessionId = generateGuid();
|
|
97
|
+
this.anonymous = config.anonymous ?? false;
|
|
98
|
+
this.telemetryLocation = config.telemetryLocation ?? 'global';
|
|
96
99
|
this.appName = resolveAppName(config.clusterCategory);
|
|
97
100
|
this.appVersion = config.appVersion ?? '';
|
|
98
101
|
this.clientType = config.clientType;
|
|
99
102
|
this.clusterCategory = config.clusterCategory;
|
|
100
103
|
this.deviceId = config.deviceId ?? 'react-native';
|
|
104
|
+
this.includeUserIdentity = config.includeUserIdentity ?? false;
|
|
101
105
|
this.minSeverity = config.minSeverity ?? 'info';
|
|
102
106
|
const {
|
|
103
107
|
osName,
|
|
@@ -124,15 +128,15 @@ export class OneDsTelemetryProvider {
|
|
|
124
128
|
if (config.commonProperties) {
|
|
125
129
|
Object.assign(this.defaultProperties, config.commonProperties);
|
|
126
130
|
}
|
|
127
|
-
|
|
131
|
+
this.postChannel = new PostChannel();
|
|
128
132
|
const instrumentationKey = config.instrumentationKey ?? resolveInstrumentationKey(config.clusterCategory);
|
|
129
|
-
const collectorUrl = resolveCollectorUrl(config.clusterCategory,
|
|
133
|
+
const collectorUrl = resolveCollectorUrl(config.clusterCategory, this.telemetryLocation);
|
|
130
134
|
const coreConfig = {
|
|
131
135
|
instrumentationKey,
|
|
132
|
-
channels: [[postChannel]]
|
|
136
|
+
channels: [[this.postChannel]]
|
|
133
137
|
};
|
|
134
138
|
coreConfig.extensionConfig = {
|
|
135
|
-
[postChannel.identifier]: {
|
|
139
|
+
[this.postChannel.identifier]: {
|
|
136
140
|
// Override endpoint explicitly — PostChannel reads overrideEndpointUrl
|
|
137
141
|
// from its own extensionConfig, not from coreConfig.endpointUrl.
|
|
138
142
|
overrideEndpointUrl: collectorUrl,
|
|
@@ -164,6 +168,7 @@ export class OneDsTelemetryProvider {
|
|
|
164
168
|
const ext = envelope.ext = envelope.ext ?? {};
|
|
165
169
|
const utc = ext['utc'] = ext['utc'] ?? {};
|
|
166
170
|
utc['eventFlags'] = (utc['eventFlags'] || 0) | 0x100000;
|
|
171
|
+
if (this.anonymous) return;
|
|
167
172
|
const app = ext['app'] = ext['app'] ?? {};
|
|
168
173
|
app['sesId'] = this._sessionId;
|
|
169
174
|
if (this.appVersion) app['ver'] = this.appVersion; // → AppInfo_Version
|
|
@@ -189,6 +194,15 @@ export class OneDsTelemetryProvider {
|
|
|
189
194
|
this.core.addTelemetryInitializer(initializer);
|
|
190
195
|
}
|
|
191
196
|
track(event) {
|
|
197
|
+
if (this.anonymous) {
|
|
198
|
+
this.core.track({
|
|
199
|
+
name: 'event',
|
|
200
|
+
time: event.timestamp,
|
|
201
|
+
baseType: 'custom',
|
|
202
|
+
data: buildAnonymousTelemetryData(event, this.appName, this.clusterCategory)
|
|
203
|
+
});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
192
206
|
const allProperties = {
|
|
193
207
|
...this.defaultProperties,
|
|
194
208
|
...event.properties
|
|
@@ -214,7 +228,7 @@ export class OneDsTelemetryProvider {
|
|
|
214
228
|
};
|
|
215
229
|
|
|
216
230
|
// User identity promoted to top-level columns directly
|
|
217
|
-
if (this.userIdentity) {
|
|
231
|
+
if (this.includeUserIdentity && this.userIdentity) {
|
|
218
232
|
data.objectId = this.userIdentity.objectId;
|
|
219
233
|
data.tenantId = this.userIdentity.tenantId;
|
|
220
234
|
}
|
|
@@ -242,6 +256,34 @@ export class OneDsTelemetryProvider {
|
|
|
242
256
|
};
|
|
243
257
|
this.core.track(item);
|
|
244
258
|
}
|
|
259
|
+
async resolveTelemetryLocation(telemetryLocation) {
|
|
260
|
+
if (!this.anonymous && telemetryLocation === this.telemetryLocation) return;
|
|
261
|
+
const previousResolution = this.locationResolution ?? Promise.resolve();
|
|
262
|
+
const currentResolution = previousResolution.catch(() => undefined).then(() => this.applyTelemetryLocation(telemetryLocation));
|
|
263
|
+
this.locationResolution = currentResolution;
|
|
264
|
+
try {
|
|
265
|
+
await currentResolution;
|
|
266
|
+
} finally {
|
|
267
|
+
if (this.locationResolution === currentResolution) {
|
|
268
|
+
this.locationResolution = undefined;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async applyTelemetryLocation(telemetryLocation) {
|
|
273
|
+
if (!this.anonymous && telemetryLocation === this.telemetryLocation) return;
|
|
274
|
+
if (telemetryLocation !== this.telemetryLocation) {
|
|
275
|
+
await this.flush();
|
|
276
|
+
this.core.updateCfg({
|
|
277
|
+
extensionConfig: {
|
|
278
|
+
[this.postChannel.identifier]: {
|
|
279
|
+
overrideEndpointUrl: resolveCollectorUrl(this.clusterCategory, telemetryLocation)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
this.telemetryLocation = telemetryLocation;
|
|
284
|
+
}
|
|
285
|
+
this.anonymous = false;
|
|
286
|
+
}
|
|
245
287
|
flush() {
|
|
246
288
|
return new Promise(resolve => {
|
|
247
289
|
this.core.flush(true, () => {
|
|
@@ -50,6 +50,13 @@ const SAS_KEY_SIG_RE = /(?:dsas_secret|sig)=[^#)\(<>\r\n\s'",\\_&]{8}[^#)\(<>\r\
|
|
|
50
50
|
*/
|
|
51
51
|
const SYMM_KEY_256_RE = /[a-z0-9/+]{43}=/gi;
|
|
52
52
|
|
|
53
|
+
/** Bearer credentials and compact JWTs embedded in otherwise arbitrary text. */
|
|
54
|
+
const BEARER_CREDENTIAL_RE = /\bbearer\s+[a-z0-9._~+\/-]+=*/gi;
|
|
55
|
+
const JWT_RE = /\beyJ[a-z0-9_-]+\.[a-z0-9_-]+\.[a-z0-9_-]+\b/gi;
|
|
56
|
+
|
|
57
|
+
/** Query strings and fragments on absolute URLs commonly carry user context. */
|
|
58
|
+
const URL_QUERY_OR_FRAGMENT_RE = /(https?:\/\/[^\s?#'"<>]+)[?#][^\s'"<>]*/gi;
|
|
59
|
+
|
|
53
60
|
/**
|
|
54
61
|
* Property key patterns that must never appear as telemetry values.
|
|
55
62
|
* Checked case-insensitively against the full key name.
|
|
@@ -61,7 +68,7 @@ const SENSITIVE_KEY_RE = /password|secret|token|credential|auth(?:orization)?|be
|
|
|
61
68
|
* Safe to use on error messages, URL paths, and arbitrary text.
|
|
62
69
|
*/
|
|
63
70
|
export function sanitizeErrorString(raw) {
|
|
64
|
-
return raw.replace(EMAIL_RE, '<upn>').replace(PRIVATE_IPV4_RE, (_, port) => port ? `<private-ip>${port}` : '<private-ip>').replace(GOOGLE_API_KEY_RE, '<credential>').replace(SAS_KEY_SIG_RE, '<credential>').replace(SYMM_KEY_256_RE, '<credential>');
|
|
71
|
+
return raw.replace(URL_QUERY_OR_FRAGMENT_RE, '$1').replace(EMAIL_RE, '<upn>').replace(PRIVATE_IPV4_RE, (_, port) => port ? `<private-ip>${port}` : '<private-ip>').replace(GOOGLE_API_KEY_RE, '<credential>').replace(SAS_KEY_SIG_RE, '<credential>').replace(SYMM_KEY_256_RE, '<credential>').replace(BEARER_CREDENTIAL_RE, 'Bearer <credential>').replace(JWT_RE, '<credential>');
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
/**
|
|
@@ -80,15 +87,29 @@ export function sanitizeUrl(url) {
|
|
|
80
87
|
* - Non-string primitives passed through unchanged
|
|
81
88
|
*/
|
|
82
89
|
export function sanitizeProperties(props) {
|
|
90
|
+
return sanitizeRecord(props, new WeakSet(), 0);
|
|
91
|
+
}
|
|
92
|
+
const MAX_SANITIZE_DEPTH = 5;
|
|
93
|
+
function sanitizeRecord(props, seen, depth) {
|
|
94
|
+
if (seen.has(props) || depth > MAX_SANITIZE_DEPTH) return {};
|
|
95
|
+
seen.add(props);
|
|
83
96
|
const result = {};
|
|
84
97
|
for (const [key, value] of Object.entries(props)) {
|
|
85
98
|
if (SENSITIVE_KEY_RE.test(key)) {
|
|
86
99
|
result[key] = '<redacted>';
|
|
87
|
-
} else if (typeof value === 'string') {
|
|
88
|
-
result[key] = sanitizeErrorString(value);
|
|
89
100
|
} else {
|
|
90
|
-
result[key] = value;
|
|
101
|
+
result[key] = sanitizeValue(value, seen, depth + 1);
|
|
91
102
|
}
|
|
92
103
|
}
|
|
93
104
|
return result;
|
|
105
|
+
}
|
|
106
|
+
function sanitizeValue(value, seen, depth) {
|
|
107
|
+
if (typeof value === 'string') return sanitizeErrorString(value);
|
|
108
|
+
if (value === null || typeof value !== 'object') return value;
|
|
109
|
+
if (depth > MAX_SANITIZE_DEPTH || seen.has(value)) return '<redacted>';
|
|
110
|
+
if (Array.isArray(value)) {
|
|
111
|
+
seen.add(value);
|
|
112
|
+
return value.map(item => sanitizeValue(item, seen, depth + 1));
|
|
113
|
+
}
|
|
114
|
+
return sanitizeRecord(value, seen, depth);
|
|
94
115
|
}
|
|
@@ -11,13 +11,23 @@
|
|
|
11
11
|
* Source: `metadata.properties.location` in the BAP Get Environments API response.
|
|
12
12
|
*/
|
|
13
13
|
const EU_BAP_LOCATIONS = new Set(['europe', 'france', 'germany', 'italy', 'poland', 'norway', 'sweden', 'switzerland', 'unitedkingdom']);
|
|
14
|
+
const NON_EU_BAP_LOCATIONS = new Set(['asia', 'australia', 'brazil', 'canada', 'india', 'japan', 'korea', 'southafrica', 'southamerica', 'unitedarabemirates', 'unitedstates']);
|
|
15
|
+
const EU_DATAVERSE_REGIONS = new Set(['che', 'emea', 'eur', 'fra', 'gbr', 'ger', 'ita', 'nor', 'pol', 'swe']);
|
|
16
|
+
const NON_EU_DATAVERSE_REGIONS = new Set(['apac', 'aus', 'can', 'ind', 'jpn', 'kor', 'latam', 'nam', 'na', 'oce', 'sam', 'sgp', 'uae', 'usa']);
|
|
17
|
+
function resolveKnownLocation(input, euValues, nonEuValues) {
|
|
18
|
+
const value = input?.trim().toLowerCase();
|
|
19
|
+
if (value && euValues.has(value)) return 'eu';
|
|
20
|
+
if (value && nonEuValues.has(value)) return 'global';
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
14
23
|
|
|
15
24
|
/**
|
|
16
25
|
* Resolve the 1DS telemetry collector location from a Power Platform BAP
|
|
17
26
|
* environment `location` string (`environment.properties.location`).
|
|
18
27
|
* Returns `'eu'` when the location maps to the EU data boundary, routing
|
|
19
28
|
* telemetry to `eu-mobile.events.data.microsoft.com` instead of the global
|
|
20
|
-
* US collector.
|
|
29
|
+
* US collector. Missing or blank locations fail closed to the EU collector so
|
|
30
|
+
* telemetry emitted before the environment is known does not leave the EUDB.
|
|
21
31
|
*
|
|
22
32
|
* Mirrors the CLI's detection in `CliLogger.ts`:
|
|
23
33
|
* ```
|
|
@@ -31,8 +41,21 @@ const EU_BAP_LOCATIONS = new Set(['europe', 'france', 'germany', 'italy', 'polan
|
|
|
31
41
|
* resolveTelemetryLocation('unitedkingdom') // → 'eu'
|
|
32
42
|
* resolveTelemetryLocation('italy') // → 'eu'
|
|
33
43
|
* resolveTelemetryLocation('unitedstates') // → 'global'
|
|
44
|
+
* resolveTelemetryLocation() // → 'eu'
|
|
34
45
|
*/
|
|
35
46
|
export function resolveTelemetryLocation(input) {
|
|
36
|
-
|
|
37
|
-
|
|
47
|
+
return resolveKnownLocation(input, EU_BAP_LOCATIONS, NON_EU_BAP_LOCATIONS) ?? 'eu';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Resolve a Dataverse Global Discovery `Instance.Region` code. */
|
|
51
|
+
export function resolveTelemetryLocationFromDataverseRegion(input) {
|
|
52
|
+
return tryResolveTelemetryLocationFromDataverseRegion(input) ?? 'eu';
|
|
53
|
+
}
|
|
54
|
+
export function tryResolveTelemetryLocationFromDataverseRegion(input) {
|
|
55
|
+
return resolveKnownLocation(input, EU_DATAVERSE_REGIONS, NON_EU_DATAVERSE_REGIONS);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Resolve launch metadata, falling back from BAP location to cluster geography. */
|
|
59
|
+
export function tryResolveTelemetryLocationFromEnvironment(location, clusterGeoShortName) {
|
|
60
|
+
return resolveKnownLocation(location, EU_BAP_LOCATIONS, NON_EU_BAP_LOCATIONS) ?? tryResolveTelemetryLocationFromDataverseRegion(clusterGeoShortName);
|
|
38
61
|
}
|
|
@@ -4,25 +4,16 @@
|
|
|
4
4
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { sanitizeErrorString } from "./TelemetrySanitizer.js";
|
|
8
|
-
|
|
9
7
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* Classifies an unknown thrown value without exporting its message, stack, or
|
|
9
|
+
* serialized contents. Error prose is not a safe telemetry contract because
|
|
10
|
+
* upstream services may include customer data or credentials in it.
|
|
13
11
|
*/
|
|
14
12
|
export function stringifyError(error) {
|
|
15
|
-
let raw;
|
|
16
13
|
if (error instanceof Error) {
|
|
17
|
-
|
|
18
|
-
} else if (typeof error === 'string') {
|
|
19
|
-
raw = error;
|
|
20
|
-
} else {
|
|
21
|
-
try {
|
|
22
|
-
raw = JSON.stringify(error);
|
|
23
|
-
} catch {
|
|
24
|
-
raw = String(error);
|
|
25
|
-
}
|
|
14
|
+
return error.name || error.constructor.name || 'Error';
|
|
26
15
|
}
|
|
27
|
-
|
|
16
|
+
if (typeof error === 'string') return 'StringError';
|
|
17
|
+
if (error && typeof error === 'object') return error.constructor?.name || 'ObjectError';
|
|
18
|
+
return `${typeof error}Error`;
|
|
28
19
|
}
|
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as Application from 'expo-application';
|
|
8
7
|
import * as SecureStore from 'expo-secure-store';
|
|
9
|
-
import { Platform } from 'react-native';
|
|
10
8
|
import { generateGuid } from "./GuidUtils.js";
|
|
11
9
|
|
|
12
10
|
// Fallback key used when the platform native ID is unavailable.
|
|
@@ -14,18 +12,9 @@ import { generateGuid } from "./GuidUtils.js";
|
|
|
14
12
|
const DEVICE_ID_FALLBACK_KEY = 'microsoft.power-apps-native-common.device_id';
|
|
15
13
|
|
|
16
14
|
/**
|
|
17
|
-
* Returns a
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - **iOS**: `getIosIdForVendorAsync()` (IDFV) — stable while ≥1 app from the
|
|
21
|
-
* same vendor bundle prefix is installed. Resets only when ALL vendor apps
|
|
22
|
-
* are removed.
|
|
23
|
-
* - **Android**: `getAndroidId()` (SSAID) — scoped to the app signing key on
|
|
24
|
-
* Android 8+; survives reinstalls as long as the signing key is unchanged.
|
|
25
|
-
*
|
|
26
|
-
* If the platform API returns null (rare edge cases: first boot, some emulators)
|
|
27
|
-
* the function falls back to a UUID persisted in `expo-secure-store`, which on
|
|
28
|
-
* iOS survives reinstalls via the Keychain and on Android is per-install only.
|
|
15
|
+
* Returns a random app-scoped telemetry identifier. It does not use IDFV,
|
|
16
|
+
* SSAID, or another platform device identifier, and can be rotated with
|
|
17
|
+
* `resetDeviceId()` for deletion and opt-out workflows.
|
|
29
18
|
*
|
|
30
19
|
* Pass the resolved value to `OneDsTelemetryProviderConfig.deviceId` at startup.
|
|
31
20
|
*
|
|
@@ -38,20 +27,6 @@ const DEVICE_ID_FALLBACK_KEY = 'microsoft.power-apps-native-common.device_id';
|
|
|
38
27
|
* ```
|
|
39
28
|
*/
|
|
40
29
|
export async function resolveDeviceId() {
|
|
41
|
-
if (Platform.OS === 'ios') {
|
|
42
|
-
const idfv = await Application.getIosIdForVendorAsync();
|
|
43
|
-
if (idfv) {
|
|
44
|
-
return idfv;
|
|
45
|
-
}
|
|
46
|
-
} else if (Platform.OS === 'android') {
|
|
47
|
-
const androidId = Application.getAndroidId();
|
|
48
|
-
if (androidId) {
|
|
49
|
-
return androidId;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Fallback: stable UUID in SecureStore (iOS: survives reinstall via Keychain;
|
|
54
|
-
// Android: per-install only, but only reached when SSAID is unavailable).
|
|
55
30
|
const existing = await SecureStore.getItemAsync(DEVICE_ID_FALLBACK_KEY);
|
|
56
31
|
if (existing) {
|
|
57
32
|
return existing;
|
|
@@ -59,4 +34,9 @@ export async function resolveDeviceId() {
|
|
|
59
34
|
const id = generateGuid();
|
|
60
35
|
await SecureStore.setItemAsync(DEVICE_ID_FALLBACK_KEY, id);
|
|
61
36
|
return id;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Deletes the app-scoped telemetry identifier so the next resolution rotates it. */
|
|
40
|
+
export async function resetDeviceId() {
|
|
41
|
+
await SecureStore.deleteItemAsync(DEVICE_ID_FALLBACK_KEY);
|
|
62
42
|
}
|
|
@@ -7,12 +7,12 @@ export type { ILogger, ScenarioTracker } from './telemetry/ILogger';
|
|
|
7
7
|
export { Logger } from './telemetry/Logger';
|
|
8
8
|
export { OneDsTelemetryProvider } from './telemetry/OneDsTelemetryProvider';
|
|
9
9
|
export { ApplicationInsightsTelemetryProvider } from './telemetry/ApplicationInsightsTelemetryProvider';
|
|
10
|
-
export { resolveTelemetryLocation } from './telemetry/resolveTelemetryLocation';
|
|
10
|
+
export { resolveTelemetryLocation, resolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromEnvironment, } from './telemetry/resolveTelemetryLocation';
|
|
11
11
|
export { stringifyError } from './telemetry/stringifyError';
|
|
12
12
|
export { sanitizeErrorString, sanitizeUrl, sanitizeProperties } from './telemetry/TelemetrySanitizer';
|
|
13
13
|
export { suppressKnownWarnings } from './telemetry/suppressKnownWarnings';
|
|
14
14
|
export { HttpClient, getHttpCorrelationProperties } from './http/HttpClient';
|
|
15
|
-
export { resolveDeviceId } from './utils/DeviceIdUtils';
|
|
15
|
+
export { resetDeviceId, resolveDeviceId } from './utils/DeviceIdUtils';
|
|
16
16
|
export { configureAppLogger, getAppLogger } from './telemetry/AppLogger';
|
|
17
17
|
export { configureCustomEventsLogger, getCustomEventsLogger, } from './telemetry/CustomEventsLogger';
|
|
18
18
|
export type { ICustomEventsLogger } from './telemetry/CustomEventsLogger';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ClusterCategory } from '../types/ClusterCategory';
|
|
2
|
+
import type { TelemetryEvent } from './TelemetryTypes';
|
|
3
|
+
export declare function buildAnonymousTelemetryData(event: TelemetryEvent, appName: string, clusterCategory: ClusterCategory): Record<string, unknown>;
|
|
4
|
+
//# sourceMappingURL=AnonymousTelemetry.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
|
-
import type { ITelemetryProvider, OneDsTelemetryProviderConfig, TelemetryEnvelope, TelemetryEvent, TelemetrySeverity, UserIdentity } from './TelemetryTypes';
|
|
4
|
+
import type { ITelemetryProvider, OneDsTelemetryProviderConfig, TelemetryEnvelope, TelemetryEvent, TelemetryLocation, TelemetrySeverity, UserIdentity } from './TelemetryTypes';
|
|
5
5
|
export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
6
|
+
private anonymous;
|
|
6
7
|
private readonly appName;
|
|
7
8
|
private readonly appVersion;
|
|
8
9
|
private readonly clientType;
|
|
@@ -13,11 +14,15 @@ export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
|
13
14
|
private readonly deviceMake;
|
|
14
15
|
private readonly deviceModel;
|
|
15
16
|
private readonly deviceType;
|
|
17
|
+
private readonly includeUserIdentity;
|
|
16
18
|
private readonly osName;
|
|
17
19
|
private readonly osVersion;
|
|
20
|
+
private readonly postChannel;
|
|
18
21
|
private readonly userLocale;
|
|
19
22
|
private readonly userTimeZone;
|
|
20
23
|
private readonly propertyColumnMap;
|
|
24
|
+
private locationResolution?;
|
|
25
|
+
private telemetryLocation;
|
|
21
26
|
readonly minSeverity: TelemetrySeverity;
|
|
22
27
|
private _sessionId;
|
|
23
28
|
private userIdentity?;
|
|
@@ -29,6 +34,8 @@ export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
|
29
34
|
*/
|
|
30
35
|
addTelemetryInitializer(initializer: (envelope: TelemetryEnvelope) => void): void;
|
|
31
36
|
track(event: TelemetryEvent): void;
|
|
37
|
+
resolveTelemetryLocation(telemetryLocation: TelemetryLocation): Promise<void>;
|
|
38
|
+
private applyTelemetryLocation;
|
|
32
39
|
flush(): Promise<void>;
|
|
33
40
|
teardown(): Promise<void>;
|
|
34
41
|
get sessionId(): string;
|
|
@@ -72,6 +72,8 @@ export interface OneDsTelemetryProviderConfig {
|
|
|
72
72
|
* and pass the result here. Falls back to `'react-native'` if omitted.
|
|
73
73
|
*/
|
|
74
74
|
deviceId?: string;
|
|
75
|
+
/** Include signed-in object and tenant IDs. Disabled by default. */
|
|
76
|
+
includeUserIdentity?: boolean;
|
|
75
77
|
/**
|
|
76
78
|
* 1DS instrumentation key (Aria project ID).
|
|
77
79
|
* When omitted, resolved automatically from `clusterCategory`.
|
|
@@ -81,6 +83,11 @@ export interface OneDsTelemetryProviderConfig {
|
|
|
81
83
|
minSeverity?: TelemetrySeverity;
|
|
82
84
|
/** Data residency location. Default: 'global'. Set to 'eu' for European environments. */
|
|
83
85
|
telemetryLocation?: TelemetryLocation;
|
|
86
|
+
/**
|
|
87
|
+
* Emit only non-identifying operational fields. Stable IDs, user identity,
|
|
88
|
+
* platform fingerprint fields, defaults, and arbitrary event properties are omitted.
|
|
89
|
+
*/
|
|
90
|
+
anonymous?: boolean;
|
|
84
91
|
commonProperties?: Record<string, string>;
|
|
85
92
|
propertyColumnMap?: PropertyColumnMap;
|
|
86
93
|
channelConfig?: Record<string, unknown>;
|
|
@@ -7,7 +7,8 @@ import type { TelemetryLocation } from './TelemetryTypes';
|
|
|
7
7
|
* environment `location` string (`environment.properties.location`).
|
|
8
8
|
* Returns `'eu'` when the location maps to the EU data boundary, routing
|
|
9
9
|
* telemetry to `eu-mobile.events.data.microsoft.com` instead of the global
|
|
10
|
-
* US collector.
|
|
10
|
+
* US collector. Missing or blank locations fail closed to the EU collector so
|
|
11
|
+
* telemetry emitted before the environment is known does not leave the EUDB.
|
|
11
12
|
*
|
|
12
13
|
* Mirrors the CLI's detection in `CliLogger.ts`:
|
|
13
14
|
* ```
|
|
@@ -21,6 +22,12 @@ import type { TelemetryLocation } from './TelemetryTypes';
|
|
|
21
22
|
* resolveTelemetryLocation('unitedkingdom') // → 'eu'
|
|
22
23
|
* resolveTelemetryLocation('italy') // → 'eu'
|
|
23
24
|
* resolveTelemetryLocation('unitedstates') // → 'global'
|
|
25
|
+
* resolveTelemetryLocation() // → 'eu'
|
|
24
26
|
*/
|
|
25
27
|
export declare function resolveTelemetryLocation(input?: string): TelemetryLocation;
|
|
28
|
+
/** Resolve a Dataverse Global Discovery `Instance.Region` code. */
|
|
29
|
+
export declare function resolveTelemetryLocationFromDataverseRegion(input?: string): TelemetryLocation;
|
|
30
|
+
export declare function tryResolveTelemetryLocationFromDataverseRegion(input?: string): TelemetryLocation | undefined;
|
|
31
|
+
/** Resolve launch metadata, falling back from BAP location to cluster geography. */
|
|
32
|
+
export declare function tryResolveTelemetryLocationFromEnvironment(location?: string, clusterGeoShortName?: string): TelemetryLocation | undefined;
|
|
26
33
|
//# sourceMappingURL=resolveTelemetryLocation.d.ts.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Classifies an unknown thrown value without exporting its message, stack, or
|
|
6
|
+
* serialized contents. Error prose is not a safe telemetry contract because
|
|
7
|
+
* upstream services may include customer data or credentials in it.
|
|
8
8
|
*/
|
|
9
9
|
export declare function stringifyError(error: unknown): string;
|
|
10
10
|
//# sourceMappingURL=stringifyError.d.ts.map
|
|
@@ -2,18 +2,9 @@
|
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* Returns a
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - **iOS**: `getIosIdForVendorAsync()` (IDFV) — stable while ≥1 app from the
|
|
9
|
-
* same vendor bundle prefix is installed. Resets only when ALL vendor apps
|
|
10
|
-
* are removed.
|
|
11
|
-
* - **Android**: `getAndroidId()` (SSAID) — scoped to the app signing key on
|
|
12
|
-
* Android 8+; survives reinstalls as long as the signing key is unchanged.
|
|
13
|
-
*
|
|
14
|
-
* If the platform API returns null (rare edge cases: first boot, some emulators)
|
|
15
|
-
* the function falls back to a UUID persisted in `expo-secure-store`, which on
|
|
16
|
-
* iOS survives reinstalls via the Keychain and on Android is per-install only.
|
|
5
|
+
* Returns a random app-scoped telemetry identifier. It does not use IDFV,
|
|
6
|
+
* SSAID, or another platform device identifier, and can be rotated with
|
|
7
|
+
* `resetDeviceId()` for deletion and opt-out workflows.
|
|
17
8
|
*
|
|
18
9
|
* Pass the resolved value to `OneDsTelemetryProviderConfig.deviceId` at startup.
|
|
19
10
|
*
|
|
@@ -26,4 +17,6 @@
|
|
|
26
17
|
* ```
|
|
27
18
|
*/
|
|
28
19
|
export declare function resolveDeviceId(): Promise<string>;
|
|
20
|
+
/** Deletes the app-scoped telemetry identifier so the next resolution rotates it. */
|
|
21
|
+
export declare function resetDeviceId(): Promise<void>;
|
|
29
22
|
//# sourceMappingURL=DeviceIdUtils.d.ts.map
|
|
@@ -7,12 +7,12 @@ export type { ILogger, ScenarioTracker } from './telemetry/ILogger.js';
|
|
|
7
7
|
export { Logger } from './telemetry/Logger.js';
|
|
8
8
|
export { OneDsTelemetryProvider } from './telemetry/OneDsTelemetryProvider.js';
|
|
9
9
|
export { ApplicationInsightsTelemetryProvider } from './telemetry/ApplicationInsightsTelemetryProvider.js';
|
|
10
|
-
export { resolveTelemetryLocation } from './telemetry/resolveTelemetryLocation.js';
|
|
10
|
+
export { resolveTelemetryLocation, resolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromDataverseRegion, tryResolveTelemetryLocationFromEnvironment, } from './telemetry/resolveTelemetryLocation.js';
|
|
11
11
|
export { stringifyError } from './telemetry/stringifyError.js';
|
|
12
12
|
export { sanitizeErrorString, sanitizeUrl, sanitizeProperties } from './telemetry/TelemetrySanitizer.js';
|
|
13
13
|
export { suppressKnownWarnings } from './telemetry/suppressKnownWarnings.js';
|
|
14
14
|
export { HttpClient, getHttpCorrelationProperties } from './http/HttpClient.js';
|
|
15
|
-
export { resolveDeviceId } from './utils/DeviceIdUtils.js';
|
|
15
|
+
export { resetDeviceId, resolveDeviceId } from './utils/DeviceIdUtils.js';
|
|
16
16
|
export { configureAppLogger, getAppLogger } from './telemetry/AppLogger.js';
|
|
17
17
|
export { configureCustomEventsLogger, getCustomEventsLogger, } from './telemetry/CustomEventsLogger.js';
|
|
18
18
|
export type { ICustomEventsLogger } from './telemetry/CustomEventsLogger.js';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ClusterCategory } from '../types/ClusterCategory.js';
|
|
2
|
+
import type { TelemetryEvent } from './TelemetryTypes.js';
|
|
3
|
+
export declare function buildAnonymousTelemetryData(event: TelemetryEvent, appName: string, clusterCategory: ClusterCategory): Record<string, unknown>;
|
|
4
|
+
//# sourceMappingURL=AnonymousTelemetry.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
|
-
import type { ITelemetryProvider, OneDsTelemetryProviderConfig, TelemetryEnvelope, TelemetryEvent, TelemetrySeverity, UserIdentity } from './TelemetryTypes.js';
|
|
4
|
+
import type { ITelemetryProvider, OneDsTelemetryProviderConfig, TelemetryEnvelope, TelemetryEvent, TelemetryLocation, TelemetrySeverity, UserIdentity } from './TelemetryTypes.js';
|
|
5
5
|
export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
6
|
+
private anonymous;
|
|
6
7
|
private readonly appName;
|
|
7
8
|
private readonly appVersion;
|
|
8
9
|
private readonly clientType;
|
|
@@ -13,11 +14,15 @@ export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
|
13
14
|
private readonly deviceMake;
|
|
14
15
|
private readonly deviceModel;
|
|
15
16
|
private readonly deviceType;
|
|
17
|
+
private readonly includeUserIdentity;
|
|
16
18
|
private readonly osName;
|
|
17
19
|
private readonly osVersion;
|
|
20
|
+
private readonly postChannel;
|
|
18
21
|
private readonly userLocale;
|
|
19
22
|
private readonly userTimeZone;
|
|
20
23
|
private readonly propertyColumnMap;
|
|
24
|
+
private locationResolution?;
|
|
25
|
+
private telemetryLocation;
|
|
21
26
|
readonly minSeverity: TelemetrySeverity;
|
|
22
27
|
private _sessionId;
|
|
23
28
|
private userIdentity?;
|
|
@@ -29,6 +34,8 @@ export declare class OneDsTelemetryProvider implements ITelemetryProvider {
|
|
|
29
34
|
*/
|
|
30
35
|
addTelemetryInitializer(initializer: (envelope: TelemetryEnvelope) => void): void;
|
|
31
36
|
track(event: TelemetryEvent): void;
|
|
37
|
+
resolveTelemetryLocation(telemetryLocation: TelemetryLocation): Promise<void>;
|
|
38
|
+
private applyTelemetryLocation;
|
|
32
39
|
flush(): Promise<void>;
|
|
33
40
|
teardown(): Promise<void>;
|
|
34
41
|
get sessionId(): string;
|
|
@@ -72,6 +72,8 @@ export interface OneDsTelemetryProviderConfig {
|
|
|
72
72
|
* and pass the result here. Falls back to `'react-native'` if omitted.
|
|
73
73
|
*/
|
|
74
74
|
deviceId?: string;
|
|
75
|
+
/** Include signed-in object and tenant IDs. Disabled by default. */
|
|
76
|
+
includeUserIdentity?: boolean;
|
|
75
77
|
/**
|
|
76
78
|
* 1DS instrumentation key (Aria project ID).
|
|
77
79
|
* When omitted, resolved automatically from `clusterCategory`.
|
|
@@ -81,6 +83,11 @@ export interface OneDsTelemetryProviderConfig {
|
|
|
81
83
|
minSeverity?: TelemetrySeverity;
|
|
82
84
|
/** Data residency location. Default: 'global'. Set to 'eu' for European environments. */
|
|
83
85
|
telemetryLocation?: TelemetryLocation;
|
|
86
|
+
/**
|
|
87
|
+
* Emit only non-identifying operational fields. Stable IDs, user identity,
|
|
88
|
+
* platform fingerprint fields, defaults, and arbitrary event properties are omitted.
|
|
89
|
+
*/
|
|
90
|
+
anonymous?: boolean;
|
|
84
91
|
commonProperties?: Record<string, string>;
|
|
85
92
|
propertyColumnMap?: PropertyColumnMap;
|
|
86
93
|
channelConfig?: Record<string, unknown>;
|
|
@@ -7,7 +7,8 @@ import type { TelemetryLocation } from './TelemetryTypes.js';
|
|
|
7
7
|
* environment `location` string (`environment.properties.location`).
|
|
8
8
|
* Returns `'eu'` when the location maps to the EU data boundary, routing
|
|
9
9
|
* telemetry to `eu-mobile.events.data.microsoft.com` instead of the global
|
|
10
|
-
* US collector.
|
|
10
|
+
* US collector. Missing or blank locations fail closed to the EU collector so
|
|
11
|
+
* telemetry emitted before the environment is known does not leave the EUDB.
|
|
11
12
|
*
|
|
12
13
|
* Mirrors the CLI's detection in `CliLogger.ts`:
|
|
13
14
|
* ```
|
|
@@ -21,6 +22,12 @@ import type { TelemetryLocation } from './TelemetryTypes.js';
|
|
|
21
22
|
* resolveTelemetryLocation('unitedkingdom') // → 'eu'
|
|
22
23
|
* resolveTelemetryLocation('italy') // → 'eu'
|
|
23
24
|
* resolveTelemetryLocation('unitedstates') // → 'global'
|
|
25
|
+
* resolveTelemetryLocation() // → 'eu'
|
|
24
26
|
*/
|
|
25
27
|
export declare function resolveTelemetryLocation(input?: string): TelemetryLocation;
|
|
28
|
+
/** Resolve a Dataverse Global Discovery `Instance.Region` code. */
|
|
29
|
+
export declare function resolveTelemetryLocationFromDataverseRegion(input?: string): TelemetryLocation;
|
|
30
|
+
export declare function tryResolveTelemetryLocationFromDataverseRegion(input?: string): TelemetryLocation | undefined;
|
|
31
|
+
/** Resolve launch metadata, falling back from BAP location to cluster geography. */
|
|
32
|
+
export declare function tryResolveTelemetryLocationFromEnvironment(location?: string, clusterGeoShortName?: string): TelemetryLocation | undefined;
|
|
26
33
|
//# sourceMappingURL=resolveTelemetryLocation.d.ts.map
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Classifies an unknown thrown value without exporting its message, stack, or
|
|
6
|
+
* serialized contents. Error prose is not a safe telemetry contract because
|
|
7
|
+
* upstream services may include customer data or credentials in it.
|
|
8
8
|
*/
|
|
9
9
|
export declare function stringifyError(error: unknown): string;
|
|
10
10
|
//# sourceMappingURL=stringifyError.d.ts.map
|
|
@@ -2,18 +2,9 @@
|
|
|
2
2
|
* Copyright (C) Microsoft Corporation. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* Returns a
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - **iOS**: `getIosIdForVendorAsync()` (IDFV) — stable while ≥1 app from the
|
|
9
|
-
* same vendor bundle prefix is installed. Resets only when ALL vendor apps
|
|
10
|
-
* are removed.
|
|
11
|
-
* - **Android**: `getAndroidId()` (SSAID) — scoped to the app signing key on
|
|
12
|
-
* Android 8+; survives reinstalls as long as the signing key is unchanged.
|
|
13
|
-
*
|
|
14
|
-
* If the platform API returns null (rare edge cases: first boot, some emulators)
|
|
15
|
-
* the function falls back to a UUID persisted in `expo-secure-store`, which on
|
|
16
|
-
* iOS survives reinstalls via the Keychain and on Android is per-install only.
|
|
5
|
+
* Returns a random app-scoped telemetry identifier. It does not use IDFV,
|
|
6
|
+
* SSAID, or another platform device identifier, and can be rotated with
|
|
7
|
+
* `resetDeviceId()` for deletion and opt-out workflows.
|
|
17
8
|
*
|
|
18
9
|
* Pass the resolved value to `OneDsTelemetryProviderConfig.deviceId` at startup.
|
|
19
10
|
*
|
|
@@ -26,4 +17,6 @@
|
|
|
26
17
|
* ```
|
|
27
18
|
*/
|
|
28
19
|
export declare function resolveDeviceId(): Promise<string>;
|
|
20
|
+
/** Deletes the app-scoped telemetry identifier so the next resolution rotates it. */
|
|
21
|
+
export declare function resetDeviceId(): Promise<void>;
|
|
29
22
|
//# sourceMappingURL=DeviceIdUtils.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/power-apps-native-common",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Shared utilities and types for Power Apps native packages",
|
|
5
5
|
"author": "Microsoft Corporation",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@microsoft/1ds-post-js": "4.4.1",
|
|
56
|
-
"@microsoft/applicationinsights-
|
|
56
|
+
"@microsoft/applicationinsights-channel-js": "3.4.3",
|
|
57
|
+
"@microsoft/applicationinsights-core-js": "3.4.3",
|
|
57
58
|
"@microsoft/applicationinsights-react-native": "4.4.1",
|
|
58
59
|
"@microsoft/applicationinsights-web": "3.4.3",
|
|
59
60
|
"uuid": "^11.1.1"
|