Commit 69b5a398 by 万齐军

rtc埋点

parent 698a04c6
...@@ -43,4 +43,6 @@ interface IAudioImService : IProvider{ ...@@ -43,4 +43,6 @@ interface IAudioImService : IProvider{
fun initRtcNetQuality() fun initRtcNetQuality()
fun initAgoraRtc(context: Context) fun initAgoraRtc(context: Context)
fun reportCallEvent(type: String, name: String, desc: String, retCode: Int?)
} }
\ No newline at end of file
...@@ -30,7 +30,9 @@ import com.hjq.permissions.XXPermissions ...@@ -30,7 +30,9 @@ import com.hjq.permissions.XXPermissions
import com.ydl.audioim.bean.AgoraInvitationBean import com.ydl.audioim.bean.AgoraInvitationBean
import com.ydl.audioim.bean.AgoraLogInfoBean import com.ydl.audioim.bean.AgoraLogInfoBean
import com.ydl.audioim.contract.IAudioHomeActivityContract import com.ydl.audioim.contract.IAudioHomeActivityContract
import com.ydl.audioim.http.AudioApiRequestUtil
import com.ydl.audioim.http.AudioNetAPi import com.ydl.audioim.http.AudioNetAPi
import com.ydl.audioim.http.RtcEvent
import com.ydl.audioim.http.command.ConnectCommand import com.ydl.audioim.http.command.ConnectCommand
import com.ydl.audioim.http.command.ConnectExceptionCommand import com.ydl.audioim.http.command.ConnectExceptionCommand
import com.ydl.audioim.http.command.NoticePushCommand import com.ydl.audioim.http.command.NoticePushCommand
...@@ -339,6 +341,7 @@ class AudioHomeActivity : ...@@ -339,6 +341,7 @@ class AudioHomeActivity :
return return
} }
Apm.reportEvent("agora_android", "occur_error", "$err") Apm.reportEvent("agora_android", "occur_error", "$err")
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.errorOccurred), errorCode = err)
channelId?.let { YDLavManager.instances.callEndStatusUpdate(it, 60, "频道错误回调$err") } channelId?.let { YDLavManager.instances.callEndStatusUpdate(it, 60, "频道错误回调$err") }
} }
...@@ -354,6 +357,7 @@ class AudioHomeActivity : ...@@ -354,6 +357,7 @@ class AudioHomeActivity :
super.onJoinChannelSuccess(channel, uid, elapsed) super.onJoinChannelSuccess(channel, uid, elapsed)
onMeJoined() onMeJoined()
callEventSave("20", "$uid 用户声网加入频道成功:channel=$channel") callEventSave("20", "$uid 用户声网加入频道成功:channel=$channel")
AudioApiRequestUtil.reportCallEvent(channel, RtcEvent(RtcEvent.Event.joinSuccess))
LogUtil.e("[agora]$uid 用户声网加入频道成功:channel=$channel") LogUtil.e("[agora]$uid 用户声网加入频道成功:channel=$channel")
AliYunRichLogsHelper.getInstance() AliYunRichLogsHelper.getInstance()
...@@ -403,6 +407,14 @@ class AudioHomeActivity : ...@@ -403,6 +407,14 @@ class AudioHomeActivity :
// } // }
} }
override fun onFirstLocalAudioFrame(elapsed: Int) {
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.localFirstFrame))
}
override fun onFirstRemoteAudioFrame(uid: Int, elapsed: Int) {
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.remoteFirstFrame))
}
/** /**
* https://docs.agora.io/cn/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler.html#a31b2974a574ec45e62bb768e17d1f49e * https://docs.agora.io/cn/Voice/API%20Reference/java/classio_1_1agora_1_1rtc_1_1_i_rtc_engine_event_handler.html#a31b2974a574ec45e62bb768e17d1f49e
* */ * */
...@@ -410,6 +422,11 @@ class AudioHomeActivity : ...@@ -410,6 +422,11 @@ class AudioHomeActivity :
super.onConnectionStateChanged(state, reason) super.onConnectionStateChanged(state, reason)
// 3 网络连接被服务器中止 该情况现在是因为后端踢人逻辑 // 3 网络连接被服务器中止 该情况现在是因为后端踢人逻辑
Apm.reportEvent("agora_android", "rtc_connection_failure", "$state,$reason") Apm.reportEvent("agora_android", "rtc_connection_failure", "$state,$reason")
AudioApiRequestUtil.reportCallEvent(
channelId,
RtcEvent(RtcEvent.Event.connectionChanged),
errorCode = state, errorReason = reason.toString()
)
if (reason == 3) { if (reason == 3) {
callEventSave("50", "通话结束:网络连接被服务器中止 该情况现在是因为后端踢人逻辑,原因(${reason}") callEventSave("50", "通话结束:网络连接被服务器中止 该情况现在是因为后端踢人逻辑,原因(${reason}")
writeAgoraLog("通话结束:网络连接被服务器中止 该情况现在是因为后端踢人逻辑,原因(${reason})") writeAgoraLog("通话结束:网络连接被服务器中止 该情况现在是因为后端踢人逻辑,原因(${reason})")
...@@ -442,6 +459,7 @@ class AudioHomeActivity : ...@@ -442,6 +459,7 @@ class AudioHomeActivity :
callEventSave("20", "${uid}加入频道回调") callEventSave("20", "${uid}加入频道回调")
LogUtil.e("[agora]远端用户/主播加入频道回调") LogUtil.e("[agora]远端用户/主播加入频道回调")
onPeerJoined() onPeerJoined()
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.remoteJoin))
AliYunRichLogsHelper.getInstance() AliYunRichLogsHelper.getInstance()
.sendRichLog(AliYunLogConfig.AGORA, "远端用户/主播加入频道回调 channelId:${channelId}") .sendRichLog(AliYunLogConfig.AGORA, "远端用户/主播加入频道回调 channelId:${channelId}")
} }
...@@ -456,6 +474,7 @@ class AudioHomeActivity : ...@@ -456,6 +474,7 @@ class AudioHomeActivity :
.sendRichLog(AliYunLogConfig.AGORA, "接通后通话结束:对方已挂断 channelId:${channelId}") .sendRichLog(AliYunLogConfig.AGORA, "接通后通话结束:对方已挂断 channelId:${channelId}")
//通话结束或挂断时,上传日志文件 //通话结束或挂断时,上传日志文件
uploadLog() uploadLog()
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.remoteLeave))
showToast("专家已挂断") showToast("专家已挂断")
//UserOffLine之后,销毁界面,解决,userOffline有回调之后,onConnectionStateChanged(服务端踢人方法没有调),导致记录时长异常。 //UserOffLine之后,销毁界面,解决,userOffline有回调之后,onConnectionStateChanged(服务端踢人方法没有调),导致记录时长异常。
leaveChannel() leaveChannel()
...@@ -1102,6 +1121,8 @@ class AudioHomeActivity : ...@@ -1102,6 +1121,8 @@ class AudioHomeActivity :
voiceManage?.getVoiceApi()?.setAudioProfile(Constants.AUDIO_PROFILE_DEFAULT, Constants.AUDIO_SCENARIO_CHATROOM_GAMING) voiceManage?.getVoiceApi()?.setAudioProfile(Constants.AUDIO_PROFILE_DEFAULT, Constants.AUDIO_SCENARIO_CHATROOM_GAMING)
voiceManage?.attachNetQualityListener(NetQuality()) voiceManage?.attachNetQualityListener(NetQuality())
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.initSdk))
} }
/** /**
...@@ -1113,12 +1134,16 @@ class AudioHomeActivity : ...@@ -1113,12 +1134,16 @@ class AudioHomeActivity :
writeAgoraLog("对方(专家)接受了通话邀请,主叫(用户)开始加入频道:$channelId") writeAgoraLog("对方(专家)接受了通话邀请,主叫(用户)开始加入频道:$channelId")
AliYunRichLogsHelper.getInstance() AliYunRichLogsHelper.getInstance()
.sendRichLog(AliYunLogConfig.AGORA, "对方(专家)接受了通话邀请,主叫(用户)开始加入频道:$channelId") .sendRichLog(AliYunLogConfig.AGORA, "对方(专家)接受了通话邀请,主叫(用户)开始加入频道:$channelId")
voiceManage?.getVoiceApi()?.joinChannel( AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.join))
val joinCode = voiceManage?.getVoiceApi()?.joinChannel(
token!!, token!!,
channelId!!, channelId!!,
"Extra Optional Data", "Extra Optional Data",
YdlCommonRouterManager.getYdlCommonRoute().getUid() YdlCommonRouterManager.getYdlCommonRoute().getUid()
) )
if (joinCode != null && joinCode < 0) {
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.joinFail), retCode = joinCode)
}
} }
/** /**
...@@ -1489,6 +1514,7 @@ class AudioHomeActivity : ...@@ -1489,6 +1514,7 @@ class AudioHomeActivity :
playFinishMusic() playFinishMusic()
// 声网离开房间 // 声网离开房间
voiceManage?.getVoiceApi()?.playEffect(EFFECT_HANGUP, "res://raw/${R.raw.effect_hand_up}") voiceManage?.getVoiceApi()?.playEffect(EFFECT_HANGUP, "res://raw/${R.raw.effect_hand_up}")
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.leave))
voiceManage?.getVoiceApi()?.leaveChannel() voiceManage?.getVoiceApi()?.leaveChannel()
} }
} }
...@@ -1726,6 +1752,10 @@ class AudioHomeActivity : ...@@ -1726,6 +1752,10 @@ class AudioHomeActivity :
} }
override fun onNetworkTypeChanged(type: Int) {
AudioApiRequestUtil.reportCallEvent(channelId, RtcEvent(RtcEvent.Event.networkTypeChanged), retCode = type)
}
override fun onRemoteAudioFeel(frozenRate: Int, qoeQuality: Int, reason: Int, mos: Int) { override fun onRemoteAudioFeel(frozenRate: Int, qoeQuality: Int, reason: Int, mos: Int) {
XLog.i("NetQuality", "frozenRate:$frozenRate,qoeQuality:$qoeQuality,reason:$reason,mos:$mos") XLog.i("NetQuality", "frozenRate:$frozenRate,qoeQuality:$qoeQuality,reason:$reason,mos:$mos")
} }
......
...@@ -9,6 +9,7 @@ import com.apm.insight.log.VLog ...@@ -9,6 +9,7 @@ import com.apm.insight.log.VLog
import com.google.gson.Gson import com.google.gson.Gson
import com.ydl.audioim.bean.AgoraInvitationBean import com.ydl.audioim.bean.AgoraInvitationBean
import com.ydl.audioim.http.AudioApiRequestUtil import com.ydl.audioim.http.AudioApiRequestUtil
import com.ydl.audioim.http.IMEvent
import com.ydl.audioim.http.command.ConnectExceptionCommand import com.ydl.audioim.http.command.ConnectExceptionCommand
import com.ydl.audioim.router.AudioImIn import com.ydl.audioim.router.AudioImIn
import com.ydl.audioim.utils.AudioLogUtils import com.ydl.audioim.utils.AudioLogUtils
...@@ -24,6 +25,7 @@ import com.ydl.ydl_av.messge_service.callback.LoginCallback ...@@ -24,6 +25,7 @@ import com.ydl.ydl_av.messge_service.callback.LoginCallback
import com.ydl.ydl_av.messge_service.request.LoginParam import com.ydl.ydl_av.messge_service.request.LoginParam
import com.ydl.ydl_av.messge_service.response.CallLocalResponse import com.ydl.ydl_av.messge_service.response.CallLocalResponse
import com.ydl.ydl_av.messge_service.response.CallRemoteResponse import com.ydl.ydl_av.messge_service.response.CallRemoteResponse
import com.ydl.ydl_av.voice.manager.YDLVoiceManager
import com.ydl.ydlcommon.app.Apm import com.ydl.ydlcommon.app.Apm
import com.ydl.ydlcommon.modular.ModularServiceManager import com.ydl.ydlcommon.modular.ModularServiceManager
import com.ydl.ydlcommon.utils.ActivityManager import com.ydl.ydlcommon.utils.ActivityManager
...@@ -63,6 +65,8 @@ class YDLavManager { ...@@ -63,6 +65,8 @@ class YDLavManager {
YDLavManager() YDLavManager()
} }
const val AUDIO_NO_AUTH_ERROR_CODE = "97"//音频权限未通过错误码 const val AUDIO_NO_AUTH_ERROR_CODE = "97"//音频权限未通过错误码
var currentChannelId: String? = null
} }
...@@ -99,6 +103,7 @@ class YDLavManager { ...@@ -99,6 +103,7 @@ class YDLavManager {
AliYunLogConfig.AGORA, AliYunLogConfig.AGORA,
"${response?.calleeId}已收到呼叫邀请,频道号${response?.ChannelId}" "${response?.calleeId}已收到呼叫邀请,频道号${response?.ChannelId}"
) )
AudioApiRequestUtil.reportCallEvent(response?.ChannelId, IMEvent(IMEvent.Event.onPeerReceived))
val dimension = hashMapOf("call" to "call_received_by_peer") val dimension = hashMapOf("call" to "call_received_by_peer")
onConfideEvent(dimension, response?.ChannelId) onConfideEvent(dimension, response?.ChannelId)
...@@ -118,6 +123,8 @@ class YDLavManager { ...@@ -118,6 +123,8 @@ class YDLavManager {
AliYunLogConfig.AGORA, AliYunLogConfig.AGORA,
"${response?.calleeId}已接收呼叫邀请" "${response?.calleeId}已接收呼叫邀请"
) )
AudioApiRequestUtil.reportCallEvent(response?.ChannelId, IMEvent(IMEvent.Event.onPeerAccepted))
currentChannelId = response?.ChannelId
//加入声网频道时机修改:主叫收到被叫接受邀请的回调后再加入声网频道 //加入声网频道时机修改:主叫收到被叫接受邀请的回调后再加入声网频道
val act = ActivityManager.getInstance().getTopTaskActivity() val act = ActivityManager.getInstance().getTopTaskActivity()
if (act is AudioHomeActivity) { if (act is AudioHomeActivity) {
...@@ -135,6 +142,7 @@ class YDLavManager { ...@@ -135,6 +142,7 @@ class YDLavManager {
AliYunLogConfig.AGORA, AliYunLogConfig.AGORA,
"${response?.calleeId}已拒绝呼叫邀请" "${response?.calleeId}已拒绝呼叫邀请"
) )
AudioApiRequestUtil.reportCallEvent(response?.ChannelId, IMEvent(IMEvent.Event.onPeerRejected))
val dimension = hashMapOf("call" to "call_refused") val dimension = hashMapOf("call" to "call_refused")
onConfideEvent(dimension, response?.ChannelId) onConfideEvent(dimension, response?.ChannelId)
val act = ActivityManager.getInstance().getTopTaskActivity() val act = ActivityManager.getInstance().getTopTaskActivity()
...@@ -161,13 +169,19 @@ class YDLavManager { ...@@ -161,13 +169,19 @@ class YDLavManager {
} }
} }
override fun onCallFailure(response: CallLocalResponse?, errorCode: Int) { override fun onCallFailure(response: CallLocalResponse?, errorCode: Int, errorMsg:String?) {
//返回给主叫 //返回给主叫
LogUtil.e("[agora]呼叫${response?.calleeId}用户失败:${response?.response}") LogUtil.e("[agora]呼叫${response?.calleeId}用户失败:${response?.response}")
AliYunRichLogsHelper.getInstance().sendRichLog( AliYunRichLogsHelper.getInstance().sendRichLog(
AliYunLogConfig.AGORA, AliYunLogConfig.AGORA,
"呼叫${response?.calleeId}用户失败:${response?.response},${errorCode}" "呼叫${response?.calleeId}用户失败:${response?.response},${errorCode}"
) )
AudioApiRequestUtil.reportCallEvent(
response?.ChannelId,
IMEvent(IMEvent.Event.callFail),
errorCode = errorCode,
errorReason = errorMsg
)
val dimension = hashMapOf( val dimension = hashMapOf(
"call" to "call_fail", "call" to "call_fail",
"call_fail" to "code${errorCode}" "call_fail" to "code${errorCode}"
...@@ -280,39 +294,15 @@ class YDLavManager { ...@@ -280,39 +294,15 @@ class YDLavManager {
closePage() closePage()
} }
override fun onOtherMsg(error: String?) { override fun onCallSuccess(response: CallLocalResponse?) {
LogUtil.e("[agora]其它消息:${error}") AudioApiRequestUtil.reportCallEvent(response?.ChannelId, IMEvent(IMEvent.Event.callSuccess))
if (error.equals("呼叫发送成功")) {
writeAgoraLog(
"声网发送通话邀请成功-------Time:${AudioLogUtils.format.format(Calendar.getInstance().time)}",
"confide.log",
true
)
AliYunRichLogsHelper.getInstance().sendRichLog(
AliYunLogConfig.AGORA,
"声网发送通话邀请成功"
)
} else {
writeAgoraLog(
"声网发送通话邀请失败${error}-------Time:${
AudioLogUtils.format.format(
Calendar.getInstance().time
)
}", "confide.log", true
)
LogHelper.getInstance().uploadLog(false)
AliYunRichLogsHelper.getInstance().sendRichLog(
AliYunLogConfig.AGORA,
"声网发送通话邀请失败${error}"
)
}
} }
}) })
} }
fun rtcCall(listenerUid: String?, channelId: String?, sendDoctocrMsg: String?) { fun rtcCall(listenerUid: String?, channelId: String?, sendDoctocrMsg: String?) {
YDLRTMClient.instances.call(listenerUid, channelId, sendDoctocrMsg) YDLRTMClient.instances.call(listenerUid, channelId, sendDoctocrMsg)
AudioApiRequestUtil.reportCallEvent(channelId, IMEvent(IMEvent.Event.startCall))
sendCustomNotification(listenerUid!!, sendDoctocrMsg!!, "1") sendCustomNotification(listenerUid!!, sendDoctocrMsg!!, "1")
} }
...@@ -346,6 +336,7 @@ class YDLavManager { ...@@ -346,6 +336,7 @@ class YDLavManager {
}) })
callEndStatusUpdate(channelId, 1, "主叫取消呼叫") callEndStatusUpdate(channelId, 1, "主叫取消呼叫")
AudioApiRequestUtil.reportCallEvent(channelId, IMEvent(IMEvent.Event.callCancel))
sendCustomNotification(listenerUid, data, "3") sendCustomNotification(listenerUid, data, "3")
} }
...@@ -412,11 +403,13 @@ class YDLavManager { ...@@ -412,11 +403,13 @@ class YDLavManager {
.observeOn(AndroidSchedulers.mainThread()).subscribe({ .observeOn(AndroidSchedulers.mainThread()).subscribe({
if ("200" == it.code) { if ("200" == it.code) {
LogUtil.e("[agora]登录av的login-uid:$userId") LogUtil.e("[agora]登录av的login-uid:$userId")
AudioApiRequestUtil.reportCallEvent(YDLVoiceManager.currentChannel, IMEvent(IMEvent.Event.rtmLogin))
YDLRTMClient.instances.login( YDLRTMClient.instances.login(
LoginParam(userId, it.data.token), LoginParam(userId, it.data.token),
object : LoginCallback { object : LoginCallback {
override fun onSuccess() { override fun onSuccess() {
//登陆成功,发起呼叫 //登陆成功,发起呼叫
AudioApiRequestUtil.reportCallEvent(YDLVoiceManager.currentChannel, IMEvent(IMEvent.Event.loginSuccess))
LogUtil.e("[agora]实时消息登录成功") LogUtil.e("[agora]实时消息登录成功")
AliYunRichLogsHelper.getInstance() AliYunRichLogsHelper.getInstance()
.sendRichLog(AliYunLogConfig.AGORA, "声网rtm登录成功,uid:$userId") .sendRichLog(AliYunLogConfig.AGORA, "声网rtm登录成功,uid:$userId")
...@@ -433,6 +426,8 @@ class YDLavManager { ...@@ -433,6 +426,8 @@ class YDLavManager {
override fun onFailure(msg: String?) { override fun onFailure(msg: String?) {
if (msg != "LOGIN_ERR_ALREADY_LOGGED_IN") { if (msg != "LOGIN_ERR_ALREADY_LOGGED_IN") {
Apm.reportEvent("rtm_android", "connectionstate_error", msg ?: "") Apm.reportEvent("rtm_android", "connectionstate_error", msg ?: "")
AudioApiRequestUtil.reportCallEvent(YDLVoiceManager.currentChannel, IMEvent(IMEvent.Event.loginFail), errorReason = msg)
} }
LogUtil.e("[agora]实时消息登录失败:$msg") LogUtil.e("[agora]实时消息登录失败:$msg")
writeAgoraLog( writeAgoraLog(
...@@ -556,6 +551,7 @@ class YDLavManager { ...@@ -556,6 +551,7 @@ class YDLavManager {
*/ */
private fun logout(isReLogin: Boolean) { private fun logout(isReLogin: Boolean) {
EventBus.getDefault().unregister(this) EventBus.getDefault().unregister(this)
AudioApiRequestUtil.reportCallEvent(YDLVoiceManager.currentChannel, IMEvent(IMEvent.Event.rtmLogout))
YDLRTMClient.instances.logout(object : LoginCallback { YDLRTMClient.instances.logout(object : LoginCallback {
override fun onSuccess() { override fun onSuccess() {
//退出登陆成功 //退出登陆成功
...@@ -654,6 +650,12 @@ class YDLavManager { ...@@ -654,6 +650,12 @@ class YDLavManager {
true true
) )
LogUtil.i("[agora]onConnectionStateChanged:state:${state} -->reason:$reason") LogUtil.i("[agora]onConnectionStateChanged:state:${state} -->reason:$reason")
AudioApiRequestUtil.reportCallEvent(
YDLVoiceManager.currentChannel,
IMEvent(IMEvent.Event.onlineStatusChange),
errorCode = state,
errorReason = reason.toString()
)
AliYunRichLogsHelper.getInstance() AliYunRichLogsHelper.getInstance()
.sendRichLog(AliYunLogConfig.AGORA, "声网rtm登录状态:${state}") .sendRichLog(AliYunLogConfig.AGORA, "声网rtm登录状态:${state}")
/* /*
......
...@@ -9,5 +9,6 @@ data class CallEventRequestBody( ...@@ -9,5 +9,6 @@ data class CallEventRequestBody(
var status: String, var status: String,
var response: String? = null, var response: String? = null,
var eventTime: String, var eventTime: String,
var remark: String? = null var remark: String? = null,
var eventType: String? = null
) )
package com.ydl.audioim.http package com.ydl.audioim.http
import androidx.annotation.IntDef
import com.google.gson.Gson import com.google.gson.Gson
import com.ydl.audioim.bean.AgoraTokenResponse import com.ydl.audioim.bean.AgoraTokenResponse
import com.ydl.audioim.bean.CallEventRequestBody import com.ydl.audioim.bean.CallEventRequestBody
...@@ -16,8 +17,10 @@ import com.ydl.ydlcommon.utils.NetworkParamsUtils ...@@ -16,8 +17,10 @@ import com.ydl.ydlcommon.utils.NetworkParamsUtils
import com.ydl.ydlcommon.utils.TimeUtil import com.ydl.ydlcommon.utils.TimeUtil
import com.ydl.ydlnet.YDLHttpUtils import com.ydl.ydlnet.YDLHttpUtils
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.RequestBody import okhttp3.RequestBody
import java.util.*
/** /**
* @author jiucheng * @author jiucheng
...@@ -111,16 +114,121 @@ class AudioApiRequestUtil { ...@@ -111,16 +114,121 @@ class AudioApiRequestUtil {
line: String, line: String,
status: String, status: String,
response: String?, response: String?,
remark: String? = null remark: String? = null,
eventType: String? = null
): Observable<BaseAPIResponse<Any>> { ): Observable<BaseAPIResponse<Any>> {
var eventTime = TimeUtil.getNowDatetime() val eventTime = TimeUtil.getNowDatetime()
var param = CallEventRequestBody(session, line, status, response, eventTime, remark); val param = CallEventRequestBody(session, line, status, response, eventTime, remark, eventType);
var str = Gson().toJson(param) val str = Gson().toJson(param)
val body = RequestBody.create( val body = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"), MediaType.parse("application/json; charset=utf-8"),
str str
) as RequestBody ) as RequestBody
return YDLHttpUtils.obtainApi(AudioNetAPi::class.java).callEventSave(body) return YDLHttpUtils.obtainApi(AudioNetAPi::class.java).callEventSave(body)
} }
fun reportCallEvent(
session: String?,
event: CallEvent,
retCode: Int? = null,
errorCode: Int? = null,
errorReason: String? = null,
@ReportLevel reportLevel: Int? = null
) {
if (session == null) return
val type = event.eventType.name.lowercase(Locale.getDefault())
val resp = hashMapOf<String, Any>(
"name" to event.name,
"desc" to event.desc,
"reportLevel" to (reportLevel ?: event.reportLevel),
)
if (retCode != null) {
resp["retCode"] = retCode
}
if (errorCode != null) {
resp["errorCode"] = errorCode
}
if (errorReason != null) {
resp["errorReason"] = errorReason
}
val response = Gson().toJson(resp)
callEventSave(session, "7", "20", response, eventType = type).subscribeOn(Schedulers.io()).subscribe()
}
}
}
const val REPORT_LEVEL_INFO = 1
const val REPORT_LEVEL_WARN = 2
const val REPORT_LEVEL_ERROR = 3
enum class EventType {
RTC, IM, LOGIN, DEVICE
}
@IntDef(REPORT_LEVEL_INFO, REPORT_LEVEL_WARN, REPORT_LEVEL_ERROR)
@kotlin.annotation.Retention(AnnotationRetention.SOURCE)
annotation class ReportLevel
sealed class CallEvent(val eventType: EventType, val name: String, val desc: String, @ReportLevel val reportLevel: Int)
class RtcEvent(val event: Event) :
CallEvent(EventType.RTC, event.name.lowercase(Locale.getDefault()), event.desc, event.reportLevel) {
@Suppress("EnumEntryName")
enum class Event(val desc: String, @ReportLevel val reportLevel: Int) {
initSdk("初始化SDK", REPORT_LEVEL_WARN),
join("本地加入房间", REPORT_LEVEL_WARN),
joinSuccess("加入房间成功", REPORT_LEVEL_INFO),
joinFail("加入房间失败", REPORT_LEVEL_ERROR),
remoteJoin("远端加入房间", REPORT_LEVEL_WARN),
remoteJoinTimeout("远端加入超时", REPORT_LEVEL_WARN),
leave("本地离开房间", REPORT_LEVEL_WARN),
remoteLeave("远端离开房间", REPORT_LEVEL_WARN),
localFirstFrame("本地音频首帧", REPORT_LEVEL_WARN),
remoteFirstFrame("远端音频首帧", REPORT_LEVEL_WARN),
networkTypeChanged("网络变化", REPORT_LEVEL_WARN),
connectionChanged("连接状态变化", REPORT_LEVEL_WARN),
errorOccurred("错误发生", REPORT_LEVEL_ERROR),
} }
} }
\ No newline at end of file
class IMEvent(event: Event) : CallEvent(EventType.IM, event.name.lowercase(Locale.getDefault()), event.desc, event.reportLevel) {
@Suppress("EnumEntryName")
enum class Event(val desc: String, @ReportLevel val reportLevel: Int) {
rtmLogin("登录RTM", REPORT_LEVEL_INFO),
rtmLogout("登出RTM", REPORT_LEVEL_INFO),
loginSuccess("登录成功", REPORT_LEVEL_INFO),
loginFail("登录失败", REPORT_LEVEL_ERROR),
onlineStatusChange("在线状态变化", REPORT_LEVEL_WARN),
startCall("开始呼叫", REPORT_LEVEL_INFO),
onPeerReceived("到达对方", REPORT_LEVEL_INFO),
onPeerAccepted("对方已接受", REPORT_LEVEL_INFO),
onPeerRejected("对方已拒绝", REPORT_LEVEL_WARN),
callSuccess("呼叫成功", REPORT_LEVEL_INFO),
callFail("呼叫失败", REPORT_LEVEL_ERROR),
callCancel("呼叫取消", REPORT_LEVEL_WARN),
}
}
class LoginEvent(event: Event) :
CallEvent(EventType.LOGIN, event.name.lowercase(Locale.getDefault()), event.desc, event.reportLevel) {
@Suppress("EnumEntryName")
enum class Event(val desc: String, @ReportLevel val reportLevel: Int) {
userLogin("用户登录", REPORT_LEVEL_INFO),
userLogout("用户登出", REPORT_LEVEL_INFO),
userLoginSuccess("登录成功", REPORT_LEVEL_INFO),
userLoginFail("登录失败", REPORT_LEVEL_ERROR),
}
}
class DeviceEvent(event: Event) :
CallEvent(EventType.DEVICE, event.name.lowercase(Locale.getDefault()), event.desc, event.reportLevel) {
@Suppress("EnumEntryName")
enum class Event(val desc: String, @ReportLevel val reportLevel: Int) {
beForeground("回到前台", REPORT_LEVEL_INFO),
beBackground("进入后台", REPORT_LEVEL_WARN),
onTrimMemory("内存使用等级", REPORT_LEVEL_WARN),
onLowMemory("内存低", REPORT_LEVEL_WARN),
}
}
...@@ -5,10 +5,13 @@ import android.content.Context ...@@ -5,10 +5,13 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import com.alibaba.android.arouter.facade.annotation.Route import com.alibaba.android.arouter.facade.annotation.Route
import com.google.gson.Gson
import com.ydl.audioim.BuildConfig import com.ydl.audioim.BuildConfig
import com.ydl.audioim.YDLavManager import com.ydl.audioim.YDLavManager
import com.ydl.audioim.api.IAudioImService import com.ydl.audioim.api.IAudioImService
import com.ydl.audioim.http.AudioApiRequestUtil
import com.ydl.audioim.http.AudioNetAPi import com.ydl.audioim.http.AudioNetAPi
import com.ydl.audioim.http.REPORT_LEVEL_INFO
import com.ydl.audioim.widget.AxbConfirmDialog import com.ydl.audioim.widget.AxbConfirmDialog
import com.ydl.devicesidlib.DeviceIDHelper import com.ydl.devicesidlib.DeviceIDHelper
import com.ydl.ydl_av.voice.listener.RtcGlobalNet import com.ydl.ydl_av.voice.listener.RtcGlobalNet
...@@ -70,6 +73,20 @@ class AudioImServiceImp : IAudioImService { ...@@ -70,6 +73,20 @@ class AudioImServiceImp : IAudioImService {
YDLVoiceManager.init(context.applicationContext, BuildConfig.AGORA_APPID) YDLVoiceManager.init(context.applicationContext, BuildConfig.AGORA_APPID)
} }
override fun reportCallEvent(type: String, name: String, desc: String, retCode: Int?) {
val resp = hashMapOf<String, Any>(
"name" to name,
"desc" to desc,
"reportLevel" to REPORT_LEVEL_INFO
)
if (retCode != null) {
resp["retCode"] = retCode
}
val toJson = Gson().toJson(resp)
AudioApiRequestUtil.callEventSave(YDLVoiceManager.currentChannel, "7", "20", toJson, eventType = type)
}
override fun init(context: Context?) { override fun init(context: Context?) {
} }
......
...@@ -26,7 +26,9 @@ import com.google.gson.Gson ...@@ -26,7 +26,9 @@ import com.google.gson.Gson
import com.tbruyelle.rxpermissions2.RxPermissions import com.tbruyelle.rxpermissions2.RxPermissions
import com.ydl.audioim.R import com.ydl.audioim.R
import com.ydl.audioim.YDLavManager import com.ydl.audioim.YDLavManager
import com.ydl.audioim.http.AudioApiRequestUtil
import com.ydl.audioim.http.AudioNetAPi import com.ydl.audioim.http.AudioNetAPi
import com.ydl.audioim.http.RtcEvent
import com.ydl.audioim.http.command.ConnectExceptionCommand import com.ydl.audioim.http.command.ConnectExceptionCommand
import com.ydl.audioim.http.command.PayLoad import com.ydl.audioim.http.command.PayLoad
import com.ydl.audioim.player.AudioPlayer import com.ydl.audioim.player.AudioPlayer
...@@ -713,6 +715,7 @@ class ConsultantAudioHomeActivity : ...@@ -713,6 +715,7 @@ class ConsultantAudioHomeActivity :
voiceManage?.attachVoiceEventHandler(mRtcEventHandler) voiceManage?.attachVoiceEventHandler(mRtcEventHandler)
voiceManage?.attachNetQualityListener(NetQuality()) voiceManage?.attachNetQualityListener(NetQuality())
voiceManage?.getVoiceApi()?.setAudioProfile(Constants.AUDIO_PROFILE_DEFAULT, Constants.AUDIO_SCENARIO_CHATROOM_GAMING) voiceManage?.getVoiceApi()?.setAudioProfile(Constants.AUDIO_PROFILE_DEFAULT, Constants.AUDIO_SCENARIO_CHATROOM_GAMING)
AudioApiRequestUtil.reportCallEvent(mAudioMessageBean?.channelId, RtcEvent(RtcEvent.Event.initSdk))
} }
...@@ -1051,6 +1054,7 @@ class ConsultantAudioHomeActivity : ...@@ -1051,6 +1054,7 @@ class ConsultantAudioHomeActivity :
36, 36,
"被叫加入频道后主叫未加入超时" "被叫加入频道后主叫未加入超时"
) )
AudioApiRequestUtil.reportCallEvent(mAudioMessageBean?.channelId, RtcEvent(RtcEvent.Event.remoteJoinTimeout))
AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:15s后如果还是处于连接中,则直接退出当前页面 channelId:${mAudioMessageBean?.channelId}") AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "咨询用户端:15s后如果还是处于连接中,则直接退出当前页面 channelId:${mAudioMessageBean?.channelId}")
writeAgoraLog("通话未接通挂断:连接中的状态超过5s自动挂断") writeAgoraLog("通话未接通挂断:连接中的状态超过5s自动挂断")
...@@ -1187,6 +1191,10 @@ class ConsultantAudioHomeActivity : ...@@ -1187,6 +1191,10 @@ class ConsultantAudioHomeActivity :
} }
override fun onNetworkTypeChanged(type: Int) {
AudioApiRequestUtil.reportCallEvent(mAudioMessageBean?.channelId, RtcEvent(RtcEvent.Event.networkTypeChanged), retCode = type)
}
override fun onRemoteAudioFeel(frozenRate: Int, qoeQuality: Int, reason: Int, mos: Int) { override fun onRemoteAudioFeel(frozenRate: Int, qoeQuality: Int, reason: Int, mos: Int) {
XLog.i("NetQuality", "frozenRate:$frozenRate,qoeQuality:$qoeQuality,reason:$reason,mos:$mos") XLog.i("NetQuality", "frozenRate:$frozenRate,qoeQuality:$qoeQuality,reason:$reason,mos:$mos")
} }
......
...@@ -11,11 +11,13 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{ ...@@ -11,11 +11,13 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{
private final String KEY_CALLEE="callee"; private final String KEY_CALLEE="callee";
private final String KEY_DURATION="duration"; private final String KEY_DURATION="duration";
private final String KEY_IS_CONSULT_ORDER = "isConsultOrder"; //是否是咨询单,true是 private final String KEY_IS_CONSULT_ORDER = "isConsultOrder"; //是否是咨询单,true是
private final String KEY_PULL_CALL = "pullCall"; //是否是咨询单,true是
private String status; private String status;
private String caller; private String caller;
private String callee; private String callee;
private String duration; private String duration;
private String isConsultOrder; private String isConsultOrder;
private Integer pullCall;//标识是可以拉起通话的 0或空 则不拉起
public CustomAttachConsultCallStatus() { public CustomAttachConsultCallStatus() {
super(CustomAttachmentType.TYPE_CUSTOMER_CONSULT_CALL_STATUS); super(CustomAttachmentType.TYPE_CUSTOMER_CONSULT_CALL_STATUS);
...@@ -28,6 +30,7 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{ ...@@ -28,6 +30,7 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{
this.callee=data.getString(KEY_CALLEE); this.callee=data.getString(KEY_CALLEE);
this.duration=data.getString(KEY_DURATION); this.duration=data.getString(KEY_DURATION);
this.isConsultOrder=data.getString(KEY_IS_CONSULT_ORDER); this.isConsultOrder=data.getString(KEY_IS_CONSULT_ORDER);
this.pullCall = data.getInteger(KEY_PULL_CALL);
} }
@Override @Override
...@@ -38,6 +41,7 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{ ...@@ -38,6 +41,7 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{
data.put(KEY_CALLEE, callee); data.put(KEY_CALLEE, callee);
data.put(KEY_DURATION, duration); data.put(KEY_DURATION, duration);
data.put(KEY_IS_CONSULT_ORDER, isConsultOrder); data.put(KEY_IS_CONSULT_ORDER, isConsultOrder);
data.put(KEY_PULL_CALL, pullCall);
return data; return data;
} }
...@@ -58,4 +62,8 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{ ...@@ -58,4 +62,8 @@ public class CustomAttachConsultCallStatus extends CustomAttachment{
} }
public String getIsConsultOrder() {return isConsultOrder;} public String getIsConsultOrder() {return isConsultOrder;}
public Integer getPullCall() {
return pullCall;
}
} }
\ No newline at end of file
...@@ -59,6 +59,7 @@ dependencies { ...@@ -59,6 +59,7 @@ dependencies {
// implementation project(":ydl-tuicore") // implementation project(":ydl-tuicore")
implementation project(":api:user") implementation project(":api:user")
implementation project(":api:course") implementation project(":api:course")
implementation project(":api:audioim")
implementation project(":api:im") implementation project(":api:im")
implementation project(":api:fm") implementation project(":api:fm")
implementation project(":api:dynamic") implementation project(":api:dynamic")
......
...@@ -2,7 +2,9 @@ package com.yidianling.user ...@@ -2,7 +2,9 @@ package com.yidianling.user
import android.app.Activity import android.app.Activity
import com.tencent.bugly.crashreport.CrashReport import com.tencent.bugly.crashreport.CrashReport
import com.ydl.audioim.api.IAudioImService
import com.ydl.ydlcommon.data.http.RxUtils import com.ydl.ydlcommon.data.http.RxUtils
import com.ydl.ydlcommon.modular.findRouteService
import com.ydl.ydlcommon.utils.ActivityManager import com.ydl.ydlcommon.utils.ActivityManager
import com.ydl.ydlcommon.utils.BuryPointUtils import com.ydl.ydlcommon.utils.BuryPointUtils
import com.ydl.ydlcommon.utils.log.AliYunLogConfig import com.ydl.ydlcommon.utils.log.AliYunLogConfig
...@@ -88,6 +90,7 @@ object LoginUtils { ...@@ -88,6 +90,7 @@ object LoginUtils {
@JvmStatic @JvmStatic
fun logout() { fun logout() {
EventBus.getDefault().post(UserLogoutEvent()) EventBus.getDefault().post(UserLogoutEvent())
findRouteService(IAudioImService::class.java).reportCallEvent("login", "userLogout", "用户登出", null)
UserHttpImpl.getInstance().logout(Logout()) UserHttpImpl.getInstance().logout(Logout())
.compose(RxUtils.resultData()) .compose(RxUtils.resultData())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
......
...@@ -2,7 +2,9 @@ package com.yidianling.user.ui.login.presenter ...@@ -2,7 +2,9 @@ package com.yidianling.user.ui.login.presenter
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.text.TextUtils import android.text.TextUtils
import com.ydl.audioim.api.IAudioImService
import com.ydl.ydlcommon.app.Apm import com.ydl.ydlcommon.app.Apm
import com.ydl.ydlcommon.modular.findRouteService
import com.ydl.ydlcommon.mvp.base.BasePresenter import com.ydl.ydlcommon.mvp.base.BasePresenter
import com.ydl.ydlcommon.router.YdlCommonOut import com.ydl.ydlcommon.router.YdlCommonOut
import com.ydl.ydlcommon.utils.StringUtils import com.ydl.ydlcommon.utils.StringUtils
...@@ -105,6 +107,7 @@ class InputPassWordPresenterImpl : ...@@ -105,6 +107,7 @@ class InputPassWordPresenterImpl :
) )
var param = PhoneLoginPwdParam(StringUtils.md5(inputPassword), phoneCountryCode, phone) var param = PhoneLoginPwdParam(StringUtils.md5(inputPassword), phoneCountryCode, phone)
findRouteService(IAudioImService::class.java).reportCallEvent("login", "userLogin", "用户登录", null)
mModel.userLoginByPassword(param) mModel.userLoginByPassword(param)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
...@@ -117,6 +120,7 @@ class InputPassWordPresenterImpl : ...@@ -117,6 +120,7 @@ class InputPassWordPresenterImpl :
ToastUtil.toastShort(it.msg) ToastUtil.toastShort(it.msg)
Apm.reportEvent("login_android", "password_error", "密码登录失败,$phoneCountryCode-$phone") Apm.reportEvent("login_android", "password_error", "密码登录失败,$phoneCountryCode-$phone")
mView.startAnim() mView.startAnim()
findRouteService(IAudioImService::class.java).reportCallEvent("login", "userLoginFail", "用户登录失败", null)
} else { } else {
if (it.data.userInfo?.user_type == 2) { if (it.data.userInfo?.user_type == 2) {
mView.showNormalDialog() mView.showNormalDialog()
...@@ -135,6 +139,7 @@ class InputPassWordPresenterImpl : ...@@ -135,6 +139,7 @@ class InputPassWordPresenterImpl :
} }
mView.closeActivity() mView.closeActivity()
} }
findRouteService(IAudioImService::class.java).reportCallEvent("login", "userLoginSuccess", "用户登录成功", null)
AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.LOGIN, "手机号密码 登录成功") AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.LOGIN, "手机号密码 登录成功")
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment