lith %!s(int64=3) %!d(string=hai) anos
pai
achega
69693ff328

+ 2 - 1
dotnet/ServiceCenter/App.ServiceCenter/App.ServiceCenter.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
 	<PropertyGroup>
 		<publish>ServiceCenter</publish>
@@ -29,6 +29,7 @@
 		<ProjectReference Include="..\..\Library\Sers\Sers.CL\Zmq\FullDuplex\Sers.CL.Zmq.FullDuplex\Sers.CL.Zmq.FullDuplex.csproj" />
 		<ProjectReference Include="..\..\Library\Sers\Sers.CL\Zmq\ThreadWait\Sers.CL.ClrZmq.ThreadWait\Sers.CL.ClrZmq.ThreadWait.csproj" />
 		<ProjectReference Include="..\..\Library\Sers\Sers.Gateway\Sers.Gateway\Sers.Gateway.csproj" />
+		<ProjectReference Include="..\Sers.ServiceCenter\Apm\Sers.Gover.Apm.Txt\Sers.Gover.Apm.Txt.csproj" />
 		<ProjectReference Include="..\Sers.ServiceCenter\Apm\Sers.Gover.Apm.Zipkin\Sers.Gover.Apm.Zipkin.csproj" />
 		<ProjectReference Include="..\Sers.ServiceCenter\Sers.Gover\Sers.Gover.csproj" />
 	</ItemGroup>

+ 244 - 0
dotnet/ServiceCenter/Sers.ServiceCenter/Apm/Sers.Gover.Apm.Txt/AppEvent.cs

@@ -0,0 +1,244 @@
+using Newtonsoft.Json.Linq;
+using Sers.Core.Module.App.AppEvent;
+using Sers.Core.Module.Message;
+using Sers.Core.Module.Rpc;
+using Sers.Gover.Base;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Vit.Core.Module.Log;
+using Vit.Extensions;
+using Vit.Extensions.IEnumerable;
+
+namespace Sers.Gover.Apm.Txt
+{
+
+    public class AppEvent : IAppEvent
+    {
+
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        Action<Object, Vit.Core.Util.Pipelines.ByteData> ApiScopeEvent(RpcContextData rpcData, ApiMessage apiRequestMessage)
+        {
+            //记录请求数据
+
+            var beginTime = DateTime.Now;       
+
+
+            return (s, apiReplyMessage) => {
+
+                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 = new ApiMessage();
+                                    apiResponseMessage.Unpack(apiReplyMessage.ToArraySegment());
+                                }
+                                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 = new ApiMessage();
+                                    apiResponseMessage.Unpack(apiReplyMessage.ToArraySegment());
+                                }
+                                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();
+
+                msg.Append(Environment.NewLine).Append("┍------------ ---------┑");
+
+                msg.Append(Environment.NewLine).Append("--BeginTime:").Append(beginTime.ToString("[HH:mm:ss.ffffff]"));
+                msg.Append(Environment.NewLine).Append("--EndTime  :").Append(endTime.ToString("[HH:mm:ss.ffffff]"));
+                msg.Append(Environment.NewLine).Append("--duration :").Append((endTime - beginTime).TotalMilliseconds).Append(" ms");
+
+         
+                config.tags?.ForEach(item =>
+                {
+                    //try
+                    //{
+                        var key = GetTagValue(item.Key);
+                        var value = GetTagValue(item.Value);
+                        if (key != null)
+                        {
+                            msg.Append(Environment.NewLine).Append("--" + key + ":").Append(value);
+                        }
+                    //}
+                    //catch
+                    //{
+                    //}
+                });                
+                 
+
+                msg.Append(Environment.NewLine).Append("┕------------ ---------┙").Append(Environment.NewLine);
+
+                Logger.log.LogTxt(Level.ApiTrace, msg.ToString()); 
+            };
+        }
+
+
+        public void InitEvent(JObject arg)
+        {
+            config = arg.Deserialize<Config>();
+
+            Logger.Info("[Sers.Gover.Apm.Txt]初始化中...  ");
+        }
+
+
+        Config config;
+
+        public void BeforeStart()
+        {
+            if (config == null) return;
+
+            GoverApiCenterService.Instance.AddApiScopeEvent(ApiScopeEvent);
+
+            Logger.Info("[Sers.Gover.Apm.Txt]初始化成功");
+        }
+
+
+
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        public void OnStart()
+        { 
+        }
+
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        public void AfterStart()
+        {         
+        }
+
+
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        public void BeforeStop()
+        {
+          
+           
+        }
+
+
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        public void AfterStop()
+        {
+            
+        }
+    }
+
+
+    #region Config Model
+    class Config
+    {  
+        public IDictionary<string, string> tags;
+    }
+    #endregion
+
+}

+ 28 - 0
dotnet/ServiceCenter/Sers.ServiceCenter/Apm/Sers.Gover.Apm.Txt/Sers.Gover.Apm.Txt.csproj

@@ -0,0 +1,28 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<TargetFramework>netstandard2.0</TargetFramework>
+		<Version>2.1.8-temp</Version>
+	</PropertyGroup>
+
+	<PropertyGroup>
+		<Authors>Lith</Authors>
+		<Description>Sers微服务-服务中心Apm。对Zipkin的支持。</Description>
+		<PackageProjectUrl>https://github.com/serset/Sers</PackageProjectUrl>
+	</PropertyGroup>
+
+	<PropertyGroup>
+		<DocumentationFile>bin\Debug\netstandard2.0\Sers.Gover.Apm.Zipkin.xml</DocumentationFile>
+	</PropertyGroup>
+
+	<ItemGroup>
+		<PackageReference Include="zipkin4net" Version="1.5.0" />
+	</ItemGroup>
+
+	<ItemGroup>
+		<ProjectReference Include="..\..\Sers.Gover\Sers.Gover.csproj" />
+	</ItemGroup>
+
+
+
+</Project>

+ 43 - 0
dotnet/ServiceCenter/Sers.ServiceCenter/Apm/Sers.Gover.Apm.Txt/appsettings.json

@@ -0,0 +1,43 @@
+{
+  "Sers": {
+
+    /* 动态加载的App事件 */
+    "AppEvent": [
+      { //记录请求Trace到 Log/{yyyy-MM}/[{yyyy-MM-dd}]ApiTrace.txt文件
+
+        /* 在此Assembly中加载类 */
+        "assemblyFile": "Sers.Gover.Apm.Txt.dll",
+        /* 动态加载的类名,必须继承接口 Sers.Core.Module.App.AppEvent.IAppEvent */
+        "className": "Sers.Gover.Apm.Txt.AppEvent",
+
+
+        "tags": {
+          // 可为 requestRpc requestData responseRpc responseData
+          "From": "Sers.Gover.Apm.Txt",
+
+          "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}}"
+
+        }
+      }
+    ]
+
+
+  }
+
+
+
+}

+ 4 - 4
dotnet/ServiceCenter/Sers.ServiceCenter/Apm/Sers.Gover.Apm.Zipkin/AppEvent.cs

@@ -147,7 +147,7 @@ namespace Sers.Gover.Apm.Zipkin
                                 {
                                     requestRpc_json = requestRpc_oriString.Deserialize<JObject>();
                                 }
-                                return requestRpc_json.SelectToken(path).ConvertToString();
+                                return requestRpc_json?.SelectToken(path).ConvertToString();
 
                             case "requestData":
                                 if (requestData_oriString == null)
@@ -162,7 +162,7 @@ namespace Sers.Gover.Apm.Zipkin
                                 {
                                     requestData_json = requestData_oriString.Deserialize<JObject>();
                                 }
-                                return requestData_json.SelectToken(path).ConvertToString();
+                                return requestData_json?.SelectToken(path).ConvertToString();
 
                             case "responseRpc":
                                 if (apiResponseMessage == null)
@@ -182,7 +182,7 @@ namespace Sers.Gover.Apm.Zipkin
                                 {
                                     responseRpc_json = responseRpc_oriString.Deserialize<JObject>();
                                 }
-                                return responseRpc_json.SelectToken(path).ConvertToString();
+                                return responseRpc_json?.SelectToken(path).ConvertToString();
 
                             case "responseData":
                                 if (apiResponseMessage == null)
@@ -202,7 +202,7 @@ namespace Sers.Gover.Apm.Zipkin
                                 {
                                     responseData_json = responseData_oriString.Deserialize<JObject>();
                                 }
-                                return responseData_json.SelectToken(path).ConvertToString();
+                                return responseData_json?.SelectToken(path).ConvertToString();
                         }
                     }
                     catch