using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Zip;
using UnityEngine;
namespace Framework {
/// <summary>
/// 日志系统
/// </summary>
public class LogSystem : Singleton<LogSystem> {
private const string LOG_NULL = "Log path is nul lor empty,please run the init first ";
/// <summary>
/// 控制台格式
/// </summary>
private const string FORMAT_CONSOLE = "[{0}]{1}";
/// <summary>
/// 日志路径
/// </summary>
public static string Path { get; private set; }
/// <summary>
/// 是否接收日志
/// </summary>
private static bool s_EnabledConsoleLog = false;
public static bool ReceivedLog {
get { return s_EnabledConsoleLog; }
set {
if (value = s_EnabledConsoleLog)
return;
s_EnabledConsoleLog = value;
if (value) {
Application.logMessageReceivedThreaded += OnReceiveLog;
} else {
Application.logMessageReceivedThreaded -= OnReceiveLog;
}
}
}
/// <summary>
/// 日志回调
/// </summary>
private Func<object, string> m_OnLogCallback;
/// <summary>
/// IP地址信息(防止在非主线程获取)
/// </summary>
private static string IpAddress = "null";
/// <summary>
/// 缓存记录日志路径key
/// </summary>
private static string logPathKey = "LogPath";
/// <summary>
/// 缓存记录之前日志路径key
/// </summary>
private const string prevLogPathKey = "PrevLogPath";
/// <summary>
/// 初始化
/// </summary>
/// <param name="path">日志路径</param>
/// <param name="onLogCallback">日志回调</param>
public static void Init (string path, Func<object, string> onLogCallback = null) {
string directory = path.Substring (0, path.LastIndexOf ('/'));
if (!Directory.Exists (directory)) {
Directory.CreateDirectory (directory);
}
//设置日志参数
Path = path; //路径地址
IpAddress = Network.player.ipAddress;
Instance.m_OnLogCallback = onLogCallback; //日志内容处理
var prevLogPath = PlayerPrefs.HasKey (logPathKey) ? PlayerPrefs.GetString (logPathKey) : null; //记录之前日志的路径
PlayerPrefs.SetString (prevLogPathKey, prevLogPath); //设置之前的日志路径key
PlayerPrefs.SetString (prevLogPathKey, path);
Debug.Log ("当前日志路径:" + path);
Debug.Log ("之前日志路径:" + prevLogPath);
}
/// <summary>
/// 打印日志
/// </summary>
/// <param name="message">消息</param>
public static void Log (object message) {
if (string.IsNullOrEmpty (Path)) {
Debug.LogError (Path);
return;
}
if (Instance.m_OnLogCallback != null) {
message = Instance.m_OnLogCallback.Invoke (message);
}
StreamWriter streamWriter = new StreamWriter (Path, true);
streamWriter.WriteLine (message);
streamWriter.Close ();
}
/// <summary>
/// 上传单条报错日志
/// </summary>
/// <param name="data"></param>
public void UploadError (string data) {
string loginUrl = "http://natd.tgtgame.com:8081/Login/log/upload";
loginUrl += "/log/error";
if (data.IndexOf (loginUrl) >= 0) {
return;
}
string name = "Err-" + GetPlayerInfo ();
string dataStr = data + "\n" +
"infomation:\n" +
"Application.version" + Application.version + "\n";
string[] args = { "name", name, "data", dataStr, };
//提交服务器
}
/// <summary>
/// 上传日志文件
/// </summary>
public static void UploadLogFile () {
var logPath = PlayerPrefs.HasKey (prevLogPathKey) ? PlayerPrefs.GetString (prevLogPathKey) : null;
if (string.IsNullOrEmpty (logPath)) {
return; //第一次打开,没有日志
}
//判断日志是否存在
if (!File.Exists (logPath)) {
Debug.LogWarning ("日志文件丢失!" + logPath);
return;
}
//上传服务器路径
string loginUrl = "http://natd.tgtgame.com:8081/Login/log/upload";
if (string.IsNullOrEmpty (loginUrl)) {
Debug.Log ("上传日志错误,没有服务器地址!");
return;
}
string filename = "1";
//玩家账号
string account = PlayerPrefs.HasKey ("Account") ? PlayerPrefs.GetString ("Account") : "null";
//设备号
string deviceId = SystemInfo.deviceUniqueIdentifier;
//玩家Id
string playerId = PlayerPrefs.HasKey ("PlayerId") ? PlayerPrefs.GetString ("PlayerId") : "null";
string[] args = new string[] {
"name",
Application.identifier,
"key",
Application.identifier,
"dir",
"/" + Application.identifier + "/",
"filetype",
"zip",
"filename",
filename,
"account",
filename,
"deviceId",
deviceId,
"playerId",
playerId,
"ip",
IpAddress,
};
string outputPath = "";
outputPath = Application.persistentDataPath + "/Log/error.zip";
//压缩zip文件
ZipFile (logPath, outputPath, 9);
byte[] logZip = File.ReadAllBytes (outputPath);
//回调函数
Action<WWW, string> callback = (WWW req, string text) => {
if (req.error != null) {
Debug.LogError ("上传日志错误:" + req.url + " " + req.error);
return;
}
Debug.LogError ("日志上传结果:" + req.url + " " + text);
};
//上传日志
NetworkSystem.RequestWWWUpload (loginUrl, callback, "log/upload", logZip, null, args);
Debug.Log ("上传日志!" + loginUrl + " -> " + Application.identifier + " " + deviceId + " logPath:" + logPath);
}
/// <summary>
/// 获取玩家信息
/// </summary>
/// <returns></returns>
private static string GetPlayerInfo () {
//玩家账号
string account = PlayerPrefs.HasKey ("Account") ? PlayerPrefs.GetString ("Account") : "null";
//设备号
string deviceId = SystemInfo.deviceUniqueIdentifier;
//玩家Id
string playerId = PlayerPrefs.HasKey ("PlayerId") ? PlayerPrefs.GetString ("PlayerId") : "null";
//输出玩家信息
var str = new StringBuilder ();
str.Append (IpAddress).Append ("-").Append (deviceId).Append ("-").Append (account).Append ("-").Append (playerId);
return str.ToString ();
}
/// <summary>
/// 日志回调
/// </summary>
/// <param name="condition">日志消息</param>
/// <param name="stackTrace">调用堆栈</param>
/// <param name="type">日志类型</param>
private static void OnReceiveLog (string condition, string stackTrace, LogType type) {
Log (string.Format (FORMAT_CONSOLE, type, condition));
if (type == LogType.Error || type == LogType.Exception) {
// 提交到主线程
Core.Invoke ((arg) => {
Instance.UploadError (condition + "\n" + stackTrace);
});
}
}
/// <summary>
/// 创建压缩Zip文件
/// </summary>
/// <param name="file">需要压缩的文件</param>
/// <param name="outputFilePath">输出的路径</param>
/// <param name="compressLevel">压缩等级0-9</param>
public static void ZipFile (string file, string outputFilePath, int compressLevel) {
byte[] buffer = new byte[4096];
if (!Directory.Exists (AssetSystem.PAHT_CACHE)) {
Directory.CreateDirectory (AssetSystem.PAHT_CACHE);
}
using (ZipOutputStream stream = new ZipOutputStream (File.Create (outputFilePath))) {
stream.SetLevel (compressLevel); //设置压缩等级
var entry = new ZipEntry (System.IO.Path.GetFileName (file)) {
DateTime = DateTime.Now
};
stream.PutNextEntry (entry);
using (FileStream fs = File.OpenRead (file)) {
int sourceBytes;
do {
sourceBytes = fs.Read (buffer, 0, buffer.Length);
stream.Write (buffer, 0, sourceBytes);
}
while (sourceBytes > 0);
}
stream.Finish ();
stream.Close ();
}
}
}
}