1+ import { nanoid } from 'nanoid' ;
2+ import { ClientError , ErrorCode } from './lib/ClientError' ;
13import {
2- ClientError ,
4+ ClientMetricMeasurement ,
35 DEFAULT_ANAM_API_VERSION ,
46 DEFAULT_ANAM_METRICS_BASE_URL ,
5- ErrorCode ,
6- setErrorMetricsBaseUrl ,
7- setCurrentSessionInfo ,
8- } from './lib/ClientError ' ;
7+ setClientMetricsBaseUrl ,
8+ sendClientMetric ,
9+ setMetricsContext ,
10+ } from './lib/ClientMetrics ' ;
911import {
1012 CoreApiRestClient ,
1113 InternalEventEmitter ,
@@ -21,6 +23,7 @@ import {
2123 PersonaConfig ,
2224 StartSessionOptions ,
2325 StartSessionResponse ,
26+ ConnectionClosedCode ,
2427} from './types' ;
2528import { TalkMessageStream } from './types/TalkMessageStream' ;
2629import { Buffer } from 'buffer' ;
@@ -64,7 +67,7 @@ export default class AnamClient {
6467 this . clientOptions = options ;
6568
6669 if ( options ?. api ?. baseUrl || options ?. api ?. apiVersion ) {
67- setErrorMetricsBaseUrl (
70+ setClientMetricsBaseUrl (
6871 options . api . baseUrl || DEFAULT_ANAM_METRICS_BASE_URL ,
6972 options . api . apiVersion || DEFAULT_ANAM_API_VERSION ,
7073 ) ;
@@ -114,7 +117,9 @@ export default class AnamClient {
114117 if ( sessionToken ) {
115118 const decodedToken = this . decodeJwt ( sessionToken ) ;
116119 this . organizationId = decodedToken . accountId ;
117- setCurrentSessionInfo ( this . sessionId , this . organizationId ) ;
120+ setMetricsContext ( {
121+ organizationId : this . organizationId ,
122+ } ) ;
118123
119124 const tokenType = decodedToken . type ?. toLowerCase ( ) ;
120125
@@ -187,6 +192,11 @@ export default class AnamClient {
187192 const { heartbeatIntervalSeconds, maxWsReconnectionAttempts, iceServers } =
188193 clientConfig ;
189194
195+ this . sessionId = sessionId ;
196+ setMetricsContext ( {
197+ sessionId : this . sessionId ,
198+ } ) ;
199+
190200 try {
191201 this . streamingClient = new StreamingClient (
192202 sessionId ,
@@ -212,11 +222,22 @@ export default class AnamClient {
212222 audioDeviceId : this . clientOptions ?. audioDeviceId ,
213223 disableInputAudio : this . clientOptions ?. disableInputAudio ,
214224 } ,
225+ metrics : {
226+ showPeerConnectionStatsReport :
227+ this . clientOptions ?. metrics ?. showPeerConnectionStatsReport ??
228+ false ,
229+ peerConnectionStatsReportOutputFormat :
230+ this . clientOptions ?. metrics
231+ ?. peerConnectionStatsReportOutputFormat ?? 'console' ,
232+ } ,
215233 } ,
216234 this . publicEventEmitter ,
217235 this . internalEventEmitter ,
218236 ) ;
219237 } catch ( error ) {
238+ setMetricsContext ( {
239+ sessionId : null ,
240+ } ) ;
220241 throw new ClientError (
221242 'Failed to initialize streaming client' ,
222243 ErrorCode . CLIENT_ERROR_CODE_SERVER_ERROR ,
@@ -228,8 +249,6 @@ export default class AnamClient {
228249 ) ;
229250 }
230251
231- this . sessionId = sessionId ;
232- setCurrentSessionInfo ( this . sessionId , this . organizationId ) ;
233252 return sessionId ;
234253 }
235254
@@ -253,15 +272,26 @@ export default class AnamClient {
253272 public async stream (
254273 userProvidedAudioStream ?: MediaStream ,
255274 ) : Promise < MediaStream [ ] > {
275+ if ( this . _isStreaming ) {
276+ throw new Error ( 'Already streaming' ) ;
277+ }
278+ // generate a new ID here to track the attempt
279+ const attemptCorrelationId = nanoid ( ) ;
280+ setMetricsContext ( {
281+ attemptCorrelationId,
282+ sessionId : null , // reset sessionId
283+ } ) ;
284+ sendClientMetric (
285+ ClientMetricMeasurement . CLIENT_METRIC_MEASUREMENT_SESSION_ATTEMPT ,
286+ '1' ,
287+ ) ;
256288 if ( this . clientOptions ?. disableInputAudio && userProvidedAudioStream ) {
257289 console . warn (
258290 'AnamClient:Input audio is disabled. User provided audio stream will be ignored.' ,
259291 ) ;
260292 }
261293 await this . startSessionIfNeeded ( userProvidedAudioStream ) ;
262- if ( this . _isStreaming ) {
263- throw new Error ( 'Already streaming' ) ;
264- }
294+
265295 this . _isStreaming = true ;
266296 return new Promise < MediaStream [ ] > ( ( resolve ) => {
267297 // set stream callbacks to capture the stream
@@ -311,6 +341,16 @@ export default class AnamClient {
311341 videoElementId : string ,
312342 userProvidedAudioStream ?: MediaStream ,
313343 ) : Promise < void > {
344+ // generate a new ID here to track the attempt
345+ const attemptCorrelationId = nanoid ( ) ;
346+ setMetricsContext ( {
347+ attemptCorrelationId,
348+ sessionId : null , // reset sessionId
349+ } ) ;
350+ sendClientMetric (
351+ ClientMetricMeasurement . CLIENT_METRIC_MEASUREMENT_SESSION_ATTEMPT ,
352+ '1' ,
353+ ) ;
314354 if ( this . clientOptions ?. disableInputAudio && userProvidedAudioStream ) {
315355 console . warn (
316356 'AnamClient:Input audio is disabled. User provided audio stream will be ignored.' ,
@@ -371,10 +411,18 @@ export default class AnamClient {
371411
372412 public async stopStreaming ( ) : Promise < void > {
373413 if ( this . streamingClient ) {
374- this . streamingClient . stopConnection ( ) ;
414+ this . publicEventEmitter . emit (
415+ AnamEvent . CONNECTION_CLOSED ,
416+ ConnectionClosedCode . NORMAL ,
417+ ) ;
418+ await this . streamingClient . stopConnection ( ) ;
375419 this . streamingClient = null ;
376420 this . sessionId = null ;
377- setCurrentSessionInfo ( null , this . organizationId ) ;
421+ setMetricsContext ( {
422+ attemptCorrelationId : null ,
423+ sessionId : null ,
424+ organizationId : this . organizationId ,
425+ } ) ;
378426 this . _isStreaming = false ;
379427 }
380428 }
0 commit comments