mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 02:36:14 +00:00
提交Unity 联机Pro
This commit is contained in:
143
JNFrame2/Assets/Plugins/Best HTTP/Source/Logger/DefaultLogger.cs
Normal file
143
JNFrame2/Assets/Plugins/Best HTTP/Source/Logger/DefaultLogger.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// A basic logger implementation to be able to log intelligently additional informations about the plugin's internal mechanism.
|
||||
/// </summary>
|
||||
public class DefaultLogger : BestHTTP.Logger.ILogger
|
||||
{
|
||||
public Loglevels Level { get; set; }
|
||||
|
||||
public ILogOutput Output
|
||||
{
|
||||
get { return this._output; }
|
||||
set
|
||||
{
|
||||
if (this._output != value)
|
||||
{
|
||||
if (this._output != null)
|
||||
this._output.Dispose();
|
||||
this._output = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private ILogOutput _output;
|
||||
|
||||
public string FormatVerbose { get; set; }
|
||||
public string FormatInfo { get; set; }
|
||||
public string FormatWarn { get; set; }
|
||||
public string FormatErr { get; set; }
|
||||
public string FormatEx { get; set; }
|
||||
|
||||
public DefaultLogger()
|
||||
{
|
||||
FormatVerbose = "[{0}] D [{1}]: {2}";
|
||||
FormatInfo = "[{0}] I [{1}]: {2}";
|
||||
FormatWarn = "[{0}] W [{1}]: {2}";
|
||||
FormatErr = "[{0}] Err [{1}]: {2}";
|
||||
FormatEx = "[{0}] Ex [{1}]: {2} - Message: {3} StackTrace: {4}";
|
||||
|
||||
Level = UnityEngine.Debug.isDebugBuild ? Loglevels.Warning : Loglevels.Error;
|
||||
this.Output = new UnityOutput();
|
||||
}
|
||||
|
||||
public void Verbose(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null)
|
||||
{
|
||||
if (Level <= Loglevels.All)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(Loglevels.All, string.Format(FormatVerbose, GetFormattedTime(), division, msg));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
public void Information(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null)
|
||||
{
|
||||
if (Level <= Loglevels.Information)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(Loglevels.Information, string.Format(FormatInfo, GetFormattedTime(), division, msg));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
public void Warning(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null)
|
||||
{
|
||||
if (Level <= Loglevels.Warning)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(Loglevels.Warning, string.Format(FormatWarn, GetFormattedTime(), division, msg));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
public void Error(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null)
|
||||
{
|
||||
if (Level <= Loglevels.Error)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(Loglevels.Error, string.Format(FormatErr, GetFormattedTime(), division, msg));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
public void Exception(string division, string msg, Exception ex, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null)
|
||||
{
|
||||
if (Level <= Loglevels.Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
string exceptionMessage = string.Empty;
|
||||
if (ex == null)
|
||||
exceptionMessage = "null";
|
||||
else
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
Exception exception = ex;
|
||||
int counter = 1;
|
||||
while (exception != null)
|
||||
{
|
||||
sb.AppendFormat("{0}: {1} {2}", counter++.ToString(), exception.Message, exception.StackTrace);
|
||||
|
||||
exception = exception.InnerException;
|
||||
|
||||
if (exception != null)
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
exceptionMessage = sb.ToString();
|
||||
}
|
||||
|
||||
this.Output.Write(Loglevels.Exception, string.Format(FormatEx,
|
||||
GetFormattedTime(),
|
||||
division,
|
||||
msg,
|
||||
exceptionMessage,
|
||||
ex != null ? ex.StackTrace : "null"));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
private string GetFormattedTime()
|
||||
{
|
||||
return DateTime.Now.Ticks.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0c6097670314f141ad42c8060f64ecb
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
|
||||
using BestHTTP.Extensions;
|
||||
using BestHTTP.PlatformSupport.Memory;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
public sealed class FileOutput : ILogOutput
|
||||
{
|
||||
private System.IO.Stream fileStream;
|
||||
|
||||
public FileOutput(string fileName)
|
||||
{
|
||||
this.fileStream = HTTPManager.IOService.CreateFileStream(fileName, PlatformSupport.FileSystem.FileStreamModes.Create);
|
||||
}
|
||||
|
||||
public void Write(Loglevels level, string logEntry)
|
||||
{
|
||||
if (this.fileStream != null && !string.IsNullOrEmpty(logEntry))
|
||||
{
|
||||
int count = System.Text.Encoding.UTF8.GetByteCount(logEntry);
|
||||
var buffer = BufferPool.Get(count, true);
|
||||
|
||||
try
|
||||
{
|
||||
System.Text.Encoding.UTF8.GetBytes(logEntry, 0, logEntry.Length, buffer, 0);
|
||||
|
||||
this.fileStream.Write(buffer, 0, count);
|
||||
this.fileStream.WriteLine();
|
||||
}
|
||||
finally
|
||||
{
|
||||
BufferPool.Release(buffer);
|
||||
}
|
||||
|
||||
this.fileStream.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.fileStream != null)
|
||||
{
|
||||
this.fileStream.Close();
|
||||
this.fileStream = null;
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7d6b077b7753e44e943b5f433b3158d
|
||||
timeCreated: 1591097750
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
65
JNFrame2/Assets/Plugins/Best HTTP/Source/Logger/ILogger.cs
Normal file
65
JNFrame2/Assets/Plugins/Best HTTP/Source/Logger/ILogger.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
/// <summary>
|
||||
/// Available logging levels.
|
||||
/// </summary>
|
||||
public enum Loglevels : int
|
||||
{
|
||||
/// <summary>
|
||||
/// All message will be logged.
|
||||
/// </summary>
|
||||
All,
|
||||
|
||||
/// <summary>
|
||||
/// Only Informations and above will be logged.
|
||||
/// </summary>
|
||||
Information,
|
||||
|
||||
/// <summary>
|
||||
/// Only Warnings and above will be logged.
|
||||
/// </summary>
|
||||
Warning,
|
||||
|
||||
/// <summary>
|
||||
/// Only Errors and above will be logged.
|
||||
/// </summary>
|
||||
Error,
|
||||
|
||||
/// <summary>
|
||||
/// Only Exceptions will be logged.
|
||||
/// </summary>
|
||||
Exception,
|
||||
|
||||
/// <summary>
|
||||
/// No logging will occur.
|
||||
/// </summary>
|
||||
None
|
||||
}
|
||||
|
||||
public interface ILogOutput : IDisposable
|
||||
{
|
||||
void Write(Loglevels level, string logEntry);
|
||||
}
|
||||
|
||||
public interface ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// The minimum severity to log
|
||||
/// </summary>
|
||||
Loglevels Level { get; set; }
|
||||
|
||||
ILogOutput Output { get; set; }
|
||||
|
||||
void Verbose(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null);
|
||||
|
||||
void Information(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null);
|
||||
|
||||
void Warning(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null);
|
||||
|
||||
void Error(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null);
|
||||
|
||||
void Exception(string division, string msg, Exception ex, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41bbbfdb18d1d6f479d52229e8e4e827
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
public sealed class LoggingContext
|
||||
{
|
||||
private enum LoggingContextFieldType
|
||||
{
|
||||
Long,
|
||||
Bool,
|
||||
String,
|
||||
AnotherContext
|
||||
}
|
||||
|
||||
private struct LoggingContextField
|
||||
{
|
||||
public string key;
|
||||
public long longValue;
|
||||
public bool boolValue;
|
||||
public string stringValue;
|
||||
public LoggingContext loggingContextValue;
|
||||
public LoggingContextFieldType fieldType;
|
||||
}
|
||||
|
||||
private List<LoggingContextField> fields = null;
|
||||
private static System.Random random = new System.Random();
|
||||
|
||||
private LoggingContext() { }
|
||||
|
||||
public LoggingContext(object boundto)
|
||||
{
|
||||
var name = boundto.GetType().Name;
|
||||
Add("TypeName", name);
|
||||
|
||||
long hash = 0;
|
||||
lock (random)
|
||||
hash = ((long)boundto.GetHashCode() << 32 | (long)name.GetHashCode()) ^ ((long)this.GetHashCode() << 16) | (long)(random.Next(int.MaxValue) << 32) | (long)random.Next(int.MaxValue);
|
||||
Add("Hash", hash);
|
||||
}
|
||||
|
||||
public void Add(string key, long value)
|
||||
{
|
||||
Add(new LoggingContextField { fieldType = LoggingContextFieldType.Long, key = key, longValue = value });
|
||||
}
|
||||
|
||||
public void Add(string key, bool value)
|
||||
{
|
||||
Add(new LoggingContextField { fieldType = LoggingContextFieldType.Bool, key = key, boolValue = value });
|
||||
}
|
||||
|
||||
public void Add(string key, string value)
|
||||
{
|
||||
Add(new LoggingContextField { fieldType = LoggingContextFieldType.String, key = key, stringValue = value });
|
||||
}
|
||||
|
||||
public void Add(string key, LoggingContext value)
|
||||
{
|
||||
|
||||
Add(new LoggingContextField { fieldType = LoggingContextFieldType.AnotherContext, key = key, loggingContextValue = value });
|
||||
}
|
||||
|
||||
private void Add(LoggingContextField field)
|
||||
{
|
||||
if (this.fields == null)
|
||||
this.fields = new List<LoggingContextField>();
|
||||
|
||||
Remove(field.key);
|
||||
this.fields.Add(field);
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
this.fields.RemoveAll(field => field.key == key);
|
||||
}
|
||||
|
||||
public LoggingContext Clone()
|
||||
{
|
||||
LoggingContext newContext = new LoggingContext();
|
||||
|
||||
if (this.fields != null && this.fields.Count > 0)
|
||||
{
|
||||
newContext.fields = new List<LoggingContextField>(this.fields.Count);
|
||||
for (int i = 0; i < this.fields.Count; ++i)
|
||||
{
|
||||
var field = this.fields[i];
|
||||
|
||||
switch (field.fieldType)
|
||||
{
|
||||
case LoggingContextFieldType.Long:
|
||||
case LoggingContextFieldType.Bool:
|
||||
case LoggingContextFieldType.String:
|
||||
newContext.fields.Add(field);
|
||||
break;
|
||||
|
||||
case LoggingContextFieldType.AnotherContext:
|
||||
newContext.Add(field.key, field.loggingContextValue.Clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newContext;
|
||||
}
|
||||
|
||||
public void ToJson(System.Text.StringBuilder sb)
|
||||
{
|
||||
if (this.fields == null || this.fields.Count == 0)
|
||||
{
|
||||
sb.Append("null");
|
||||
return;
|
||||
}
|
||||
|
||||
sb.Append("{");
|
||||
for (int i = 0; i < this.fields.Count; ++i)
|
||||
{
|
||||
var field = this.fields[i];
|
||||
|
||||
if (field.fieldType != LoggingContextFieldType.AnotherContext)
|
||||
{
|
||||
if (i > 0)
|
||||
sb.Append(", ");
|
||||
|
||||
sb.AppendFormat("\"{0}\": ", field.key);
|
||||
}
|
||||
|
||||
switch (field.fieldType)
|
||||
{
|
||||
case LoggingContextFieldType.Long:
|
||||
sb.Append(field.longValue);
|
||||
break;
|
||||
case LoggingContextFieldType.Bool:
|
||||
sb.Append(field.boolValue ? "true" : "false");
|
||||
break;
|
||||
case LoggingContextFieldType.String:
|
||||
sb.AppendFormat("\"{0}\"", Escape(field.stringValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("}");
|
||||
|
||||
for (int i = 0; i < this.fields.Count; ++i)
|
||||
{
|
||||
var field = this.fields[i];
|
||||
|
||||
switch (field.fieldType)
|
||||
{
|
||||
case LoggingContextFieldType.AnotherContext:
|
||||
sb.Append(", ");
|
||||
field.loggingContextValue.ToJson(sb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static string Escape(string original)
|
||||
{
|
||||
return PlatformSupport.Text.StringBuilderPool.ReleaseAndGrab(PlatformSupport.Text.StringBuilderPool.Get(1)
|
||||
.Append(original)
|
||||
.Replace("\\", "\\\\")
|
||||
.Replace("\"", "\\\"")
|
||||
.Replace("/", "\\/")
|
||||
.Replace("\b", "\\b")
|
||||
.Replace("\f", "\\f")
|
||||
.Replace("\n", "\\n")
|
||||
.Replace("\r", "\\r")
|
||||
.Replace("\t", "\\t"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2c848a07a285a7428a454b190e7c3a6
|
||||
timeCreated: 1591097750
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,318 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text;
|
||||
|
||||
using BestHTTP.PlatformSupport.Threading;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
|
||||
|
||||
|
||||
public sealed class ThreadedLogger : BestHTTP.Logger.ILogger, IDisposable
|
||||
{
|
||||
public Loglevels Level { get; set; }
|
||||
public ILogOutput Output { get { return this._output; }
|
||||
set
|
||||
{
|
||||
if (this._output != value)
|
||||
{
|
||||
if (this._output != null)
|
||||
this._output.Dispose();
|
||||
this._output = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private ILogOutput _output;
|
||||
|
||||
public int InitialStringBufferCapacity = 256;
|
||||
|
||||
#if !UNITY_WEBGL || UNITY_EDITOR
|
||||
public TimeSpan ExitThreadAfterInactivity = TimeSpan.FromMinutes(1);
|
||||
|
||||
private ConcurrentQueue<LogJob> jobs = new ConcurrentQueue<LogJob>();
|
||||
private System.Threading.AutoResetEvent newJobEvent = new System.Threading.AutoResetEvent(false);
|
||||
|
||||
private volatile int threadCreated;
|
||||
|
||||
private volatile bool isDisposed;
|
||||
#endif
|
||||
|
||||
private StringBuilder sb = new StringBuilder(0);
|
||||
|
||||
public ThreadedLogger()
|
||||
{
|
||||
this.Level = UnityEngine.Debug.isDebugBuild ? Loglevels.Warning : Loglevels.Error;
|
||||
this.Output = new UnityOutput();
|
||||
}
|
||||
|
||||
public void Verbose(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null) {
|
||||
AddJob(Loglevels.All, division, msg, null, context1, context2, context3);
|
||||
}
|
||||
|
||||
public void Information(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null) {
|
||||
AddJob(Loglevels.Information, division, msg, null, context1, context2, context3);
|
||||
}
|
||||
|
||||
public void Warning(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null) {
|
||||
AddJob(Loglevels.Warning, division, msg, null, context1, context2, context3);
|
||||
}
|
||||
|
||||
public void Error(string division, string msg, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null) {
|
||||
AddJob(Loglevels.Error, division, msg, null, context1, context2, context3);
|
||||
}
|
||||
|
||||
public void Exception(string division, string msg, Exception ex, LoggingContext context1 = null, LoggingContext context2 = null, LoggingContext context3 = null) {
|
||||
AddJob(Loglevels.Exception, division, msg, ex, context1, context2, context3);
|
||||
}
|
||||
|
||||
private void AddJob(Loglevels level, string div, string msg, Exception ex, LoggingContext context1, LoggingContext context2, LoggingContext context3)
|
||||
{
|
||||
if (this.Level > level)
|
||||
return;
|
||||
|
||||
sb.EnsureCapacity(InitialStringBufferCapacity);
|
||||
|
||||
#if !UNITY_WEBGL || UNITY_EDITOR
|
||||
if (this.isDisposed)
|
||||
return;
|
||||
#endif
|
||||
|
||||
var job = new LogJob
|
||||
{
|
||||
level = level,
|
||||
division = div,
|
||||
msg = msg,
|
||||
ex = ex,
|
||||
time = DateTime.Now,
|
||||
threadId = System.Threading.Thread.CurrentThread.ManagedThreadId,
|
||||
stackTrace = System.Environment.StackTrace,
|
||||
context1 = context1 != null ? context1.Clone() : null,
|
||||
context2 = context2 != null ? context2.Clone() : null,
|
||||
context3 = context3 != null ? context3.Clone() : null
|
||||
};
|
||||
|
||||
#if !UNITY_WEBGL || UNITY_EDITOR
|
||||
// Start the consumer thread before enqueuing to get up and running sooner
|
||||
if (System.Threading.Interlocked.CompareExchange(ref this.threadCreated, 1, 0) == 0)
|
||||
BestHTTP.PlatformSupport.Threading.ThreadedRunner.RunLongLiving(ThreadFunc);
|
||||
|
||||
this.jobs.Enqueue(job);
|
||||
try
|
||||
{
|
||||
this.newJobEvent.Set();
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(job.level, job.ToJson(sb));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return;
|
||||
}
|
||||
|
||||
// newJobEvent might timed out between the previous threadCreated check and newJobEvent.Set() calls closing the thread.
|
||||
// So, here we check threadCreated again and create a new thread if needed.
|
||||
if (System.Threading.Interlocked.CompareExchange(ref this.threadCreated, 1, 0) == 0)
|
||||
BestHTTP.PlatformSupport.Threading.ThreadedRunner.RunLongLiving(ThreadFunc);
|
||||
#else
|
||||
this.Output.Write(job.level, job.ToJson(sb));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !UNITY_WEBGL || UNITY_EDITOR
|
||||
private void ThreadFunc()
|
||||
{
|
||||
ThreadedRunner.SetThreadName("BestHTTP.Logger");
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
// Waiting for a new log-job timed out
|
||||
if (!this.newJobEvent.WaitOne(this.ExitThreadAfterInactivity))
|
||||
{
|
||||
// clear StringBuilder's inner cache and exit the thread
|
||||
sb.Length = 0;
|
||||
sb.Capacity = 0;
|
||||
System.Threading.Interlocked.Exchange(ref this.threadCreated, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
LogJob job;
|
||||
while (this.jobs.TryDequeue(out job))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Output.Write(job.level, job.ToJson(sb));
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
} while (!HTTPManager.IsQuitting);
|
||||
System.Threading.Interlocked.Exchange(ref this.threadCreated, 0);
|
||||
|
||||
// When HTTPManager.IsQuitting is true, there is still logging that will create a new thread after the last one quit
|
||||
// and always writing a new entry about the exiting thread would be too much overhead.
|
||||
// It would also hard to know what's the last log entry because some are generated on another thread non-deterministically.
|
||||
|
||||
//var lastLog = new LogJob
|
||||
//{
|
||||
// level = Loglevels.All,
|
||||
// division = "ThreadedLogger",
|
||||
// msg = "Log Processing Thread Quitting!",
|
||||
// time = DateTime.Now,
|
||||
// threadId = System.Threading.Thread.CurrentThread.ManagedThreadId,
|
||||
//};
|
||||
//
|
||||
//this.Output.WriteVerbose(lastLog.ToJson(sb));
|
||||
}
|
||||
catch
|
||||
{
|
||||
System.Threading.Interlocked.Exchange(ref this.threadCreated, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
#if !UNITY_WEBGL || UNITY_EDITOR
|
||||
this.isDisposed = true;
|
||||
|
||||
if (this.newJobEvent != null)
|
||||
{
|
||||
this.newJobEvent.Close();
|
||||
this.newJobEvent = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this.Output != null)
|
||||
{
|
||||
this.Output.Dispose();
|
||||
this.Output = new UnityOutput();
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
[BestHTTP.PlatformSupport.IL2CPP.Il2CppEagerStaticClassConstructionAttribute]
|
||||
struct LogJob
|
||||
{
|
||||
private static string[] LevelStrings = new string[] { "Verbose", "Information", "Warning", "Error", "Exception" };
|
||||
public Loglevels level;
|
||||
public string division;
|
||||
public string msg;
|
||||
public Exception ex;
|
||||
|
||||
public DateTime time;
|
||||
public int threadId;
|
||||
public string stackTrace;
|
||||
|
||||
public LoggingContext context1;
|
||||
public LoggingContext context2;
|
||||
public LoggingContext context3;
|
||||
|
||||
private static string WrapInColor(string str, string color)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return string.Format("<b><color={1}>{0}</color></b>", str, color);
|
||||
#else
|
||||
return str;
|
||||
#endif
|
||||
}
|
||||
|
||||
public string ToJson(StringBuilder sb)
|
||||
{
|
||||
sb.Length = 0;
|
||||
|
||||
sb.AppendFormat("{{\"tid\":{0},\"div\":\"{1}\",\"msg\":\"{2}\"",
|
||||
WrapInColor(this.threadId.ToString(), "yellow"),
|
||||
WrapInColor(this.division, "yellow"),
|
||||
WrapInColor(LoggingContext.Escape(this.msg), "yellow"));
|
||||
|
||||
if (ex != null)
|
||||
{
|
||||
sb.Append(",\"ex\": [");
|
||||
|
||||
Exception exception = this.ex;
|
||||
|
||||
while (exception != null)
|
||||
{
|
||||
sb.Append("{\"msg\": \"");
|
||||
sb.Append(LoggingContext.Escape(exception.Message));
|
||||
sb.Append("\", \"stack\": \"");
|
||||
sb.Append(LoggingContext.Escape(exception.StackTrace));
|
||||
sb.Append("\"}");
|
||||
|
||||
exception = exception.InnerException;
|
||||
|
||||
if (exception != null)
|
||||
sb.Append(",");
|
||||
}
|
||||
|
||||
sb.Append("]");
|
||||
}
|
||||
|
||||
if (this.stackTrace != null)
|
||||
{
|
||||
sb.Append(",\"stack\":\"");
|
||||
ProcessStackTrace(sb);
|
||||
sb.Append("\"");
|
||||
}
|
||||
else
|
||||
sb.Append(",\"stack\":\"\"");
|
||||
|
||||
if (this.context1 != null || this.context2 != null || this.context3 != null)
|
||||
{
|
||||
sb.Append(",\"ctxs\":[");
|
||||
|
||||
if (this.context1 != null)
|
||||
this.context1.ToJson(sb);
|
||||
|
||||
if (this.context2 != null)
|
||||
{
|
||||
if (this.context1 != null)
|
||||
sb.Append(",");
|
||||
|
||||
this.context2.ToJson(sb);
|
||||
}
|
||||
|
||||
if (this.context3 != null)
|
||||
{
|
||||
if (this.context1 != null || this.context2 != null)
|
||||
sb.Append(",");
|
||||
|
||||
this.context3.ToJson(sb);
|
||||
}
|
||||
|
||||
sb.Append("]");
|
||||
}
|
||||
else
|
||||
sb.Append(",\"ctxs\":[]");
|
||||
|
||||
sb.AppendFormat(",\"t\":{0},\"ll\":\"{1}\",",
|
||||
this.time.Ticks.ToString(),
|
||||
LevelStrings[(int)this.level]);
|
||||
|
||||
sb.Append("\"bh\":1}");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private void ProcessStackTrace(StringBuilder sb)
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.stackTrace))
|
||||
return;
|
||||
|
||||
var lines = this.stackTrace.Split('\n');
|
||||
|
||||
// skip top 4 lines that would show the logger.
|
||||
for (int i = 3; i < lines.Length; ++i)
|
||||
sb.Append(LoggingContext.Escape(lines[i].Replace("BestHTTP.", "")));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4209c767f5d900e4e87b9ae93cacad35
|
||||
timeCreated: 1588765781
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace BestHTTP.Logger
|
||||
{
|
||||
public sealed class UnityOutput : ILogOutput
|
||||
{
|
||||
public void Write(Loglevels level, string logEntry)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case Loglevels.All:
|
||||
case Loglevels.Information:
|
||||
UnityEngine.Debug.Log(logEntry);
|
||||
break;
|
||||
|
||||
case Loglevels.Warning:
|
||||
UnityEngine.Debug.LogWarning(logEntry);
|
||||
break;
|
||||
|
||||
case Loglevels.Error:
|
||||
case Loglevels.Exception:
|
||||
UnityEngine.Debug.LogError(logEntry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc3465944e901424f8b8b181e5c95e30
|
||||
timeCreated: 1591097750
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user