@snap/camera-kit 0.10.0 → 0.12.0
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 +242 -67
- package/docs/html/assets/search.js +1 -1
- package/docs/html/classes/CameraKit.html +116 -100
- package/docs/html/classes/CameraKitSession.html +175 -153
- package/docs/html/classes/CameraKitSource.html +109 -101
- package/docs/html/classes/LensPerformanceMeasurement.html +98 -94
- package/docs/html/classes/LensPerformanceMetrics.html +83 -81
- package/docs/html/classes/LensRepository.html +120 -109
- package/docs/html/classes/LensSources.html +86 -82
- package/docs/html/classes/Transform2D.html +98 -94
- package/docs/html/classes/TypedCustomEvent.html +83 -82
- package/docs/html/classes/TypedEventTarget.html +92 -91
- package/docs/html/functions/Injectable.html +87 -80
- package/docs/html/functions/bootstrapCameraKit.html +89 -86
- package/docs/html/functions/createExtension.html +76 -75
- package/docs/html/functions/createImageSource.html +80 -77
- package/docs/html/functions/createMediaStreamSource.html +80 -77
- package/docs/html/functions/createUserMediaSource.html +84 -81
- package/docs/html/functions/createVideoSource.html +80 -77
- package/docs/html/functions/estimateLensPerformance.html +76 -75
- package/docs/html/functions/getRequiredBootstrapURLs.html +78 -76
- package/docs/html/functions/lensSourcesFactory.html +74 -74
- package/docs/html/functions/uriHandlersFactory.html +76 -75
- package/docs/html/index.html +233 -117
- package/docs/html/interfaces/CameraKitBootstrapConfiguration.html +107 -100
- package/docs/html/interfaces/CameraKitSourceSubscriber.html +82 -81
- package/docs/html/interfaces/ComputedFrameMetrics.html +94 -84
- package/docs/html/interfaces/CreateSessionOptions.html +86 -83
- package/docs/html/interfaces/EstimatedLensPerformance.html +85 -84
- package/docs/html/interfaces/Lens.html +114 -106
- package/docs/html/interfaces/LensSource.html +102 -94
- package/docs/html/interfaces/MediaStreamSourceOptions.html +80 -80
- package/docs/html/interfaces/Preview.html +81 -79
- package/docs/html/interfaces/Snapcode.html +86 -83
- package/docs/html/interfaces/UriCancelRequest.html +80 -80
- package/docs/html/interfaces/UriHandler.html +102 -93
- package/docs/html/interfaces/UriRequest.html +95 -90
- package/docs/html/interfaces/UriResponse.html +89 -89
- package/docs/html/interfaces/VideoSourceOptions.html +77 -77
- package/docs/html/modules.html +153 -153
- package/docs/html/types/AssetLoader.html +75 -74
- package/docs/html/types/AssetTiming.html +75 -74
- package/docs/html/types/BenchmarkError.html +73 -73
- package/docs/html/types/BootstrapError.html +75 -74
- package/docs/html/types/CacheKeyNotFoundError.html +73 -73
- package/docs/html/types/CameraKitDeviceInfo.html +75 -74
- package/docs/html/types/CameraKitSessionEventListener.html +75 -74
- package/docs/html/types/CameraKitSessionEvents.html +82 -74
- package/docs/html/types/CameraKitSourceError.html +73 -73
- package/docs/html/types/CameraKitSourceInfo.html +73 -73
- package/docs/html/types/CameraKitSourceOptions.html +75 -74
- package/docs/html/types/ConfigurationError.html +75 -74
- package/docs/html/types/Keyboard.html +85 -80
- package/docs/html/types/KeyboardEvents.html +84 -74
- package/docs/html/types/LegalError.html +73 -73
- package/docs/html/types/LensAssetError.html +75 -74
- package/docs/html/types/LensContentValidationError.html +73 -73
- package/docs/html/types/LensError.html +73 -73
- package/docs/html/types/LensExecutionError.html +75 -74
- package/docs/html/types/LensImagePickerError.html +75 -74
- package/docs/html/types/LensLaunchParams.html +75 -74
- package/docs/html/types/LensMetricsEvents.html +75 -74
- package/docs/html/types/LensPerformanceCluster.html +75 -74
- package/docs/html/types/LensView.html +75 -74
- package/docs/html/types/LensWait.html +75 -74
- package/docs/html/types/PersistentStoreError.html +75 -74
- package/docs/html/types/PlatformNotSupportedError.html +75 -74
- package/docs/html/types/PublicContainer.html +75 -74
- package/docs/html/types/RenderTarget.html +75 -74
- package/docs/html/types/Uri.html +73 -73
- package/docs/html/types/UriHandlers.html +75 -74
- package/docs/html/types/WebGLError.html +73 -73
- package/docs/html/variables/extensionRequestContext.html +75 -74
- package/docs/md/README.md +242 -67
- package/docs/md/classes/CameraKit.md +14 -1
- package/docs/md/classes/CameraKitSession.md +1 -1
- package/docs/md/classes/CameraKitSource.md +1 -1
- 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 +15 -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 +1 -1
- package/docs/md/interfaces/MediaStreamSourceOptions.md +1 -1
- package/docs/md/interfaces/Preview.md +1 -1
- package/docs/md/interfaces/Snapcode.md +1 -1
- package/docs/md/interfaces/UriCancelRequest.md +1 -1
- package/docs/md/interfaces/UriHandler.md +1 -1
- package/docs/md/interfaces/UriRequest.md +8 -1
- package/docs/md/interfaces/UriResponse.md +1 -1
- package/docs/md/interfaces/VideoSourceOptions.md +1 -1
- package/docs/md/modules.md +2 -2
- package/lib/CameraKit.d.ts +33 -14
- package/lib/CameraKit.js +32 -4
- package/lib/CameraKit.js.map +1 -1
- package/lib/assertPlatformSupported.d.ts +3 -1
- package/lib/assertPlatformSupported.js +13 -2
- package/lib/assertPlatformSupported.js.map +1 -1
- package/lib/bootstrapCameraKit.js +7 -3
- package/lib/bootstrapCameraKit.js.map +1 -1
- package/lib/common/__mocks__/loadScript.d.ts +1 -1
- package/lib/common/__mocks__/loadScript.js +1 -1
- package/lib/common/__mocks__/loadScript.js.map +1 -1
- package/lib/common/cameraKitUserAgent.js +17 -2
- package/lib/common/cameraKitUserAgent.js.map +1 -1
- package/lib/common/dialog.d.ts +59 -0
- package/lib/common/dialog.js +160 -0
- package/lib/common/dialog.js.map +1 -0
- package/lib/common/hash.d.ts +5 -0
- package/lib/common/hash.js +17 -0
- package/lib/common/hash.js.map +1 -0
- package/lib/common/loadScript.d.ts +6 -1
- package/lib/common/loadScript.js +9 -2
- package/lib/common/loadScript.js.map +1 -1
- package/lib/common/localization.d.ts +17 -10
- package/lib/common/localization.js +653 -18
- package/lib/common/localization.js.map +1 -1
- package/lib/common/pageVisibility.d.ts +34 -20
- package/lib/common/pageVisibility.js +57 -48
- package/lib/common/pageVisibility.js.map +1 -1
- package/lib/configuration.d.ts +2 -0
- package/lib/configuration.js +1 -0
- package/lib/configuration.js.map +1 -1
- package/lib/dependency-injection/Container.d.ts +2 -2
- package/lib/dependency-injection/Container.js +10 -10
- package/lib/dependency-injection/Container.js.map +1 -1
- package/lib/dependency-injection/RootServices.d.ts +5 -1
- package/lib/dependency-injection/RootServices.js.map +1 -1
- package/lib/environment.json +1 -1
- package/lib/extensions/LensSources.d.ts +5 -5
- package/lib/extensions/LensSources.js +9 -9
- package/lib/extensions/LensSources.js.map +1 -1
- package/lib/extensions/UriHandlers.d.ts +1 -1
- package/lib/generated-proto/blizzard/cameraKitEvents.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.d.ts +0 -26
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.js +0 -15
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.d.ts +0 -59
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.js +0 -10
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.d.ts +5 -13
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.js +61 -7
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.d.ts +0 -55
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.js +0 -12
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.d.ts +0 -5
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.js +0 -7
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.d.ts +0 -23
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.js +0 -15
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.js.map +1 -1
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.d.ts +43 -56
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.js +17 -2
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.d.ts +0 -8
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.js +0 -1
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.d.ts +0 -45
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.js +0 -46
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.d.ts +578 -104
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.js +0 -1
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.d.ts +0 -129
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.js +0 -24
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.d.ts +84 -22
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.js +0 -1
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.d.ts +177 -466
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.js +80 -399
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.d.ts +0 -9
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.js +0 -3
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.js.map +1 -1
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.d.ts +0 -1
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js +0 -2
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js.map +1 -1
- package/lib/generated-proto/pb_schema/common/ruid.d.ts +0 -27
- package/lib/generated-proto/pb_schema/common/ruid.js +0 -20
- package/lib/generated-proto/pb_schema/common/ruid.js.map +1 -1
- package/lib/generated-proto/pb_schema/common/value.d.ts +0 -9
- package/lib/generated-proto/pb_schema/common/value.js +0 -1
- package/lib/generated-proto/pb_schema/common/value.js.map +1 -1
- package/lib/generated-proto/pb_schema/google/protobuf/any.d.ts +0 -105
- package/lib/generated-proto/pb_schema/google/protobuf/any.js +0 -1
- package/lib/generated-proto/pb_schema/google/protobuf/any.js.map +1 -1
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.d.ts +0 -64
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.js +0 -1
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.js.map +1 -1
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.d.ts +0 -54
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.js +0 -1
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/geocircle.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/geocircle.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/geopoint.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/geopoint.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/launch_params.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/launch_params.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/launchdata.d.ts +0 -2
- package/lib/generated-proto/pb_schema/lenses/launchdata.js +0 -3
- package/lib/generated-proto/pb_schema/lenses/launchdata.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/lures.d.ts +0 -2
- package/lib/generated-proto/pb_schema/lenses/lures.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/lures.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/persistent_store.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/persistent_store.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/snappable.d.ts +0 -19
- package/lib/generated-proto/pb_schema/lenses/snappable.js +0 -2
- package/lib/generated-proto/pb_schema/lenses/snappable.js.map +1 -1
- package/lib/generated-proto/pb_schema/lenses/user_data.d.ts +0 -18
- package/lib/generated-proto/pb_schema/lenses/user_data.js +0 -1
- package/lib/generated-proto/pb_schema/lenses/user_data.js.map +1 -1
- package/lib/handlers/HandlerChainBuilder.js +7 -2
- package/lib/handlers/HandlerChainBuilder.js.map +1 -1
- package/lib/handlers/batchingHandler.d.ts +8 -2
- package/lib/handlers/batchingHandler.js +5 -8
- package/lib/handlers/batchingHandler.js.map +1 -1
- package/lib/handlers/mappingHandler.d.ts +5 -1
- package/lib/handlers/mappingHandler.js +6 -4
- package/lib/handlers/mappingHandler.js.map +1 -1
- package/lib/handlers/rateLimitingHandler.d.ts +5 -1
- package/lib/handlers/rateLimitingHandler.js +6 -4
- package/lib/handlers/rateLimitingHandler.js.map +1 -1
- package/lib/handlers/responseCachingHandler.d.ts +1 -1
- package/lib/handlers/responseCachingHandler.js.map +1 -1
- package/lib/handlers/retryingHandler.d.ts +5 -1
- package/lib/handlers/retryingHandler.js +13 -9
- package/lib/handlers/retryingHandler.js.map +1 -1
- package/lib/legal/legalPrompt.d.ts +7 -4
- package/lib/legal/legalPrompt.js +126 -135
- package/lib/legal/legalPrompt.js.map +1 -1
- package/lib/legal/legalState.d.ts +2 -2
- package/lib/legal/legalState.js +52 -38
- package/lib/legal/legalState.js.map +1 -1
- package/lib/lens/LensRepository.d.ts +5 -3
- package/lib/lens/LensRepository.js +8 -5
- package/lib/lens/LensRepository.js.map +1 -1
- package/lib/lens/assets/LensAssetsProvider.js +18 -3
- package/lib/lens/assets/LensAssetsProvider.js.map +1 -1
- package/lib/lens/lensHttpUtil.d.ts +3 -2
- package/lib/lens/lensHttpUtil.js +5 -5
- package/lib/lens/lensHttpUtil.js.map +1 -1
- package/lib/lens-core-module/generated-types.d.ts +21 -0
- package/lib/lens-core-module/generated-types.js.map +1 -1
- package/lib/lens-core-module/loader/lensCoreFactory.js +3 -1
- package/lib/lens-core-module/loader/lensCoreFactory.js.map +1 -1
- package/lib/lensCoreWasmVersions.json +3 -3
- package/lib/logger/logEntries.d.ts +1 -1
- package/lib/logger/logEntries.js +3 -3
- package/lib/logger/logEntries.js.map +1 -1
- package/lib/logger/logger.d.ts +7 -2
- package/lib/logger/logger.js +9 -4
- package/lib/logger/logger.js.map +1 -1
- package/lib/media-sources/MediaStreamSource.js +13 -4
- package/lib/media-sources/MediaStreamSource.js.map +1 -1
- package/lib/metrics/businessEventsReporter.d.ts +4 -2
- package/lib/metrics/businessEventsReporter.js +27 -14
- package/lib/metrics/businessEventsReporter.js.map +1 -1
- package/lib/metrics/metricsHandler.d.ts +3 -2
- package/lib/metrics/metricsHandler.js +3 -3
- package/lib/metrics/metricsHandler.js.map +1 -1
- package/lib/metrics/operational/Count.d.ts +17 -0
- package/lib/metrics/operational/Count.js +28 -0
- package/lib/metrics/operational/Count.js.map +1 -0
- package/lib/metrics/operational/Histogram.d.ts +17 -0
- package/lib/metrics/operational/Histogram.js +23 -0
- package/lib/metrics/operational/Histogram.js.map +1 -0
- package/lib/metrics/operational/Metric.d.ts +20 -0
- package/lib/metrics/operational/Metric.js +26 -0
- package/lib/metrics/operational/Metric.js.map +1 -0
- package/lib/metrics/operational/Timer.d.ts +91 -0
- package/lib/metrics/operational/Timer.js +122 -0
- package/lib/metrics/operational/Timer.js.map +1 -0
- package/lib/metrics/{operationalMetricsReporter.d.ts → operational/operationalMetricsReporter.d.ts} +16 -4
- package/lib/metrics/{operationalMetricsReporter.js → operational/operationalMetricsReporter.js} +31 -13
- package/lib/metrics/operational/operationalMetricsReporter.js.map +1 -0
- package/lib/metrics/reporters/reportBenchmarks.d.ts +1 -1
- package/lib/metrics/reporters/reportBenchmarks.js +1 -1
- package/lib/metrics/reporters/reportBenchmarks.js.map +1 -1
- package/lib/metrics/reporters/reportGlobalException.d.ts +1 -1
- package/lib/metrics/reporters/reportGlobalException.js +1 -1
- package/lib/metrics/reporters/reportGlobalException.js.map +1 -1
- package/lib/metrics/reporters/reportHttpMetrics.d.ts +1 -1
- package/lib/metrics/reporters/reportHttpMetrics.js +1 -1
- package/lib/metrics/reporters/reportHttpMetrics.js.map +1 -1
- package/lib/metrics/reporters/reportLegalState.d.ts +1 -1
- package/lib/metrics/reporters/reportLegalState.js +1 -1
- package/lib/metrics/reporters/reportLegalState.js.map +1 -1
- package/lib/metrics/reporters/reportLensAndAssetDownload.d.ts +1 -1
- package/lib/metrics/reporters/reportLensAndAssetDownload.js +1 -1
- package/lib/metrics/reporters/reportLensAndAssetDownload.js.map +1 -1
- package/lib/metrics/reporters/reportLensValidationFailed.d.ts +1 -1
- package/lib/metrics/reporters/reportLensView.d.ts +2 -2
- package/lib/metrics/reporters/reportLensView.js +23 -17
- package/lib/metrics/reporters/reportLensView.js.map +1 -1
- package/lib/metrics/reporters/reportLensWait.d.ts +2 -2
- package/lib/metrics/reporters/reportLensWait.js +1 -1
- package/lib/metrics/reporters/reportLensWait.js.map +1 -1
- package/lib/metrics/reporters/reportSessionException.d.ts +1 -1
- package/lib/metrics/reporters/reporters.d.ts +6 -6
- package/lib/metrics/reporters/reporters.js +3 -3
- package/lib/metrics/reporters/reporters.js.map +1 -1
- package/lib/observable-operators/unsubscribed.d.ts +12 -0
- package/lib/observable-operators/unsubscribed.js +27 -0
- package/lib/observable-operators/unsubscribed.js.map +1 -0
- package/lib/remote-configuration/cofHandler.d.ts +11 -7
- package/lib/remote-configuration/cofHandler.js +77 -67
- package/lib/remote-configuration/cofHandler.js.map +1 -1
- package/lib/remote-configuration/remoteConfiguration.d.ts +20 -6
- package/lib/remote-configuration/remoteConfiguration.js +24 -7
- package/lib/remote-configuration/remoteConfiguration.js.map +1 -1
- package/lib/session/CameraKitSession.d.ts +4 -3
- package/lib/session/CameraKitSession.js +6 -5
- package/lib/session/CameraKitSession.js.map +1 -1
- package/lib/session/LensKeyboard.d.ts +1 -1
- package/lib/session/LensPerformanceMeasurement.d.ts +2 -0
- package/lib/session/LensPerformanceMeasurement.js +27 -4
- package/lib/session/LensPerformanceMeasurement.js.map +1 -1
- package/lib/session/lensState.d.ts +5 -4
- package/lib/session/lensState.js +94 -39
- package/lib/session/lensState.js.map +1 -1
- package/package.json +12 -12
- package/lib/metrics/operationalMetricsReporter.js.map +0 -1
package/lib/logger/logger.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Subject } from "rxjs";
|
|
2
2
|
import { entries } from "../common/entries";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* The
|
|
4
|
+
* A reference to the recently created log messages subject.
|
|
5
|
+
* The subject is overridden in resetLogger() method, which is called during CameraKit bootstrapping.
|
|
6
6
|
*/
|
|
7
7
|
let logEntriesSubject = new Subject();
|
|
8
8
|
/**
|
|
@@ -18,10 +18,15 @@ export const logLevelMap = {
|
|
|
18
18
|
debug: 0,
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
|
-
* Initializes new logger subject.
|
|
21
|
+
* Initializes a new logger subject.
|
|
22
|
+
*
|
|
23
|
+
* Note: currently only one `CameraKit` instance is allowed to listen to log messages at a time, therefore that is
|
|
24
|
+
* necessary to avoid sharing the same subject between multiple `CameraKit` instances by calling`resetLogger()`.
|
|
25
|
+
* Also, `resetLogger()` should be called when there is no interest in logged messages.
|
|
26
|
+
* This allows the previous logEntriesSubject to be GCec.
|
|
22
27
|
* @internal
|
|
23
28
|
*/
|
|
24
|
-
export function
|
|
29
|
+
export function resetLogger() {
|
|
25
30
|
return (logEntriesSubject = new Subject());
|
|
26
31
|
}
|
|
27
32
|
/**
|
package/lib/logger/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,IAAI,iBAAiB,GAAG,IAAI,OAAO,EAAY,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACX,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,IAAI,iBAAiB,GAAG,IAAI,OAAO,EAAY,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACX,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW;IACvB,OAAO,CAAC,iBAAiB,GAAG,IAAI,OAAO,EAAY,CAAC,CAAC;AACzD,CAAC;AAYD;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACpC,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE;QACnD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,QAAe,EAAE,EAAE;YACnC,iBAAiB,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,IAAI,IAAI,EAAE;gBAChB,MAAM;gBACN,KAAK;gBACL,QAAQ;aACX,CAAC,CAAC;QACP,CAAC,CAAC;QACF,OAAO,MAAM,CAAC;IAClB,CAAC,EAAE,EAAY,CAAC,CAAC;AACrB,CAAC","sourcesContent":["import { Subject } from \"rxjs\";\nimport { entries } from \"../common/entries\";\n\n/**\n * A reference to the recently created log messages subject.\n * The subject is overridden in resetLogger() method, which is called during CameraKit bootstrapping.\n */\nlet logEntriesSubject = new Subject<LogEntry>();\n\n/**\n * This map associates log level names with their corresponding level value.\n * This means that a configured log level will match all log entries with a level value greater than\n * or equal to the configured value.\n */\nexport const logLevelMap = {\n error: 3,\n warn: 2,\n log: 1,\n info: 1,\n debug: 0,\n};\n\n/**\n * Initializes a new logger subject.\n *\n * Note: currently only one `CameraKit` instance is allowed to listen to log messages at a time, therefore that is\n * necessary to avoid sharing the same subject between multiple `CameraKit` instances by calling`resetLogger()`.\n * Also, `resetLogger()` should be called when there is no interest in logged messages.\n * This allows the previous logEntriesSubject to be GCec.\n * @internal\n */\nexport function resetLogger() {\n return (logEntriesSubject = new Subject<LogEntry>());\n}\n\nexport interface LogEntry {\n time: Date;\n module: string;\n level: keyof Logger;\n messages: any[];\n}\n\nexport type LogLevelName = keyof typeof logLevelMap;\nexport type Logger = Record<LogLevelName, (message?: any, ...optionalParams: any[]) => void>;\n\n/**\n * Gets logger for a given module.\n *\n * @internal\n *\n * @param module Module name.\n * @returns Logger instance.\n */\nexport function getLogger(module: string): Logger {\n return entries(logLevelMap).reduce((logger, [level]) => {\n logger[level] = (...messages: any[]) => {\n logEntriesSubject.next({\n time: new Date(),\n module,\n level,\n messages,\n });\n };\n return logger;\n }, {} as Logger);\n}\n"]}
|
|
@@ -12,6 +12,13 @@ function closeWorklet(worklet) {
|
|
|
12
12
|
worklet.port.onmessage = null;
|
|
13
13
|
worklet.disconnect();
|
|
14
14
|
}
|
|
15
|
+
function closeAudioContext(audioContext) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
if (!audioContext || audioContext.state === "closed")
|
|
18
|
+
return;
|
|
19
|
+
return audioContext.close();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
15
22
|
/**
|
|
16
23
|
* Create a {@link CameraKitSource} from a user's media device -- this calls
|
|
17
24
|
* [MediaDevices.getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) to get a
|
|
@@ -103,7 +110,7 @@ export function createMediaStreamSource(stream, options = {}) {
|
|
|
103
110
|
// To ensure there are not leaks, it is better to close any existing connections.
|
|
104
111
|
closeWorklet(worklet);
|
|
105
112
|
audioSource === null || audioSource === void 0 ? void 0 : audioSource.disconnect();
|
|
106
|
-
yield (audioContext
|
|
113
|
+
yield closeAudioContext(audioContext);
|
|
107
114
|
}
|
|
108
115
|
catch (error) {
|
|
109
116
|
// We still want to continue if anything above failed
|
|
@@ -129,6 +136,10 @@ export function createMediaStreamSource(stream, options = {}) {
|
|
|
129
136
|
// developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process
|
|
130
137
|
// inputs[n][m] is the list of samples in the n-th input at the m-th channel.
|
|
131
138
|
const leftSamples = e.data.buffer[0][0];
|
|
139
|
+
// Firefox might have leftSamples undefined:
|
|
140
|
+
// https://jira.sc-corp.net/browse/CAMKIT-5189
|
|
141
|
+
if (!leftSamples)
|
|
142
|
+
return;
|
|
132
143
|
let inputBuffers = [leftSamples];
|
|
133
144
|
if (simulateStereoAudio) {
|
|
134
145
|
const rightSamples = e.data.buffer[0].length > 1 ? e.data.buffer[0][1] : leftSamples.slice();
|
|
@@ -159,9 +170,7 @@ export function createMediaStreamSource(stream, options = {}) {
|
|
|
159
170
|
audioSource = undefined;
|
|
160
171
|
}
|
|
161
172
|
if (audioContext) {
|
|
162
|
-
yield audioContext
|
|
163
|
-
reportError(error);
|
|
164
|
-
});
|
|
173
|
+
yield closeAudioContext(audioContext).catch(reportError);
|
|
165
174
|
audioContext = undefined;
|
|
166
175
|
}
|
|
167
176
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaStreamSource.js","sourceRoot":"","sources":["../../src/media-sources/MediaStreamSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { ensureError } from \"../common/errorHelpers\";\nimport { Transform2D } from \"../transforms\";\nimport { CameraKitSource, CameraKitSourceOptions } from \"./CameraKitSource\";\n\nconst defaultOptions: MediaStreamSourceOptions = {\n transform: Transform2D.Identity,\n disableSourceAudio: false,\n};\n\nfunction closeWorklet(worklet: AudioWorkletNode | undefined) {\n if (!worklet) return;\n worklet.port.onmessage = null;\n worklet.disconnect();\n}\n\n/** @category Rendering */\nexport interface MediaStreamSourceOptions {\n transform: Transform2D;\n disableSourceAudio: boolean; // defaults to false\n}\n\n/**\n * Create a {@link CameraKitSource} from a user's media device -- this calls\n * [MediaDevices.getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) to get a\n * MediaStream and then calls {@link createMediaStreamSource}.\n *\n * @param constraints Specify contraints used to get a MediaStream from a media device. By default we simply request\n * a video stream.\n * @param options\n * @param options.transform By default we horizontally mirror the video stream. The most common use-case is to obtain a\n * stream from a front-facing web cam, which requires mirroring to be viewed naturally.\n * @param options.cameraType By default we set this to 'front' to indicate a camera pointed at the user (e.g. a webcam).\n * @param options.fpsLimit By default we set no limit on FPS – if the source device has a known FPS setting this limit\n * may prevent CameraKit from using more compute resources than strictly necessary.\n * @returns A Promise, resolving to {@link CameraKitSource}\n *\n * @category Rendering\n *\n * @deprecated The helper will be removed in one of the future releases.\n * Consumer apps are responsible for acquiring a media stream,\n * which can then be supplied to {@link createMediaStreamSource}.\n */\nexport async function createUserMediaSource(\n constraints: MediaStreamConstraints = { video: true },\n options: CameraKitSourceOptions<MediaStreamSourceOptions> = {}\n): Promise<CameraKitSource> {\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n return createMediaStreamSource(stream, { transform: Transform2D.MirrorX, cameraType: \"front\", ...options });\n}\n\n/**\n * Create a {@link CameraKitSource} from any\n * [MediaStream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream).\n *\n * @param stream Any MediaStream, such as obtained via `canvas.captureStream()` or `mediaDevices.getUserMedia()`.\n * @param options\n * @param options.transform We apply no transformation by default.\n * @param options.disableSourceAudio By default we pass audio to lens. Settings this to true will disable sending audio\n * to the lens.\n * @param options.cameraType By default we set this to 'front', which is the camera type most Lenses expect.\n * @param options.fpsLimit By default we set no limit on FPS – if the MediaStream has a known FPS setting this limit\n * may prevent CameraKit from using more compute resources than strictly necessary.\n *\n * @category Rendering\n */\nexport function createMediaStreamSource(\n stream: MediaStream,\n options: CameraKitSourceOptions<MediaStreamSourceOptions> = {}\n): CameraKitSource {\n const optionsNotNull = {\n ...defaultOptions,\n ...options,\n };\n\n const { width, height } =\n stream.getVideoTracks().length > 0 ? stream.getVideoTracks()[0].getSettings() : { width: 0, height: 0 };\n const enableSourceAudio: boolean = stream.getAudioTracks().length > 0 && !optionsNotNull.disableSourceAudio;\n\n const simulateStereoAudio = true;\n const sampleRate: number = 44100;\n\n let audioContext: AudioContext | undefined = undefined;\n let audioSource: MediaStreamAudioSourceNode | undefined = undefined;\n let worklet: AudioWorkletNode | undefined = undefined;\n let microphoneRecorderUrl: string;\n\n if (enableSourceAudio) {\n // https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_AudioWorklet\n const microphoneRecorderWorklet = `\n class MicrophoneWorkletProcessor extends AudioWorkletProcessor {\n process(inputs, outputs, parameters) {\n this.port.postMessage({\n eventType: 'data',\n buffer: inputs\n });\n return true;\n }\n }\n registerProcessor('microphone-worklet', MicrophoneWorkletProcessor);`;\n const microphoneRecorderBlob = new Blob([microphoneRecorderWorklet], {\n type: \"application/javascript\",\n });\n microphoneRecorderUrl = URL.createObjectURL(microphoneRecorderBlob);\n }\n\n return new CameraKitSource(\n { media: stream },\n {\n onAttach: async (source, lensCore, reportError) => {\n if (width !== undefined && height !== undefined) await source.setRenderSize(width, height);\n await source.setTransform(optionsNotNull.transform);\n\n if (enableSourceAudio) {\n // Audio paramters set has to be called before lens is applied\n lensCore.setAudioParameters({\n parameters: {\n numChannels: simulateStereoAudio ? 2 : 1,\n sampleRate,\n },\n onFailure: (error: Error) => {\n reportError(error);\n },\n });\n\n try {\n // There is a possibility of the onAttach method being called twice in a row due to a bug.\n // To ensure there are not leaks, it is better to close any existing connections.\n closeWorklet(worklet);\n audioSource?.disconnect();\n await audioContext?.close();\n } catch (error) {\n // We still want to continue if anything above failed\n reportError(ensureError(error));\n }\n\n audioContext = new AudioContext();\n audioSource = audioContext.createMediaStreamSource(stream);\n const scopedAudioSource = audioSource;\n audioContext.audioWorklet\n .addModule(microphoneRecorderUrl)\n .then(() => {\n if (audioContext) {\n worklet = new AudioWorkletNode(audioContext, \"microphone-worklet\");\n scopedAudioSource.connect(worklet);\n worklet.connect(audioContext.destination);\n // NOTE: We subscribe to messages here, and they will continue to arrive\n // even after audioContext.close() is called. To disconnect the audio worklets\n // created here, we need to track two variables - worklet and audioSource.\n // By calling disconnect() on them, we can properly\n // disconnect the audio worklets.\n worklet.port.onmessage = (e) => {\n if (e.data.eventType === \"data\") {\n // developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process\n // inputs[n][m] is the list of samples in the n-th input at the m-th channel.\n const leftSamples = e.data.buffer[0][0] as Float32Array;\n let inputBuffers = [leftSamples];\n if (simulateStereoAudio) {\n const rightSamples =\n e.data.buffer[0].length > 1 ? e.data.buffer[0][1] : leftSamples.slice();\n inputBuffers.push(rightSamples);\n }\n\n lensCore.processAudioSampleBuffer({\n input: inputBuffers,\n onFailure: (error: Error) => {\n reportError(error);\n },\n });\n }\n };\n }\n })\n .catch((error: Error) => {\n reportError(error);\n });\n }\n },\n onDetach: async (reportError) => {\n if (worklet) {\n closeWorklet(worklet);\n worklet = undefined;\n }\n if (audioSource) {\n audioSource.disconnect();\n audioSource = undefined;\n }\n if (audioContext) {\n await audioContext.close().catch((error: Error) => {\n reportError(error);\n });\n audioContext = undefined;\n }\n },\n },\n options\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MediaStreamSource.js","sourceRoot":"","sources":["../../src/media-sources/MediaStreamSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { ensureError } from \"../common/errorHelpers\";\nimport { Transform2D } from \"../transforms\";\nimport { CameraKitSource, CameraKitSourceOptions } from \"./CameraKitSource\";\n\nconst defaultOptions: MediaStreamSourceOptions = {\n transform: Transform2D.Identity,\n disableSourceAudio: false,\n};\n\nfunction closeWorklet(worklet: AudioWorkletNode | undefined) {\n if (!worklet) return;\n worklet.port.onmessage = null;\n worklet.disconnect();\n}\n\nasync function closeAudioContext(audioContext: AudioContext | undefined) {\n if (!audioContext || audioContext.state === \"closed\") return;\n return audioContext.close();\n}\n\n/** @category Rendering */\nexport interface MediaStreamSourceOptions {\n transform: Transform2D;\n disableSourceAudio: boolean; // defaults to false\n}\n\n/**\n * Create a {@link CameraKitSource} from a user's media device -- this calls\n * [MediaDevices.getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) to get a\n * MediaStream and then calls {@link createMediaStreamSource}.\n *\n * @param constraints Specify contraints used to get a MediaStream from a media device. By default we simply request\n * a video stream.\n * @param options\n * @param options.transform By default we horizontally mirror the video stream. The most common use-case is to obtain a\n * stream from a front-facing web cam, which requires mirroring to be viewed naturally.\n * @param options.cameraType By default we set this to 'front' to indicate a camera pointed at the user (e.g. a webcam).\n * @param options.fpsLimit By default we set no limit on FPS – if the source device has a known FPS setting this limit\n * may prevent CameraKit from using more compute resources than strictly necessary.\n * @returns A Promise, resolving to {@link CameraKitSource}\n *\n * @category Rendering\n *\n * @deprecated The helper will be removed in one of the future releases.\n * Consumer apps are responsible for acquiring a media stream,\n * which can then be supplied to {@link createMediaStreamSource}.\n */\nexport async function createUserMediaSource(\n constraints: MediaStreamConstraints = { video: true },\n options: CameraKitSourceOptions<MediaStreamSourceOptions> = {}\n): Promise<CameraKitSource> {\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n return createMediaStreamSource(stream, { transform: Transform2D.MirrorX, cameraType: \"front\", ...options });\n}\n\n/**\n * Create a {@link CameraKitSource} from any\n * [MediaStream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream).\n *\n * @param stream Any MediaStream, such as obtained via `canvas.captureStream()` or `mediaDevices.getUserMedia()`.\n * @param options\n * @param options.transform We apply no transformation by default.\n * @param options.disableSourceAudio By default we pass audio to lens. Settings this to true will disable sending audio\n * to the lens.\n * @param options.cameraType By default we set this to 'front', which is the camera type most Lenses expect.\n * @param options.fpsLimit By default we set no limit on FPS – if the MediaStream has a known FPS setting this limit\n * may prevent CameraKit from using more compute resources than strictly necessary.\n *\n * @category Rendering\n */\nexport function createMediaStreamSource(\n stream: MediaStream,\n options: CameraKitSourceOptions<MediaStreamSourceOptions> = {}\n): CameraKitSource {\n const optionsNotNull = {\n ...defaultOptions,\n ...options,\n };\n\n const { width, height } =\n stream.getVideoTracks().length > 0 ? stream.getVideoTracks()[0].getSettings() : { width: 0, height: 0 };\n const enableSourceAudio: boolean = stream.getAudioTracks().length > 0 && !optionsNotNull.disableSourceAudio;\n\n const simulateStereoAudio = true;\n const sampleRate: number = 44100;\n\n let audioContext: AudioContext | undefined = undefined;\n let audioSource: MediaStreamAudioSourceNode | undefined = undefined;\n let worklet: AudioWorkletNode | undefined = undefined;\n let microphoneRecorderUrl: string;\n\n if (enableSourceAudio) {\n // https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_AudioWorklet\n const microphoneRecorderWorklet = `\n class MicrophoneWorkletProcessor extends AudioWorkletProcessor {\n process(inputs, outputs, parameters) {\n this.port.postMessage({\n eventType: 'data',\n buffer: inputs\n });\n return true;\n }\n }\n registerProcessor('microphone-worklet', MicrophoneWorkletProcessor);`;\n const microphoneRecorderBlob = new Blob([microphoneRecorderWorklet], {\n type: \"application/javascript\",\n });\n microphoneRecorderUrl = URL.createObjectURL(microphoneRecorderBlob);\n }\n\n return new CameraKitSource(\n { media: stream },\n {\n onAttach: async (source, lensCore, reportError) => {\n if (width !== undefined && height !== undefined) await source.setRenderSize(width, height);\n await source.setTransform(optionsNotNull.transform);\n\n if (enableSourceAudio) {\n // Audio paramters set has to be called before lens is applied\n lensCore.setAudioParameters({\n parameters: {\n numChannels: simulateStereoAudio ? 2 : 1,\n sampleRate,\n },\n onFailure: (error: Error) => {\n reportError(error);\n },\n });\n\n try {\n // There is a possibility of the onAttach method being called twice in a row due to a bug.\n // To ensure there are not leaks, it is better to close any existing connections.\n closeWorklet(worklet);\n audioSource?.disconnect();\n await closeAudioContext(audioContext);\n } catch (error) {\n // We still want to continue if anything above failed\n reportError(ensureError(error));\n }\n\n audioContext = new AudioContext();\n audioSource = audioContext.createMediaStreamSource(stream);\n const scopedAudioSource = audioSource;\n audioContext.audioWorklet\n .addModule(microphoneRecorderUrl)\n .then(() => {\n if (audioContext) {\n worklet = new AudioWorkletNode(audioContext, \"microphone-worklet\");\n scopedAudioSource.connect(worklet);\n worklet.connect(audioContext.destination);\n // NOTE: We subscribe to messages here, and they will continue to arrive\n // even after audioContext.close() is called. To disconnect the audio worklets\n // created here, we need to track two variables - worklet and audioSource.\n // By calling disconnect() on them, we can properly\n // disconnect the audio worklets.\n worklet.port.onmessage = (e) => {\n if (e.data.eventType === \"data\") {\n // developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process\n // inputs[n][m] is the list of samples in the n-th input at the m-th channel.\n const leftSamples = e.data.buffer[0][0] as Float32Array;\n\n // Firefox might have leftSamples undefined:\n // https://jira.sc-corp.net/browse/CAMKIT-5189\n if (!leftSamples) return;\n\n let inputBuffers = [leftSamples];\n if (simulateStereoAudio) {\n const rightSamples =\n e.data.buffer[0].length > 1 ? e.data.buffer[0][1] : leftSamples.slice();\n inputBuffers.push(rightSamples);\n }\n\n lensCore.processAudioSampleBuffer({\n input: inputBuffers,\n onFailure: (error: Error) => {\n reportError(error);\n },\n });\n }\n };\n }\n })\n .catch((error: Error) => {\n reportError(error);\n });\n }\n },\n onDetach: async (reportError) => {\n if (worklet) {\n closeWorklet(worklet);\n worklet = undefined;\n }\n if (audioSource) {\n audioSource.disconnect();\n audioSource = undefined;\n }\n if (audioContext) {\n await closeAudioContext(audioContext).catch(reportError);\n audioContext = undefined;\n }\n },\n },\n options\n );\n}\n"]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { FetchHandler } from "../handlers/defaultFetchHandler";
|
|
2
2
|
import * as blizzard from "../generated-proto/blizzard/cameraKitEvents";
|
|
3
|
+
import { PageVisibility } from "../common/pageVisibility";
|
|
4
|
+
import { CameraKitConfiguration } from "../configuration";
|
|
3
5
|
import { MetricsEventTarget } from "./metricsEventTarget";
|
|
4
6
|
/**
|
|
5
7
|
* Translate between an external metric name, which is exposed to SDK users, and an internal Blizzard event name,
|
|
@@ -30,8 +32,8 @@ export type MakeTaggedBusinessEvent<K extends keyof CameraKitBusinessEventMap> =
|
|
|
30
32
|
name: K;
|
|
31
33
|
} & CameraKitBusinessEventMap[K];
|
|
32
34
|
export declare const businessEventsReporterFactory: {
|
|
33
|
-
(args_0: MetricsEventTarget, args_1: FetchHandler): void;
|
|
35
|
+
(args_0: MetricsEventTarget, args_1: FetchHandler, args_2: PageVisibility, args_3: CameraKitConfiguration): void;
|
|
34
36
|
token: "businessEventsReporter";
|
|
35
|
-
dependencies: readonly ["metricsEventTarget", "metricsHandler"];
|
|
37
|
+
dependencies: readonly ["metricsEventTarget", "metricsHandler", "pageVisibility", "configuration"];
|
|
36
38
|
};
|
|
37
39
|
export {};
|
|
@@ -7,20 +7,27 @@ import { HandlerChainBuilder } from "../handlers/HandlerChainBuilder";
|
|
|
7
7
|
import { createMappingHandler } from "../handlers/mappingHandler";
|
|
8
8
|
import * as blizzard from "../generated-proto/blizzard/cameraKitEvents";
|
|
9
9
|
import { getLogger } from "../logger/logger";
|
|
10
|
+
import { pageVisibilityFactory } from "../common/pageVisibility";
|
|
11
|
+
import { configurationToken } from "../configuration";
|
|
10
12
|
import { metricsHandlerFactory } from "./metricsHandler";
|
|
11
13
|
import { metricsEventTargetFactory } from "./metricsEventTarget";
|
|
12
14
|
const logger = getLogger("BusinessEventsReporter");
|
|
13
15
|
// CameraKit's prod metrics endpoint.
|
|
14
16
|
// See: https://github.sc-corp.net/Snapchat/pb_schema/blob/2a966db/proto/camera_kit/v3/service.proto#L133
|
|
15
|
-
const
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
17
|
+
const relativePath = "/com.snap.camerakit.v3.Metrics/metrics/business_events";
|
|
18
|
+
// It is rather cumbersome to check the actual final size of a batch, but we can easily limit the number of events we
|
|
19
|
+
// include in each batch -- looking at historical data, typical events average ~1.3kb per event. But there are some
|
|
20
|
+
// events (like CAMERA_KIT_EXCEPTION, which includes a stack trace) that can be much larger.
|
|
21
|
+
//
|
|
22
|
+
// To prevent us running over the 64kibibyte limit imposed by browsers on `keep-alive` requests, we'll set quite a low
|
|
23
|
+
// limit to ensure we don't lose events which are larger in size than we expect.
|
|
24
|
+
const BUSINESS_EVENT_BATCH_MAX_SIZE = 10;
|
|
20
25
|
const BUSINESS_EVENT_BATCH_MAX_AGE_MS = 5000;
|
|
21
|
-
function listenAndReport(metricsEventTarget, metricsHandler, eventHandlers) {
|
|
26
|
+
function listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, eventHandlers, apiHostname) {
|
|
22
27
|
const sessionId = v4();
|
|
23
28
|
logger.log(`Session ID: ${sessionId}`);
|
|
29
|
+
// Blizzard convention is to start the sequenceId at 1.
|
|
30
|
+
let sequenceId = 1;
|
|
24
31
|
const handler = new HandlerChainBuilder(metricsHandler)
|
|
25
32
|
.map(createMappingHandler((events) => {
|
|
26
33
|
const body = {
|
|
@@ -29,16 +36,16 @@ function listenAndReport(metricsEventTarget, metricsHandler, eventHandlers) {
|
|
|
29
36
|
serverEvents: events,
|
|
30
37
|
},
|
|
31
38
|
};
|
|
32
|
-
return new Request(
|
|
39
|
+
return new Request(`https://${apiHostname}${relativePath}`, {
|
|
33
40
|
method: "POST",
|
|
34
41
|
body: JSON.stringify(body),
|
|
35
42
|
credentials: "include",
|
|
36
|
-
//
|
|
43
|
+
// When this is true it makes fetch behave like `Navigator.sendBeacon` – that is, the request
|
|
37
44
|
// will still be made even if the page terminates.
|
|
38
45
|
// https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
39
|
-
keepalive:
|
|
46
|
+
keepalive: pageVisibility.isDuringVisibilityTransition("hidden"),
|
|
40
47
|
});
|
|
41
|
-
}))
|
|
48
|
+
}, pageVisibility))
|
|
42
49
|
.map(createBatchingHandler({
|
|
43
50
|
batchReduce: (previousBundle, businessEvent) => {
|
|
44
51
|
const bundle = previousBundle !== null && previousBundle !== void 0 ? previousBundle : [];
|
|
@@ -47,6 +54,7 @@ function listenAndReport(metricsEventTarget, metricsHandler, eventHandlers) {
|
|
|
47
54
|
},
|
|
48
55
|
isBatchComplete: (bundle) => bundle.length >= BUSINESS_EVENT_BATCH_MAX_SIZE,
|
|
49
56
|
maxBatchAge: BUSINESS_EVENT_BATCH_MAX_AGE_MS,
|
|
57
|
+
pageVisibility,
|
|
50
58
|
})).handler;
|
|
51
59
|
const makeBlizzardEvent = (event) => {
|
|
52
60
|
return Object.assign(Object.assign({}, event), { cameraKitEventBase: blizzard.CameraKitEventBase.fromPartial({
|
|
@@ -75,7 +83,7 @@ function listenAndReport(metricsEventTarget, metricsHandler, eventHandlers) {
|
|
|
75
83
|
osType: userAgent.osType,
|
|
76
84
|
osVersion: userAgent.osVersion,
|
|
77
85
|
maxSequenceIdOnInstance: 0,
|
|
78
|
-
sequenceId:
|
|
86
|
+
sequenceId: sequenceId++,
|
|
79
87
|
eventData,
|
|
80
88
|
}));
|
|
81
89
|
};
|
|
@@ -93,7 +101,12 @@ function listenAndReport(metricsEventTarget, metricsHandler, eventHandlers) {
|
|
|
93
101
|
});
|
|
94
102
|
});
|
|
95
103
|
}
|
|
96
|
-
export const businessEventsReporterFactory = Injectable("businessEventsReporter", [
|
|
104
|
+
export const businessEventsReporterFactory = Injectable("businessEventsReporter", [
|
|
105
|
+
metricsEventTargetFactory.token,
|
|
106
|
+
metricsHandlerFactory.token,
|
|
107
|
+
pageVisibilityFactory.token,
|
|
108
|
+
configurationToken,
|
|
109
|
+
], (metricsEventTarget, metricsHandler, pageVisibility, configuration) => {
|
|
97
110
|
/**
|
|
98
111
|
* This defines a mapping from a business event's external name (the name we document in public API docs), to
|
|
99
112
|
* its internal representation as a Blizzard ServerEvent.
|
|
@@ -112,7 +125,7 @@ export const businessEventsReporterFactory = Injectable("businessEventsReporter"
|
|
|
112
125
|
* https://github.sc-corp.net/Snapchat/snapchat/tree/master/blizzard/schema/blizzard-schema/
|
|
113
126
|
* codeGen/src/main/java/com/snapchat/analytics/schema/events/cameraKit
|
|
114
127
|
*/
|
|
115
|
-
listenAndReport(metricsEventTarget, metricsHandler, {
|
|
128
|
+
listenAndReport(metricsEventTarget, metricsHandler, pageVisibility, {
|
|
116
129
|
assetDownload: (event) => [
|
|
117
130
|
"CAMERA_KIT_ASSET_DOWNLOAD",
|
|
118
131
|
{ cameraKitAssetDownload: blizzard.CameraKitAssetDownload.fromPartial(event) },
|
|
@@ -155,6 +168,6 @@ export const businessEventsReporterFactory = Injectable("businessEventsReporter"
|
|
|
155
168
|
"CAMERA_KIT_SESSION",
|
|
156
169
|
{ cameraKitSession: blizzard.CameraKitSession.fromPartial(event) },
|
|
157
170
|
],
|
|
158
|
-
});
|
|
171
|
+
}, configuration.apiHostname);
|
|
159
172
|
});
|
|
160
173
|
//# 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 { 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 BUSINESS_EVENTS_ENDPOINT = \"https://api-kit.snapchat.com/com.snap.camerakit.v3.Metrics/metrics/business_events\";\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. staying under the `keepalive` request body limit of 64 kibibytes.\nconst BUSINESS_EVENT_BATCH_MAX_SIZE = 100;\nconst BUSINESS_EVENT_BATCH_MAX_AGE_MS = 5000;\n\nfunction listenAndReport(\n metricsEventTarget: MetricsEventTarget,\n metricsHandler: FetchHandler,\n eventHandlers: EventHandlers\n): void {\n const sessionId = v4();\n logger.log(`Session ID: ${sessionId}`);\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 return new Request(BUSINESS_EVENTS_ENDPOINT, {\n method: \"POST\",\n body: JSON.stringify(body),\n credentials: \"include\",\n\n // Setting this to true 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: true,\n });\n })\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 })\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: 0,\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 [metricsEventTargetFactory.token, metricsHandlerFactory.token] as const,\n (metricsEventTarget: MetricsEventTarget, metricsHandler: FetchHandler) => {\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(metricsEventTarget, metricsHandler, {\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 }\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 { 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,9 +1,10 @@
|
|
|
1
1
|
import { FetchHandler } from "../handlers/defaultFetchHandler";
|
|
2
|
+
import { PageVisibility } from "../common/pageVisibility";
|
|
2
3
|
/**
|
|
3
4
|
* @internal
|
|
4
5
|
*/
|
|
5
6
|
export declare const metricsHandlerFactory: {
|
|
6
|
-
(args_0: FetchHandler): import("../handlers/HandlerChainBuilder").Handler<RequestInfo, Response, RequestInit | undefined>;
|
|
7
|
+
(args_0: FetchHandler, args_1: PageVisibility): import("../handlers/HandlerChainBuilder").Handler<RequestInfo, Response, RequestInit | undefined>;
|
|
7
8
|
token: "metricsHandler";
|
|
8
|
-
dependencies: readonly ["cameraKitServiceFetchHandler"];
|
|
9
|
+
dependencies: readonly ["cameraKitServiceFetchHandler", "pageVisibility"];
|
|
9
10
|
};
|
|
@@ -2,12 +2,12 @@ import { Injectable } from "../dependency-injection/Injectable";
|
|
|
2
2
|
import { cameraKitServiceFetchHandlerFactory } from "../handlers/cameraKitServiceFetchHandlerFactory";
|
|
3
3
|
import { HandlerChainBuilder } from "../handlers/HandlerChainBuilder";
|
|
4
4
|
import { createRateLimitingHandler } from "../handlers/rateLimitingHandler";
|
|
5
|
+
import { pageVisibilityFactory } from "../common/pageVisibility";
|
|
5
6
|
const METRIC_REQUEST_RATE_LIMIT_MS = 1000; // send at most one metric request per second.
|
|
6
7
|
/**
|
|
7
8
|
* @internal
|
|
8
9
|
*/
|
|
9
|
-
export const metricsHandlerFactory = Injectable("metricsHandler", [cameraKitServiceFetchHandlerFactory.token], (fetchHandler) => {
|
|
10
|
-
return new HandlerChainBuilder(fetchHandler).map(createRateLimitingHandler(METRIC_REQUEST_RATE_LIMIT_MS))
|
|
11
|
-
.handler;
|
|
10
|
+
export const metricsHandlerFactory = Injectable("metricsHandler", [cameraKitServiceFetchHandlerFactory.token, pageVisibilityFactory.token], (fetchHandler, pageVisibility) => {
|
|
11
|
+
return new HandlerChainBuilder(fetchHandler).map(createRateLimitingHandler(METRIC_REQUEST_RATE_LIMIT_MS, pageVisibility)).handler;
|
|
12
12
|
});
|
|
13
13
|
//# sourceMappingURL=metricsHandler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metricsHandler.js","sourceRoot":"","sources":["../../src/metrics/metricsHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,OAAO,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAC;AACtG,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"metricsHandler.js","sourceRoot":"","sources":["../../src/metrics/metricsHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,OAAO,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAC;AACtG,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjF,MAAM,4BAA4B,GAAG,IAAI,CAAC,CAAC,8CAA8C;AAEzF;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAC3C,gBAAgB,EAChB,CAAC,mCAAmC,CAAC,KAAK,EAAE,qBAAqB,CAAC,KAAK,CAAU,EACjF,CAAC,YAA0B,EAAE,cAA8B,EAAE,EAAE;IAC3D,OAAO,IAAI,mBAAmB,CAAC,YAAY,CAAC,CAAC,GAAG,CAC5C,yBAAyB,CAAC,4BAA4B,EAAE,cAAc,CAAC,CAC1E,CAAC,OAAO,CAAC;AACd,CAAC,CACJ,CAAC","sourcesContent":["import { Injectable } from \"../dependency-injection/Injectable\";\nimport { FetchHandler } from \"../handlers/defaultFetchHandler\";\nimport { cameraKitServiceFetchHandlerFactory } from \"../handlers/cameraKitServiceFetchHandlerFactory\";\nimport { HandlerChainBuilder } from \"../handlers/HandlerChainBuilder\";\nimport { createRateLimitingHandler } from \"../handlers/rateLimitingHandler\";\nimport { PageVisibility, pageVisibilityFactory } from \"../common/pageVisibility\";\n\nconst METRIC_REQUEST_RATE_LIMIT_MS = 1000; // send at most one metric request per second.\n\n/**\n * @internal\n */\nexport const metricsHandlerFactory = Injectable(\n \"metricsHandler\",\n [cameraKitServiceFetchHandlerFactory.token, pageVisibilityFactory.token] as const,\n (fetchHandler: FetchHandler, pageVisibility: PageVisibility) => {\n return new HandlerChainBuilder(fetchHandler).map(\n createRateLimitingHandler(METRIC_REQUEST_RATE_LIMIT_MS, pageVisibility)\n ).handler;\n }\n);\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OperationalMetric } from "../../generated-proto/pb_schema/camera_kit/v3/operational_metrics";
|
|
2
|
+
import { Metric, MetricDimensions } from "./Metric";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export type CountMetric = OperationalMetric & {
|
|
5
|
+
metric: Extract<OperationalMetric["metric"], {
|
|
6
|
+
$case: "count";
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
/** @internal */
|
|
10
|
+
export declare class Count extends Metric {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
static count(name: string, n: number, dimensions?: MetricDimensions): Count;
|
|
13
|
+
private count;
|
|
14
|
+
constructor(name: string, dimensions?: MetricDimensions);
|
|
15
|
+
increment(count: number): number;
|
|
16
|
+
toOperationalMetric(): CountMetric[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Metric, serializeMetricDimensions } from "./Metric";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export class Count extends Metric {
|
|
4
|
+
static count(name, n, dimensions = {}) {
|
|
5
|
+
const count = new Count(name, dimensions);
|
|
6
|
+
count.increment(n);
|
|
7
|
+
return count;
|
|
8
|
+
}
|
|
9
|
+
constructor(name, dimensions = {}) {
|
|
10
|
+
super(name, dimensions);
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.count = 0;
|
|
13
|
+
}
|
|
14
|
+
increment(count) {
|
|
15
|
+
this.count += count;
|
|
16
|
+
return this.count;
|
|
17
|
+
}
|
|
18
|
+
toOperationalMetric() {
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
name: `${this.name}${serializeMetricDimensions(this.dimensions)}`,
|
|
22
|
+
timestamp: new Date(),
|
|
23
|
+
metric: { $case: "count", count: this.count },
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=Count.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Count.js","sourceRoot":"","sources":["../../../src/metrics/operational/Count.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAoB,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAO/E,gBAAgB;AAChB,MAAM,OAAO,KAAM,SAAQ,MAAM;IAC7B,MAAM,CAAC,KAAK,CAAC,IAAY,EAAE,CAAS,EAAE,aAA+B,EAAE;QACnE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC1C,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,KAAK,CAAC;IACjB,CAAC;IAID,YAAqB,IAAY,EAAE,aAA+B,EAAE;QAChE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QADP,SAAI,GAAJ,IAAI,CAAQ;QAFzB,UAAK,GAAG,CAAC,CAAC;IAIlB,CAAC;IAED,SAAS,CAAC,KAAa;QACnB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,mBAAmB;QACf,OAAO;YACH;gBACI,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;gBACjE,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;aAChD;SACJ,CAAC;IACN,CAAC;CACJ","sourcesContent":["import { OperationalMetric } from \"../../generated-proto/pb_schema/camera_kit/v3/operational_metrics\";\nimport { Metric, MetricDimensions, serializeMetricDimensions } from \"./Metric\";\n\n/** @internal */\nexport type CountMetric = OperationalMetric & {\n metric: Extract<OperationalMetric[\"metric\"], { $case: \"count\" }>;\n};\n\n/** @internal */\nexport class Count extends Metric {\n static count(name: string, n: number, dimensions: MetricDimensions = {}): Count {\n const count = new Count(name, dimensions);\n count.increment(n);\n return count;\n }\n\n private count = 0;\n\n constructor(readonly name: string, dimensions: MetricDimensions = {}) {\n super(name, dimensions);\n }\n\n increment(count: number): number {\n this.count += count;\n return this.count;\n }\n\n toOperationalMetric(): CountMetric[] {\n return [\n {\n name: `${this.name}${serializeMetricDimensions(this.dimensions)}`,\n timestamp: new Date(),\n metric: { $case: \"count\", count: this.count },\n },\n ];\n }\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OperationalMetric } from "../../generated-proto/pb_schema/camera_kit/v3/operational_metrics";
|
|
2
|
+
import { Metric, MetricDimensions } from "./Metric";
|
|
3
|
+
/** @internal */
|
|
4
|
+
export type HistogramMetric = OperationalMetric & {
|
|
5
|
+
metric: Extract<OperationalMetric["metric"], {
|
|
6
|
+
$case: "histogram";
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
/** @internal */
|
|
10
|
+
export declare class Histogram extends Metric {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
static level(name: string, level: number, dimsensions?: MetricDimensions): Histogram;
|
|
13
|
+
private readonly levels;
|
|
14
|
+
constructor(name: string, dimensions?: MetricDimensions);
|
|
15
|
+
add(level: number): void;
|
|
16
|
+
toOperationalMetric(): HistogramMetric[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Metric, serializeMetricDimensions } from "./Metric";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export class Histogram extends Metric {
|
|
4
|
+
static level(name, level, dimsensions = {}) {
|
|
5
|
+
const histogram = new Histogram(name, dimsensions);
|
|
6
|
+
histogram.add(level);
|
|
7
|
+
return histogram;
|
|
8
|
+
}
|
|
9
|
+
constructor(name, dimensions = {}) {
|
|
10
|
+
super(name, dimensions);
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.levels = [];
|
|
13
|
+
}
|
|
14
|
+
add(level) {
|
|
15
|
+
this.levels.push(level);
|
|
16
|
+
}
|
|
17
|
+
toOperationalMetric() {
|
|
18
|
+
const timestamp = new Date();
|
|
19
|
+
const name = `${this.name}${serializeMetricDimensions(this.dimensions)}`;
|
|
20
|
+
return this.levels.map((level) => ({ name, timestamp, metric: { $case: "histogram", histogram: level } }));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=Histogram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Histogram.js","sourceRoot":"","sources":["../../../src/metrics/operational/Histogram.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAoB,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAO/E,gBAAgB;AAChB,MAAM,OAAO,SAAU,SAAQ,MAAM;IACjC,MAAM,CAAC,KAAK,CAAC,IAAY,EAAE,KAAa,EAAE,cAAgC,EAAE;QACxE,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACnD,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,SAAS,CAAC;IACrB,CAAC;IAID,YAAqB,IAAY,EAAE,aAA+B,EAAE;QAChE,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QADP,SAAI,GAAJ,IAAI,CAAQ;QAFhB,WAAM,GAAa,EAAE,CAAC;IAIvC,CAAC;IAED,GAAG,CAAC,KAAa;QACb,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,mBAAmB;QACf,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACzE,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/G,CAAC;CACJ","sourcesContent":["import { OperationalMetric } from \"../../generated-proto/pb_schema/camera_kit/v3/operational_metrics\";\nimport { Metric, MetricDimensions, serializeMetricDimensions } from \"./Metric\";\n\n/** @internal */\nexport type HistogramMetric = OperationalMetric & {\n metric: Extract<OperationalMetric[\"metric\"], { $case: \"histogram\" }>;\n};\n\n/** @internal */\nexport class Histogram extends Metric {\n static level(name: string, level: number, dimsensions: MetricDimensions = {}): Histogram {\n const histogram = new Histogram(name, dimsensions);\n histogram.add(level);\n return histogram;\n }\n\n private readonly levels: number[] = [];\n\n constructor(readonly name: string, dimensions: MetricDimensions = {}) {\n super(name, dimensions);\n }\n\n add(level: number): void {\n this.levels.push(level);\n }\n\n toOperationalMetric(): HistogramMetric[] {\n const timestamp = new Date();\n const name = `${this.name}${serializeMetricDimensions(this.dimensions)}`;\n return this.levels.map((level) => ({ name, timestamp, metric: { $case: \"histogram\", histogram: level } }));\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OperationalMetric } from "../../generated-proto/pb_schema/camera_kit/v3/operational_metrics";
|
|
2
|
+
type MetricConstructor<T> = new (name: string, dimensions: MetricDimensions) => T;
|
|
3
|
+
declare const nameDelimiter = "_";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export type MetricDimensions = Record<string, string | number>;
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare abstract class Metric {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly dimensions: MetricDimensions;
|
|
10
|
+
constructor(name: string, dimensions?: MetricDimensions);
|
|
11
|
+
child<ChildName extends string, T extends Metric>(constructor: MetricConstructor<T>, name: ChildName, dimensions?: MetricDimensions): T;
|
|
12
|
+
abstract toOperationalMetric(): Required<OperationalMetric>[];
|
|
13
|
+
}
|
|
14
|
+
/** @internal */
|
|
15
|
+
export type JoinMetricNames<Parent extends string, Child extends string> = `${Parent}${typeof nameDelimiter}${Child}`;
|
|
16
|
+
/** @internal */
|
|
17
|
+
export declare function joinMetricNames(names: string[]): string;
|
|
18
|
+
/** @internal */
|
|
19
|
+
export declare function serializeMetricDimensions(dimensions: MetricDimensions): string;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const nameDelimiter = "_";
|
|
2
|
+
const dimensionDelimiter = ".";
|
|
3
|
+
const delimiterRegex = new RegExp(`^${nameDelimiter}+|${nameDelimiter}+$`, "g");
|
|
4
|
+
/** @internal */
|
|
5
|
+
export class Metric {
|
|
6
|
+
constructor(name, dimensions = {}) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.dimensions = dimensions;
|
|
9
|
+
}
|
|
10
|
+
child(constructor, name, dimensions = {}) {
|
|
11
|
+
return new constructor(`${this.name}${nameDelimiter}${name}`, dimensions);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/** @internal */
|
|
15
|
+
export function joinMetricNames(names) {
|
|
16
|
+
return names.join(nameDelimiter).replace(delimiterRegex, "");
|
|
17
|
+
}
|
|
18
|
+
/** @internal */
|
|
19
|
+
export function serializeMetricDimensions(dimensions) {
|
|
20
|
+
if (Object.keys(dimensions).length === 0)
|
|
21
|
+
return "";
|
|
22
|
+
return `${dimensionDelimiter}${Array.from(Object.entries(dimensions))
|
|
23
|
+
.map((d) => d.join(dimensionDelimiter))
|
|
24
|
+
.join(dimensionDelimiter)}`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=Metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Metric.js","sourceRoot":"","sources":["../../../src/metrics/operational/Metric.ts"],"names":[],"mappings":"AAIA,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,IAAI,aAAa,KAAK,aAAa,IAAI,EAAE,GAAG,CAAC,CAAC;AAKhF,gBAAgB;AAChB,MAAM,OAAgB,MAAM;IACxB,YAAqB,IAAY,EAAW,aAA+B,EAAE;QAAxD,SAAI,GAAJ,IAAI,CAAQ;QAAW,eAAU,GAAV,UAAU,CAAuB;IAAG,CAAC;IAEjF,KAAK,CACD,WAAiC,EACjC,IAAe,EACf,aAA+B,EAAE;QAEjC,OAAO,IAAI,WAAW,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,aAAa,GAAG,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;IAC9E,CAAC;CAGJ;AAKD,gBAAgB;AAChB,MAAM,UAAU,eAAe,CAAC,KAAe;IAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,yBAAyB,CAAC,UAA4B;IAClE,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpD,OAAO,GAAG,kBAAkB,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;SACtC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;AACpC,CAAC","sourcesContent":["import { OperationalMetric } from \"../../generated-proto/pb_schema/camera_kit/v3/operational_metrics\";\n\ntype MetricConstructor<T> = new (name: string, dimensions: MetricDimensions) => T;\n\nconst nameDelimiter = \"_\";\nconst dimensionDelimiter = \".\";\nconst delimiterRegex = new RegExp(`^${nameDelimiter}+|${nameDelimiter}+$`, \"g\");\n\n/** @internal */\nexport type MetricDimensions = Record<string, string | number>;\n\n/** @internal */\nexport abstract class Metric {\n constructor(readonly name: string, readonly dimensions: MetricDimensions = {}) {}\n\n child<ChildName extends string, T extends Metric>(\n constructor: MetricConstructor<T>,\n name: ChildName,\n dimensions: MetricDimensions = {}\n ): T {\n return new constructor(`${this.name}${nameDelimiter}${name}`, dimensions);\n }\n\n abstract toOperationalMetric(): Required<OperationalMetric>[];\n}\n\n/** @internal */\nexport type JoinMetricNames<Parent extends string, Child extends string> = `${Parent}${typeof nameDelimiter}${Child}`;\n\n/** @internal */\nexport function joinMetricNames(names: string[]): string {\n return names.join(nameDelimiter).replace(delimiterRegex, \"\");\n}\n\n/** @internal */\nexport function serializeMetricDimensions(dimensions: MetricDimensions): string {\n if (Object.keys(dimensions).length === 0) return \"\";\n return `${dimensionDelimiter}${Array.from(Object.entries(dimensions))\n .map((d) => d.join(dimensionDelimiter))\n .join(dimensionDelimiter)}`;\n}\n"]}
|