430 lines
13 KiB
C#
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,
|
|
}
|
|
}
|
|
|