@snap/camera-kit 0.12.0 → 0.13.1
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 +3 -3
- package/docs/html/assets/search.js +1 -1
- package/docs/html/classes/CameraKit.html +12 -7
- package/docs/html/classes/CameraKitSession.html +27 -7
- package/docs/html/classes/CameraKitSource.html +26 -17
- package/docs/html/classes/LensPerformanceMeasurement.html +12 -7
- package/docs/html/classes/LensPerformanceMetrics.html +12 -7
- package/docs/html/classes/LensRepository.html +12 -7
- package/docs/html/classes/LensSources.html +12 -7
- package/docs/html/classes/Transform2D.html +12 -7
- package/docs/html/classes/TypedCustomEvent.html +12 -7
- package/docs/html/classes/TypedEventTarget.html +12 -7
- package/docs/html/functions/Injectable.html +12 -7
- package/docs/html/functions/bootstrapCameraKit.html +12 -7
- package/docs/html/functions/createExtension.html +12 -7
- package/docs/html/functions/createImageSource.html +12 -7
- package/docs/html/functions/createMediaStreamSource.html +12 -7
- package/docs/html/functions/createUserMediaSource.html +12 -7
- package/docs/html/functions/createVideoSource.html +12 -7
- package/docs/html/functions/estimateLensPerformance.html +12 -7
- package/docs/html/functions/getRequiredBootstrapURLs.html +12 -7
- package/docs/html/functions/lensSourcesFactory.html +12 -7
- package/docs/html/functions/{uriHandlersFactory.html → remoteApiServicesFactory.html} +16 -14
- package/docs/html/index.html +16 -11
- package/docs/html/interfaces/CameraKitBootstrapConfiguration.html +12 -7
- package/docs/html/interfaces/CameraKitSourceSubscriber.html +12 -7
- package/docs/html/interfaces/ComputedFrameMetrics.html +12 -7
- package/docs/html/interfaces/CreateSessionOptions.html +12 -7
- package/docs/html/interfaces/EstimatedLensPerformance.html +12 -7
- package/docs/html/interfaces/Lens.html +12 -7
- package/docs/html/interfaces/LensSource.html +16 -11
- package/docs/html/interfaces/MediaStreamSourceOptions.html +12 -7
- package/docs/html/interfaces/Preview.html +12 -7
- package/docs/html/interfaces/RemoteApiRequest.html +164 -0
- package/docs/html/interfaces/RemoteApiResponse.html +156 -0
- package/docs/html/interfaces/{UriHandler.html → RemoteApiService.html} +34 -68
- package/docs/html/interfaces/Snapcode.html +12 -7
- package/docs/html/interfaces/UriCancelRequest.html +12 -7
- package/docs/html/interfaces/UriRequest.html +13 -8
- package/docs/html/interfaces/UriResponse.html +12 -7
- package/docs/html/interfaces/VideoSourceOptions.html +12 -7
- package/docs/html/modules.html +22 -12
- package/docs/html/types/AssetLoader.html +12 -7
- package/docs/html/types/AssetTiming.html +12 -7
- package/docs/html/types/BenchmarkError.html +12 -7
- package/docs/html/types/BootstrapError.html +12 -7
- package/docs/html/types/CacheKeyNotFoundError.html +12 -7
- package/docs/html/types/CameraKitDeviceInfo.html +19 -9
- package/docs/html/types/CameraKitDeviceOptions.html +119 -0
- package/docs/html/types/CameraKitSessionEventListener.html +12 -7
- package/docs/html/types/CameraKitSessionEvents.html +12 -7
- package/docs/html/types/CameraKitSourceError.html +12 -7
- package/docs/html/types/CameraKitSourceInfo.html +12 -7
- package/docs/html/types/CameraKitSourceOptions.html +13 -8
- package/docs/html/types/ConfigurationError.html +12 -7
- package/docs/html/types/Keyboard.html +12 -7
- package/docs/html/types/KeyboardEvents.html +12 -7
- package/docs/html/types/LegalError.html +12 -7
- package/docs/html/types/LensAssetError.html +12 -7
- package/docs/html/types/LensContentValidationError.html +12 -7
- package/docs/html/types/LensError.html +12 -7
- package/docs/html/types/LensExecutionError.html +12 -7
- package/docs/html/types/LensImagePickerError.html +12 -7
- package/docs/html/types/LensLaunchParams.html +12 -7
- package/docs/html/types/LensMetricsEvents.html +12 -7
- package/docs/html/types/LensPerformanceCluster.html +12 -7
- package/docs/html/types/LensView.html +12 -7
- package/docs/html/types/LensWait.html +12 -7
- package/docs/html/types/PersistentStoreError.html +12 -7
- package/docs/html/types/PlatformNotSupportedError.html +12 -7
- package/docs/html/types/PublicContainer.html +12 -7
- package/docs/html/types/RemoteApiRequestHandler.html +141 -0
- package/docs/html/types/{UriHandlers.html → RemoteApiServices.html} +15 -13
- package/docs/html/types/RemoteApiStatus.html +114 -0
- package/docs/html/types/RenderTarget.html +12 -7
- package/docs/html/types/Uri.html +12 -7
- package/docs/html/types/WebGLError.html +12 -7
- package/docs/html/variables/extensionRequestContext.html +12 -7
- package/docs/md/README.md +3 -3
- package/docs/md/classes/CameraKit.md +1 -1
- package/docs/md/classes/CameraKitSession.md +19 -1
- package/docs/md/classes/CameraKitSource.md +19 -7
- package/docs/md/classes/LensPerformanceMeasurement.md +1 -1
- package/docs/md/classes/LensPerformanceMetrics.md +1 -1
- package/docs/md/classes/LensRepository.md +1 -1
- package/docs/md/classes/LensSources.md +1 -1
- package/docs/md/classes/Transform2D.md +1 -1
- package/docs/md/classes/TypedCustomEvent.md +1 -1
- package/docs/md/classes/TypedEventTarget.md +1 -1
- package/docs/md/interfaces/CameraKitBootstrapConfiguration.md +1 -1
- package/docs/md/interfaces/CameraKitSourceSubscriber.md +1 -1
- package/docs/md/interfaces/ComputedFrameMetrics.md +1 -1
- package/docs/md/interfaces/CreateSessionOptions.md +1 -1
- package/docs/md/interfaces/EstimatedLensPerformance.md +1 -1
- package/docs/md/interfaces/Lens.md +1 -1
- package/docs/md/interfaces/LensSource.md +3 -3
- package/docs/md/interfaces/MediaStreamSourceOptions.md +1 -1
- package/docs/md/interfaces/Preview.md +1 -1
- package/docs/md/interfaces/RemoteApiRequest.md +46 -0
- package/docs/md/interfaces/RemoteApiResponse.md +37 -0
- package/docs/md/interfaces/RemoteApiService.md +45 -0
- package/docs/md/interfaces/Snapcode.md +1 -1
- package/docs/md/interfaces/UriCancelRequest.md +1 -1
- package/docs/md/interfaces/UriRequest.md +2 -2
- package/docs/md/interfaces/UriResponse.md +1 -1
- package/docs/md/interfaces/VideoSourceOptions.md +1 -1
- package/docs/md/modules.md +66 -15
- package/lib/CameraKit.js +3 -1
- package/lib/CameraKit.js.map +1 -1
- package/lib/__tests__/data.d.ts +1 -1
- package/lib/__tests__/data.js +1 -0
- package/lib/__tests__/data.js.map +1 -1
- package/lib/bootstrapCameraKit.js +12 -10
- package/lib/bootstrapCameraKit.js.map +1 -1
- package/lib/common/any.d.ts +17 -0
- package/lib/common/any.js +36 -0
- package/lib/common/any.js.map +1 -0
- package/lib/common/cameraKitUserAgent.d.ts +5 -0
- package/lib/common/cameraKitUserAgent.js +2 -1
- package/lib/common/cameraKitUserAgent.js.map +1 -1
- package/lib/common/date.d.ts +3 -0
- package/lib/common/date.js +13 -0
- package/lib/common/date.js.map +1 -0
- package/lib/common/errorHelpers.js +1 -1
- package/lib/common/errorHelpers.js.map +1 -1
- package/lib/common/time.d.ts +1 -0
- package/lib/common/time.js +1 -0
- package/lib/common/time.js.map +1 -1
- package/lib/common/types.d.ts +8 -0
- package/lib/common/types.js.map +1 -1
- package/lib/dependency-injection/RootServices.d.ts +2 -0
- package/lib/dependency-injection/RootServices.js.map +1 -1
- package/lib/environment.json +1 -1
- package/lib/extensions/LensSources.d.ts +2 -2
- package/lib/extensions/LensSources.js +7 -3
- package/lib/extensions/LensSources.js.map +1 -1
- package/lib/extensions/RemoteApiServices.d.ts +101 -0
- package/lib/extensions/RemoteApiServices.js +198 -0
- package/lib/extensions/RemoteApiServices.js.map +1 -0
- package/lib/extensions/UriHandlers.d.ts +10 -17
- package/lib/extensions/UriHandlers.js +5 -60
- package/lib/extensions/UriHandlers.js.map +1 -1
- package/lib/extensions/uriHandlersRegister.d.ts +21 -0
- package/lib/extensions/uriHandlersRegister.js +72 -0
- package/lib/extensions/uriHandlersRegister.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/features/remote_api_info.d.ts +31 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/features/remote_api_info.js +43 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/features/remote_api_info.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.d.ts +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/remote_api/remote_api_service.d.ts +569 -0
- package/lib/generated-proto/pb_schema/lenses/remote_api/remote_api_service.js +1175 -0
- package/lib/generated-proto/pb_schema/lenses/remote_api/remote_api_service.js.map +1 -0
- package/lib/handlers/defaultFetchHandler.js +17 -4
- package/lib/handlers/defaultFetchHandler.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/legal/legalState.js +1 -1
- package/lib/legal/legalState.js.map +1 -1
- package/lib/lens/lensHttpUtil.js +26 -4
- package/lib/lens/lensHttpUtil.js.map +1 -1
- package/lib/lens-core-module/generated-types.d.ts +24 -4
- package/lib/lens-core-module/generated-types.js.map +1 -1
- package/lib/lensCoreWasmVersions.json +3 -3
- package/lib/logger/registerLogEntriesSubscriber.js +13 -1
- package/lib/logger/registerLogEntriesSubscriber.js.map +1 -1
- package/lib/media-sources/CameraKitSource.d.ts +13 -3
- package/lib/media-sources/CameraKitSource.js +2 -8
- package/lib/media-sources/CameraKitSource.js.map +1 -1
- package/lib/media-sources/FunctionSource.d.ts +1 -1
- package/lib/media-sources/FunctionSource.js +1 -1
- package/lib/media-sources/FunctionSource.js.map +1 -1
- package/lib/media-sources/ImageSource.d.ts +1 -1
- package/lib/media-sources/ImageSource.js +1 -1
- package/lib/media-sources/ImageSource.js.map +1 -1
- package/lib/media-sources/MediaStreamSource.d.ts +1 -1
- package/lib/media-sources/MediaStreamSource.js +2 -1
- package/lib/media-sources/MediaStreamSource.js.map +1 -1
- package/lib/media-sources/VideoSource.d.ts +1 -1
- package/lib/media-sources/VideoSource.js +1 -1
- package/lib/media-sources/VideoSource.js.map +1 -1
- package/lib/metrics/businessEventsReporter.d.ts +3 -2
- package/lib/metrics/businessEventsReporter.js +125 -65
- package/lib/metrics/businessEventsReporter.js.map +1 -1
- package/lib/metrics/operational/operationalMetricsReporter.js +23 -5
- package/lib/metrics/operational/operationalMetricsReporter.js.map +1 -1
- package/lib/metrics/reporters/reportHttpMetrics.d.ts +0 -7
- package/lib/metrics/reporters/reportHttpMetrics.js +3 -2
- package/lib/metrics/reporters/reportHttpMetrics.js.map +1 -1
- package/lib/metrics/reporters/reportLensView.d.ts +1 -1
- package/lib/metrics/reporters/reportLensView.js +41 -13
- package/lib/metrics/reporters/reportLensView.js.map +1 -1
- package/lib/metrics/reporters/reportUserSession.js +15 -16
- package/lib/metrics/reporters/reportUserSession.js.map +1 -1
- package/lib/metrics/reporters/reporters.d.ts +1 -1
- package/lib/persistence/ExpiringPersistence.d.ts +2 -1
- package/lib/persistence/ExpiringPersistence.js +15 -1
- package/lib/persistence/ExpiringPersistence.js.map +1 -1
- package/lib/persistence/IndexedDBPersistence.d.ts +1 -1
- package/lib/persistence/IndexedDBPersistence.js +11 -1
- package/lib/persistence/IndexedDBPersistence.js.map +1 -1
- package/lib/persistence/Persistence.d.ts +1 -1
- package/lib/persistence/Persistence.js.map +1 -1
- package/lib/remote-configuration/preloadConfiguration.d.ts +7 -0
- package/lib/remote-configuration/preloadConfiguration.js +15 -0
- package/lib/remote-configuration/preloadConfiguration.js.map +1 -0
- package/lib/remote-configuration/remoteConfiguration.d.ts +5 -1
- package/lib/remote-configuration/remoteConfiguration.js +10 -2
- package/lib/remote-configuration/remoteConfiguration.js.map +1 -1
- package/lib/session/CameraKitSession.d.ts +7 -2
- package/lib/session/CameraKitSession.js +1 -0
- package/lib/session/CameraKitSession.js.map +1 -1
- package/lib/session/sessionState.d.ts +2 -2
- package/lib/session/sessionState.js +3 -3
- package/lib/session/sessionState.js.map +1 -1
- package/package.json +2 -1
- package/docs/md/interfaces/UriHandler.md +0 -63
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { __awaiter } from "tslib";
|
|
1
2
|
import { v4 } from "uuid";
|
|
3
|
+
import { catchError, from, of, switchMap, take } from "rxjs";
|
|
2
4
|
import { cameraKitUserAgent as userAgent } from "../common/cameraKitUserAgent";
|
|
3
5
|
import { entries } from "../common/entries";
|
|
4
6
|
import { Injectable } from "../dependency-injection/Injectable";
|
|
@@ -9,6 +11,10 @@ import * as blizzard from "../generated-proto/blizzard/cameraKitEvents";
|
|
|
9
11
|
import { getLogger } from "../logger/logger";
|
|
10
12
|
import { pageVisibilityFactory } from "../common/pageVisibility";
|
|
11
13
|
import { configurationToken } from "../configuration";
|
|
14
|
+
import { remoteConfigurationFactory } from "../remote-configuration/remoteConfiguration";
|
|
15
|
+
import { IndexedDBPersistence } from "../persistence/IndexedDBPersistence";
|
|
16
|
+
import { ExpiringPersistence } from "../persistence/ExpiringPersistence";
|
|
17
|
+
import { convertDaysToSeconds } from "../common/time";
|
|
12
18
|
import { metricsHandlerFactory } from "./metricsHandler";
|
|
13
19
|
import { metricsEventTargetFactory } from "./metricsEventTarget";
|
|
14
20
|
const logger = getLogger("BusinessEventsReporter");
|
|
@@ -23,7 +29,37 @@ const relativePath = "/com.snap.camerakit.v3.Metrics/metrics/business_events";
|
|
|
23
29
|
// limit to ensure we don't lose events which are larger in size than we expect.
|
|
24
30
|
const BUSINESS_EVENT_BATCH_MAX_SIZE = 10;
|
|
25
31
|
const BUSINESS_EVENT_BATCH_MAX_AGE_MS = 5000;
|
|
26
|
-
|
|
32
|
+
const connectivityTypeMapping = {
|
|
33
|
+
cellular: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_MOBILE,
|
|
34
|
+
bluetooth: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_BLUETOOTH,
|
|
35
|
+
wifi: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_WIFI,
|
|
36
|
+
unknown: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNKNOWN,
|
|
37
|
+
none: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNREACHABLE,
|
|
38
|
+
};
|
|
39
|
+
const vendorUuidKey = "vendorUuid";
|
|
40
|
+
const vendorUuidExpiry = convertDaysToSeconds(60);
|
|
41
|
+
/**
|
|
42
|
+
* Retrieves or generates a vendor UUID (Universally Unique Identifier).
|
|
43
|
+
*
|
|
44
|
+
* @param persistence - The persistence storage interface where UUID is stored.
|
|
45
|
+
* @returns {Promise<string | undefined>} - A Promise that resolves to the vendor UUID or undefined,
|
|
46
|
+
* if any failure occurs or opt-in is not enabled.
|
|
47
|
+
*/
|
|
48
|
+
const getOrGenerateVendorUuid = (persistence) => __awaiter(void 0, void 0, void 0, function* () {
|
|
49
|
+
try {
|
|
50
|
+
const storedUuid = yield persistence.retrieve(vendorUuidKey);
|
|
51
|
+
if (storedUuid) {
|
|
52
|
+
return storedUuid;
|
|
53
|
+
}
|
|
54
|
+
const newUuid = v4();
|
|
55
|
+
yield persistence.store(vendorUuidKey, newUuid);
|
|
56
|
+
return newUuid;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw new Error("Failed to generate vendor UUID");
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
function listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, eventHandlers, apiHostname, appVendorUuid) {
|
|
27
63
|
const sessionId = v4();
|
|
28
64
|
logger.log(`Session ID: ${sessionId}`);
|
|
29
65
|
// Blizzard convention is to start the sequenceId at 1.
|
|
@@ -57,6 +93,8 @@ function listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, eve
|
|
|
57
93
|
pageVisibility,
|
|
58
94
|
})).handler;
|
|
59
95
|
const makeBlizzardEvent = (event) => {
|
|
96
|
+
var _a;
|
|
97
|
+
const deviceConnectivity = (_a = connectivityTypeMapping[userAgent.connectionType]) !== null && _a !== void 0 ? _a : blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNKNOWN;
|
|
60
98
|
return Object.assign(Object.assign({}, event), { cameraKitEventBase: blizzard.CameraKitEventBase.fromPartial({
|
|
61
99
|
kitEventBase: blizzard.KitEventBase.fromPartial({
|
|
62
100
|
locale: userAgent.locale,
|
|
@@ -73,8 +111,9 @@ function listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, eve
|
|
|
73
111
|
// We overload appId, using the origin instead because it's nice and human-readable (our backed adds
|
|
74
112
|
// the true appId as oauth_client_id before forwarding events to Blizzard).
|
|
75
113
|
appId: userAgent.origin,
|
|
76
|
-
deviceConnectivity
|
|
114
|
+
deviceConnectivity,
|
|
77
115
|
sessionId: sessionId,
|
|
116
|
+
appVendorUuid,
|
|
78
117
|
}) });
|
|
79
118
|
};
|
|
80
119
|
const sendServerEvent = (eventName, eventData) => {
|
|
@@ -106,68 +145,89 @@ export const businessEventsReporterFactory = Injectable("businessEventsReporter"
|
|
|
106
145
|
metricsHandlerFactory.token,
|
|
107
146
|
pageVisibilityFactory.token,
|
|
108
147
|
configurationToken,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
148
|
+
remoteConfigurationFactory.token,
|
|
149
|
+
], (metricsEventTarget, metricsHandler, pageVisibility, configuration, remoteConfiguration) => {
|
|
150
|
+
const vendorAnalyticsPersistence = new ExpiringPersistence(() => vendorUuidExpiry, new IndexedDBPersistence({ databaseName: "SessionHistory" }));
|
|
151
|
+
remoteConfiguration
|
|
152
|
+
.getInitializationConfig()
|
|
153
|
+
.pipe(take(1), switchMap(({ appVendorUuidOptIn }) => {
|
|
154
|
+
if (appVendorUuidOptIn) {
|
|
155
|
+
return from(getOrGenerateVendorUuid(vendorAnalyticsPersistence));
|
|
156
|
+
}
|
|
157
|
+
return of(undefined);
|
|
158
|
+
}), catchError((error) => {
|
|
159
|
+
logger.warn(`Failed to retrieve or generate vendor UUID.`, error);
|
|
160
|
+
return of(undefined);
|
|
161
|
+
}))
|
|
162
|
+
.subscribe({
|
|
163
|
+
next: (appVendorUuid) => {
|
|
164
|
+
/**
|
|
165
|
+
* This defines a mapping from a business event's external name (the name we document in public
|
|
166
|
+
* API docs), to its internal representation as a Blizzard ServerEvent.
|
|
167
|
+
*
|
|
168
|
+
* It is important that we do this, since the naming of these internal business events are
|
|
169
|
+
* unintuitive and will not make sense to SDK users.
|
|
170
|
+
*
|
|
171
|
+
* To specify the internal event, we must give the ServerEvent's eventName, the specific property
|
|
172
|
+
* name which contains the event data (this is a "oneof" property on ServerEvent), and use the
|
|
173
|
+
* correct event type's `fromPartial` method (this is generated from the ServerEvent protobuf).
|
|
174
|
+
*
|
|
175
|
+
* These events are documented here:
|
|
176
|
+
* https://docs.google.com/document/d/1-kSzFWCWw9Qo3D08FR1_cqeHTsUtk9p3p3uOptzWDTY/
|
|
177
|
+
*
|
|
178
|
+
* They are defined in code here:
|
|
179
|
+
* https://github.sc-corp.net/Snapchat/snapchat/tree/master/blizzard/schema/blizzard-schema/
|
|
180
|
+
* codeGen/src/main/java/com/snapchat/analytics/schema/events/cameraKit
|
|
181
|
+
*/
|
|
182
|
+
listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, {
|
|
183
|
+
assetDownload: (event) => [
|
|
184
|
+
"CAMERA_KIT_ASSET_DOWNLOAD",
|
|
185
|
+
{ cameraKitAssetDownload: blizzard.CameraKitAssetDownload.fromPartial(event) },
|
|
186
|
+
],
|
|
187
|
+
assetValidationFailed: (event) => [
|
|
188
|
+
"CAMERA_KIT_ASSET_VALIDATION_FAILED",
|
|
189
|
+
{
|
|
190
|
+
cameraKitAssetValidationFailed: blizzard.CameraKitAssetValidationFailed.fromPartial(event),
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
benchmarkComplete: (event) => [
|
|
194
|
+
"CAMERA_KIT_WEB_BENCHMARK_COMPLETE",
|
|
195
|
+
{
|
|
196
|
+
cameraKitWebBenchmarkComplete: blizzard.CameraKitWebBenchmarkComplete.fromPartial(event),
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
exception: (event) => [
|
|
200
|
+
"CAMERA_KIT_EXCEPTION",
|
|
201
|
+
{ cameraKitException: blizzard.CameraKitException.fromPartial(event) },
|
|
202
|
+
],
|
|
203
|
+
legalPrompt: (event) => [
|
|
204
|
+
"CAMERA_KIT_LEGAL_PROMPT",
|
|
205
|
+
{ cameraKitLegalPrompt: blizzard.CameraKitLegalPrompt.fromPartial(event) },
|
|
206
|
+
],
|
|
207
|
+
lensDownload: (event) => [
|
|
208
|
+
"CAMERA_KIT_LENS_DOWNLOAD",
|
|
209
|
+
{ cameraKitLensDownload: blizzard.CameraKitLensDownload.fromPartial(event) },
|
|
210
|
+
],
|
|
211
|
+
lensView: (event) => [
|
|
212
|
+
"CAMERA_KIT_WEB_LENS_SWIPE",
|
|
213
|
+
{ cameraKitWebLensSwipe: blizzard.CameraKitWebLensSwipe.fromPartial(event) },
|
|
214
|
+
],
|
|
215
|
+
lensWait: (event) => [
|
|
216
|
+
"CAMERA_KIT_LENS_SPIN",
|
|
217
|
+
{ cameraKitLensSpin: blizzard.CameraKitLensSpin.fromPartial(event) },
|
|
218
|
+
],
|
|
219
|
+
lensContentValidationFailed: (event) => [
|
|
220
|
+
"CAMERA_KIT_LENS_CONTENT_VALIDATION_FAILED",
|
|
221
|
+
{
|
|
222
|
+
cameraKitLensContentValidationFailed: blizzard.CameraKitLensContentValidationFailed.fromPartial(event),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
session: (event) => [
|
|
226
|
+
"CAMERA_KIT_SESSION",
|
|
227
|
+
{ cameraKitSession: blizzard.CameraKitSession.fromPartial(event) },
|
|
228
|
+
],
|
|
229
|
+
}, configuration.apiHostname, appVendorUuid);
|
|
230
|
+
},
|
|
231
|
+
});
|
|
172
232
|
});
|
|
173
233
|
//# sourceMappingURL=businessEventsReporter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"businessEventsReporter.js","sourceRoot":"","sources":["../../src/metrics/businessEventsReporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { v4 } from \"uuid\";\nimport { cameraKitUserAgent as userAgent } from \"../common/cameraKitUserAgent\";\nimport { entries } from \"../common/entries\";\nimport { Injectable } from \"../dependency-injection/Injectable\";\nimport { EventOfType } from \"../events/TypedCustomEvent\";\nimport { EventsFromTarget } from \"../events/TypedEventTarget\";\nimport { FetchHandler } from \"../handlers/defaultFetchHandler\";\nimport { createBatchingHandler } from \"../handlers/batchingHandler\";\nimport { HandlerChainBuilder } from \"../handlers/HandlerChainBuilder\";\nimport { createMappingHandler } from \"../handlers/mappingHandler\";\nimport * as blizzard from \"../generated-proto/blizzard/cameraKitEvents\";\nimport { getLogger } from \"../logger/logger\";\nimport { PageVisibility, pageVisibilityFactory } from \"../common/pageVisibility\";\nimport { CameraKitApiHostname, CameraKitConfiguration, configurationToken } from \"../configuration\";\nimport { metricsHandlerFactory } from \"./metricsHandler\";\nimport { MetricsEventTarget, metricsEventTargetFactory } from \"./metricsEventTarget\";\n\nconst logger = getLogger(\"BusinessEventsReporter\");\n\ntype Nullables<T> = { [K in keyof T]-?: undefined extends T[K] ? K : never }[keyof T];\ntype UndefinedToOptional<T> = Partial<Pick<T, Nullables<T>>> & Omit<T, Nullables<T>>;\n\ntype CameraKitBusinessEvents = EventsFromTarget<MetricsEventTarget>[\"detail\"];\n\ntype MakeBlizzardEvent<E> = Omit<E, \"name\"> & { cameraKitEventBase: blizzard.CameraKitEventBase };\n\ntype CreateEventData<EventType extends EventsFromTarget<MetricsEventTarget>[\"type\"]> = (\n event: MakeBlizzardEvent<EventOfType<EventType, EventsFromTarget<MetricsEventTarget>>[\"detail\"]>\n) => [string, UndefinedToOptional<blizzard.ServerEventData>];\n\ntype EventHandlers = {\n [EventType in EventsFromTarget<MetricsEventTarget>[\"type\"]]: CreateEventData<EventType>;\n};\n\n/**\n * Translate between an external metric name, which is exposed to SDK users, and an internal Blizzard event name,\n * property name, and constructor.\n *\n * It is very important that we do this, since the naming of these internal business events are unintuitive and will\n * not make sense to SDK users.\n *\n * For a full list of business events (using their internal names), see:\n * https://docs.google.com/document/d/1-kSzFWCWw9Qo3D08FR1_cqeHTsUtk9p3p3uOptzWDTY/\n */\ntype CameraKitBusinessEventMap = {\n assetDownload: MakeBusinessEvent<blizzard.CameraKitAssetDownload>;\n assetValidationFailed: MakeBusinessEvent<blizzard.CameraKitAssetValidationFailed>;\n benchmarkComplete: MakeBusinessEvent<blizzard.CameraKitWebBenchmarkComplete>;\n exception: MakeBusinessEvent<blizzard.CameraKitException>;\n legalPrompt: MakeBusinessEvent<blizzard.CameraKitLegalPrompt>;\n lensDownload: MakeBusinessEvent<blizzard.CameraKitLensDownload>;\n lensView: MakeBusinessEvent<blizzard.CameraKitWebLensSwipe>;\n lensWait: MakeBusinessEvent<blizzard.CameraKitLensSpin>;\n lensContentValidationFailed: MakeBusinessEvent<blizzard.CameraKitLensContentValidationFailed>;\n session: MakeBusinessEvent<blizzard.CameraKitSession>;\n};\n\n/**\n * This interface is defined in the CameraKit pb_schema proto definition – but the generated TypeScript does not handle\n * the `Any` type properly. It does not conform to the Proto3 canonical JSON mapping scheme, as defined here:\n * https://developers.google.com/protocol-buffers/docs/proto3#json\n *\n * To solve this (since we only need one message from the CameraKit schema), we'll just manually define the correct\n * interface here.\n */\ninterface SetBusinessEventsRequest {\n batchEvents: {\n \"@type\": \"com.snapchat.analytics.blizzard.ServerEventBatch\";\n serverEvents: blizzard.ServerEvent[];\n };\n}\n\n// CameraKit's prod metrics endpoint.\n// See: https://github.sc-corp.net/Snapchat/pb_schema/blob/2a966db/proto/camera_kit/v3/service.proto#L133\nconst relativePath = \"/com.snap.camerakit.v3.Metrics/metrics/business_events\";\n\n// It is rather cumbersome to check the actual final size of a batch, but we can easily limit the number of events we\n// include in each batch -- looking at historical data, typical events average ~1.3kb per event. But there are some\n// events (like CAMERA_KIT_EXCEPTION, which includes a stack trace) that can be much larger.\n//\n// To prevent us running over the 64kibibyte limit imposed by browsers on `keep-alive` requests, we'll set quite a low\n// limit to ensure we don't lose events which are larger in size than we expect.\nconst BUSINESS_EVENT_BATCH_MAX_SIZE = 10;\nconst BUSINESS_EVENT_BATCH_MAX_AGE_MS = 5000;\n\nfunction listenAndReport(\n metricsEventTarget: MetricsEventTarget,\n metricsHandler: FetchHandler,\n pageVisibility: PageVisibility,\n eventHandlers: EventHandlers,\n apiHostname: CameraKitApiHostname\n): void {\n const sessionId = v4();\n logger.log(`Session ID: ${sessionId}`);\n\n // Blizzard convention is to start the sequenceId at 1.\n let sequenceId = 1;\n\n const handler = new HandlerChainBuilder(metricsHandler)\n .map(\n createMappingHandler((events: blizzard.ServerEvent[]) => {\n const body: SetBusinessEventsRequest = {\n batchEvents: {\n \"@type\": \"com.snapchat.analytics.blizzard.ServerEventBatch\",\n serverEvents: events,\n },\n };\n\n return new Request(`https://${apiHostname}${relativePath}`, {\n method: \"POST\",\n body: JSON.stringify(body),\n credentials: \"include\",\n\n // When this is true it makes fetch behave like `Navigator.sendBeacon` – that is, the request\n // will still be made even if the page terminates.\n // https://developer.mozilla.org/en-US/docs/Web/API/fetch\n keepalive: pageVisibility.isDuringVisibilityTransition(\"hidden\"),\n });\n }, pageVisibility)\n )\n .map(\n createBatchingHandler({\n batchReduce: (\n previousBundle: blizzard.ServerEvent[] | undefined,\n businessEvent: blizzard.ServerEvent\n ) => {\n const bundle = previousBundle ?? [];\n bundle.push(businessEvent);\n return bundle;\n },\n isBatchComplete: (bundle) => bundle.length >= BUSINESS_EVENT_BATCH_MAX_SIZE,\n maxBatchAge: BUSINESS_EVENT_BATCH_MAX_AGE_MS,\n pageVisibility,\n })\n ).handler;\n\n const makeBlizzardEvent = <E extends CameraKitBusinessEvents>(event: E): MakeBlizzardEvent<E> => {\n return {\n ...event,\n cameraKitEventBase: blizzard.CameraKitEventBase.fromPartial({\n kitEventBase: blizzard.KitEventBase.fromPartial({\n locale: userAgent.locale,\n kitVariant: blizzard.KitType.CAMERA_KIT_WEB,\n kitVariantVersion: userAgent.sdkShortVersion,\n kitClientTimestampMillis: Date.now(),\n }),\n deviceCluster: 0,\n cameraKitVersion: userAgent.sdkLongVersion,\n lensCoreVersion: userAgent.lensCoreVersion,\n deviceModel: userAgent.deviceModel,\n cameraKitVariant: blizzard.CameraKitVariant.CAMERA_KIT_VARIANT_PARTNER,\n cameraKitFlavor: blizzard.CameraKitFlavor.CAMERA_KIT_FLAVOR_DEBUG,\n // We overload appId, using the origin instead because it's nice and human-readable (our backed adds\n // the true appId as oauth_client_id before forwarding events to Blizzard).\n appId: userAgent.origin,\n deviceConnectivity: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_WIFI,\n sessionId: sessionId,\n }),\n };\n };\n\n const sendServerEvent = (\n eventName: string,\n eventData: UndefinedToOptional<blizzard.ServerEventData>\n ): Promise<void> => {\n return handler(\n blizzard.ServerEvent.fromPartial({\n eventName,\n osType: userAgent.osType,\n osVersion: userAgent.osVersion,\n maxSequenceIdOnInstance: 0,\n sequenceId: sequenceId++,\n eventData,\n })\n );\n };\n\n entries(eventHandlers).forEach(([eventType, createEventData]) => {\n metricsEventTarget.addEventListener(eventType, ({ detail }) => {\n // Safety: When iterating over object keys in a mapped type, we lose the association between the key type\n // and the value type – at each iteration, the key type is a union of all possible keys and the value type\n // is a union of all possible values. When the value is a function with an argument, and that argument\n // depends on the key type (which is a union), the contravariance of the argument type means that the union\n // becomes an intersection. In our case here, this means the compiler expects each argument to contain all\n // properties from all event types. The cast is safe because the mapped `EventHandlers` type ensures that\n // `createEventData` takes an argument of the type corresponding its key's `eventType`'s event detail.\n const [eventName, eventData] = createEventData(makeBlizzardEvent(detail) as any);\n sendServerEvent(eventName, eventData);\n });\n });\n}\n\nexport type MakeBusinessEvent<E> = Omit<\n {\n [K in keyof E]: Exclude<E[K], undefined> extends Record<keyof any, any>\n ? MakeBusinessEvent<Exclude<E[K], undefined>>\n : E[K];\n },\n \"cameraKitEventBase\"\n>;\n\nexport type MakeTaggedBusinessEvent<K extends keyof CameraKitBusinessEventMap> = {\n name: K;\n} & CameraKitBusinessEventMap[K];\n\nexport const businessEventsReporterFactory = Injectable(\n \"businessEventsReporter\",\n [\n metricsEventTargetFactory.token,\n metricsHandlerFactory.token,\n pageVisibilityFactory.token,\n configurationToken,\n ] as const,\n (\n metricsEventTarget: MetricsEventTarget,\n metricsHandler: FetchHandler,\n pageVisibility: PageVisibility,\n configuration: CameraKitConfiguration\n ) => {\n /**\n * This defines a mapping from a business event's external name (the name we document in public API docs), to\n * its internal representation as a Blizzard ServerEvent.\n *\n * It is important that we do this, since the naming of these internal business events are unintuitive and will\n * not make sense to SDK users.\n *\n * To specify the internal event, we must give the ServerEvent's eventName, the specific property name which\n * contains the event data (this is a \"oneof\" property on ServerEvent), and use the correct event type's\n * `fromPartial` method (this is generated from the ServerEvent protobuf).\n *\n * These events are documented here:\n * https://docs.google.com/document/d/1-kSzFWCWw9Qo3D08FR1_cqeHTsUtk9p3p3uOptzWDTY/\n *\n * They are defined in code here:\n * https://github.sc-corp.net/Snapchat/snapchat/tree/master/blizzard/schema/blizzard-schema/\n * codeGen/src/main/java/com/snapchat/analytics/schema/events/cameraKit\n */\n listenAndReport(\n metricsEventTarget,\n metricsHandler,\n pageVisibility,\n {\n assetDownload: (event) => [\n \"CAMERA_KIT_ASSET_DOWNLOAD\",\n { cameraKitAssetDownload: blizzard.CameraKitAssetDownload.fromPartial(event) },\n ],\n assetValidationFailed: (event) => [\n \"CAMERA_KIT_ASSET_VALIDATION_FAILED\",\n { cameraKitAssetValidationFailed: blizzard.CameraKitAssetValidationFailed.fromPartial(event) },\n ],\n benchmarkComplete: (event) => [\n \"CAMERA_KIT_WEB_BENCHMARK_COMPLETE\",\n { cameraKitWebBenchmarkComplete: blizzard.CameraKitWebBenchmarkComplete.fromPartial(event) },\n ],\n exception: (event) => [\n \"CAMERA_KIT_EXCEPTION\",\n { cameraKitException: blizzard.CameraKitException.fromPartial(event) },\n ],\n legalPrompt: (event) => [\n \"CAMERA_KIT_LEGAL_PROMPT\",\n { cameraKitLegalPrompt: blizzard.CameraKitLegalPrompt.fromPartial(event) },\n ],\n lensDownload: (event) => [\n \"CAMERA_KIT_LENS_DOWNLOAD\",\n { cameraKitLensDownload: blizzard.CameraKitLensDownload.fromPartial(event) },\n ],\n lensView: (event) => [\n \"CAMERA_KIT_WEB_LENS_SWIPE\",\n { cameraKitWebLensSwipe: blizzard.CameraKitWebLensSwipe.fromPartial(event) },\n ],\n lensWait: (event) => [\n \"CAMERA_KIT_LENS_SPIN\",\n { cameraKitLensSpin: blizzard.CameraKitLensSpin.fromPartial(event) },\n ],\n lensContentValidationFailed: (event) => [\n \"CAMERA_KIT_LENS_CONTENT_VALIDATION_FAILED\",\n {\n cameraKitLensContentValidationFailed:\n blizzard.CameraKitLensContentValidationFailed.fromPartial(event),\n },\n ],\n session: (event) => [\n \"CAMERA_KIT_SESSION\",\n { cameraKitSession: blizzard.CameraKitSession.fromPartial(event) },\n ],\n },\n configuration.apiHostname\n );\n }\n);\n"]}
|
|
1
|
+
{"version":3,"file":"businessEventsReporter.js","sourceRoot":"","sources":["../../src/metrics/businessEventsReporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { v4 } from \"uuid\";\nimport { catchError, from, of, switchMap, take } from \"rxjs\";\nimport { ConnectionType, cameraKitUserAgent as userAgent } from \"../common/cameraKitUserAgent\";\nimport { entries } from \"../common/entries\";\nimport { Injectable } from \"../dependency-injection/Injectable\";\nimport { EventOfType } from \"../events/TypedCustomEvent\";\nimport { EventsFromTarget } from \"../events/TypedEventTarget\";\nimport { FetchHandler } from \"../handlers/defaultFetchHandler\";\nimport { createBatchingHandler } from \"../handlers/batchingHandler\";\nimport { HandlerChainBuilder } from \"../handlers/HandlerChainBuilder\";\nimport { createMappingHandler } from \"../handlers/mappingHandler\";\nimport * as blizzard from \"../generated-proto/blizzard/cameraKitEvents\";\nimport { getLogger } from \"../logger/logger\";\nimport { PageVisibility, pageVisibilityFactory } from \"../common/pageVisibility\";\nimport { CameraKitApiHostname, CameraKitConfiguration, configurationToken } from \"../configuration\";\nimport { remoteConfigurationFactory, RemoteConfiguration } from \"../remote-configuration/remoteConfiguration\";\nimport { IndexedDBPersistence } from \"../persistence/IndexedDBPersistence\";\nimport { ExpiringPersistence } from \"../persistence/ExpiringPersistence\";\nimport { convertDaysToSeconds } from \"../common/time\";\nimport { metricsHandlerFactory } from \"./metricsHandler\";\nimport { MetricsEventTarget, metricsEventTargetFactory } from \"./metricsEventTarget\";\n\nconst logger = getLogger(\"BusinessEventsReporter\");\n\ntype Nullables<T> = { [K in keyof T]-?: undefined extends T[K] ? K : never }[keyof T];\ntype UndefinedToOptional<T> = Partial<Pick<T, Nullables<T>>> & Omit<T, Nullables<T>>;\n\ntype CameraKitBusinessEvents = EventsFromTarget<MetricsEventTarget>[\"detail\"];\n\ntype MakeBlizzardEvent<E> = Omit<E, \"name\"> & { cameraKitEventBase: blizzard.CameraKitEventBase };\n\ntype CreateEventData<EventType extends EventsFromTarget<MetricsEventTarget>[\"type\"]> = (\n event: MakeBlizzardEvent<EventOfType<EventType, EventsFromTarget<MetricsEventTarget>>[\"detail\"]>\n) => [string, UndefinedToOptional<blizzard.ServerEventData>];\n\ntype EventHandlers = {\n [EventType in EventsFromTarget<MetricsEventTarget>[\"type\"]]: CreateEventData<EventType>;\n};\n\n/**\n * Translate between an external metric name, which is exposed to SDK users, and an internal Blizzard event name,\n * property name, and constructor.\n *\n * It is very important that we do this, since the naming of these internal business events are unintuitive and will\n * not make sense to SDK users.\n *\n * For a full list of business events (using their internal names), see:\n * https://docs.google.com/document/d/1-kSzFWCWw9Qo3D08FR1_cqeHTsUtk9p3p3uOptzWDTY/\n */\ntype CameraKitBusinessEventMap = {\n assetDownload: MakeBusinessEvent<blizzard.CameraKitAssetDownload>;\n assetValidationFailed: MakeBusinessEvent<blizzard.CameraKitAssetValidationFailed>;\n benchmarkComplete: MakeBusinessEvent<blizzard.CameraKitWebBenchmarkComplete>;\n exception: MakeBusinessEvent<blizzard.CameraKitException>;\n legalPrompt: MakeBusinessEvent<blizzard.CameraKitLegalPrompt>;\n lensDownload: MakeBusinessEvent<blizzard.CameraKitLensDownload>;\n lensView: MakeBusinessEvent<blizzard.CameraKitWebLensSwipe>;\n lensWait: MakeBusinessEvent<blizzard.CameraKitLensSpin>;\n lensContentValidationFailed: MakeBusinessEvent<blizzard.CameraKitLensContentValidationFailed>;\n session: MakeBusinessEvent<blizzard.CameraKitSession>;\n};\n\n/**\n * This interface is defined in the CameraKit pb_schema proto definition – but the generated TypeScript does not handle\n * the `Any` type properly. It does not conform to the Proto3 canonical JSON mapping scheme, as defined here:\n * https://developers.google.com/protocol-buffers/docs/proto3#json\n *\n * To solve this (since we only need one message from the CameraKit schema), we'll just manually define the correct\n * interface here.\n */\ninterface SetBusinessEventsRequest {\n batchEvents: {\n \"@type\": \"com.snapchat.analytics.blizzard.ServerEventBatch\";\n serverEvents: blizzard.ServerEvent[];\n };\n}\n\n// CameraKit's prod metrics endpoint.\n// See: https://github.sc-corp.net/Snapchat/pb_schema/blob/2a966db/proto/camera_kit/v3/service.proto#L133\nconst relativePath = \"/com.snap.camerakit.v3.Metrics/metrics/business_events\";\n\n// It is rather cumbersome to check the actual final size of a batch, but we can easily limit the number of events we\n// include in each batch -- looking at historical data, typical events average ~1.3kb per event. But there are some\n// events (like CAMERA_KIT_EXCEPTION, which includes a stack trace) that can be much larger.\n//\n// To prevent us running over the 64kibibyte limit imposed by browsers on `keep-alive` requests, we'll set quite a low\n// limit to ensure we don't lose events which are larger in size than we expect.\nconst BUSINESS_EVENT_BATCH_MAX_SIZE = 10;\nconst BUSINESS_EVENT_BATCH_MAX_AGE_MS = 5000;\n\nconst connectivityTypeMapping: Partial<Record<ConnectionType, blizzard.CameraKitConnectivityType>> = {\n cellular: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_MOBILE,\n bluetooth: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_BLUETOOTH,\n wifi: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_WIFI,\n unknown: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNKNOWN,\n none: blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNREACHABLE,\n};\n\nconst vendorUuidKey = \"vendorUuid\";\nconst vendorUuidExpiry = convertDaysToSeconds(60);\n\n/**\n * Retrieves or generates a vendor UUID (Universally Unique Identifier).\n *\n * @param persistence - The persistence storage interface where UUID is stored.\n * @returns {Promise<string | undefined>} - A Promise that resolves to the vendor UUID or undefined,\n * if any failure occurs or opt-in is not enabled.\n */\nconst getOrGenerateVendorUuid = async (persistence: ExpiringPersistence<string>): Promise<string | undefined> => {\n try {\n const storedUuid = await persistence.retrieve(vendorUuidKey);\n if (storedUuid) {\n return storedUuid;\n }\n\n const newUuid = v4();\n await persistence.store(vendorUuidKey, newUuid);\n\n return newUuid;\n } catch (error) {\n throw new Error(\"Failed to generate vendor UUID\");\n }\n};\n\nfunction listenAndReport(\n metricsEventTarget: MetricsEventTarget,\n metricsHandler: FetchHandler,\n pageVisibility: PageVisibility,\n eventHandlers: EventHandlers,\n apiHostname: CameraKitApiHostname,\n appVendorUuid: string | undefined\n): void {\n const sessionId = v4();\n logger.log(`Session ID: ${sessionId}`);\n\n // Blizzard convention is to start the sequenceId at 1.\n let sequenceId = 1;\n\n const handler = new HandlerChainBuilder(metricsHandler)\n .map(\n createMappingHandler((events: blizzard.ServerEvent[]) => {\n const body: SetBusinessEventsRequest = {\n batchEvents: {\n \"@type\": \"com.snapchat.analytics.blizzard.ServerEventBatch\",\n serverEvents: events,\n },\n };\n\n return new Request(`https://${apiHostname}${relativePath}`, {\n method: \"POST\",\n body: JSON.stringify(body),\n credentials: \"include\",\n\n // When this is true it makes fetch behave like `Navigator.sendBeacon` – that is, the request\n // will still be made even if the page terminates.\n // https://developer.mozilla.org/en-US/docs/Web/API/fetch\n keepalive: pageVisibility.isDuringVisibilityTransition(\"hidden\"),\n });\n }, pageVisibility)\n )\n .map(\n createBatchingHandler({\n batchReduce: (\n previousBundle: blizzard.ServerEvent[] | undefined,\n businessEvent: blizzard.ServerEvent\n ) => {\n const bundle = previousBundle ?? [];\n bundle.push(businessEvent);\n return bundle;\n },\n isBatchComplete: (bundle) => bundle.length >= BUSINESS_EVENT_BATCH_MAX_SIZE,\n maxBatchAge: BUSINESS_EVENT_BATCH_MAX_AGE_MS,\n pageVisibility,\n })\n ).handler;\n\n const makeBlizzardEvent = <E extends CameraKitBusinessEvents>(event: E): MakeBlizzardEvent<E> => {\n const deviceConnectivity =\n connectivityTypeMapping[userAgent.connectionType!] ??\n blizzard.CameraKitConnectivityType.CAMERA_KIT_CONNECTIVITY_TYPE_UNKNOWN;\n\n return {\n ...event,\n cameraKitEventBase: blizzard.CameraKitEventBase.fromPartial({\n kitEventBase: blizzard.KitEventBase.fromPartial({\n locale: userAgent.locale,\n kitVariant: blizzard.KitType.CAMERA_KIT_WEB,\n kitVariantVersion: userAgent.sdkShortVersion,\n kitClientTimestampMillis: Date.now(),\n }),\n deviceCluster: 0,\n cameraKitVersion: userAgent.sdkLongVersion,\n lensCoreVersion: userAgent.lensCoreVersion,\n deviceModel: userAgent.deviceModel,\n cameraKitVariant: blizzard.CameraKitVariant.CAMERA_KIT_VARIANT_PARTNER,\n cameraKitFlavor: blizzard.CameraKitFlavor.CAMERA_KIT_FLAVOR_DEBUG,\n // We overload appId, using the origin instead because it's nice and human-readable (our backed adds\n // the true appId as oauth_client_id before forwarding events to Blizzard).\n appId: userAgent.origin,\n deviceConnectivity,\n sessionId: sessionId,\n appVendorUuid,\n }),\n };\n };\n\n const sendServerEvent = (\n eventName: string,\n eventData: UndefinedToOptional<blizzard.ServerEventData>\n ): Promise<void> => {\n return handler(\n blizzard.ServerEvent.fromPartial({\n eventName,\n osType: userAgent.osType,\n osVersion: userAgent.osVersion,\n maxSequenceIdOnInstance: 0,\n sequenceId: sequenceId++,\n eventData,\n })\n );\n };\n\n entries(eventHandlers).forEach(([eventType, createEventData]) => {\n metricsEventTarget.addEventListener(eventType, ({ detail }) => {\n // Safety: When iterating over object keys in a mapped type, we lose the association between the key type\n // and the value type – at each iteration, the key type is a union of all possible keys and the value type\n // is a union of all possible values. When the value is a function with an argument, and that argument\n // depends on the key type (which is a union), the contravariance of the argument type means that the union\n // becomes an intersection. In our case here, this means the compiler expects each argument to contain all\n // properties from all event types. The cast is safe because the mapped `EventHandlers` type ensures that\n // `createEventData` takes an argument of the type corresponding its key's `eventType`'s event detail.\n const [eventName, eventData] = createEventData(makeBlizzardEvent(detail) as any);\n sendServerEvent(eventName, eventData);\n });\n });\n}\n\nexport type MakeBusinessEvent<E> = Omit<\n {\n [K in keyof E]: Exclude<E[K], undefined> extends Record<keyof any, any>\n ? MakeBusinessEvent<Exclude<E[K], undefined>>\n : E[K];\n },\n \"cameraKitEventBase\"\n>;\n\nexport type MakeTaggedBusinessEvent<K extends keyof CameraKitBusinessEventMap> = {\n name: K;\n} & CameraKitBusinessEventMap[K];\n\nexport const businessEventsReporterFactory = Injectable(\n \"businessEventsReporter\",\n [\n metricsEventTargetFactory.token,\n metricsHandlerFactory.token,\n pageVisibilityFactory.token,\n configurationToken,\n remoteConfigurationFactory.token,\n ] as const,\n (\n metricsEventTarget: MetricsEventTarget,\n metricsHandler: FetchHandler,\n pageVisibility: PageVisibility,\n configuration: CameraKitConfiguration,\n remoteConfiguration: RemoteConfiguration\n ) => {\n const vendorAnalyticsPersistence = new ExpiringPersistence<string>(\n () => vendorUuidExpiry,\n new IndexedDBPersistence({ databaseName: \"SessionHistory\" })\n );\n\n remoteConfiguration\n .getInitializationConfig()\n .pipe(\n take(1),\n switchMap(({ appVendorUuidOptIn }) => {\n if (appVendorUuidOptIn) {\n return from(getOrGenerateVendorUuid(vendorAnalyticsPersistence));\n }\n return of(undefined);\n }),\n catchError((error) => {\n logger.warn(`Failed to retrieve or generate vendor UUID.`, error);\n return of(undefined);\n })\n )\n .subscribe({\n next: (appVendorUuid) => {\n /**\n * This defines a mapping from a business event's external name (the name we document in public\n * API docs), to its internal representation as a Blizzard ServerEvent.\n *\n * It is important that we do this, since the naming of these internal business events are\n * unintuitive and will not make sense to SDK users.\n *\n * To specify the internal event, we must give the ServerEvent's eventName, the specific property\n * name which contains the event data (this is a \"oneof\" property on ServerEvent), and use the\n * correct event type's `fromPartial` method (this is generated from the ServerEvent protobuf).\n *\n * These events are documented here:\n * https://docs.google.com/document/d/1-kSzFWCWw9Qo3D08FR1_cqeHTsUtk9p3p3uOptzWDTY/\n *\n * They are defined in code here:\n * https://github.sc-corp.net/Snapchat/snapchat/tree/master/blizzard/schema/blizzard-schema/\n * codeGen/src/main/java/com/snapchat/analytics/schema/events/cameraKit\n */\n listenAndReport(\n metricsEventTarget,\n metricsHandler,\n pageVisibility,\n {\n assetDownload: (event) => [\n \"CAMERA_KIT_ASSET_DOWNLOAD\",\n { cameraKitAssetDownload: blizzard.CameraKitAssetDownload.fromPartial(event) },\n ],\n assetValidationFailed: (event) => [\n \"CAMERA_KIT_ASSET_VALIDATION_FAILED\",\n {\n cameraKitAssetValidationFailed:\n blizzard.CameraKitAssetValidationFailed.fromPartial(event),\n },\n ],\n benchmarkComplete: (event) => [\n \"CAMERA_KIT_WEB_BENCHMARK_COMPLETE\",\n {\n cameraKitWebBenchmarkComplete:\n blizzard.CameraKitWebBenchmarkComplete.fromPartial(event),\n },\n ],\n exception: (event) => [\n \"CAMERA_KIT_EXCEPTION\",\n { cameraKitException: blizzard.CameraKitException.fromPartial(event) },\n ],\n legalPrompt: (event) => [\n \"CAMERA_KIT_LEGAL_PROMPT\",\n { cameraKitLegalPrompt: blizzard.CameraKitLegalPrompt.fromPartial(event) },\n ],\n lensDownload: (event) => [\n \"CAMERA_KIT_LENS_DOWNLOAD\",\n { cameraKitLensDownload: blizzard.CameraKitLensDownload.fromPartial(event) },\n ],\n lensView: (event) => [\n \"CAMERA_KIT_WEB_LENS_SWIPE\",\n { cameraKitWebLensSwipe: blizzard.CameraKitWebLensSwipe.fromPartial(event) },\n ],\n lensWait: (event) => [\n \"CAMERA_KIT_LENS_SPIN\",\n { cameraKitLensSpin: blizzard.CameraKitLensSpin.fromPartial(event) },\n ],\n lensContentValidationFailed: (event) => [\n \"CAMERA_KIT_LENS_CONTENT_VALIDATION_FAILED\",\n {\n cameraKitLensContentValidationFailed:\n blizzard.CameraKitLensContentValidationFailed.fromPartial(event),\n },\n ],\n session: (event) => [\n \"CAMERA_KIT_SESSION\",\n { cameraKitSession: blizzard.CameraKitSession.fromPartial(event) },\n ],\n },\n configuration.apiHostname,\n appVendorUuid\n );\n },\n });\n }\n);\n"]}
|
|
@@ -109,13 +109,31 @@ export const operationalMetricReporterFactory = Injectable("operationalMetricsRe
|
|
|
109
109
|
});
|
|
110
110
|
}, pageVisibility))
|
|
111
111
|
.map(createBatchingHandler({
|
|
112
|
-
// The batching logic here is very simple – it could be improved by e.g.
|
|
113
|
-
//
|
|
112
|
+
// The batching logic here is very simple – it could be improved by e.g.
|
|
113
|
+
// computing statistics to reduce overall data sent, etc. Right now this is
|
|
114
114
|
// premature optimization, but could become a good idea in the future.
|
|
115
115
|
batchReduce: (previousBundle, metric) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
var _a, _b;
|
|
117
|
+
let metrics = [...((_a = previousBundle === null || previousBundle === void 0 ? void 0 : previousBundle.metrics) !== null && _a !== void 0 ? _a : [])];
|
|
118
|
+
// For "count" metrics, it's straightforward to merge them into
|
|
119
|
+
// a single metric with the same name.
|
|
120
|
+
const existingCountIndex = ((_b = metric.metric) === null || _b === void 0 ? void 0 : _b.$case) === "count"
|
|
121
|
+
? metrics.findIndex((m) => { var _a; return metric.name === m.name && ((_a = m.metric) === null || _a === void 0 ? void 0 : _a.$case) === "count"; })
|
|
122
|
+
: -1;
|
|
123
|
+
if (existingCountIndex >= 0) {
|
|
124
|
+
// Safety: Given the condition above, we can be sure that both the existing and new metrics
|
|
125
|
+
// are of the "count" type.
|
|
126
|
+
const existingValue = metrics[existingCountIndex].metric;
|
|
127
|
+
const newValue = metric.metric;
|
|
128
|
+
metrics.splice(existingCountIndex, 1, Object.assign(Object.assign({}, metric), { metric: {
|
|
129
|
+
$case: "count",
|
|
130
|
+
count: existingValue.count + newValue.count,
|
|
131
|
+
} }));
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
metrics.push(metric);
|
|
135
|
+
}
|
|
136
|
+
return { metrics };
|
|
119
137
|
},
|
|
120
138
|
isBatchComplete: (bundle) => bundle.metrics.length >= METRIC_BATCH_MAX_SIZE,
|
|
121
139
|
maxBatchAge: METRIC_BATCH_MAX_AGE_MS,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operationalMetricsReporter.js","sourceRoot":"","sources":["../../../src/metrics/operational/operationalMetricsReporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from \"../../dependency-injection/Injectable\";\nimport { FetchHandler } from \"../../handlers/defaultFetchHandler\";\nimport { HandlerChainBuilder } from \"../../handlers/HandlerChainBuilder\";\nimport { createBatchingHandler } from \"../../handlers/batchingHandler\";\nimport {\n OperationalMetric,\n OperationalMetricsBundle,\n} from \"../../generated-proto/pb_schema/camera_kit/v3/operational_metrics\";\nimport { SetOperationalMetricsRequest } from \"../../generated-proto/pb_schema/camera_kit/v3/service\";\nimport { createMappingHandler } from \"../../handlers/mappingHandler\";\nimport { PageVisibility, pageVisibilityFactory } from \"../../common/pageVisibility\";\nimport { metricsHandlerFactory } from \"../metricsHandler\";\nimport { CameraKitConfiguration, configurationToken } from \"../../configuration\";\nimport { Metric } from \"./Metric\";\n\ntype MetricsHandler = (metric: OperationalMetric) => Promise<void>;\n\n// CameraKit's prod metrics endpoint.\n// See: https://github.sc-corp.net/Snapchat/pb_schema/blob/c390b9c/proto/camera_kit/v3/service.proto#L126\n\nconst DIMENSION_DELIMITER = \".\";\n\n// These values are (currently) arbitrarily selected.\n// TODO: Once we have gathered a sufficient quantity of metrics data, we should tune these numbers to ensure we're\n// operating with the right cost vs. alarming SLA vs. IDB storage size tradeoffs.\nconst METRIC_BATCH_MAX_SIZE = 100;\nconst METRIC_BATCH_MAX_AGE_MS = 5000;\n\n/**\n * Use this class to report operational metrics – these are metrics that describe aspects of the SDK's performance,\n * which may be used to assess and investigate operational issues.\n */\n/** @internal */\nexport class OperationalMetricsReporter {\n constructor(private readonly metricsHandler: MetricsHandler) {}\n\n /**\n * Record a count.\n *\n * @param name\n * @param count\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n count(name: string, count: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"count\", count }, dimensions);\n }\n\n /**\n * Record a duration in milliseconds.\n *\n * @param name\n * @param latencyMillis\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n timer(name: string, latencyMillis: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"latencyMillis\", latencyMillis }, dimensions);\n }\n\n /**\n * Record a histogram.\n *\n * @param name\n * @param histogram\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n histogram(name: string, histogram: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"histogram\", histogram }, dimensions);\n }\n\n /**\n * TODO: This entire class in no longer necessary, since the new Timer/Count/Histogram classes offer a cleaner API\n * for recording metrics. Once we migrate all operational metrics to use those new APIs, this class can be removed\n * and call sites will just call the metrics handler directly.\n *\n * @param metric Any concrete Metric (e.g. Count, Timer, Histogram)\n * @returns\n */\n async report(metric: Metric): Promise<void> {\n await Promise.all(metric.toOperationalMetric().map((metric) => this.metricsHandler(metric)));\n }\n\n private record(\n name: string,\n metric: Required<OperationalMetric>[\"metric\"],\n dimensions?: Map<string, string | number>\n ): Promise<void> {\n // The naming convention (metricName.dimensionName.dimensionValue.dimensionName.dimensionValue...) is mentioned\n // the Graphene docs here https://wiki.sc-corp.net/display/METRICS/Graphene\n // TODO: find explicit documentation of the API, if it exists.\n const serializedDimensions = dimensions\n ? `.${Array.from(dimensions.entries())\n .map((d) => d.join(DIMENSION_DELIMITER))\n .join(DIMENSION_DELIMITER)}`\n : \"\";\n\n return this.metricsHandler({\n name: `${name}${serializedDimensions}`,\n timestamp: new Date(),\n metric,\n });\n }\n}\n\n/**\n * @internal\n */\nexport const operationalMetricReporterFactory = Injectable(\n \"operationalMetricsReporter\",\n [metricsHandlerFactory.token, pageVisibilityFactory.token, configurationToken] as const,\n (metricsHandler: FetchHandler, pageVisibility: PageVisibility, configuration: CameraKitConfiguration) => {\n const handler = new HandlerChainBuilder(metricsHandler)\n .map(\n createMappingHandler((metrics: OperationalMetricsBundle) => {\n const request: SetOperationalMetricsRequest = { metrics };\n return new Request(\n // eslint-disable-next-line max-len\n `https://${configuration.apiHostname}/com.snap.camerakit.v3.Metrics/metrics/operational_metrics`,\n {\n method: \"POST\",\n body: JSON.stringify(SetOperationalMetricsRequest.toJSON(request)),\n credentials: \"include\",\n\n // When this is true it makes fetch behave like `Navigator.sendBeacon` – that is, the\n // request will still be made even if the page terminates.\n // https://developer.mozilla.org/en-US/docs/Web/API/fetch\n keepalive: pageVisibility.isDuringVisibilityTransition(\"hidden\"),\n }\n );\n }, pageVisibility)\n )\n .map(\n createBatchingHandler({\n // The batching logic here is very simple – it could be improved by e.g. combining counts with\n // the same name, computing statistics to reduce overall data sent, etc. Right now this is\n // premature optimization, but could become a good idea in the future.\n batchReduce: (previousBundle: OperationalMetricsBundle | undefined, metric: OperationalMetric) => {\n const bundle = previousBundle ?? { metrics: [] };\n bundle.metrics.push(metric);\n return bundle;\n },\n isBatchComplete: (bundle) => bundle.metrics.length >= METRIC_BATCH_MAX_SIZE,\n maxBatchAge: METRIC_BATCH_MAX_AGE_MS,\n pageVisibility,\n })\n ).handler;\n\n return new OperationalMetricsReporter(handler);\n }\n);\n"]}
|
|
1
|
+
{"version":3,"file":"operationalMetricsReporter.js","sourceRoot":"","sources":["../../../src/metrics/operational/operationalMetricsReporter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from \"../../dependency-injection/Injectable\";\nimport { FetchHandler } from \"../../handlers/defaultFetchHandler\";\nimport { HandlerChainBuilder } from \"../../handlers/HandlerChainBuilder\";\nimport { createBatchingHandler } from \"../../handlers/batchingHandler\";\nimport {\n OperationalMetric,\n OperationalMetricsBundle,\n} from \"../../generated-proto/pb_schema/camera_kit/v3/operational_metrics\";\nimport { SetOperationalMetricsRequest } from \"../../generated-proto/pb_schema/camera_kit/v3/service\";\nimport { createMappingHandler } from \"../../handlers/mappingHandler\";\nimport { PageVisibility, pageVisibilityFactory } from \"../../common/pageVisibility\";\nimport { metricsHandlerFactory } from \"../metricsHandler\";\nimport { CameraKitConfiguration, configurationToken } from \"../../configuration\";\nimport { Metric } from \"./Metric\";\n\ntype MetricsHandler = (metric: OperationalMetric) => Promise<void>;\ntype CountMetricValue = Extract<OperationalMetric[\"metric\"], { $case: \"count\" }>;\n\n// CameraKit's prod metrics endpoint.\n// See: https://github.sc-corp.net/Snapchat/pb_schema/blob/c390b9c/proto/camera_kit/v3/service.proto#L126\n\nconst DIMENSION_DELIMITER = \".\";\n\n// These values are (currently) arbitrarily selected.\n// TODO: Once we have gathered a sufficient quantity of metrics data, we should tune these numbers to ensure we're\n// operating with the right cost vs. alarming SLA vs. IDB storage size tradeoffs.\nconst METRIC_BATCH_MAX_SIZE = 100;\nconst METRIC_BATCH_MAX_AGE_MS = 5000;\n\n/**\n * Use this class to report operational metrics – these are metrics that describe aspects of the SDK's performance,\n * which may be used to assess and investigate operational issues.\n */\n/** @internal */\nexport class OperationalMetricsReporter {\n constructor(private readonly metricsHandler: MetricsHandler) {}\n\n /**\n * Record a count.\n *\n * @param name\n * @param count\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n count(name: string, count: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"count\", count }, dimensions);\n }\n\n /**\n * Record a duration in milliseconds.\n *\n * @param name\n * @param latencyMillis\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n timer(name: string, latencyMillis: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"latencyMillis\", latencyMillis }, dimensions);\n }\n\n /**\n * Record a histogram.\n *\n * @param name\n * @param histogram\n * @param dimensions An optional Map containing dimensions which describe the metric.\n * For example: `new Map([['status', '200']])`\n * @returns Promise which resolves when the metric has been handled.\n */\n histogram(name: string, histogram: number, dimensions?: Map<string, string>): Promise<void> {\n return this.record(name, { $case: \"histogram\", histogram }, dimensions);\n }\n\n /**\n * TODO: This entire class in no longer necessary, since the new Timer/Count/Histogram classes offer a cleaner API\n * for recording metrics. Once we migrate all operational metrics to use those new APIs, this class can be removed\n * and call sites will just call the metrics handler directly.\n *\n * @param metric Any concrete Metric (e.g. Count, Timer, Histogram)\n * @returns\n */\n async report(metric: Metric): Promise<void> {\n await Promise.all(metric.toOperationalMetric().map((metric) => this.metricsHandler(metric)));\n }\n\n private record(\n name: string,\n metric: Required<OperationalMetric>[\"metric\"],\n dimensions?: Map<string, string | number>\n ): Promise<void> {\n // The naming convention (metricName.dimensionName.dimensionValue.dimensionName.dimensionValue...) is mentioned\n // the Graphene docs here https://wiki.sc-corp.net/display/METRICS/Graphene\n // TODO: find explicit documentation of the API, if it exists.\n const serializedDimensions = dimensions\n ? `.${Array.from(dimensions.entries())\n .map((d) => d.join(DIMENSION_DELIMITER))\n .join(DIMENSION_DELIMITER)}`\n : \"\";\n\n return this.metricsHandler({\n name: `${name}${serializedDimensions}`,\n timestamp: new Date(),\n metric,\n });\n }\n}\n\n/**\n * @internal\n */\nexport const operationalMetricReporterFactory = Injectable(\n \"operationalMetricsReporter\",\n [metricsHandlerFactory.token, pageVisibilityFactory.token, configurationToken] as const,\n (metricsHandler: FetchHandler, pageVisibility: PageVisibility, configuration: CameraKitConfiguration) => {\n const handler = new HandlerChainBuilder(metricsHandler)\n .map(\n createMappingHandler((metrics: OperationalMetricsBundle) => {\n const request: SetOperationalMetricsRequest = { metrics };\n return new Request(\n // eslint-disable-next-line max-len\n `https://${configuration.apiHostname}/com.snap.camerakit.v3.Metrics/metrics/operational_metrics`,\n {\n method: \"POST\",\n body: JSON.stringify(SetOperationalMetricsRequest.toJSON(request)),\n credentials: \"include\",\n\n // When this is true it makes fetch behave like `Navigator.sendBeacon` – that is, the\n // request will still be made even if the page terminates.\n // https://developer.mozilla.org/en-US/docs/Web/API/fetch\n keepalive: pageVisibility.isDuringVisibilityTransition(\"hidden\"),\n }\n );\n }, pageVisibility)\n )\n .map(\n createBatchingHandler({\n // The batching logic here is very simple – it could be improved by e.g.\n // computing statistics to reduce overall data sent, etc. Right now this is\n // premature optimization, but could become a good idea in the future.\n batchReduce: (previousBundle: OperationalMetricsBundle | undefined, metric: OperationalMetric) => {\n let metrics = [...(previousBundle?.metrics ?? [])];\n\n // For \"count\" metrics, it's straightforward to merge them into\n // a single metric with the same name.\n const existingCountIndex =\n metric.metric?.$case === \"count\"\n ? metrics.findIndex((m) => metric.name === m.name && m.metric?.$case === \"count\")\n : -1;\n if (existingCountIndex >= 0) {\n // Safety: Given the condition above, we can be sure that both the existing and new metrics\n // are of the \"count\" type.\n const existingValue = metrics[existingCountIndex].metric as CountMetricValue;\n const newValue = metric.metric as CountMetricValue;\n metrics.splice(existingCountIndex, 1, {\n ...metric,\n metric: {\n $case: \"count\",\n count: existingValue.count + newValue.count,\n },\n });\n } else {\n metrics.push(metric);\n }\n\n return { metrics };\n },\n isBatchComplete: (bundle) => bundle.metrics.length >= METRIC_BATCH_MAX_SIZE,\n maxBatchAge: METRIC_BATCH_MAX_AGE_MS,\n pageVisibility,\n })\n ).handler;\n\n return new OperationalMetricsReporter(handler);\n }\n);\n"]}
|
|
@@ -2,13 +2,6 @@ import { CofDimensions } from "../../remote-configuration/cofHandler";
|
|
|
2
2
|
import { Dimensions, RequestStateEventTarget } from "../../handlers/requestStateEmittingHandler";
|
|
3
3
|
import { OperationalMetricsReporter } from "../operational/operationalMetricsReporter";
|
|
4
4
|
import { AssetDownloadDimensions, LensDownloadDimensions } from "./reportLensAndAssetDownload";
|
|
5
|
-
declare global {
|
|
6
|
-
interface Navigator {
|
|
7
|
-
connection?: {
|
|
8
|
-
type?: "bluetooth" | "cellular" | "ethernet" | "none" | "wifi" | "wimax" | "other" | "unknown";
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
5
|
export declare const isRelevantRequest: (value: Dimensions) => value is CofDimensions | AssetDownloadDimensions | LensDownloadDimensions;
|
|
13
6
|
export declare const reportHttpMetrics: {
|
|
14
7
|
(args_0: OperationalMetricsReporter, args_1: RequestStateEventTarget): void;
|
|
@@ -4,6 +4,7 @@ import { scan } from "../../events/scan";
|
|
|
4
4
|
import { COF_REQUEST_TYPE } from "../../remote-configuration/cofHandler";
|
|
5
5
|
import { requestStateEventTargetFactory, } from "../../handlers/requestStateEmittingHandler";
|
|
6
6
|
import { operationalMetricReporterFactory, } from "../operational/operationalMetricsReporter";
|
|
7
|
+
import { cameraKitUserAgent as userAgent } from "../../common/cameraKitUserAgent";
|
|
7
8
|
import { isLensOrAssetRequest } from "./reportLensAndAssetDownload";
|
|
8
9
|
const getContentType = (dimensions) => {
|
|
9
10
|
switch (dimensions.requestType) {
|
|
@@ -47,7 +48,7 @@ export const isRelevantRequest = (value) => {
|
|
|
47
48
|
};
|
|
48
49
|
export const reportHttpMetrics = Injectable("reportHttpMetrics", [operationalMetricReporterFactory.token, requestStateEventTargetFactory.token], (reporter, requestStateEventTarget) => {
|
|
49
50
|
scan({ name: "inProgress", inProgress: new Map() })(requestStateEventTarget, ["started", "completed", "errored"], (state, event) => {
|
|
50
|
-
var _a
|
|
51
|
+
var _a;
|
|
51
52
|
const { inProgress } = state;
|
|
52
53
|
const { dimensions, requestId, timeMs } = event.detail;
|
|
53
54
|
if (!isRelevantRequest(dimensions))
|
|
@@ -67,7 +68,7 @@ export const reportHttpMetrics = Injectable("reportHttpMetrics", [operationalMet
|
|
|
67
68
|
const status = getStatus(event);
|
|
68
69
|
const operationalDimensions = new Map([
|
|
69
70
|
["content_type", getContentType(dimensions)],
|
|
70
|
-
["network_type", (
|
|
71
|
+
["network_type", (_a = userAgent.connectionType) !== null && _a !== void 0 ? _a : "unknown"],
|
|
71
72
|
["status", status],
|
|
72
73
|
]);
|
|
73
74
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reportHttpMetrics.js","sourceRoot":"","sources":["../../../src/metrics/reporters/reportHttpMetrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAiB,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAIH,8BAA8B,GACjC,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACH,gCAAgC,GAEnC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAA2B,oBAAoB,EAA0B,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"reportHttpMetrics.js","sourceRoot":"","sources":["../../../src/metrics/reporters/reportHttpMetrics.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertUnreachable } from \"../../common/assertions\";\nimport { Injectable } from \"../../dependency-injection/Injectable\";\nimport { scan } from \"../../events/scan\";\nimport { CofDimensions, COF_REQUEST_TYPE } from \"../../remote-configuration/cofHandler\";\nimport {\n Dimensions,\n RequestStateEventTarget,\n RequestStateEvents,\n requestStateEventTargetFactory,\n} from \"../../handlers/requestStateEmittingHandler\";\nimport {\n operationalMetricReporterFactory,\n OperationalMetricsReporter,\n} from \"../operational/operationalMetricsReporter\";\nimport { cameraKitUserAgent as userAgent } from \"../../common/cameraKitUserAgent\";\nimport { AssetDownloadDimensions, isLensOrAssetRequest, LensDownloadDimensions } from \"./reportLensAndAssetDownload\";\n\ntype InProgressMap = Map<number, { startTimeMs: number }>;\ninterface InProgress {\n name: \"inProgress\";\n inProgress: InProgressMap;\n}\ninterface Completed {\n name: \"completed\";\n inProgress: InProgressMap;\n dimensions: Map<string, string>;\n downloadTimeMs: number;\n downloadSizeKb: number;\n}\ntype RequestState = InProgress | Completed;\n\nconst getContentType = (dimensions: LensDownloadDimensions | AssetDownloadDimensions | CofDimensions): string => {\n switch (dimensions.requestType) {\n case \"lens_content\":\n return \"lens_content\";\n case \"asset\":\n return dimensions.assetType;\n case COF_REQUEST_TYPE:\n return COF_REQUEST_TYPE;\n default:\n assertUnreachable(dimensions);\n }\n};\n\nconst getSizeKb = (event: RequestStateEvents): number => {\n switch (event.type) {\n case \"started\":\n case \"errored\":\n return 0;\n case \"completed\":\n return event.detail.sizeByte / 1024;\n default:\n assertUnreachable(event);\n }\n};\n\nconst getStatus = (event: RequestStateEvents): string => {\n switch (event.type) {\n case \"started\":\n case \"errored\":\n // We'll use status 0 to indicate that an exception occurred during the request. This is somewhat in keeping\n // with browsers that set the response status to 0 if the request was not able to be made (e.g. CORs\n // preflight failed, or the user canceled the request).\n return \"0\";\n case \"completed\":\n return event.detail.status.toString();\n default:\n assertUnreachable(event);\n }\n};\n\nexport const isRelevantRequest = (\n value: Dimensions\n): value is LensDownloadDimensions | AssetDownloadDimensions | CofDimensions => {\n return isLensOrAssetRequest(value) || value[\"requestType\"] === COF_REQUEST_TYPE;\n};\n\nexport const reportHttpMetrics = Injectable(\n \"reportHttpMetrics\",\n [operationalMetricReporterFactory.token, requestStateEventTargetFactory.token] as const,\n (reporter: OperationalMetricsReporter, requestStateEventTarget: RequestStateEventTarget) => {\n scan<RequestState>({ name: \"inProgress\", inProgress: new Map() })(\n requestStateEventTarget,\n [\"started\", \"completed\", \"errored\"],\n (state, event) => {\n const { inProgress } = state;\n const { dimensions, requestId, timeMs } = event.detail;\n\n if (!isRelevantRequest(dimensions)) return state;\n\n switch (event.type) {\n case \"started\":\n inProgress.set(requestId, { startTimeMs: timeMs });\n return { name: \"inProgress\", inProgress };\n case \"completed\":\n case \"errored\":\n const completedRequest = inProgress.get(requestId);\n if (!completedRequest) return state;\n inProgress.delete(requestId);\n\n const downloadTimeMs = timeMs - completedRequest.startTimeMs;\n const downloadSizeKb = getSizeKb(event);\n const status = getStatus(event);\n const operationalDimensions = new Map<string, string>([\n [\"content_type\", getContentType(dimensions)],\n [\"network_type\", userAgent.connectionType ?? \"unknown\"],\n [\"status\", status],\n ]);\n\n return {\n name: \"completed\",\n inProgress: state.inProgress,\n dimensions: operationalDimensions,\n downloadSizeKb,\n downloadTimeMs,\n };\n default:\n assertUnreachable(event);\n }\n }\n ).addEventListener(\"state\", ({ detail: state }) => {\n if (state.name !== \"completed\") return;\n\n const { dimensions, downloadTimeMs, downloadSizeKb } = state;\n\n reporter.count(\"download_finished\", 1, dimensions);\n reporter.timer(\"download_latency\", downloadTimeMs, dimensions);\n reporter.histogram(\"download_size_kb\", downloadSizeKb, dimensions);\n });\n }\n);\n"]}
|
|
@@ -30,7 +30,7 @@ export declare const reportLensView: {
|
|
|
30
30
|
}> | import("@snap/state-management").Action<"downloadComplete", import("../..").Lens> | import("@snap/state-management").Action<"turnedOn", import("../..").Lens> | import("@snap/state-management").Action<"resourcesLoaded", import("../..").Lens> | import("@snap/state-management").Action<"firstFrameProcessed", import("../..").Lens> | import("@snap/state-management").Action<"applyLensComplete", import("../..").Lens> | import("@snap/state-management").Action<"applyLensFailed", {
|
|
31
31
|
error: import("../../session/lensState").LensErrors;
|
|
32
32
|
lens: import("../..").Lens;
|
|
33
|
-
}> | import("@snap/state-management").Action<"applyLensAborted", import("../..").Lens> | import("@snap/state-management").Action<"removeLens", undefined> | import("@snap/state-management").Action<"turnedOff", import("../..").Lens> | import("@snap/state-management").Action<"removeLensComplete", undefined> | import("@snap/state-management").Action<"removeLensFailed", Error>, import("@snap/state-management").State<"noLensApplied", undefined> | import("@snap/state-management").State<"applyingLens", import("../..").Lens> | import("@snap/state-management").State<"lensApplied", import("../..").Lens>>, args_2: import("@snap/state-management").StateMachine<import("@snap/state-management").Action<"suspend", CameraKitSession> | import("@snap/state-management").Action<"resume", CameraKitSession>, import("@snap/state-management").State<"inactive", undefined> | import("@snap/state-management").State<"active", CameraKitSession>>, args_3: MetricsEventTarget, args_4: OperationalMetricsReporter, args_5: CameraKitConfiguration): Promise<void>;
|
|
33
|
+
}> | import("@snap/state-management").Action<"applyLensAborted", import("../..").Lens> | import("@snap/state-management").Action<"removeLens", undefined> | import("@snap/state-management").Action<"turnedOff", import("../..").Lens> | import("@snap/state-management").Action<"removeLensComplete", undefined> | import("@snap/state-management").Action<"removeLensFailed", Error>, import("@snap/state-management").State<"noLensApplied", undefined> | import("@snap/state-management").State<"applyingLens", import("../..").Lens> | import("@snap/state-management").State<"lensApplied", import("../..").Lens>>, args_2: import("@snap/state-management").StateMachine<import("@snap/state-management").Action<"suspend", CameraKitSession> | import("@snap/state-management").Action<"resume", CameraKitSession> | import("@snap/state-management").Action<"destroy", undefined>, import("@snap/state-management").State<"inactive", undefined> | import("@snap/state-management").State<"active", CameraKitSession> | import("@snap/state-management").State<"destroyed", undefined>>, args_3: MetricsEventTarget, args_4: OperationalMetricsReporter, args_5: CameraKitConfiguration): Promise<void>;
|
|
34
34
|
token: "reportLensView";
|
|
35
35
|
dependencies: readonly ["CameraKitSession", "lensState", "sessionState", "metricsEventTarget", "operationalMetricsReporter", "configuration"];
|
|
36
36
|
};
|