@alliumcloud/telemetry
v1.0.5
Published
Client-side SDK for monitoring Odyssey SDKs via the telemetry service
Readme
@alliumcloud/telemetry
Client-side SDK that instruments Alliumcloud SDKs via JavaScript Proxy — capturing API timing, errors, and lifecycle events — then batches and sends them to the Odyssey Telemetry Service.
Supports five SDKs out of the box: Asset Manager, Spatial Comms (Mediasoup), Avatar SSO, Organization Service, and Configurator Service.
Installation
npm install @alliumcloud/telemetryQuick Start
Step 1 — Create a shared telemetry instance (src/config/telemetry/sdk.ts)
With a custom baseUrl (overrides the baked-in URL):
import { TelemetrySdk } from '@alliumcloud/telemetry';
export const telemetry = TelemetrySdk.create({
baseUrl: process.env.VUE_APP_ALLIUM_BASE_URL,
flushInterval: 5000,
batchSize: 20,
});Or without baseUrl (uses the URL baked into the package at publish time via BUILD_ENV):
import { TelemetrySdk } from '@alliumcloud/telemetry';
export const telemetry = TelemetrySdk.create({
flushInterval: 5000,
batchSize: 20,
});Step 2 — Instrument each SDK at creation time
Asset Manager (src/config/asset_manager.config.ts):
import AssetManagerSDK from '@alliumcloud/asset-manager';
import { telemetry } from '@/config/telemetry/sdk';
const rawAssetSdk = AssetManagerSDK.create({ apiKey, jwksUri, accessTokenProvider });
export const assetSdk = telemetry.instrument(rawAssetSdk);Spatial Comms (src/store/mediasoup.ts):
import { SpatialCommsSDK } from '@alliumcloud/spatial-comms';
import { telemetry } from '@/config/telemetry/sdk';
const sdk = telemetry.instrument(SpatialCommsSDK.create(apiKey, getAccessToken));The sdkKey and sdkType are read directly from each SDK instance — no extra config needed. The instrumented SDK is a transparent proxy: all method calls behave exactly as before.
Configuration
TelemetrySdk.create(config?)
| Option | Default | Description |
|--------|---------|-------------|
| baseUrl | (baked at build time) | Optional. Allium platform base URL (e.g. https://api-gateway.example.com). The SDK appends /telemetry internally. If omitted, uses the URL baked into the package at publish time based on BUILD_ENV (dev / testing / prod). |
| flushInterval | 5000 | Milliseconds between automatic event flushes |
| batchSize | 20 | Flush early when the event queue reaches this size |
telemetry.instrument(sdk, options?)
| Option | Required | Description |
|--------|----------|-------------|
| sdkKey | Auto-detected from sdk.sdkKey | SDK key sent as x-sdk-key header to the telemetry service |
| sdkType | Auto-detected from sdk.serviceType | 'asset-manager', 'SPATIAL_COMMS', 'AVATAR_SSO', or 'Organization_Service' |
Returns the same SDK instance, transparently proxied. All existing calls behave identically.
telemetry.flush()
Force-sends all queued events immediately. Returns Promise<void>. Useful before page navigation.
telemetry.destroy()
Sends sdk.destroyed events for all instrumented SDKs, stops flush timers, and clears all queues. Called automatically on beforeunload.
Events Captured
Asset Manager (asset-manager)
| Event | Trigger |
|-------|---------|
| sdk.initialized | instrument() called |
| api.request | Every SDK method call — includes endpoint, method, durationMs, statusCode, success |
| upload.initiated | upload.initiate() succeeded |
| upload.completed | upload.complete() succeeded |
| upload.aborted | upload.abort() succeeded |
| upload.failed | upload.complete() or upload.abort() threw |
| asset.created | assets.create() succeeded |
| asset.status.uploaded | assets.markAsUploaded() succeeded |
| asset.status.validated | assets.markAsValidated() succeeded |
| asset.status.failed | assets.markAsFailed() succeeded |
| asset.deleted | assets.delete() succeeded |
| version.created | versions.create() succeeded |
| version.deleted | versions.delete() succeeded |
| version.deleted_by_asset | versions.deleteByAsset() succeeded |
| sanitization.project.deleted | sanitization.deleteProjectAndFootprint() succeeded |
| sdk.destroyed | telemetry.destroy() called |
Spatial Comms / Mediasoup (SPATIAL_COMMS)
| Event | Trigger |
|-------|---------|
| sdk.initialized | instrument() called |
| api.request | chat.init() and chat.sendMessage() HTTP calls |
| connection.established | joinRoom() succeeded |
| connection.closed | leaveRoom() called |
| track.published | produceTrack() succeeded |
| track.unpublished | stopVideoProducer() or stopScreenShare() called |
| peer.joined | SDK emits new-participant event |
| peer.left | SDK emits participant-left event |
| sdk.destroyed | telemetry.destroy() called |
Avatar SSO (AVATAR_SSO)
| Event | Trigger |
|-------|---------|
| sdk.initialized | instrument() called |
| api.request | Every method call — includes endpoint, method, durationMs, statusCode, success |
| auth.register | register() succeeded |
| auth.login | login() succeeded (local) or before redirect (SSO) |
| auth.logout | logout() succeeded (local) or before redirect (SSO) |
| auth.otp.verified | verifyOtp() succeeded |
| auth.exchange | exchange() returned a user |
| auth.token.refreshed | refresh() succeeded |
| profile.updated | profileUpdate() succeeded |
| profile.avatar.updated | avatarUpdate() succeeded |
| sdk.destroyed | telemetry.destroy() called |
Organization Service (Organization_Service)
| Event | Trigger |
|-------|---------|
| sdk.initialized | instrument() called |
| api.request | Every method call on all modules |
| org.created | organization.create() succeeded |
| org.updated | organization.update() succeeded |
| org.deleted | organization.delete() succeeded |
| org.user.updated | organization.updateUser() succeeded |
| org.user.deleted | organization.deleteUser() succeeded |
| org.invite.created | organizationInvites.create() succeeded |
| org.invite.accepted | organizationInvites.accept() succeeded |
| org.invite.rejected | organizationInvites.reject() succeeded |
| org.invite.deleted | organizationInvites.delete() succeeded |
| project.created | projects.create() succeeded |
| project.updated | projects.update() succeeded |
| project.deleted | projects.delete() succeeded |
| space.created | spaces.create() succeeded |
| space.updated | spaces.update() succeeded |
| space.deleted | spaces.delete() succeeded |
| space.user.updated | spaces.updateUser() succeeded |
| space.user.deleted | spaces.deleteUser() succeeded |
| space.invite.created | spaceInvites.create() succeeded |
| space.invite.accepted | spaceInvites.accept() succeeded |
| space.invite.rejected | spaceInvites.reject() succeeded |
| space.invite.deleted | spaceInvites.delete() succeeded |
| sdk.destroyed | telemetry.destroy() called |
Configurator Service (CONFIGURATOR_SERVICE)
| Event | Trigger |
|-------|---------|
| sdk.initialized | instrument() called |
| api.request | Every method call — includes endpoint, method, durationMs, statusCode, success |
| media.video.added | media.addVideo() succeeded |
| media.video.updated | media.updateVideo() succeeded |
| media.stream.added | media.addStream() succeeded |
| media.stream.updated | media.updateStream() succeeded |
| media.link.added | media.addLink() succeeded |
| media.link.updated | media.updateLink() succeeded |
| sketchfab.object.added | sketchfab.addObject() succeeded |
| sketchfab.object.updated | sketchfab.updateObject() succeeded |
| transform.position.updated | transform.updatePosition() succeeded |
| transform.rotation.updated | transform.updateRotation() succeeded |
| transform.scale.updated | transform.updateScale() succeeded |
| transform.snapped | transform.snapToGround() succeeded |
| layer.item.locked | layer.lockItem() succeeded |
| layer.item.renamed | layer.renameItem() succeeded |
| layer.item.deleted | layer.deleteItem() succeeded |
| layer.all.deleted | layer.deleteAll() succeeded |
| configurator.item.created | configuratorItems.create() succeeded |
| configurator.item.state.updated | configuratorItems.updateState() succeeded |
| configurator.object.created | configuratorObjects.create() succeeded |
| configurator.object.config.updated | configuratorObjects.updateConfiguration() succeeded |
| sdk.destroyed | telemetry.destroy() called |
How It Works
- Zero runtime dependencies — uses native
fetch,sessionStorage,performance.now(),crypto.randomUUID() - JavaScript Proxy — wraps each SDK transparently; no changes to the target SDKs required
- Session ID — generated via
crypto.randomUUID()and persisted insessionStorage(survives page navigation, cleared on tab close) - Batching — events are queued and flushed on a timer OR when the batch size is reached, up to 100 events per request
- Error transparency — exceptions are always re-thrown; telemetry capture never swallows errors
- Auto page-unload flush —
beforeunloadtriggersdestroy()automatically so in-flight events are not lost
