lith 3 anos atrás
pai
commit
3fd39273d9
16 arquivos alterados com 489 adições e 375 exclusões
  1. 60 0
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/ElasticSearchCollector.appsettings.json
  2. 97 0
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/ElasticSearchCollector.cs
  3. 4 4
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/SplunkCollector.appsettings.json
  4. 62 43
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/SplunkCollector.cs
  5. 5 127
      dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/TxtCollector.cs
  6. 6 6
      dotnet/Library/Vit/Vit.Core/Test/Vit.Core.MsTest/appsettings.json
  7. 9 9
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/Client/ElasticSearchClient.cs
  8. 57 0
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/Client/ElasticSearchRecord.cs
  9. 4 3
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/ElasticSearchCollector.cs
  10. 0 62
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/LogMessage.cs
  11. 42 0
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/LogRecord.cs
  12. 13 8
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/Client/SplunkClient.cs
  13. 63 0
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/Client/SplunkRecord.cs
  14. 0 86
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/LogMessage.cs
  15. 47 0
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/LogRecord.cs
  16. 20 27
      dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/SplunkCollector.cs

+ 60 - 0
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/ElasticSearchCollector.appsettings.json

@@ -0,0 +1,60 @@
+{
+  "Sers": {
+
+    /* ApiTrace 搜集器配置,可不指定 */
+    "ApiTrace": {
+      "Collector": [
+        { //搜集ApiTrace到 ElasticSearch
+
+          /* 搜集器名称(ApiTrace推送端根据此名称推送到对应的搜集器),若不指定则不加载 */
+          "collectorName": "default",
+
+          /* 在此Assembly中加载类 */
+          "assemblyFile": "Sers.Core.dll",
+          /* 动态加载的类名,必须继承接口 Sers.Core.Module.ApiTrace.Collector.IApiTraceCollector */
+          "className": "Sers.Core.Module.ApiTrace.Collector.ElasticSearchCollector",
+
+
+          "server": {
+            // es address, example:"http://192.168.20.20:9200"
+            "url": "http://192.168.20.20:9200",
+            //es index, example:"dev"
+            "index": "dev_apiTrace",
+            //es type, example:"_doc"
+            //"type": "_doc",
+            //若指定则在指定时间间隔统一推送数据,若不指定则立即推送。单位:ms
+            "//intervalMs": 2000
+          },
+
+          //custome object
+          "//appInfo": {
+            "namespace": "mc.sers.cloud",
+            "appName": "mc",
+            "moduleName": "sers"
+            //,"...": {}
+          },
+
+          "//tags": {
+            // 可为 requestRpc requestData responseRpc responseData
+            "route": "{{requestRpc.route}}",
+            //"{{requestRpc.route}}": "route",
+
+            "url": "{{requestRpc.http.url}}",
+            "method": "{{requestRpc.http.method}}",
+            "requestRpc": "{{requestRpc}}",
+            "requestData": "{{requestData}}",
+
+            "responseRpc": "{{responseRpc}}",
+            "responseState": "{{responseRpc.http.headers.responseState}}",
+            //"responseError_Base64": "{{responseRpc.http.headers.responseError_Base64}}"
+
+            "responseData": "{{responseData}}",
+            "responseData.error": "{{responseData.error}}"
+          }
+        }
+      ]
+    }
+
+  }
+
+}

+ 97 - 0
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/ElasticSearchCollector.cs

@@ -0,0 +1,97 @@
+using Newtonsoft.Json.Linq;
+using Sers.Core.Module.Message;
+using Sers.Core.Module.Rpc;
+
+using System;
+using System.Collections.Generic;
+using Vit.Extensions;
+using Vit.Core.Module.Log;
+using Vit.Core.Module.Log.LogCollector.ElasticSearch.Client;
+using Newtonsoft.Json;
+
+namespace Sers.Core.Module.ApiTrace.Collector
+{
+    public class ElasticSearchCollector : IApiTraceCollector
+    {
+        // ElasticSearch ApiTrace Record Format:
+        // "index": "dev", "type": "_doc"
+        /* 
+        {
+            "@timestamp":1653468236619,
+            "time": "2022-05-25T08:19:36.686Z", 
+
+            "level": "ApiTrace",
+            "apiTrace": {
+                "beginTime":"2022-03-26 02:52:00.123456",
+                "endTime":"2022-03-26 02:52:04.123456",
+                "duration":"4000.0",
+
+                //extTags
+            },
+
+            //custome object
+            "appInfo": {
+                "namespace": "mc.sers.cloud",
+                "appName": "mc",
+                "moduleName": "sers"
+                //,"...": {}
+            }
+        }
+        */
+        public class ApiTraceRecord : ElasticSearchRecord
+        {
+            [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+            public string level;
+
+            [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+            public JObject apiTrace;
+        }
+
+
+        ElasticSearchClient client;
+        JObject appInfo;
+
+        IDictionary<string, string> tagsTemplate;
+
+        public void Init(JObject arg)
+        {
+            Logger.Info("[ApiTrace.ElasticSearchCollector]初始化中");
+            client = arg["client"].Deserialize<ElasticSearchClient>();
+
+            appInfo = arg?["appInfo"]?.Deserialize<JObject>();
+            tagsTemplate = arg?["tags"]?.Deserialize<IDictionary<string, string>>();
+
+            client?.Init();
+        }
+
+        public void AppBeforeStart()
+        {
+            Logger.Info("[ApiTrace.ElasticSearchCollector]初始化成功");
+        }
+
+        public void AppBeforeStop()
+        {
+
+        }
+
+        public object TraceStart(RpcContextData rpcData)
+        {
+            return DateTime.Now;
+        }
+        public void TraceEnd(object traceData, RpcContextData rpcData, ApiMessage apiRequestMessage, Func<ApiMessage> GetApiReplyMessage)
+        {
+            JObject eventData = SplunkCollector.BuildEventData(traceData, rpcData, apiRequestMessage, GetApiReplyMessage, tagsTemplate);
+
+            var record = new ApiTraceRecord
+            {
+                Time = DateTime.UtcNow,
+
+                level = "ApiTrace",
+                apiTrace = eventData,
+
+                appInfo = appInfo
+            };
+            client.SendAsync(record);
+        }
+    }
+}

+ 4 - 4
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/SplunkCollector.appsettings.json

@@ -15,15 +15,15 @@
           "className": "Sers.Core.Module.ApiTrace.Collector.SplunkCollector",
 
 
-          "client": {
+          "server": {
             "url": "http://192.168.20.20:8088/services/collector",
             "authToken": "xxxxx",
+            "index": "dev",
             //若指定则在指定时间间隔统一推送数据,若不指定则立即推送。单位:ms
             "//intervalMs": 2000
           },
 
-          "//message": {
-            "index": "dev",
+          "//hostInfo": {
             "host": "192.168.20.20:8088",
             "source": "http:mc",
             "sourcetype": "httpevent"
@@ -37,7 +37,7 @@
             //,"...": {}
           },
 
-          "//tags": {
+          "tags": {
             // 可为 requestRpc requestData responseRpc responseData
             "route": "{{requestRpc.route}}",
             //"{{requestRpc.route}}": "route",

+ 62 - 43
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/SplunkCollector.cs

@@ -6,41 +6,46 @@ using System;
 using System.Collections.Generic;
 using Vit.Extensions;
 using Vit.Core.Module.Log;
-using Vit.Core.Module.Log.LogCollector.Splunk;
+using Vit.Core.Module.Log.LogCollector.Splunk.Client;
 
 namespace Sers.Core.Module.ApiTrace.Collector
 {
     public class SplunkCollector : IApiTraceCollector
     {
-        /*
-{
-    "host": "localhost",
-    "source": "random-data-generator",
-    "sourcetype": "my_sample_data",
-    "index": "dev",
-    "event": { 
-        "level": "ApiTrace",
-
-        "appInfo": { //custome object
-            "namespace": "mc.sers.cloud",
-            "appName": "mc",
-            "moduleName": "sers"
-            //,"...": {}
-        },
-
-        "beginTime":"2022-03-26 02:52:00.123456",
-        "endTime":"2022-03-26 02:52:04.123456",
-        "duration":"4000.0",
-
-        //extTags
-    }
-}
+        // Splunk ApiTrace Record Format:
+        /* 
+        {
+            "time": 1426279439.123,
+
+            "index": "dev",
+
+            "host": "localhost",
+            "source": "random-data-generator",
+            "sourcetype": "my_sample_data",
+
+            "event": { 
+                "level": "ApiTrace",
+
+                "appInfo": { //custome object
+                    "namespace": "mc.sers.cloud",
+                    "appName": "mc",
+                    "moduleName": "sers"
+                    //,"...": {}
+                },
+
+                "beginTime":"2022-03-26 02:52:00.123456",
+                "endTime":"2022-03-26 02:52:04.123456",
+                "duration":"4000.0",
+
+                //extTags
+            }
+        }
         */
 
 
 
         SplunkClient client;
-        SplunkRecord message;
+        SplunkRecord hostInfo;
         JObject appInfo;
 
         IDictionary<string, string> tagsTemplate;
@@ -48,11 +53,13 @@ namespace Sers.Core.Module.ApiTrace.Collector
         public void Init(JObject arg)
         {
             Logger.Info("[ApiTrace.SplunkCollector]初始化中");
-            client = arg["client"].Deserialize<SplunkClient>();
-            client.Init();
-            message = arg?["message"]?.Deserialize<SplunkRecord>();
+            client = arg["server"].Deserialize<SplunkClient>();
+
+            hostInfo = arg?["hostInfo"]?.Deserialize<SplunkRecord>();
             appInfo = arg?["appInfo"]?.Deserialize<JObject>();
             tagsTemplate = arg?["tags"]?.Deserialize<IDictionary<string, string>>();
+
+            client?.Init();
         }
 
         public void AppBeforeStart()
@@ -69,16 +76,37 @@ namespace Sers.Core.Module.ApiTrace.Collector
         {
             return DateTime.Now;
         }
+
         public void TraceEnd(object traceData, RpcContextData rpcData, ApiMessage apiRequestMessage, Func<ApiMessage> GetApiReplyMessage)
+        {
+            JObject eventData = BuildEventData(traceData, rpcData, apiRequestMessage, GetApiReplyMessage, tagsTemplate);
+            if (appInfo != null) eventData["appInfo"] = appInfo;
+
+            var record = new SplunkRecord
+            {
+                Time = DateTime.UtcNow,
+                index = hostInfo?.index,
+
+                host = hostInfo?.host ?? Environment.MachineName,
+                source = hostInfo?.source,
+                sourcetype = hostInfo?.sourcetype,
+
+                @event = eventData
+            };
+            client.SendAsync(record);
+        }
+
+
+
+        #region BuildEventData    
+        public static JObject BuildEventData(object traceData, RpcContextData rpcData, ApiMessage apiRequestMessage, Func<ApiMessage> GetApiReplyMessage, IDictionary<string, string> tagsTemplate)
         {
             var beginTime = (DateTime)traceData;
 
             var endTime = DateTime.Now;
 
-
             JObject eventData = new JObject();
             eventData["level"] = "ApiTrace";
-            if (appInfo != null) eventData["appInfo"] = appInfo;
 
             eventData["beginTime"] = beginTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff");
             eventData["endTime"] = endTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff");
@@ -206,7 +234,7 @@ namespace Sers.Core.Module.ApiTrace.Collector
             #endregion
 
 
- 
+
             tagsTemplate?.IEnumerable_ForEach(item =>
             {
                 var key = GetTagValue(item.Key)?.ConvertToString();
@@ -217,19 +245,10 @@ namespace Sers.Core.Module.ApiTrace.Collector
 
             });
 
-            var record = new SplunkRecord
-            {
-                Time = DateTime.UtcNow,
-                index = message?.index,
-                host = message?.host ?? Environment.MachineName,
-                source = message?.source,
-                sourcetype = message?.sourcetype,
+            return eventData;
+        }
 
-                @event = eventData
-            };
-            client.SendAsync(record);
+        #endregion
 
- 
-        }
     }
 }

+ 5 - 127
dotnet/Library/Sers/Sers.Core/Sers.Core/Module/ApiTrace/Collector/TxtCollector.cs

@@ -44,128 +44,6 @@ namespace Sers.Core.Module.ApiTrace.Collector
             var endTime = DateTime.Now;
 
 
-            #region method getTagValue
-
-            string requestRpc_oriString = null;
-            JObject requestRpc_json = null;
-
-            string requestData_oriString = null;
-            JObject requestData_json = null;
-
-            ApiMessage apiResponseMessage = null;
-
-            string responseRpc_oriString = null;
-            JObject responseRpc_json = null;
-
-            string responseData_oriString = null;
-            JObject responseData_json = null;
-
-            string GetTagValue(string valueString)
-            {
-                if (string.IsNullOrEmpty(valueString)) return null;
-                if (!valueString.StartsWith("{{") || !valueString.EndsWith("}}")) return valueString;
-
-                try
-                {
-
-                    valueString = valueString.Substring(2, valueString.Length - 4);
-
-                    string dataType;
-                    string path;
-
-                    var splitIndex = valueString.IndexOf('.');
-                    if (splitIndex < 0)
-                    {
-                        dataType = valueString;
-                        path = "";
-                    }
-                    else
-                    {
-                        dataType = valueString.Substring(0, splitIndex);
-                        path = valueString.Substring(splitIndex + 1);
-                    }
-
-                    switch (dataType)
-                    {
-                        case "requestRpc":
-
-                            if (requestRpc_oriString == null)
-                            {
-                                requestRpc_oriString = apiRequestMessage.rpcContextData_OriData.ArraySegmentByteToString();
-                            }
-                            if (string.IsNullOrEmpty(path))
-                            {
-                                return requestRpc_oriString;
-                            }
-                            if (requestRpc_json == null)
-                            {
-                                requestRpc_json = requestRpc_oriString.Deserialize<JObject>();
-                            }
-                            return requestRpc_json?.SelectToken(path).ConvertToString();
-
-                        case "requestData":
-                            if (requestData_oriString == null)
-                            {
-                                requestData_oriString = apiRequestMessage.value_OriData.ArraySegmentByteToString();
-                            }
-                            if (string.IsNullOrEmpty(path))
-                            {
-                                return requestData_oriString;
-                            }
-                            if (requestData_json == null)
-                            {
-                                requestData_json = requestData_oriString.Deserialize<JObject>();
-                            }
-                            return requestData_json?.SelectToken(path).ConvertToString();
-
-                        case "responseRpc":
-                            if (apiResponseMessage == null)
-                            {
-                                apiResponseMessage = GetApiReplyMessage();
-                            }
-                            if (responseRpc_oriString == null)
-                            {
-                                responseRpc_oriString = apiResponseMessage.rpcContextData_OriData.ArraySegmentByteToString();
-                            }
-                            if (string.IsNullOrEmpty(path))
-                            {
-                                return responseRpc_oriString;
-                            }
-                            if (responseRpc_json == null)
-                            {
-                                responseRpc_json = responseRpc_oriString.Deserialize<JObject>();
-                            }
-                            return responseRpc_json?.SelectToken(path).ConvertToString();
-
-                        case "responseData":
-                            if (apiResponseMessage == null)
-                            {
-                                apiResponseMessage = GetApiReplyMessage();
-                            }
-                            if (responseData_oriString == null)
-                            {
-                                responseData_oriString = apiResponseMessage.value_OriData.ArraySegmentByteToString();
-                            }
-                            if (string.IsNullOrEmpty(path))
-                            {
-                                return responseData_oriString;
-                            }
-                            if (responseData_json == null)
-                            {
-                                responseData_json = responseData_oriString.Deserialize<JObject>();
-                            }
-                            return responseData_json?.SelectToken(path).ConvertToString();
-                    }
-                }
-                catch
-                {
-                }
-                return null;
-            }
-            #endregion
-
-
-
             StringBuilder msg = new StringBuilder(1024 * 4);
 
             msg.Append(Environment.NewLine).Append("┍------------ ---------┑");
@@ -175,16 +53,16 @@ namespace Sers.Core.Module.ApiTrace.Collector
             msg.Append(Environment.NewLine).Append("--duration :").Append((endTime - beginTime).TotalMilliseconds).Append(" ms");
 
 
-            tagsTemplate?.IEnumerable_ForEach(item =>
+            JObject eventData = SplunkCollector.BuildEventData(traceData, rpcData, apiRequestMessage, GetApiReplyMessage, tagsTemplate);
+            foreach (var kv in eventData)
             {
-                var key = GetTagValue(item.Key);
-                var value = GetTagValue(item.Value);
+                var key = kv.Key;
+                var value = kv.Value;
                 if (key != null)
                 {
                     msg.Append(Environment.NewLine).Append("--" + key + ":").Append(value);
                 }
-            });
-
+            }
 
             msg.Append(Environment.NewLine).Append("┕------------ ---------┙").Append(Environment.NewLine);
 

+ 6 - 6
dotnet/Library/Vit/Vit.Core/Test/Vit.Core.MsTest/appsettings.json

@@ -21,22 +21,22 @@
           /* 动态加载的类名,必须继承接口 Vit.Core.Module.Log.LogCollector.ILogCollector */
           //"className": "Vit.Core.Module.Log.LogCollector.Splunk.SplunkCollector",
 
-          "client": {
+          "server": {
             "url": "https://192.168.20.20:8088/services/collector",
             "authToken": "xxxxx",
+            "index": "dev",
             //若指定则在指定时间间隔统一推送数据,若不指定则立即推送。单位:ms
             "//intervalMs": 2000
           },
 
-          "message": {
-            "index": "dev",
+          "//hostInfo": {            
             "host": "192.168.20.20:8088",
             "source": "http:mc",
             "sourcetype": "httpevent"
           },
 
           //custome object
-          "appInfo": {
+          "//appInfo": {
             "namespace": "sers.cloud",
             "appName": "mc",
             "moduleName": "ServiceCenter"
@@ -49,11 +49,11 @@
           /* 动态加载的类名,必须继承接口 Vit.Core.Module.Log.LogCollector.ILogCollector */
           "className": "Vit.Core.Module.Log.LogCollector.ElasticSearch.ElasticSearchCollector",
 
-          "client": {
+          "server": {
             // es address, example:"http://192.168.20.20:9200"
             "url": "http://192.168.20.20:9200",
             //es index, example:"dev"
-            "index": "dev",
+            "index": "dev_log",
             //es type, example:"_doc"
             //"type": "_doc",
             //若指定则在指定时间间隔统一推送数据,若不指定则立即推送。单位:ms

+ 9 - 9
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/LogClient.cs → dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/Client/ElasticSearchClient.cs

@@ -5,9 +5,9 @@ using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Text;
 
-namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
+namespace Vit.Core.Module.Log.LogCollector.ElasticSearch.Client
 {
-    internal class LogClient
+    public class ElasticSearchClient
     {
         /// <summary>
         /// http://192.168.20.20:9200/dev/info/_bulk
@@ -57,7 +57,7 @@ namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
 
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public void SendAsync(LogMessage record)
+        public void SendAsync(ElasticSearchRecord record)
         {
             if (recordList == null)
                 SendToServer(new[] { record });
@@ -66,7 +66,7 @@ namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
         }
 
 
-        ~LogClient()
+        ~ElasticSearchClient()
         {
             if (time != null)
             {
@@ -77,16 +77,16 @@ namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
 
 
         #region Timer
-        ConcurrentBag<LogMessage> recordList;
-        ConcurrentBag<LogMessage> recordList_Swap;
+        ConcurrentBag<ElasticSearchRecord> recordList;
+        ConcurrentBag<ElasticSearchRecord> recordList_Swap;
         Util.Threading.Timer.SersTimer_SingleThread time;
 
         private void InitTimer()
         {
             if (intervalMs.HasValue && intervalMs.Value > 0)
             {
-                recordList = new ConcurrentBag<LogMessage>();
-                recordList_Swap = new ConcurrentBag<LogMessage>();
+                recordList = new ConcurrentBag<ElasticSearchRecord>();
+                recordList_Swap = new ConcurrentBag<ElasticSearchRecord>();
                 time = new Util.Threading.Timer.SersTimer_SingleThread();
                 time.intervalMs = intervalMs.Value;
                 time.timerCallback = (e) =>
@@ -109,7 +109,7 @@ namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
         private StringBuilder buffer = new StringBuilder();
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private void SendToServer(IEnumerable<LogMessage> records)
+        private void SendToServer(IEnumerable<ElasticSearchRecord> records)
         {
             var request = new HttpRequestMessage(HttpMethod.Post, bulkUrl);
             lock (buffer)

+ 57 - 0
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/Client/ElasticSearchRecord.cs

@@ -0,0 +1,57 @@
+using Newtonsoft.Json;
+
+using System;
+
+namespace Vit.Core.Module.Log.LogCollector.ElasticSearch.Client
+{
+
+    // ElasticSearch Record Format:
+    // "index": "dev", "type": "_doc"
+    /* 
+      {
+          "@timestamp":1653468236619,
+          "time": "2022-05-25T08:19:36.686Z", 
+
+          //custome object
+          "appInfo": {
+              "namespace": "mc.sers.cloud",
+              "appName": "mc",
+              "moduleName": "sers"
+              //,"...": {}
+          }
+
+          //,"...": {}
+      }
+  */
+
+    public class ElasticSearchRecord
+    {
+
+        [JsonProperty("@timestamp", NullValueHandling = NullValueHandling.Ignore)]
+        public string timestamp;
+
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string time;
+
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public object appInfo;
+
+
+        public DateTime Time 
+        {
+            set
+            {
+                //timestamp = value.ToTimeStamp();
+                timestamp = time = ToTimeString(value);
+            }
+        }
+
+
+        public static string ToTimeString(DateTime value)
+        {
+            return value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+        }
+    }
+}

+ 4 - 3
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/ElasticSearchCollector.cs

@@ -4,6 +4,7 @@ using System;
 
 using Vit.Extensions;
 using System.Linq;
+using Vit.Core.Module.Log.LogCollector.ElasticSearch.Client;
 
 namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
 {
@@ -16,19 +17,19 @@ namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
 
             this.config = config;
 
-            client = config["client"]?.Deserialize<LogClient>();
+            client = config["client"]?.Deserialize<ElasticSearchClient>();
             appInfo = config["appInfo"]?.Deserialize<object>();
             client?.Init();
         }
 
-        internal LogClient client;
+        internal ElasticSearchClient client;
         public object appInfo;
 
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         public void Write(Log.LogMessage msg)
         {
-            var record = new LogMessage
+            var record = new LogRecord
             {
                 Time = DateTime.UtcNow,
                 level = msg.level.ToString(),

+ 0 - 62
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/LogMessage.cs

@@ -1,62 +0,0 @@
-using Newtonsoft.Json;
-
-using System;
-
-namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
-{
-    internal class LogMessage
-    {
-        /* ElasticSearchMessage Format:
-        // "index": "dev", "type": "_doc",
-          {
-              "@timestamp":1653468236619,
-              "time": "2022-05-25T08:19:36.686Z", 
-              "level": "info",
-              "message": "Something happened",
-              "metadata": [],
-              //custome object
-              "appInfo": {
-                  "namespace": "mc.sers.cloud",
-                  "appName": "mc",
-                  "moduleName": "sers"
-                  //,"...": {}
-              }
-          }
-      */
-        [JsonProperty("@timestamp", NullValueHandling = NullValueHandling.Ignore)]
-        public string timestamp;
-
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string time;
-
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string level;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string message;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public Object[] metadata;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public object appInfo;
-
-
-        public DateTime Time 
-        {
-            set
-            {
-                //timestamp = value.ToTimeStamp();
-                timestamp = time = ToTimeString(value);
-            }
-        }
-
-
-        public static string ToTimeString(DateTime value)
-        {
-            return value.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
-        }
-    }
-}

+ 42 - 0
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/ElasticSearch/LogRecord.cs

@@ -0,0 +1,42 @@
+using Newtonsoft.Json;
+
+using System;
+
+using Vit.Core.Module.Log.LogCollector.ElasticSearch.Client;
+
+namespace Vit.Core.Module.Log.LogCollector.ElasticSearch
+{
+    // ElasticSearch LogRecord Format:
+    // "index": "dev", "type": "_doc"
+    /* 
+    {
+      "@timestamp":1653468236619,
+      "time": "2022-05-25T08:19:36.686Z", 
+
+      "level": "info",
+      "message": "Something happened",
+      "metadata": [],
+
+      //custome object
+      "appInfo": {
+          "namespace": "mc.sers.cloud",
+          "appName": "mc",
+          "moduleName": "sers"
+          //,"...": {}
+      }
+    }
+    */
+    public class LogRecord : ElasticSearchRecord
+    {
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string level;
+
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string message;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public Object[] metadata;
+    }
+}

+ 13 - 8
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/LogClient.cs → dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/Client/SplunkClient.cs

@@ -5,9 +5,9 @@ using System.Net.Http;
 using Vit.Extensions;
 using System.Collections.Concurrent;
 
-namespace Vit.Core.Module.Log.LogCollector.Splunk
+namespace Vit.Core.Module.Log.LogCollector.Splunk.Client
 {
-    internal class LogClient
+    public class SplunkClient
     {
 
         /// <summary>
@@ -17,6 +17,9 @@ namespace Vit.Core.Module.Log.LogCollector.Splunk
 
         public string authToken;
 
+        public string index;
+
+
         /// <summary>
         /// 若指定则在指定时间间隔统一推送数据,若不指定则立即推送。单位:ms
         /// </summary>
@@ -55,8 +58,10 @@ namespace Vit.Core.Module.Log.LogCollector.Splunk
 
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public void SendAsync(LogMessage record)
+        public void SendAsync(SplunkRecord record)
         {
+            record.index = index;
+
             if (recordList == null)
                 SendToServer(record);
             else
@@ -64,7 +69,7 @@ namespace Vit.Core.Module.Log.LogCollector.Splunk
         }
 
 
-        ~LogClient()
+        ~SplunkClient()
         {
             if (time != null)
             {
@@ -75,16 +80,16 @@ namespace Vit.Core.Module.Log.LogCollector.Splunk
 
 
         #region Timer
-        ConcurrentBag<LogMessage> recordList;
-        ConcurrentBag<LogMessage> recordList_Swap;
+        ConcurrentBag<SplunkRecord> recordList;
+        ConcurrentBag<SplunkRecord> recordList_Swap;
         Util.Threading.Timer.SersTimer_SingleThread time;
 
         private void InitTimer()
         {
             if (intervalMs.HasValue && intervalMs.Value > 0)
             {
-                recordList = new ConcurrentBag<LogMessage>();
-                recordList_Swap = new ConcurrentBag<LogMessage>();
+                recordList = new ConcurrentBag<SplunkRecord>();
+                recordList_Swap = new ConcurrentBag<SplunkRecord>();
                 time = new Util.Threading.Timer.SersTimer_SingleThread();
                 time.intervalMs = intervalMs.Value;
                 time.timerCallback = (e) =>

+ 63 - 0
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/Client/SplunkRecord.cs

@@ -0,0 +1,63 @@
+using Newtonsoft.Json;
+
+using System;
+
+using Vit.Extensions;
+
+namespace Vit.Core.Module.Log.LogCollector.Splunk.Client
+{
+
+    /* Splunk Record Format:
+    {
+       "time": 1426279439.123,  
+
+       "index": "dev",
+
+       "host": "localhost",
+       "source": "random-data-generator",
+       "sourcetype": "my_sample_data",
+
+       "event": { 
+          //"..."
+       }
+    }
+    */
+
+
+    public class SplunkRecord
+    {
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public double? time;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string index;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string host;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string source;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string sourcetype;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public object @event;
+
+
+
+        public DateTime Time { set => time = ToEpoch(value); }
+
+
+        public static double ToEpoch(DateTime value)
+        {
+            // From Splunk HTTP Collector Protocol
+            // The default time format is epoch time format, in the format <sec>.<ms>. 
+            // For example, 1433188255.500 indicates 1433188255 seconds and 500 milliseconds after epoch, 
+            // or Monday, June 1, 2015, at 7:50:55 PM GMT.
+            // See: http://dev.splunk.com/view/SP-CAAAE6P
+            return value.ToTimeStamp() / 1000.0;
+        }
+    }
+}

+ 0 - 86
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/LogMessage.cs

@@ -1,86 +0,0 @@
-using Newtonsoft.Json;
-
-using System;
-
-using Vit.Extensions;
-
-namespace Vit.Core.Module.Log.LogCollector.Splunk
-{
-    internal class LogMessage
-    {
-
-        /* SplunkMessage Format:
-        {
-           "time": 1426279439.123,  
-           "host": "localhost",
-           "source": "random-data-generator",
-           "sourcetype": "my_sample_data",
-           "index": "dev",
-           "event": { 
-               "level": "info",
-               "message": "Something happened",
-               "metadata": [],
-                //custome object
-               "appInfo": {
-                 "namespace": "mc.sers.cloud",
-                 "appName": "mc",
-                 "moduleName": "sers"
-                 //,"...": {}
-               }
-           }
-        }
-        */
-
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public double? time;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string index;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string host;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string source;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string sourcetype;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public Event @event;
-
-
-
-        public DateTime Time { set => time = ToEpoch(value); }
-
-
-        public static double ToEpoch(DateTime value)
-        {
-            // From Splunk HTTP Collector Protocol
-            // The default time format is epoch time format, in the format <sec>.<ms>. 
-            // For example, 1433188255.500 indicates 1433188255 seconds and 500 milliseconds after epoch, 
-            // or Monday, June 1, 2015, at 7:50:55 PM GMT.
-            // See: http://dev.splunk.com/view/SP-CAAAE6P
-            return value.ToTimeStamp() / 1000.0;
-        }
-    }
-
-
-    internal class Event
-    {
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string level;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public string message;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public Object[] metadata;
-
-        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
-        public object appInfo;
-    }
-
-}

+ 47 - 0
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/LogRecord.cs

@@ -0,0 +1,47 @@
+using Newtonsoft.Json;
+
+using System;
+
+namespace Vit.Core.Module.Log.LogCollector.Splunk
+{
+
+    /* Splunk LogRecord Format:
+    {
+       "time": 1426279439.123,  
+
+       "index": "dev",
+
+       "host": "localhost",
+       "source": "random-data-generator",
+       "sourcetype": "my_sample_data",
+
+       "event": { 
+           "level": "info",
+           "message": "Something happened",
+           "metadata": [],
+            //custome object
+           "appInfo": {
+             "namespace": "mc.sers.cloud",
+             "appName": "mc",
+             "moduleName": "sers"
+             //,"...": {}
+           }
+       }
+    }
+    */
+
+    public class LogEvent
+    {
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string level;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public string message;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public Object[] metadata;
+
+        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+        public object appInfo;
+    }
+}

+ 20 - 27
dotnet/Library/Vit/Vit.Core/Vit.Core/Module/Log/LogCollector/Splunk/SplunkCollector.cs

@@ -1,8 +1,8 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
 
 using System;
 
+using Vit.Core.Module.Log.LogCollector.Splunk.Client;
 using Vit.Extensions;
 
 namespace Vit.Core.Module.Log.LogCollector.Splunk
@@ -16,51 +16,44 @@ namespace Vit.Core.Module.Log.LogCollector.Splunk
 
             this.config = config;
 
-
-            client = config["client"]?.Deserialize<LogClient>();
-            message = config["message"]?.Deserialize<LogMessage>();
+            client = config["server"]?.Deserialize<SplunkClient>();
+            hostInfo = config["hostInfo"]?.Deserialize<SplunkRecord>();
             appInfo = config["appInfo"]?.Deserialize<object>();
             client?.Init();
         }
 
 
 
-        internal LogClient client;
-        internal LogMessage message;
+        internal SplunkClient client;
+        internal SplunkRecord hostInfo;
         public object appInfo;
 
 
         [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         public void Write(Log.LogMessage msg)
         {
-            var record = new LogMessage
+            var recordEvent = new LogEvent
+            {
+                level = msg.level.ToString(),
+                message = msg.message,
+                metadata = msg.metadata,
+                appInfo = appInfo
+            };
+            if (recordEvent.metadata != null && recordEvent.metadata.Length == 0) recordEvent.metadata = null;
+            var record = new SplunkRecord
             {
                 Time = DateTime.UtcNow,
-                index = message?.index,
-                host = message?.host ?? Environment.MachineName,
-                source = message?.source,
-                sourcetype = message?.sourcetype,
+                host = hostInfo?.host ?? Environment.MachineName,
+                source = hostInfo?.source,
+                sourcetype = hostInfo?.sourcetype,
 
-                @event = new Event
-                {
-                    level = msg.level.ToString(),
-                    message = msg.message,
-                    metadata = msg.metadata,
-                    appInfo = appInfo
-                }
+                @event = recordEvent
             };
 
-            if (record.@event.metadata != null && record.@event.metadata.Length == 0) record.@event.metadata = null;
-
             client.SendAsync(record);
         }
 
 
-
-
-
-
-
-
+ 
     }
 }