com.guru.unity.sdk.core/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs

430 lines
13 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
namespace Guru
{
public class GuruAnalytics
{
// Plugin Version
public const string Version = "1.9.0";
public static readonly string Tag = "[ANA]";
private static readonly string ActionName = "logger_error";
private static IAnalyticsAgent _agent;
public static IAnalyticsAgent Agent
{
get
{
if (_agent == null)
{
#if UNITY_EDITOR
_agent = new AnalyticsAgentStub();
#elif UNITY_ANDROID
_agent = new AnalyticsAgentAndroid();
#elif UNITY_IOS
_agent = new AnalyticsAgentIOS();
#endif
}
return _agent;
}
}
private static Dictionary<string, string> _userProperties;
/// <summary>
/// 用户属性缓存字典
/// </summary>
public static Dictionary<string, string> UserProperties
{
get
{
if (_userProperties == null)
{
_userProperties = new Dictionary<string, string>(10);
}
return _userProperties;
}
}
private static bool _autoSyncProperties = false;
private static bool _enableErrorLog = false;
/// <summary>
/// 启动日志错误上报
/// </summary>
public static bool EnableErrorLog
{
get => _enableErrorLog;
set
{
_enableErrorLog = value;
if (_enableErrorLog) InitCallbacks(); // 激活错误日志回调
if (Agent != null) Agent.EnableErrorLog = _enableErrorLog;
}
}
#region 公用接口
/// <summary>
/// 初始化接口
/// </summary>
public static void Init(string appId, string deviceInfo, bool isDebug = false,
bool enableErrorLog = false, bool syncProperties = false)
{
_autoSyncProperties = syncProperties;
_enableErrorLog = enableErrorLog;
Agent?.Init(appId, deviceInfo, isDebug);
if(_enableErrorLog) InitCallbacks(); // 激活错误日志回调
}
/// <summary>
/// 设置视图名称
/// </summary>
/// <param name="screenName"></param>
public static void SetScreen(string screenName)
{
CacheUserProperty($"screen_name", screenName);
Agent?.SetScreen(screenName);
}
/// <summary>
/// 设置广告ID
/// </summary>
/// <param name="id"></param>
public static void SetAdId(string id)
{
CacheUserProperty($"ad_id", id);
Agent?.SetAdId(id);
}
/// <summary>
/// 设置用户属性
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public static void SetUserProperty(string key, string value)
{
CacheUserProperty(key, value); // 添加用户属性
Agent?.SetUserProperty(key, value);
}
/// <summary>
/// 设置Firebase ID
/// </summary>
/// <param name="id"></param>
public static void SetFirebaseId(string id)
{
CacheUserProperty($"firebase_id", id);
Agent?.SetFirebaseId(id);
}
/// <summary>
/// 设置Adjust ID
/// </summary>
/// <param name="id"></param>
public static void SetAdjustId(string id)
{
CacheUserProperty($"adjust_id", id);
Agent?.SetAdjustId(id);
}
/// <summary>
/// 设置设备ID
/// </summary>
/// <param name="deviceId"></param>
public static void SetDeviceId(string deviceId)
{
CacheUserProperty($"device_id", deviceId);
Agent?.SetDeviceId(deviceId);
}
public static void SetAndroidID(string androidId)
{
CacheUserProperty(Analytics.PropertyAndroidID, androidId);
}
public static void SetIDFV(string idfv)
{
CacheUserProperty(Analytics.PropertyIDFV, idfv);
}
public static void SetIDFA(string idfa)
{
CacheUserProperty(Analytics.PropertyIDFA, idfa);
}
/// <summary>
/// 设置用户ID
/// </summary>
/// <param name="uid"></param>
public static void SetUid(string uid)
{
CacheUserProperty($"uid", uid);
Agent?.SetUid(uid);
}
/// <summary>
/// 上报事件成功率
/// </summary>
public static void ReportEventSuccessRate() => Agent?.ReportEventSuccessRate();
/// <summary>
/// 上报打点事件
/// </summary>
/// <param name="eventName">事件名称</param>
/// <param name="data">INT类型的值</param>
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null)
{
if(_autoSyncProperties)
UpdateAllUserProperties(); // 每次打点更新用户属性
string raw = "";
if (data != null && data.Count > 0)
{
raw = BuildParamsJson(data);
}
Debug.Log($"{Tag} event:{eventName} | raw: {raw}");
Agent?.LogEvent(eventName, raw);
}
private static string BuildParamsString(Dictionary<string, dynamic> data)
{
string raw = "";
List<string> strList = new List<string>(data.Count);
foreach (var kvp in data)
{
strList.Add(BuildStringValue(kvp));
raw = string.Join(",", strList);
}
return raw;
}
private static string BuildParamsJson(Dictionary<string, dynamic> data)
{
try
{
// 强制转换加入国家设置
return JsonConvert.SerializeObject(data, new JsonSerializerSettings()
{
Culture = new CultureInfo("en-US"),
});
}
catch (Exception e)
{
Debug.LogError(e);
}
return "";
}
/// <summary>
/// 构建带有类型格式的Str值
/// </summary>
/// <param name="kvp"></param>
/// <returns></returns>
private static string BuildStringValue(KeyValuePair<string, dynamic> kvp)
{
if (kvp.Value is int || kvp.Value is long)
{
return $"{kvp.Key}:i{kvp.Value}";
}
if (kvp.Value is double || kvp.Value is float)
{
double dValue = (double)((object)kvp.Value);
return $"{kvp.Key}:d{dValue.ToString("F11", new CultureInfo("en-US"))}"; // 保留精度进行转换
}
return $"{kvp.Key}:s{kvp.Value}";
}
/// <summary>
/// 设置太极02值
/// </summary>
/// <param name="value"></param>
public static void SetTch02Value(double value)
{
Debug.Log($"{Tag} set tch_02_value:{value}");
Agent?.SetTch02Value(value);
}
#endregion
#region iOS独有接口
#if UNITY_IOS
// 触发测试崩溃埋点
public static void TestCrash() => AnalyticsAgentIOS.TestCrashEvent();
#endif
#endregion
#region 用户属性
/// <summary>
/// 记录用户属性
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
private static void CacheUserProperty(string key, string value)
{
bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value;
UserProperties[key] = value;
// if (needUpdate) UpdateAllUserProperties();
}
private static void UpdateAllUserProperties()
{
if (UserProperties != null && UserProperties.Count > 0)
{
var keys = UserProperties.Keys.ToArray();
int i = 0;
string key = "";
while (i < keys.Length)
{
key = keys[i];
if(!string.IsNullOrEmpty(key)) SetUserProperty(key, UserProperties[key]);
i++;
}
keys = null;
}
}
#endregion
#region 日志回调
private static void InitCallbacks()
{
try
{
GuruSDKCallback.RemoveCallback(OnSDKCallback);
GuruSDKCallback.AddCallback(OnSDKCallback);
if (Agent != null)
Agent.InitCallback(GuruSDKCallback.ObjectName, GuruSDKCallback.MethodName);
}
catch (Exception ex)
{
Analytics.LogCrashlytics(ex);
}
}
/// <summary>
/// 获取SDK回调
/// </summary>
/// <param name="msg"></param>
private static void OnSDKCallback(string msg)
{
//------- message send to unity ----------
Debug.Log($"{Tag} get callback errorInfo:\n{msg}");
try
{
var response = JsonConvert.DeserializeObject<JObject>(msg);
if (response.TryGetValue("action", out var jAct))
{
if (jAct.ToString() == ActionName
&& response.TryGetValue("data", out var jData) && jData is JObject data)
{
int code = -1;
string message = msg;
if (data.TryGetValue("code", out var jCode))
{
int.TryParse(jCode.ToString(), out code);
}
if (data.TryGetValue("msg", out var jMsg))
{
message = jMsg.ToString();
}
var errorCode = (AnalyticsCode)code;
switch (errorCode)
{
case AnalyticsCode.Network_Lost:
case AnalyticsCode.ERROR_API:
case AnalyticsCode.ERROR_DNS:
case AnalyticsCode.ERROR_ZIP:
case AnalyticsCode.ERROR_LOAD_MARK:
case AnalyticsCode.ERROR_RESPONSE:
case AnalyticsCode.ERROR_CACHE_CONTROL:
case AnalyticsCode.ERROR_DELETE_EXPIRED:
OnLoggerErrorEvent(code, message);
break;
}
return;
}
}
Debug.LogError($"{Tag} Parse callback Error");
}
catch (Exception ex)
{
Analytics.LogCrashlytics(ex);
}
}
/// <summary>
/// 上报错误信息
/// </summary>
/// <param name="code"></param>
/// <param name="errorInfo"></param>
private static void OnLoggerErrorEvent(int code, string errorInfo = "")
{
Dictionary<string, dynamic> parameters = new Dictionary<string, dynamic>()
{
{"item_category", "error_event"},
{"item_name", ((AnalyticsCode)code).ToString()},
{"country", IPMConfig.IPM_COUNTRY_CODE},
{"network", Application.internetReachability.ToString()},
};
if (!string.IsNullOrEmpty(errorInfo))
{
int len = 32;
if (errorInfo.Length > len) errorInfo = errorInfo.TrimStart().Substring(0, len);
parameters["err"] = errorInfo;
}
Debug.Log($"{Tag} --- ErrorLogInfo:: code:{code}\tinfo:{errorInfo}");
// Only for firebase GA
Analytics.LogEvent("dev_audit", parameters,
new Analytics.EventSetting() { EnableFirebaseAnalytics = true });
}
#endregion
}
/// <summary>
/// 网络状态枚举
/// </summary>
public enum AnalyticsCode
{
Unknown = -1,
Network_Lost = 22,
ERROR_API = 101,
ERROR_RESPONSE = 102,
ERROR_CACHE_CONTROL = 103,
ERROR_DELETE_EXPIRED = 104,
ERROR_LOAD_MARK = 105,
ERROR_DNS = 106,
ERROR_ZIP = 107,
}
}