Explorar el Código

1.developview界面增加log分类切换。
2.版本生成部分代码。已完成70%。

Jiangsheng hace 3 días
padre
commit
1e72b71154

+ 10 - 2
SKMC.API/Common/Logger/LogDataService.cs

@@ -12,7 +12,11 @@ namespace SKMC.Api.Common.Logger
     {
         private static LogDataService instance;
 
-        private readonly object lockObject = new object();
+        private readonly object lockEventObject = new object();
+        private readonly object lockProductionObject = new object();
+        private readonly object lockParameterObject = new object();
+        private readonly object lockProcessObject = new object();
+        private readonly object lockActionObject = new object();
         public ObservableCollection<LoggingEventModel> LogEventModels { get; set; } = new ObservableCollection<LoggingEventModel>();
         public ObservableCollection<LoggingEventModel> LogProductionModels { get; set; } = new ObservableCollection<LoggingEventModel>();
         public ObservableCollection<LoggingEventModel> LogParameterModels { get; set; } = new ObservableCollection<LoggingEventModel>();
@@ -27,7 +31,11 @@ namespace SKMC.Api.Common.Logger
 
         private LogDataService()
         {
-            //BindingOperations.EnableCollectionSynchronization(LogEventModels, lockObject);
+            BindingOperations.EnableCollectionSynchronization(LogEventModels, lockEventObject);
+            BindingOperations.EnableCollectionSynchronization(LogProductionModels, lockProductionObject);
+            BindingOperations.EnableCollectionSynchronization(LogParameterModels, lockParameterObject);
+            BindingOperations.EnableCollectionSynchronization(LogProcessModels, lockProcessObject);
+            BindingOperations.EnableCollectionSynchronization(LogActionModels, lockActionObject);
         }
     }
 }

+ 15 - 1
SKMC.API/Common/Logger/LogFactory.cs

@@ -1,4 +1,5 @@
-using System;
+using NLog;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.CompilerServices;
@@ -9,6 +10,19 @@ namespace SKMC.Api.Common.Logger
 {
     public class LogFactory
     {
+        static LogFactory()
+        {
+            // NLog特殊处理,需要先注册Target再获取LOG实例,否则Target内部方法无法触发。
+            NLog.LogManager.Setup()
+                .SetupExtensions(ext =>
+                {
+                    ext.RegisterTarget<LoggingProductionTarget>("LoggingProductionTarget");
+                    ext.RegisterTarget<LoggingParameterTarget>("LoggingParameterTarget");
+                    ext.RegisterTarget<LoggingProcessTarget>("LoggingProcessTarget");
+                    ext.RegisterTarget<LoggingActionTarget>("LoggingActionTarget");
+                })
+                .LoadConfigurationFromFile("nlog.config");
+        }
         /// <summary>
         /// "Log4Net" 或 "NLog"
         /// </summary>

+ 78 - 0
SKMC.API/Common/Version/GitCommandHelper.cs

@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+namespace SKMC.Api.Common.Version
+{
+    /// <summary>
+    /// git指令帮助类
+    /// </summary>
+    internal static class GitCommandHelper
+    {
+        private static readonly Dictionary<string, Dictionary<string, string>> _cache = new Dictionary<string, Dictionary<string, string>>();
+        private static readonly object _lock = new object();
+        /// <summary>
+        /// 通过执行git指令获取git提交的哈希值/id
+        /// </summary>
+        /// <param name="workingDir">git文件存在的文件夹</param>
+        /// <param name="args"></param>
+        /// <param name="noCache"></param>
+        /// <returns></returns>
+        public static string Run(string workingDir, string args, bool noCache = false)
+        {
+            if (string.IsNullOrEmpty(workingDir)) return string.Empty;
+
+            lock (_lock)
+            {
+                if (!noCache && _cache.TryGetValue(workingDir, out var dict) && dict.TryGetValue(args, out var v))
+                    return v;
+            }
+
+            try
+            {
+                var psi = new ProcessStartInfo
+                {
+                    FileName = "git",
+                    Arguments = args,
+                    WorkingDirectory = workingDir,
+                    UseShellExecute = false,
+                    RedirectStandardOutput = true,
+                    RedirectStandardError = true,
+                    StandardOutputEncoding = Encoding.UTF8,
+                    CreateNoWindow = true
+                };
+
+                var process = System.Diagnostics.Process.Start(psi);
+                process.WaitForExit(1000);
+                var output = process.StandardOutput.ReadToEnd().Trim();
+                var error = process.StandardError.ReadToEnd().Trim();
+
+                if (process.ExitCode != 0 || !string.IsNullOrEmpty(error))
+                    return string.Empty;
+
+                lock (_lock)
+                {
+                    if (!_cache.ContainsKey(workingDir))
+                        _cache[workingDir] = new Dictionary<string, string>();
+                    _cache[workingDir][args] = output;
+                }
+
+                return output;
+            }
+            catch
+            {
+                return string.Empty;
+            }
+        }
+
+        public static void ClearCache(string dir = null)
+        {
+            lock (_lock)
+            {
+                if (dir == null) _cache.Clear();
+                else _cache.Remove(dir);
+            }
+        }
+    }
+}

+ 35 - 0
SKMC.API/Common/Version/ModuleVersion.cs

@@ -0,0 +1,35 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+
+namespace SKMC.Api.Common.Version
+{
+    public class ModuleVersion
+    {
+        public string Name { get; set; }
+        public string CommitHash { get; set; }
+        public string ShortVersion => string.IsNullOrEmpty(CommitHash) || CommitHash.Length < 7
+            ? CommitHash
+            : CommitHash.Substring(0, 7);
+
+        public string Branch { get; set; }
+        public string Author { get; set; }
+        public DateTime CommitTime { get; set; }
+        public string CommitMessage { get; set; }
+        public bool HasUncommittedChanges { get; set; }
+        public string Path { get; set; }
+        public string DisplayVersion
+        {
+            get
+            {
+                var shortHash = string.IsNullOrEmpty(CommitHash) || CommitHash.Length < 7
+                    ? "unknown"
+                    : CommitHash.Substring(0, 7);
+                return $"1.0.0.git{shortHash}";
+            }
+        }
+        public string AssemblyFileVersion { get; set; }
+        public string Dependencies { get; set; } = string.Empty;
+        public string DependedBy { get; set; } = string.Empty;
+    }
+}

+ 41 - 0
SKMC.API/Common/Version/ModuleVersionEntity.cs

@@ -0,0 +1,41 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SKMC.Api.Common.Version
+{
+    [SugarTable("SKMC_MODULE_VERSION")]
+    public class ModuleVersionEntity
+    {
+        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+        public long Id { get; set; }
+        public string Name { get; set; }
+        public string CommitHash { get; set; }
+        public string ShortVersion => string.IsNullOrEmpty(CommitHash) || CommitHash.Length < 7
+            ? CommitHash
+            : CommitHash.Substring(0, 7);
+
+        public string Branch { get; set; }
+        public string Author { get; set; }
+        public DateTime CommitTime { get; set; }
+        public string CommitMessage { get; set; }
+        public bool HasUncommittedChanges { get; set; }
+        public string Path { get; set; }
+        public string DisplayVersion
+        {
+            get
+            {
+                var shortHash = string.IsNullOrEmpty(CommitHash) || CommitHash.Length < 7
+                    ? "unknown"
+                    : CommitHash.Substring(0, 7);
+                return $"1.0.0.git{shortHash}";
+            }
+        }
+        public string AssemblyFileVersion { get; set; }
+        public string Dependencies { get; set; }
+        public string DependedBy { get; set; }
+    }
+}

+ 14 - 0
SKMC.API/Common/Version/ProjectVersion.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+
+namespace SKMC.Api.Common.Version
+{
+    public class ProjectVersion
+    {
+        public string ProjectName { get; set; }
+        public string RootCommitHash { get; set; }
+        public DateTime BuildTime { get; set; }
+        public List<ModuleVersion> Modules { get; set; } = new List<ModuleVersion>();
+        public string ErrorMessage { get; set; }
+    }
+}

+ 116 - 0
SKMC.API/Common/Version/RuntimeVersionProvider.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace SKMC.Api.Common.Version
+{
+    public class RuntimeVersionProvider
+    {
+        /// <summary>
+        /// 获取模块版本信息
+        /// </summary>
+        /// <param name="directory">路径</param>
+        /// <returns></returns>
+        public ModuleVersion GetModuleVersion(string directory)
+        {
+            if (!Directory.Exists(directory))
+                return new ModuleVersion { Name = Path.GetFileName(directory) };
+
+            var commit = GitCommandHelper.Run(directory, "rev-parse HEAD");
+            var branch = GitCommandHelper.Run(directory, "rev-parse --abbrev-ref HEAD");
+            var author = GitCommandHelper.Run(directory, "log -1 --format=%an");
+            var time = GitCommandHelper.Run(directory, "log -1 --format=%ci");
+            var msg = GitCommandHelper.Run(directory, "log -1 --format=%s");
+            var dirty = !string.IsNullOrEmpty(GitCommandHelper.Run(directory, "status --porcelain", noCache: true));
+
+            DateTime.TryParse(time?.Split('+')[0]?.Trim(), out var commitTime);
+            var moduleVersion = new ModuleVersion
+            {
+                Name = Path.GetFileName(directory),
+                CommitHash = commit,
+                Branch = branch,
+                Author = author,
+                CommitTime = commitTime,
+                CommitMessage = msg,
+                HasUncommittedChanges = dirty,
+                Path = directory,
+                AssemblyFileVersion = GetAssemblyVersion(directory)
+            };
+            return moduleVersion;
+        }
+        /// <summary>
+        /// 获取项目版本
+        /// </summary>
+        /// <param name="rootDir"></param>
+        /// <returns></returns>
+        public ProjectVersion GetProjectVersions(string rootDir)
+        {
+            var project = new ProjectVersion
+            {
+                ProjectName = Path.GetFileName(rootDir),
+                BuildTime = DateTime.Now,
+                RootCommitHash = GitCommandHelper.Run(rootDir, "rev-parse HEAD")
+            };
+
+            foreach (var dir in Directory.GetDirectories(rootDir))
+            {
+                var folderName = Path.GetFileName(dir);
+                // 过滤文件
+                if (folderName.Equals(".git") || folderName.Equals("packages") || folderName.Equals("bin") || folderName.Equals("obj"))
+                    continue;
+                // 查找是否存在csproj格式文件
+                if (Directory.GetFiles(dir, "*.csproj", SearchOption.TopDirectoryOnly).Length > 0)
+                {
+                    project.Modules.Add(GetModuleVersion(dir));
+                }
+            }
+
+            return project;
+        }
+
+        public string FindGitRoot(string startDir)
+        {
+            try
+            {
+                var dir = new DirectoryInfo(startDir);
+                while (dir != null)
+                {
+                    if (Directory.Exists(Path.Combine(dir.FullName, ".git")))
+                        return dir.FullName;
+                    dir = dir.Parent;
+                }
+            }
+            catch { }
+            return null;
+        }
+        private string GetAssemblyVersion(string modulePath)
+        {
+            try
+            {
+                var moduleName = Path.GetFileName(modulePath);
+                var dllPath = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory), $"{moduleName}.dll");
+                var exePath = Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory), $"{moduleName}.exe");
+
+                if (!System.IO.File.Exists(dllPath) && !System.IO.File.Exists(exePath))
+                    return "unknown";
+
+                var path = new[] { exePath, dllPath }.FirstOrDefault(System.IO.File.Exists);
+                var assembly = Assembly.LoadFrom(path);
+                var informationalVersion = assembly.GetCustomAttributesData()
+                    .FirstOrDefault(a => a.AttributeType == typeof(AssemblyInformationalVersionAttribute))?
+                    .ConstructorArguments.FirstOrDefault().Value?.ToString();
+
+                if (!string.IsNullOrEmpty(informationalVersion))
+                    return informationalVersion;
+
+                return $"{assembly.GetName().Version}";
+            }
+            catch
+            {
+                return "unknown";
+            }
+        }
+    }
+}

+ 145 - 0
SKMC.API/Common/Version/VersionHelper.cs

@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Xml.Linq;
+
+namespace SKMC.Api.Common.Version
+{
+    public static class VersionHelper
+    {
+        private static readonly RuntimeVersionProvider _provider = new RuntimeVersionProvider();
+        private static readonly Dictionary<string, ProjectVersion> projectsCacher = new Dictionary<string, ProjectVersion>();
+        /// <summary>
+        /// 获取当前工程/项目版本
+        /// </summary>
+        /// <param name="rootDirectory"></param>
+        /// <returns></returns>
+        public static ProjectVersion GetCurrentProjectVersion(string rootDirectory)
+        {
+            try
+            {
+                var gitRoot = _provider.FindGitRoot(rootDirectory);
+                if (string.IsNullOrEmpty(gitRoot))
+                {
+                    return new ProjectVersion { ErrorMessage = "未找到Git仓库" };
+                }
+                else
+                {
+                    var pro = GetFullProjectInfo(gitRoot);
+                    projectsCacher.Add(pro.ProjectName, pro);
+                    return pro;
+                }
+            }
+            catch (Exception ex)
+            {
+                return new ProjectVersion { ErrorMessage = ex.Message };
+            }
+        }
+
+        /// <summary>
+        /// 获取整个项目的版本信息
+        /// </summary>
+        /// <param name="rootPath"></param>
+        /// <returns></returns>
+        public static ProjectVersion GetFullProjectInfo(string rootPath)
+        {
+            var project = _provider.GetProjectVersions(rootPath);
+            GetDependencyResolve(project);
+            return project;
+        }
+
+        //public static string GetMainGitVersion()
+        //{
+        //    var p = GetCurrentProjectVersion();
+        //    var hash = string.IsNullOrEmpty(p?.RootCommitHash)
+        //        ? "unknown"
+        //        : p.RootCommitHash.Substring(0, 7);
+
+        //    return $"1.0.0.git{hash}";
+        //}
+
+        /// <summary>
+        /// 通过检索csproj文件,获取模块依赖信息
+        /// </summary>
+        /// <param name="project"></param>
+        public static void GetDependencyResolve(ProjectVersion project)
+        {
+            var moduleMap = project.Modules.ToDictionary(m => m.Name.ToLower());
+
+            foreach (var module in project.Modules)
+            {
+                var csproj = Directory.GetFiles(module.Path, "*.csproj").FirstOrDefault();
+                if (csproj == null) continue;
+
+                var doc = XDocument.Load(csproj);
+                XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
+
+                var refs = doc.Descendants(ns + "ProjectReference")
+                    .Select(x => x.Attribute("Include")?.Value)
+                    .Where(x => !string.IsNullOrEmpty(x))
+                    .ToList();
+
+                List<string> depy = new List<string>();
+                List<string> depb = new List<string>();
+                foreach (var rel in refs)
+                {
+                    var name = Path.GetFileNameWithoutExtension(rel).ToLower();
+                    if (moduleMap.TryGetValue(name, out var dep))
+                    {
+                        if (!module.Dependencies.Contains(dep.Name))
+                            depy.Add(dep.Name);
+
+                        if (!dep.DependedBy.Contains(module.Name))
+                            depb.Add(module.Name);
+                    }
+                }
+                module.Dependencies = string.Join(",", depy);
+                module.DependedBy = string.Join(",", depb);
+            }
+        }
+        /// <summary>
+        /// 模块合并
+        /// </summary>
+        public static ProjectVersion ModuleMerge()
+        {
+            var project = new ProjectVersion
+            {
+                BuildTime = DateTime.Now
+            };
+            foreach (var proj in projectsCacher)
+            {
+                project.ProjectName += proj.Value.ProjectName + "/";
+                project.ErrorMessage += proj.Value.ErrorMessage;
+                project.Modules.AddRange(proj.Value.Modules);
+            }
+            return project;
+        }
+
+        /// <summary>
+        /// 生成文本
+        /// </summary>
+        /// <param name="project"></param>
+        /// <returns></returns>
+        public static string GenerateText(ProjectVersion project)
+        {
+            var sb = new StringBuilder();
+            sb.AppendLine($"项目:{project.ProjectName}");
+            sb.AppendLine($"根版本:{project.RootCommitHash?.Substring(0, 7) ?? "unknown"}");
+            sb.AppendLine();
+
+            foreach (var m in project.Modules)
+            {
+                sb.AppendLine($"模块:{m.Name}");
+                sb.AppendLine($"版本:{m.ShortVersion} {(m.HasUncommittedChanges ? "[未提交]" : "")}");
+                sb.AppendLine($"依赖:{string.Join(", ", m.Dependencies)}");
+                sb.AppendLine($"被依赖:{string.Join(", ", m.DependedBy)}");
+                sb.AppendLine($"DLL 文件版本:{m.AssemblyFileVersion}");
+                sb.AppendLine();
+            }
+
+            return sb.ToString();
+        }
+    }
+}

+ 10 - 0
SKMC.API/SKMC.API.csproj

@@ -103,6 +103,16 @@
     <Compile Include="Client\Config\ClientConstants.cs" />
     <Compile Include="Client\Config\ClientException.cs" />
     <Compile Include="Client\Views\BaseEditorModel.cs" />
+    <Compile Include="Common\Logger\LoggingActionTarget.cs" />
+    <Compile Include="Common\Logger\LoggingParameterTarget.cs" />
+    <Compile Include="Common\Logger\LoggingProcessTarget.cs" />
+    <Compile Include="Common\Logger\LoggingProductionTarget.cs" />
+    <Compile Include="Common\Version\GitCommandHelper.cs" />
+    <Compile Include="Common\Version\ModuleVersion.cs" />
+    <Compile Include="Common\Version\ModuleVersionEntity.cs" />
+    <Compile Include="Common\Version\ProjectVersion.cs" />
+    <Compile Include="Common\Version\RuntimeVersionProvider.cs" />
+    <Compile Include="Common\Version\VersionHelper.cs" />
     <Compile Include="Core\Exceptions\ExceptionCacher.cs" />
     <Compile Include="Common\DB\IModelConverter.cs" />
     <Compile Include="Client\Access\ClientAccess.cs" />