You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Gateway/Proxy/LogSetting.cs

345 lines
11 KiB
C#

2 years ago
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.IO.Compression;
using UMC.Data;
using UMC.Net;
using UMC.Proxy.Entities;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
namespace UMC.Proxy
{
class LogSetting : UMC.Data.DataProvider
{
public static LogSetting Instance()
{
if (_Instance == null)
{
_Instance = new LogSetting();
_Instance.LoadConf();
}
return _Instance;
}
static LogSetting _Instance;
String _sql, _dbkey;
bool _isWriter = false;
string[] _csvFields;
Uri _httpUrl;
String _method;
public virtual bool IsWriter
{
get
{
return _isWriter;
}
}
public void LoadConf()
{
Data.Provider provider;
var pc = Reflection.Configuration("assembly");
if (pc != null)
{
provider = pc["Log"] ?? Data.Provider.Create("Log", "none");
}
else
{
provider = Data.Provider.Create("Log", "none");
}
if (this.csvWriter != null)
{
try
{
this.csvWriter.Close();
this.csvWriter.Dispose();
}
catch
{
}
}
this.Provider = provider;
switch (provider.Type)
{
case "csv":
this._isWriter = true;
var fields = provider["field"];
var fs = new List<string>(new string[] { "Address", "Site", "Path", "Username", "Duration", "Time", "Status", "UserAgent", "Account", "Referrer", "Attachment", "Server" });
if (String.IsNullOrEmpty(fields) == false)
{
foreach (var c in fields.Split(','))
{
var k = c.Trim();
if (String.IsNullOrEmpty(k) == false)
{
if (fs.Exists(r => String.Equals(r, k)) == false)
{
fs.Add(k);
}
}
}
}
this._csvFields = fs.ToArray();
break;
case "json":
this._isWriter = true;
try
{
this._httpUrl = new Uri(provider["url"]);
this._method = provider["method"];
}
catch
{
this._isWriter = false;
}
break;
case "sql":
var _table = provider["table"];
this._dbkey = provider["database"];
if (String.IsNullOrEmpty(_table) == false && String.IsNullOrEmpty(this._dbkey) == false)
{
var sb = new System.Text.StringBuilder();
sb.Append("INSERT INTO ");
sb.Append(_table);
sb.Append("(");
var values = new System.Text.StringBuilder();
var dbp = Database.Instance(this._dbkey).DbProvider;
this._isWriter = true;
for (var i = 0; i < provider.Attributes.Count; i++)
{
var key = provider.Attributes.GetKey(i);
switch (key)
{
case "name":
case "type":
case "table":
case "database":
break;
default:
if (values.Length > 0)
{
values.Append(",");
sb.Append(",");
}
values.Append("{");
values.Append(provider.Attributes.Get(i));
values.Append("}");
sb.Append(dbp.QuotePrefix);
sb.Append(key);
sb.Append(dbp.QuoteSuffix);
break;
}
}
sb.Append(")VALUES(");
sb.Append(values.ToString());
sb.Append(")");
this._sql = sb.ToString();
}
break;
}
}
ConcurrentQueue<Web.WebMeta> _logMetas = new ConcurrentQueue<Web.WebMeta>();
public virtual void Write(Web.WebMeta logMeta)
{
if (_isWriter)
{
_logMetas.Enqueue(logMeta);
if (IsWriting == false)
{
IsWriting = true;
System.Threading.Tasks.Task.Factory.StartNew(WriteLog);
}
}
}
void WriteJson(Web.WebMeta value, int time)
{
var req = _httpUrl.WebRequest();
Action<NetHttpResponse> action = (xhr) =>
{
if (xhr.StatusCode == System.Net.HttpStatusCode.OK)
{
error = 0;
}
else
{
xhr.ReadAsString(str =>
{
UMC.Data.Utility.Error("Proxy", DateTime.Now, value, str);
}, ex =>
{
UMC.Data.Utility.Error("Proxy", DateTime.Now, value, ex.ToString());
});
error++;
}
if (error > 100)
{
_isWriter = false;
}
if (time > 200)
{
IsWriting = false;
}
else if (_logMetas.TryDequeue(out value))
{
this.WriteJson(value, time + 1);
}
else
{
IsWriting = false;
}
};
if (String.Equals("PUT", this._method))
{
req.Put(value, action);
}
else
{
req.Post(value, action);
}
}
Regex regSql = new Regex("\\{(?<key>[\\w\\.\\$,\\[\\]_-]+)\\}");
void WriteSQL(Web.WebMeta value)
{
var dv = value.GetDictionary();
var ls = new List<Object>();
var sql = regSql.Replace(_sql, r =>
{
var key = r.Groups["key"].Value;
ls.Add(Get(key, dv));
return "{" + (ls.Count - 1) + "}";
});
Database.Instance(_dbkey).Sqler().ExecuteNonQuery(sql, ls.ToArray());
}
int _Day;
System.IO.StreamWriter csvWriter;
void WriteCsv(Web.WebMeta value)
{
var now = DateTime.Now;
if (_Day != now.Day)
{
_Day = now.Day;
if (csvWriter != null)
{
csvWriter.Close();
csvWriter.Dispose();
}
var file = UMC.Data.Reflection.ConfigPath(String.Format("Static\\log\\Proxy\\{0:yy-MM-dd}.log", now));
if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(file)))
{
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(file));
}
this.csvWriter = new System.IO.StreamWriter(file, true);
}
var dv = value.GetDictionary();
foreach (var f in this._csvFields)
{
CSV.CSVFormat(this.csvWriter, Get(f, dv));
this.csvWriter.Write(',');
}
this.csvWriter.WriteLine();
this.csvWriter.Flush();
}
object Get(String key, System.Collections.Hashtable value)
{
var em = value.GetEnumerator();
while (em.MoveNext())
{
var k = em.Key as string;
if (String.Equals(key, k, StringComparison.CurrentCultureIgnoreCase))
{
return em.Value;
}
}
return null;
}
int error = 0;
bool IsWriting = false;
void WriteLog()
{
Web.WebMeta value;
switch (this.Provider.Type)
{
case "csv":
case "sql":
while (_logMetas.TryDequeue(out value))
{
try
{
if (this.Provider.Type == "csv")
{
this.WriteCsv(value);
}
else
{
this.WriteSQL(value);
}
error = 0;
}
catch (Exception ex)
{
error++;
UMC.Data.Utility.Error("Proxy", DateTime.Now, value, ex.ToString());
}
if (error > 100)
{
_isWriter = false;
break;
}
}
IsWriting = false;
break;
default:
if (_logMetas.TryDequeue(out value))
{
this.WriteJson(value, 0);
}
else
{
IsWriting = false;
}
break;
}
}
public static void Instance(LogSetting logSetting, Provider provider)
{
logSetting.Provider = provider;
_Instance = logSetting;
}
}
}