Sfoglia il codice sorgente

feat: 添加sip注册时间和减小sip心跳到30s和收集sdk日志

余尚辉 1 mese fa
parent
commit
3af239d659
7 ha cambiato i file con 321 aggiunte e 84 eliminazioni
  1. 1 1
      rollup.config.js
  2. 96 1
      src/api/fetchApi.ts
  3. 74 74
      src/hs-cti/HsCTI-trash.ts
  4. 74 2
      src/hs-cti/HsCTI.ts
  5. 45 3
      src/hs-cti/HsSocket.ts
  6. 28 0
      src/hs-cti/tools.ts
  7. 3 3
      src/sdk.html

+ 1 - 1
rollup.config.js

@@ -146,7 +146,7 @@ export default [
         open: true, // 自动打开浏览器
         contentBase: ['dist', 'src'], // 包含 dist 和 src 作为静态资源的根目录
         host: '0.0.0.0', // 可以通过局域网访问
-        port: 8099, // 服务器运行端口
+        port: 8088, // 服务器运行端口
         openPage: '/sdk.html' // 直接打开的页面路径,src/sdk.html
       })
     ],

+ 96 - 1
src/api/fetchApi.ts

@@ -1,4 +1,6 @@
+import { TrackSource } from '../hs-cti/type'
 import { Logger } from '../Logger'
+import { getDateTime } from '../utils'
 import { getBaseOption, BaseOption } from '../hs-cti/storage'
 import type { CTIRes } from '../hs-cti/outputType'
 
@@ -34,6 +36,12 @@ export async function JPOST({ baseUrl, url, data }: Request): Promise<CTIRes> {
     apiLogger.error(
       `api response | ${url} | Request failed with status ${response.status}`
     )
+    serverTrack({
+      source: TrackSource.FeAPIError,
+      api_name: url,
+      ext: { req: data },
+      ...getBaseOption(BaseOption.TrackParams)
+    })
   }
 
   return response.json() as Promise<CTIRes>
@@ -55,16 +63,103 @@ export const hsTrackJPOST = ({
         url,
         data
       })
-      const { code } = res
+      const { code, msg } = res
+      const response = {
+        api_name: url,
+        ext: {
+          req: data,
+          res_code: code,
+          res_msg: msg
+        },
+        ...getBaseOption(BaseOption.TrackParams)
+      }
       if (code === 0) {
         apiLogger.log(`api response | ${url} | ${JSON.stringify(res)}`)
+        serverTrack({ source: TrackSource.FeAPI, ...response })
       } else {
         apiLogger.error(`api response | ${url} | ${JSON.stringify(res)}`)
+        serverTrack({ source: TrackSource.FeAPIError, ...response })
       }
       resolve(res)
     } catch (e) {
+      serverTrack({
+        source: TrackSource.FeAPIError,
+        api_name: url,
+        ...getBaseOption(BaseOption.TrackParams)
+      })
       apiLogger.error(`api response | ${url} | ${JSON.stringify(e)}`)
       reject(e)
     }
   })
 }
+
+// export const serverTrack = (ext: object) => {
+//   const env = getBaseOption(BaseOption.ENV)
+//   const isDev = env === 'development'
+//   if (isDev) return
+//   try {
+//     const params = `?biz=cti&userTagType=userid&userTag=0&metaVersion=1.0.0&event=cti_event`
+//     JPOST({
+//       baseUrl:
+//         getBaseOption(BaseOption.ENV) == 'production'
+//           ? `https://${window.DOMAINNAME}/fs_api`
+//           : 'http://pbx.fuxicarbon.com',
+//       url: `/jmstrack${params}`,
+//       data: { ...ext, event_time: getDateTime(), env }
+//     })
+//   } catch (e) {
+//     apiLogger.error(`server track error | ${JSON.stringify(e)}`)
+//   }
+// }
+// const trackingImg = new Image()
+
+// export const serverTrack = (ext: object) => {
+//   const env = getBaseOption(BaseOption.ENV)
+//   if (env === 'development') return
+
+//   try {
+//     // 将埋点参数转换为 URL 查询字符串
+//     const params = new URLSearchParams({
+//       biz: 'cti',
+//       userTagType: 'userid',
+//       userTag: '0',
+//       metaVersion: '1.0.0',
+//       event: 'cti_event',
+//       event_time: getDateTime(),
+//       env,
+//       ...Object.fromEntries(
+//         Object.entries(ext).map(([key, value]) => [key, String(value)])
+//       )
+//     }).toString()
+
+//     // 计算埋点 URL
+//     const trackingUrl =
+//       getBaseOption(BaseOption.ENV) === 'production'
+//         ? `https://${window.DOMAINNAME}/open/agent/sdkAnalytics?${params}`
+//         : `https://pbx.fuxicarbon.com/open/agent/sdkAnalytics?${params}`
+
+//     // 直接更新全局 Image 对象的 src,无需操作 DOM
+//     // trackingImg.src = trackingUrl
+//   } catch (e) {
+//     apiLogger.error(`server track error | ${JSON.stringify(e)}`)
+//   }
+// }
+
+export const serverTrack = (ext: object) => {
+  const env = getBaseOption(BaseOption.ENV)
+  const isDev = env === 'development'
+  if (isDev) return
+  try {
+    const params = `?biz=cti&userTagType=userid&userTag=0&metaVersion=1.0.0&event=cti_event`
+    JPOST({
+      baseUrl:
+        getBaseOption(BaseOption.ENV) === 'production'
+          ? `https://${window.DOMAINNAME}/fs_api`
+          : 'http://pbx.fuxicarbon.com:8090',
+      url: `/open/agent/sdkAnalytics${params}`,
+      data: { ...ext, event_time: getDateTime(), env }
+    })
+  } catch (e) {
+    apiLogger.error(`server track error | ${JSON.stringify(e)}`)
+  }
+}

+ 74 - 74
src/hs-cti/HsCTI-trash.ts

@@ -48,7 +48,7 @@ import {
   type SIPStatusChangeParams,
   type CTIEventParams,
   AudioName,
-  // TrackSource,
+  TrackSource,
   SocketEvent,
   ExceptMessage
 } from './type'
@@ -71,12 +71,12 @@ import type {
   CTIManualCallOptions,
   InitOptions
 } from '../api/hs-cti/ctiSdkModel'
-// import { serverTrack } from '../api/fetchApi'
+import { serverTrack } from '../api/fetchApi'
 import {
   setBaseOption,
   resetBaseOption,
-  BaseOption
-  // getBaseOption
+  BaseOption,
+  getBaseOption
 } from './storage'
 /**
  * 本地提示音
@@ -324,12 +324,12 @@ export class SdCTI extends EventEmitter {
 
     this._socket.on(SocketEvent.SocketDownEvent, ({ eventData }) => {
       const { eventName, ext } = eventData
-      // serverTrack({
-      //   ...getBaseOption(BaseOption.TrackParams),
-      //   source: TrackSource.FeIMDown,
-      //   event_name: eventName,
-      //   ext
-      // })
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        event_name: eventName,
+        ext
+      })
       this.logger.log(
         `socket server down | ${eventName} | ${JSON.stringify(ext)}`
       )
@@ -357,15 +357,15 @@ export class SdCTI extends EventEmitter {
       this.logger.error(
         `cti_flow_id | 不一致! fe: ${ctiFlowId}, server: ${extCtiFlowId}, eventName: ${eventName}`
       )
-      // serverTrack({
-      //   ...getBaseOption(BaseOption.TrackParams),
-      //   source: TrackSource.FeIMDown,
-      //   event_name: 'socket_down_cti_flow_id_diff',
-      //   ext: {
-      //     server_event_name: upperCamelToLowerSnake(eventName),
-      //     server_cti_flow_id: extCtiFlowId
-      //   }
-      // })
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        event_name: 'socket_down_cti_flow_id_diff',
+        ext: {
+          server_event_name: upperCamelToLowerSnake(eventName),
+          server_cti_flow_id: extCtiFlowId
+        }
+      })
       return
     }
 
@@ -384,13 +384,13 @@ export class SdCTI extends EventEmitter {
     error?: string | object
   ) {
     this.logger.debug(`sdk emit | ${eventName} | ${JSON.stringify(ext)}`)
-    // serverTrack({
-    //   ...getBaseOption(BaseOption.TrackParams),
-    //   source: TrackSource.FeEmit,
-    //   event_name: eventName,
-    //   ext,
-    //   error
-    // })
+    serverTrack({
+      ...getBaseOption(BaseOption.TrackParams),
+      source: TrackSource.FeEmit,
+      event_name: eventName,
+      ext,
+      error
+    })
     try {
       this.emit(eventName, ext)
       console.log(error)
@@ -579,15 +579,15 @@ export class SdCTI extends EventEmitter {
         this._sipUserAgent!.transport.disconnect()
         console.log(res)
         // 报告链接错误,上报错误
-        // serverTrack({
-        //   ...getBaseOption(BaseOption.TrackParams),
-        //   source: TrackSource.FeSIP,
-        //   event_name: CTIEvent.OnCtiError,
-        //   msg: 'sip_heart_beat_err',
-        //   method: 'optionsPingRun',
-        //   code: HskTerminatedCode.SipHeartBeatErr,
-        //   error: `${JSON.stringify(res)}`
-        // })
+        serverTrack({
+          ...getBaseOption(BaseOption.TrackParams),
+          source: TrackSource.FeSIP,
+          event_name: CTIEvent.OnCtiError,
+          msg: 'sip_heart_beat_err',
+          method: 'optionsPingRun',
+          code: HskTerminatedCode.SipHeartBeatErr,
+          error: `${JSON.stringify(res)}`
+        })
         // this.logger.error('heartbeat' + res?.message.statusCode)
       }
 
@@ -652,11 +652,11 @@ export class SdCTI extends EventEmitter {
     this._sipRegisterer.stateChange.addListener((newState: RegistererState) => {
       const state = `sip_registerer_state_${upperCamelToLowerSnake(newState)}`
       this.logger.debug(state)
-      // serverTrack({
-      //   ...getBaseOption(BaseOption.TrackParams),
-      //   source: TrackSource.FeSIP,
-      //   event_name: state
-      // })
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeSIP,
+        event_name: state
+      })
       switch (newState) {
         case RegistererState.Registered:
           this.setSipStatus({ status: SIPStatus.Ready })
@@ -754,11 +754,11 @@ export class SdCTI extends EventEmitter {
     })
     const trackName = `sip_session_state_${upperCamelToLowerSnake(status)}`
     this.logger.log(trackName)
-    // serverTrack({
-    //   ...getBaseOption(BaseOption.TrackParams),
-    //   source: TrackSource.FeSIP,
-    //   event_name: trackName
-    // })
+    serverTrack({
+      ...getBaseOption(BaseOption.TrackParams),
+      source: TrackSource.FeSIP,
+      event_name: trackName
+    })
   }
   /**
    * @private register的事件接收器,例如register动作是否成功
@@ -829,15 +829,15 @@ export class SdCTI extends EventEmitter {
           self.scene === Scene.Manual &&
           ctiFlowId !== self._baseParams.ctiFlowId
         ) {
-          // serverTrack({
-          //   ...getBaseOption(BaseOption.TrackParams),
-          //   source: TrackSource.FeSIP,
-          //   event_name: 'sip_cti_flow_id_diff',
-          //   ext: {
-          //     server_cti_flow_id: ctiFlowId,
-          //     call_id: callId
-          //   }
-          // })
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: TrackSource.FeSIP,
+            event_name: 'sip_cti_flow_id_diff',
+            ext: {
+              server_cti_flow_id: ctiFlowId,
+              call_id: callId
+            }
+          })
           self.logger.error(
             `cti_flow_id 不一致! fe: ${self._baseParams.ctiFlowId} | P-LIBRA-CtiFlowId: ${ctiFlowId}`
           )
@@ -1030,11 +1030,11 @@ export class SdCTI extends EventEmitter {
         this.clearSocketAndSip()
       }
     } else {
-      // serverTrack({
-      //   ...getBaseOption(BaseOption.TrackParams),
-      //   source: TrackSource.FeStatus,
-      //   event_name: `socket_status_${upperCamelToLowerSnake(status)}`
-      // })
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeStatus,
+        event_name: `socket_status_${upperCamelToLowerSnake(status)}`
+      })
     }
   }
   /**
@@ -1072,11 +1072,11 @@ export class SdCTI extends EventEmitter {
       )
       this.clearSocketAndSip()
     } else {
-      // serverTrack({
-      //   ...getBaseOption(BaseOption.TrackParams),
-      //   source: TrackSource.FeStatus,
-      //   event_name: `sip_status_${upperCamelToLowerSnake(status)}`
-      // })
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeStatus,
+        event_name: `sip_status_${upperCamelToLowerSnake(status)}`
+      })
     }
   }
   /**
@@ -1295,11 +1295,11 @@ export class SdCTI extends EventEmitter {
             data: 'answer',
             msg: 'SIP 接起电话成功'
           })
-          // serverTrack({
-          //   ...getBaseOption(BaseOption.TrackParams),
-          //   source: TrackSource.FeSIP,
-          //   event_name: 'sip_accept_success'
-          // })
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: TrackSource.FeSIP,
+            event_name: 'sip_accept_success'
+          })
           this.logger.debug('sip_accept_success')
         })
         .catch(err => {
@@ -1331,11 +1331,11 @@ export class SdCTI extends EventEmitter {
             data: 'bye',
             msg: 'SIP 挂断电话成功'
           })
-          // serverTrack({
-          //   ...getBaseOption(BaseOption.TrackParams),
-          //   source: TrackSource.FeSIP,
-          //   event_name: 'sip_bye_success'
-          // })
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: TrackSource.FeSIP,
+            event_name: 'sip_bye_success'
+          })
           this.logger.debug('sip_bye_success')
         })
         .catch(err => {

+ 74 - 2
src/hs-cti/HsCTI.ts

@@ -25,6 +25,7 @@ import {
   setBaseOption,
   resetBaseOption,
   BaseOption,
+  getBaseOption,
   getClientId
 } from './storage'
 import {
@@ -32,12 +33,13 @@ import {
   ExceptMessage,
   type SIPStatusChangeParams,
   type SocketStatusChangeParams,
+  TrackSource,
   SocketEvent,
   CTIEventParams,
   SimpleUserPlusDelegate,
   SimpleUserPlusOptions
 } from './type'
-
+import { serverTrack } from '../api/fetchApi'
 import { upperCamelToLowerSnake } from '@/utils'
 import {
   agentCheckIn,
@@ -225,6 +227,7 @@ export class HsCTI extends EventEmitter {
     switch (this.scene) {
       case Scene.Robot:
       case Scene.Monitor:
+        // 播放响铃放到业务前端
         this.stopAudio(AudioName.RingAudio, true)
         break
       case Scene.Manual:
@@ -276,7 +279,7 @@ export class HsCTI extends EventEmitter {
       // IM 重试次数
       imRetryCount: 3,
       // FS 心跳间隔
-      fsHeartTime: 60,
+      fsHeartTime: 30,
       // FS 重试次数,
       fsRetryCount: 3,
       // FS 重试间隔时间
@@ -326,6 +329,12 @@ export class HsCTI extends EventEmitter {
     })
     this._socket.on(SocketEvent.SocketDownEvent, ({ eventData }) => {
       const { eventName, ext } = eventData
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        event_name: eventName,
+        ext
+      })
       this.logger.log(
         `socket server down | ${eventName} | ${JSON.stringify(ext)}`
       )
@@ -353,6 +362,15 @@ export class HsCTI extends EventEmitter {
       this.logger.error(
         `cti_flow_id | 不一致! fe: ${ctiFlowId}, server: ${extCtiFlowId}, eventName: ${eventName}`
       )
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        event_name: 'socket_down_cti_flow_id_diff',
+        ext: {
+          server_event_name: upperCamelToLowerSnake(eventName),
+          server_cti_flow_id: extCtiFlowId
+        }
+      })
       return
     }
 
@@ -403,6 +421,9 @@ export class HsCTI extends EventEmitter {
       reconnectionAttempts: initOptions.fsRetryCount,
       reconnectionDelay: initOptions.fsRetryTime,
       optionsPingInterval: initOptions.fsHeartTime,
+      registererOptions: {
+        expires: initOptions.fsRegisterExpireTime
+      },
       media: {
         remote: {
           audio: this._remoteAudio
@@ -506,6 +527,7 @@ export class HsCTI extends EventEmitter {
           call_id: callId
         })
         this.sessionStateChangeAndTrack(invitation.state)
+        // 播放响铃放到业务前端
         if ([Scene.Robot, Scene.Monitor].includes(this.scene)) {
           this.playAudio(AudioName.RingAudio)
         }
@@ -573,6 +595,11 @@ export class HsCTI extends EventEmitter {
     })
     const trackName = `sip_session_state_${upperCamelToLowerSnake(status)}`
     this.logger.log(trackName)
+    serverTrack({
+      ...getBaseOption(BaseOption.TrackParams),
+      source: TrackSource.FeSIP,
+      event_name: trackName
+    })
   }
 
   /**
@@ -639,6 +666,12 @@ export class HsCTI extends EventEmitter {
         }
       )
       this.clearSocketAndSip()
+    } else {
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeStatus,
+        event_name: `socket_status_${upperCamelToLowerSnake(status)}`
+      })
     }
   }
 
@@ -677,6 +710,12 @@ export class HsCTI extends EventEmitter {
         }
       )
       this.clearSocketAndSip()
+    } else {
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeStatus,
+        event_name: `sip_status_${upperCamelToLowerSnake(status)}`
+      })
     }
   }
 
@@ -722,6 +761,13 @@ export class HsCTI extends EventEmitter {
     if (eventName === CTIEvent.OnCtiError) {
       this._callStatus = CallStatus.Stopped
     }
+    serverTrack({
+      ...getBaseOption(BaseOption.TrackParams),
+      source: TrackSource.FeEmit,
+      event_name: eventName,
+      ext,
+      error
+    })
     try {
       this.emit(eventName, ext)
       console.log(error)
@@ -792,6 +838,11 @@ export class HsCTI extends EventEmitter {
     this._baseParams.scene = Scene.Manual
     // 如果当前通话状态处于外呼开始,则不允许再次调用此方法并上报埋点
     if (this._callStatus === CallStatus.Started) {
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeMethod,
+        event_name: 'call_repeat'
+      })
       return
     }
     this._callStatus = CallStatus.Started
@@ -844,6 +895,11 @@ export class HsCTI extends EventEmitter {
             data: 'answer',
             msg: 'SIP 接起电话成功'
           })
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: TrackSource.FeSIP,
+            event_name: 'sip_answer_success'
+          })
           this.logger.debug('sip_accept_success')
         })
         .catch(err => {
@@ -875,6 +931,11 @@ export class HsCTI extends EventEmitter {
             data: 'bye',
             msg: 'SIP 挂断电话成功'
           })
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: TrackSource.FeSIP,
+            event_name: 'sip_bye_success'
+          })
           this.logger.debug('sip_bye_success')
         })
         .catch(err => {
@@ -887,6 +948,12 @@ export class HsCTI extends EventEmitter {
           reject(errorData)
           if (err.message !== 'Session does not exist.') {
             this.eventEmitAndTrack(CTIEvent.OnCtiError, errorData, `${err}`)
+          } else {
+            serverTrack({
+              ...getBaseOption(BaseOption.TrackParams),
+              source: TrackSource.FeMethod,
+              event_name: 'bye_no_sip_session'
+            })
           }
           this.logger.error(`${CTIEvent.OnCtiError} | ${err}`)
         })
@@ -963,6 +1030,11 @@ export class HsCTI extends EventEmitter {
 
   /** @public unInit 卸载 SDK,checkOut 成功后断开 socket 和 sip 连接,并销毁 SdCTI 实例 */
   public async unInit() {
+    serverTrack({
+      ...getBaseOption(BaseOption.TrackParams),
+      source: TrackSource.FeMethod,
+      event_name: 'sdk_un_init'
+    })
     await this.checkOut()
     this.setCTIStatus(CTIStatus.Terminated)
     this.initInstanceOptions()

+ 45 - 3
src/hs-cti/HsSocket.ts

@@ -1,9 +1,10 @@
 import io from 'socket.io-client'
-import { setBaseOption, BaseOption } from './storage'
-import { type SocketOptions, SocketEvent } from './type'
-import { SocketStatus, HskTerminatedCode } from './outputType'
+import { setBaseOption, BaseOption, getBaseOption } from './storage'
+import { type SocketOptions, SocketEvent, TrackSource } from './type'
+import { SocketStatus, HskTerminatedCode, CTIErrorType } from './outputType'
 import EventEmitter from '../eventemitter'
 import { Logger } from '../Logger'
+import { serverTrack } from '../api/fetchApi'
 
 class HsSocket extends EventEmitter {
   private logger: Logger
@@ -65,13 +66,34 @@ class HsSocket extends EventEmitter {
 
     /** https://socket.io/docs/v2/client-api/#event-error */
     this.socket.on('error', (error: object) => {
+      const errorMessage = `socket_error | ${JSON.stringify(error)}`
       this.logger.error(`socket_error | ${JSON.stringify(error)}`)
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        ext: {
+          type: CTIErrorType.SdkError,
+          code: HskTerminatedCode.SocketOnError
+        },
+        event_name: 'socket_error',
+        error: errorMessage
+      })
     })
 
     /** https://socket.io/docs/v2/client-api/#event-connect_error-1 */
     this.socket.on('connect_error', (error: object) => {
       const errorData = `socket_connect_error | ${JSON.stringify(error)}`
       this.logger.warn(errorData)
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeIMDown,
+        event_name: 'socket_connect_error',
+        ext: {
+          type: CTIErrorType.SdkError,
+          code: HskTerminatedCode.SocketOnConnectError
+        },
+        error: errorData
+      })
     })
 
     this.socket.on('reconnecting', (res: string) => {
@@ -108,6 +130,16 @@ class HsSocket extends EventEmitter {
     /** https://socket.io/docs/v2/client-api/#event-disconnect */
     this.socket.on('disconnect', (reason: string) => {
       const errorMessage = `socket_disconnect | ${reason}`
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        event_name: 'socket_disconnect',
+        source: TrackSource.FeIMDown,
+        ext: {
+          type: CTIErrorType.SdkError,
+          code: HskTerminatedCode.SocketOnDisconnect
+        },
+        error: errorMessage
+      })
       this.logger.warn(errorMessage)
     })
 
@@ -204,6 +236,11 @@ class HsSocket extends EventEmitter {
 
   /** @private sendHeartbeat 客户端上行心跳事件 */
   private sendHeartbeat() {
+    // serverTrack({
+    //   ...getBaseOption(BaseOption.TrackParams),
+    //   source: 'fe-heartbeat',
+    //   event_name: 'im_heartbeat_emit'
+    // })
     this.socket &&
       this.socket.emit(
         'heartbeat',
@@ -211,6 +248,11 @@ class HsSocket extends EventEmitter {
           ...this.socketOptions
         }),
         () => {
+          serverTrack({
+            ...getBaseOption(BaseOption.TrackParams),
+            source: 'fe-heartbeat',
+            event_name: 'im_heartbeat_ok'
+          })
           this.startHeartbeat()
         }
       )

+ 28 - 0
src/hs-cti/tools.ts

@@ -16,6 +16,8 @@ import {
   Scene,
   SdkErrorCode
 } from './outputType'
+import { serverTrack } from '../api/fetchApi'
+import { getBaseOption, BaseOption } from './storage'
 
 /**
  * @function getServerErrorType 根据服务端返回的 code 生成错误类型
@@ -34,6 +36,11 @@ export function getUserMedia() {
     const originalMethod = descriptor.value
 
     descriptor.value = function (...args: unknown[]) {
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeMedia,
+        event_name: 'get_user_media_start'
+      })
       if (
         navigator &&
         navigator.mediaDevices &&
@@ -45,6 +52,11 @@ export function getUserMedia() {
             video: false
           })
           .then(() => {
+            serverTrack({
+              ...getBaseOption(BaseOption.TrackParams),
+              source: TrackSource.FeMedia,
+              event_name: 'get_user_media_success'
+            })
             this.logger.debug('media | getUserMedia | 获取浏览器媒体权限成功')
 
             return originalMethod.apply(this, args)
@@ -103,6 +115,12 @@ export function getUserMedia() {
 function assignStreamError(type: string, error: Error, logger: Logger) {
   const err = `Failed to ${type} media: ${error}`
   logger.error(err)
+  serverTrack({
+    ...getBaseOption(BaseOption.TrackParams),
+    source: TrackSource.FeMedia,
+    event_name: 'assign_stream_remote_audio_error',
+    error: err
+  })
 }
 
 /**
@@ -120,6 +138,11 @@ export function assignStream(
   element.autoplay = true
   element.srcObject = stream
 
+  serverTrack({
+    ...getBaseOption(BaseOption.TrackParams),
+    source: TrackSource.FeMedia,
+    event_name: 'assign_stream_remote_audio'
+  })
   logger.log(`media | 把语音流接入到本地播放`)
 
   /** Load and start playback of media. */
@@ -155,6 +178,11 @@ export function checkCTIStatus(msg: string) {
 
     descriptor.value = function (...args: unknown[]) {
       /** 调用 SDK method */
+      serverTrack({
+        ...getBaseOption(BaseOption.TrackParams),
+        source: TrackSource.FeMethod,
+        event_name: methodName
+      })
       this.logger.log(`sdk method | ${methodName} | ${msg}`)
 
       /** 校验 CTIStatus, 如果不是 Ready 状态,直接报错 */

+ 3 - 3
src/sdk.html

@@ -8,8 +8,8 @@
   <meta name="description" content="JsSIP based example web application." />
 
   <!-- <script src="https://static.fuxicarbon.com/hs-cti/socket.io.min.js"></script> -->
-  <script src="http://static.fuxicarbon.com/hs-cti/socket.io.min.js"></script>
-  <script src="http://static.fuxicarbon.com/hs-cti/SIP.min.js"></script>
+  <script src="https://static.fuxicarbon.com/hs-cti/socket.io.min.js"></script>
+  <script src="https://static.fuxicarbon.com/hs-cti/SIP.min.js"></script>
   <script src="hs-cti.es6.umd.js"></script>
 
   <style type="text/css">
@@ -32,7 +32,7 @@
 const { Scene, getInstance, LoggerLevels } = window.HS_CTI
 const HS_CTI = getInstance({
     // 真实的坐席 ID
-    agent_id:'1103',
+    agent_id:'1108',
     // 目前每个业务线写死一个值,用于业务线区分
     saas_id: 'mdj',
     // 目前每个业务线写死,用于后端鉴权,前端仅透传