diff --git a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/AspNetCoreLogContext.cs b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/AspNetCoreLogContext.cs index 3141ebe05..165542262 100644 --- a/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/AspNetCoreLogContext.cs +++ b/framework/src/Bing.AspNetCore/Bing/AspNetCore/Logs/AspNetCoreLogContext.cs @@ -28,14 +28,11 @@ public class AspNetCoreLogContext : LogContext /// /// 初始化一个类型的实例 /// - /// 作用域字典 /// Web客户端信息提供程序 /// Http上下文访问器 public AspNetCoreLogContext( - ScopedDictionary scopedDictionary, - IHttpContextAccessor httpContextAccessor, + IHttpContextAccessor httpContextAccessor, IWebClientInfoProvider webClientInfoProvider) - : base(scopedDictionary) { HttpContextAccessor = httpContextAccessor; WebClientInfoProvider = webClientInfoProvider; @@ -50,9 +47,10 @@ protected override LogContextInfo CreateInfo() logContextInfo.Ip = WebClientInfoProvider.ClientIpAddress; logContextInfo.Browser = WebClientInfoProvider.ClientIpAddress; - logContextInfo.Url = HttpContextAccessor.HttpContext?.Request?.GetDisplayUrl(); - + logContextInfo.IsWebEnv = HttpContextAccessor.HttpContext?.Request != null; + if (logContextInfo.IsWebEnv) + logContextInfo.TraceId = TraceId; return logContextInfo; } @@ -65,7 +63,7 @@ protected override string GetTraceId() if (!string.IsNullOrWhiteSpace(correlationId)) return correlationId; var traceId = HttpContextAccessor.HttpContext?.TraceIdentifier; - return string.IsNullOrWhiteSpace(traceId) ? Guid.NewGuid().ToString() : Guid.TryParse(traceId, out _) ? traceId : Guid.NewGuid().ToString(); + return string.IsNullOrWhiteSpace(traceId) ? Guid.NewGuid().ToString("N") : Guid.TryParse(traceId, out _) ? traceId : Guid.NewGuid().ToString("N"); } } } diff --git a/framework/src/Bing.Data/Bing/Data/Queries/Conditions/DateSegmentCondition.cs b/framework/src/Bing.Data/Bing/Data/Queries/Conditions/DateSegmentCondition.cs index 22a2a2fcd..075bc797c 100644 --- a/framework/src/Bing.Data/Bing/Data/Queries/Conditions/DateSegmentCondition.cs +++ b/framework/src/Bing.Data/Bing/Data/Queries/Conditions/DateSegmentCondition.cs @@ -26,13 +26,6 @@ public DateSegmentCondition(Expression> propertyExpress { } - /// - /// 最小值是否大于最大值 - /// - /// 最小值 - /// 最大值 - protected override bool IsMinGreaterMax(DateTime? min, DateTime? max) => min > max; - /// /// 获取最小值表达式 /// diff --git a/framework/src/Bing.Datas.Dapper/Bing/Data/Sql/Queries/SqlQuery.cs b/framework/src/Bing.Datas.Dapper/Bing/Data/Sql/Queries/SqlQuery.cs index 4349cdf30..c482fd280 100644 --- a/framework/src/Bing.Datas.Dapper/Bing/Data/Sql/Queries/SqlQuery.cs +++ b/framework/src/Bing.Datas.Dapper/Bing/Data/Sql/Queries/SqlQuery.cs @@ -6,6 +6,7 @@ using Bing.Data.Sql.Diagnostics; using Bing.Helpers; using Bing.Logs; +using Bing.Logs.Internal; using Dapper; namespace Bing.Data.Sql.Queries @@ -264,7 +265,7 @@ protected override void WriteTraceLog(string sql, IReadOnlyDictionary + /// 日志 + /// + public ILog Log => LazyServiceProvider.LazyGetService() ?? NullLog.Instance; + /// /// 当前用户 /// @@ -158,7 +164,7 @@ protected virtual string GetUserName() protected void EnableLog(DbContextOptionsBuilder builder) { ConfiguringIgnoreEvent(builder); - var log = GetLog(); + var log = Log; if (IsEnabled(log) == false) return; builder.EnableSensitiveDataLogging(); @@ -170,6 +176,7 @@ protected void EnableLog(DbContextOptionsBuilder builder) /// 配置忽略事件 /// /// 配置事件 + /// 参考:https://docs.microsoft.com/zh-cn/ef/core/logging-events-diagnostics protected virtual void ConfiguringIgnoreEvent(DbContextOptionsBuilder builder) { builder.ConfigureWarnings(x => x.Ignore( @@ -196,21 +203,6 @@ protected virtual void ConfiguringIgnoreEvent(DbContextOptionsBuilder builder) )); } - /// - /// 获取日志操作 - /// - protected virtual ILog GetLog() - { - try - { - return Log.GetLog(EfLog.TraceLogName); - } - catch - { - return Log.Null; - } - } - /// /// 是否启用EF日志 /// diff --git a/framework/src/Bing.Datas.EntityFramework/Logs/EfLog.cs b/framework/src/Bing.Datas.EntityFramework/Logs/EfLog.cs index 256b80ba5..4ae24bfab 100644 --- a/framework/src/Bing.Datas.EntityFramework/Logs/EfLog.cs +++ b/framework/src/Bing.Datas.EntityFramework/Logs/EfLog.cs @@ -38,13 +38,16 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except Func formatter) { var config = GetConfig(); - var log = Bing.Logs.Log.GetLog(TraceLogName); + var log = GetUnitOfWork()?.Log; + if (log == null) + return; if (IsEnabled(eventId, config, exception) == false) return; if (!string.IsNullOrWhiteSpace(GetUnitOfWork().TraceId)) log.Tag(GetUnitOfWork()?.TraceId); + log.Tag(TraceLogName); log - .Caption("执行EF操作:") + .Caption($"执行EF操作:{formatter(state, exception)}") .Content($"工作单元跟踪号:{GetUnitOfWork()?.TraceId}") .Content($"事件ID:{eventId.Id}") .Content($"事件名称:{eventId.Name}"); diff --git a/framework/src/Bing.Events/Cap/MessageEventBus.cs b/framework/src/Bing.Events/Cap/MessageEventBus.cs index 663722851..b7de9a40f 100644 --- a/framework/src/Bing.Events/Cap/MessageEventBus.cs +++ b/framework/src/Bing.Events/Cap/MessageEventBus.cs @@ -25,15 +25,24 @@ public class MessageEventBus : IMessageEventBus /// public ITransactionActionManager TransactionActionManager { get; set; } + /// + /// 日志操作 + /// + protected ILog Log { get; set; } + /// /// 初始化一个类型的实例 /// /// 事件发布器 /// 事务操作管理器 - public MessageEventBus(ICapPublisher publisher, ITransactionActionManager transactionActionManager) + /// 日志操作 + public MessageEventBus(ICapPublisher publisher, + ITransactionActionManager transactionActionManager, + ILog log) { Publisher = publisher ?? throw new ArgumentNullException(nameof(publisher)); TransactionActionManager = transactionActionManager ?? throw new ArgumentNullException(nameof(transactionActionManager)); + Log = log; } /// @@ -86,7 +95,7 @@ private async Task InternalPublishAsync(string name, object data, IDictionary回调名称 private void WriteLog(string name, object data, string callback) { - var log = Log.GetLog(this); + var log = Log; if (log.IsDebugEnabled == false) return; log.Tag(name) diff --git a/framework/src/Bing.Logs.Exceptionless/Bing/Logs/Exceptionless/ExceptionlessProvider.cs b/framework/src/Bing.Logs.Exceptionless/Bing/Logs/Exceptionless/ExceptionlessProvider.cs index 11848b21d..d2174d5b9 100644 --- a/framework/src/Bing.Logs.Exceptionless/Bing/Logs/Exceptionless/ExceptionlessProvider.cs +++ b/framework/src/Bing.Logs.Exceptionless/Bing/Logs/Exceptionless/ExceptionlessProvider.cs @@ -1,4 +1,4 @@ -using System; +using System.Diagnostics; using System.Linq; using Bing.Configuration; using Bing.Extensions; @@ -72,6 +72,7 @@ public void WriteLog(LogLevel level, ILogContent content) // 致命错误 if (level == LogLevel.Fatal || level == LogLevel.Error) builder.MarkAsCritical(); + Debug.WriteLine($"【Exceptionless】Thread: {content.ThreadId}, LogId: {content.LogId}, TraceId: {content.TraceId}, Message: {GetMessage(content)}, Tags: [{content.Tags.ExpandAndToString()}]"); SetUser(content); SetSource(builder, content); SetReferenceId(builder, content); diff --git a/framework/src/Bing.Logs/Bing/Logs/Aspects/LogAttributeBase.cs b/framework/src/Bing.Logs/Bing/Logs/Aspects/LogAttributeBase.cs index 5252037dc..130cdc619 100644 --- a/framework/src/Bing.Logs/Bing/Logs/Aspects/LogAttributeBase.cs +++ b/framework/src/Bing.Logs/Bing/Logs/Aspects/LogAttributeBase.cs @@ -3,6 +3,7 @@ using AspectCore.DynamicProxy.Parameters; using Bing.Aspects.Base; using Bing.Extensions; +using Microsoft.Extensions.DependencyInjection; namespace Bing.Logs.Aspects { @@ -17,7 +18,7 @@ public abstract class LogAttributeBase : InterceptorBase public override async Task Invoke(AspectContext context, AspectDelegate next) { var methodName = GetMethodName(context); - var log = Log.GetLog(methodName); + var log = context.ServiceProvider.GetService(); if (!Enabled(log)) return; ExecuteBefore(log, context, methodName); diff --git a/framework/src/Bing.Logs/Bing/Logs/Extensions/LogExtensions.cs b/framework/src/Bing.Logs/Bing/Logs/Extensions/LogExtensions.cs index 853a580be..e5b4d0e4e 100644 --- a/framework/src/Bing.Logs/Bing/Logs/Extensions/LogExtensions.cs +++ b/framework/src/Bing.Logs/Bing/Logs/Extensions/LogExtensions.cs @@ -25,7 +25,7 @@ public static ILog BusinessId(this ILog log, string businessId) { return log.Set(content => { - if (string.IsNullOrWhiteSpace(content.BusinessId) == false) + if (string.IsNullOrWhiteSpace(content.BusinessId) == false) content.BusinessId += ","; content.BusinessId += businessId; }); @@ -90,7 +90,7 @@ public static ILog Params(this ILog log, IDictionary dictionary) { if (dictionary == null || dictionary.Count == 0) return log; - foreach (var item in dictionary) + foreach (var item in dictionary) Params(log, item.Key, item.Value.SafeString()); return log; } diff --git a/framework/src/Bing.Logs/Bing/Logs/LogBase.cs b/framework/src/Bing.Logs/Bing/Logs/LogBase.cs index cee54770b..cf1ef6d55 100644 --- a/framework/src/Bing.Logs/Bing/Logs/LogBase.cs +++ b/framework/src/Bing.Logs/Bing/Logs/LogBase.cs @@ -245,10 +245,10 @@ public void Fatal(string message) /// 日志内容 protected virtual void Init(TContent content) { - Context.InitLogId(); content.LogName = Provider.LogName; content.TraceId = Context.TraceId; - content.LogId = Context.LogId; + if (string.IsNullOrWhiteSpace(content.LogId)) + content.LogId = Context.LogId; content.OperationTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); content.Duration = Context.Stopwatch.Elapsed.Description(); content.Ip = Context.Ip; diff --git a/framework/src/Bing/Bing/Logging/LoggerExtensions.cs b/framework/src/Bing/Bing/Logging/LoggerExtensions.cs new file mode 100644 index 000000000..420cca8ec --- /dev/null +++ b/framework/src/Bing/Bing/Logging/LoggerExtensions.cs @@ -0,0 +1,81 @@ +using System; +using Microsoft.Extensions.Logging; + +namespace Bing.Logging +{ + /// + /// 日志() 扩展 + /// + public static class LoggerExtensions + { + /// + /// 基于日志级别输出日志 + /// + /// 日志 + /// 日志级别 + /// 消息 + /// 参数 + public static void LogWithLevel(this ILogger logger, LogLevel logLevel, string message, params object[] args) + { + switch (logLevel) + { + case LogLevel.Trace: + logger.LogTrace(message, args); + break; + case LogLevel.Debug: + logger.LogDebug(message, args); + break; + case LogLevel.Information: + logger.LogInformation(message, args); + break; + case LogLevel.Warning: + logger.LogWarning(message, args); + break; + case LogLevel.Error: + logger.LogError(message, args); + break; + case LogLevel.Critical: + logger.LogCritical(message, args); + break; + default: + logger.LogDebug(message, args); + break; + } + } + + /// + /// 基于日志级别输出日志 + /// + /// 日志 + /// 日志级别 + /// 消息 + /// 异常 + public static void LogWithLevel(this ILogger logger, LogLevel logLevel, string message, Exception exception) + { + switch (logLevel) + { + case LogLevel.Trace: + logger.LogTrace(exception, message); + break; + case LogLevel.Debug: + logger.LogDebug(exception, message); + break; + case LogLevel.Information: + logger.LogInformation(exception, message); + break; + case LogLevel.Warning: + logger.LogWarning(exception, message); + break; + case LogLevel.Error: + logger.LogError(exception, message); + break; + case LogLevel.Critical: + logger.LogCritical(exception, message); + break; + default: + logger.LogDebug(exception, message); + break; + } + } + } +} diff --git a/framework/src/Bing/Logs/Abstractions/ILogContext.cs b/framework/src/Bing/Logs/Abstractions/ILogContext.cs index 229e79fc9..2b11cdfe4 100644 --- a/framework/src/Bing/Logs/Abstractions/ILogContext.cs +++ b/framework/src/Bing/Logs/Abstractions/ILogContext.cs @@ -44,9 +44,9 @@ public interface ILogContext /// string Url { get; } - /// - /// 初始化日志标识 - /// - void InitLogId(); + ///// + ///// 初始化日志标识 + ///// + //void InitLogId(); } } diff --git a/framework/src/Bing/Logs/Core/LogContext.cs b/framework/src/Bing/Logs/Core/LogContext.cs index b58059780..bc7211a56 100644 --- a/framework/src/Bing/Logs/Core/LogContext.cs +++ b/framework/src/Bing/Logs/Core/LogContext.cs @@ -1,8 +1,6 @@ using System; using System.Diagnostics; using System.Net; -using Bing.Collections; -using Bing.DependencyInjection; using Bing.Logs.Abstractions; using Bing.Logs.Internal; using Bing.Tracing; @@ -16,42 +14,23 @@ public class LogContext : ILogContext { #region 属性 - /// - /// 日志上下文信息 - /// - private LogContextInfo _info; - - /// - /// 序号 - /// - private int _orderId; - - /// - /// 作用域字典 - /// - private readonly ScopedDictionary _scopedDictionary; + private int _orderId = 0; /// /// 日志标识 /// - public string LogId => $"{TraceId}-{GetInfo().GetOrderId()}"; + public string LogId => GetInfo().IsWebEnv ? $"{GetInfo().TraceId}-{_orderId++}" : GetInfo().GetLogId(); /// /// 跟踪号 /// - public string TraceId => $"{TraceIdContext.Current?.TraceId ?? GetInfo().TraceId}"; - - ///// - ///// 跟踪号 - ///// - //public string TraceId - //{ - // get - // { - // TraceIdContext.Current ??= new TraceIdContext(string.Empty); - // return TraceIdContext.Current.TraceId; - // } - //} + public string TraceId + { + get + { + return (TraceIdContext.Current ??= new TraceIdContext(string.Empty)).TraceId; + } + } /// /// 计时器 @@ -80,53 +59,12 @@ public class LogContext : ILogContext #endregion - #region 构造函数 - - /// - /// 初始化一个类型的实例 - /// - /// 作用域字典 - public LogContext(ScopedDictionary scopedDictionary) - { - _orderId = 0; - _scopedDictionary = scopedDictionary; - } - - #endregion - - /// - /// 初始化日志标识 - /// - public void InitLogId() - { - var key = "Bing.Logs.LogContext_orderId"; - _scopedDictionary[key] = _scopedDictionary.ContainsKey(key) ? ++_orderId : _orderId; - } - - ///// - ///// 获取日志上下文信息 - ///// - //private LogContextInfo GetInfo() - //{ - // if (_info != null) - // return _info; - // var key = "Bing.Logs.LogContext"; - // _info = _scopedDictionary.ContainsKey(key) ? _scopedDictionary[key] as LogContextInfo : null; - // if (_info != null) - // return _info; - // _info = CreateInfo(); - // _scopedDictionary[key] = _info; - // return _info; - //} - /// /// 获取日志上下文信息 /// private LogContextInfo GetInfo() { - if (LogContextInfo.Current == null) - LogContextInfo.Current = CreateInfo(); - return LogContextInfo.Current; + return LogContextInfo.Current ?? (LogContextInfo.Current = CreateInfo()); } /// @@ -143,7 +81,7 @@ protected virtual LogContextInfo CreateInfo() => /// /// 获取跟踪号 /// - protected virtual string GetTraceId() => Guid.NewGuid().ToString(); + protected virtual string GetTraceId() => Guid.NewGuid().ToString("N"); /// /// 获取计时器 diff --git a/framework/src/Bing/Logs/Internal/LogContextInfo.cs b/framework/src/Bing/Logs/Internal/LogContextInfo.cs index 457091329..42b0a739d 100644 --- a/framework/src/Bing/Logs/Internal/LogContextInfo.cs +++ b/framework/src/Bing/Logs/Internal/LogContextInfo.cs @@ -45,6 +45,11 @@ public class LogContextInfo /// public string Url { get; set; } + /// + /// 是否Web环境 + /// + public bool IsWebEnv { get; set; } + /// /// 当前日志上下文信息 /// @@ -71,5 +76,15 @@ public static LogContextInfo Current /// 获取序号 /// public int GetOrderId() => _orderId++; + + /// + /// 获取日志标识 + /// + public string GetLogId() + { + var logId= $"{TraceId}-{GetOrderId()}"; + Debug.WriteLine($"【LogContextInfo】LogId: {logId}"); + return logId; + } } } diff --git a/framework/tests/Bing.Datas.Test.Integration/Sql/Builders/SqlServer/Clauses/WhereClauseTest.cs b/framework/tests/Bing.Datas.Test.Integration/Sql/Builders/SqlServer/Clauses/WhereClauseTest.cs index 446326da5..ce8f84d61 100644 --- a/framework/tests/Bing.Datas.Test.Integration/Sql/Builders/SqlServer/Clauses/WhereClauseTest.cs +++ b/framework/tests/Bing.Datas.Test.Integration/Sql/Builders/SqlServer/Clauses/WhereClauseTest.cs @@ -564,7 +564,7 @@ public void Test_WhereIfNotEmpty_7() Expression> condition = t => t.Email.Contains("a") && t.IntValue == 1; AssertHelper.Throws(() => { _clause.WhereIfNotEmpty(condition); - }, string.Format("仅允许添加一个条件,条件:{0}", condition)); + }, $"仅允许添加一个条件,条件:{condition}"); } #endregion diff --git a/framework/tests/Bing.EventBus.Tests/Startup.cs b/framework/tests/Bing.EventBus.Tests/Startup.cs index a7692bfe8..ee4462751 100644 --- a/framework/tests/Bing.EventBus.Tests/Startup.cs +++ b/framework/tests/Bing.EventBus.Tests/Startup.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Xunit.DependencyInjection; using Xunit.DependencyInjection.Logging; + namespace Bing.EventBus.Tests { /// diff --git a/framework/tests/Bing.MailKit.Tests/MailKitEmailSenderTest.cs b/framework/tests/Bing.MailKit.Tests/MailKitEmailSenderTest.cs index 3e50d1d95..b66dba99f 100644 --- a/framework/tests/Bing.MailKit.Tests/MailKitEmailSenderTest.cs +++ b/framework/tests/Bing.MailKit.Tests/MailKitEmailSenderTest.cs @@ -59,14 +59,14 @@ public MailKitEmailSenderTest(ITestOutputHelper output) : base(output) [Fact] public void Test_SendEmail() { - var box = new EmailBox - { - Subject = "MailKit 测试发送邮件", - To = _to, - Body = "

测试一下红色字体的邮件

", - IsBodyHtml = true, - }; - this._mailKitEmailSender.Send(box); + //var box = new EmailBox + //{ + // Subject = "MailKit 测试发送邮件", + // To = _to, + // Body = "

测试一下红色字体的邮件

", + // IsBodyHtml = true, + //}; + //this._mailKitEmailSender.Send(box); } /// diff --git a/framework/tests/Bing.Tests/Applications/CrudServiceTest.Save.cs b/framework/tests/Bing.Tests/Applications/CrudServiceTest.Save.cs index c153f854f..b8b320c11 100644 --- a/framework/tests/Bing.Tests/Applications/CrudServiceTest.Save.cs +++ b/framework/tests/Bing.Tests/Applications/CrudServiceTest.Save.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using AutoMapper; using Bing.AutoMapper; +using Bing.DependencyInjection; using Bing.Tests.Samples; using NSubstitute; using Xunit; @@ -79,6 +80,7 @@ public CrudServiceTest() _unitOfWork = Substitute.For(); _repository = Substitute.For(); _service = new CrudServiceSample(_unitOfWork, _repository); + _service.LazyServiceProvider = Substitute.For(); var allAssemblyFinder = new AppDomainAllAssemblyFinder(); var mapperProfileTypeFinder = new MapperProfileTypeFinder(allAssemblyFinder); var instances = mapperProfileTypeFinder diff --git a/framework/tests/Bing.Tests/Applications/QueryServiceTest.cs b/framework/tests/Bing.Tests/Applications/QueryServiceTest.cs index 70f45f76a..67a077cd0 100644 --- a/framework/tests/Bing.Tests/Applications/QueryServiceTest.cs +++ b/framework/tests/Bing.Tests/Applications/QueryServiceTest.cs @@ -1,7 +1,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using AutoMapper; +using Bing.AutoMapper; +using Bing.DependencyInjection; +using Bing.ObjectMapping; +using Bing.Reflection; using Bing.Tests.Samples; using NSubstitute; using Xunit; @@ -54,8 +60,26 @@ public QueryServiceTest() _entity2 = new EntitySample(_id2) { Name = "B" }; _repository = Substitute.For(); _service = new QueryServiceSample(_repository); - //var mapper = new AutoMapperMapper(); - //MapperExtensions.SetMapper(mapper); + _service.LazyServiceProvider = Substitute.For(); + var allAssemblyFinder = new AppDomainAllAssemblyFinder(); + var mapperProfileTypeFinder = new MapperProfileTypeFinder(allAssemblyFinder); + var instances = mapperProfileTypeFinder + .FindAll() + .Select(type => Bing.Reflection.Reflections.CreateInstance(type)) + .ToList(); + var configuration = new MapperConfiguration(cfg => + { + foreach (var instance in instances) + { + + Debug.WriteLine($"初始化AutoMapper配置:{instance.GetType().FullName}"); + instance.CreateMap(); + // ReSharper disable once SuspiciousTypeConversion.Global + cfg.AddProfile(instance as Profile); + } + }); + var mapper = new AutoMapperObjectMapper(configuration, instances); + ObjectMapperExtensions.SetMapper(mapper); } /// diff --git a/framework/tests/Bing.Tests/Datas/Queries/Criterias/DateSegmentCriteriaTest.cs b/framework/tests/Bing.Tests/Datas/Queries/Criterias/DateSegmentCriteriaTest.cs index 3906bbb58..f30db9411 100644 --- a/framework/tests/Bing.Tests/Datas/Queries/Criterias/DateSegmentCriteriaTest.cs +++ b/framework/tests/Bing.Tests/Datas/Queries/Criterias/DateSegmentCriteriaTest.cs @@ -35,59 +35,127 @@ public DateSegmentCriteriaTest(ITestOutputHelper output) { _output = output; _min = DateTime.Parse("2000-1-1 10:10:10"); - _max = DateTime.Parse("2000-1-2 10:10:10"); + _max = DateTime.Parse("2000-1-3 10:10:10"); } /// - /// 测试 - 获取查询条件 + /// 测试 - 获取查询条件 - 不包含边界 /// [Fact] - public void Test_GetPredicate() + public void Test_GetCondition_Neither() + { + var result = new StringBuilder(); + result.Append("t => ((t.DateValue >= Convert(Parse(\"2000/1/2 0:00:00\"), DateTime))"); + result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/3 0:00:00\"), DateTime)))"); + + var condition= new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Neither); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } + + /// + /// 测试 - 获取查询条件 - 不包含边界【可空】 + /// + [Fact] + public void Test_GetCondition_Neither_With_Nullable() + { + var result = new StringBuilder(); + result.Append("t => ((t.NullableDateValue >= Convert(Parse(\"2000/1/2 0:00:00\"), Nullable`1))"); + result.Append(" AndAlso (t.NullableDateValue < Convert(Parse(\"2000/1/3 0:00:00\"), Nullable`1)))"); + + var condition = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Neither); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } + + /// + /// 测试 - 获取查询条件 - 包含左边 + /// + [Fact] + public void Test_GetCondition_Left() { var result = new StringBuilder(); result.Append("t => ((t.DateValue >= Convert(Parse(\"2000/1/1 0:00:00\"), DateTime))"); result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/3 0:00:00\"), DateTime)))"); - var criteria = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Both); - _output.WriteLine(criteria.GetCondition().ToString()); - Assert.Equal(result.ToString(), criteria.GetCondition().ToString()); - result = new StringBuilder(); + var condition = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Left); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } + + /// + /// 测试 - 获取查询条件 - 包含左边【可空】 + /// + [Fact] + public void Test_GetCondition_Left_With_Nullable() + { + var result = new StringBuilder(); result.Append("t => ((t.NullableDateValue >= Convert(Parse(\"2000/1/1 0:00:00\"), Nullable`1))"); result.Append(" AndAlso (t.NullableDateValue < Convert(Parse(\"2000/1/3 0:00:00\"), Nullable`1)))"); - var criteria2 = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Both); - _output.WriteLine(criteria2.GetCondition().ToString()); - Assert.Equal(result.ToString(), criteria2.GetCondition().ToString()); + + var condition = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Left); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); } /// - /// 测试 - 获取查询条件 - 设置边界 + /// 测试 - 获取查询条件 - 包含右边 /// [Fact] - public void Test_GetPredicate_Boundary() + public void Test_GetCondition_Right() { var result = new StringBuilder(); - result.Append("t => ((t.DateValue > Convert(Parse(\"2000/1/1 0:00:00\"), DateTime))"); - result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/3 0:00:00\"), DateTime)))"); - var criteria = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Neither); - Assert.Equal(result.ToString(), criteria.GetCondition().ToString()); + result.Append("t => ((t.DateValue >= Convert(Parse(\"2000/1/2 0:00:00\"), DateTime))"); + result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/4 0:00:00\"), DateTime)))"); + + var condition = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Right); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } - result = new StringBuilder(); + /// + /// 测试 - 获取查询条件 - 包含右边【可空】 + /// + [Fact] + public void Test_GetCondition_Right_With_Nullable() + { + var result = new StringBuilder(); + result.Append("t => ((t.NullableDateValue >= Convert(Parse(\"2000/1/2 0:00:00\"), Nullable`1))"); + result.Append(" AndAlso (t.NullableDateValue < Convert(Parse(\"2000/1/4 0:00:00\"), Nullable`1)))"); + + var condition = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Right); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } + + /// + /// 测试 - 获取查询条件 - 包含两边 + /// + [Fact] + public void Test_GetCondition_Both() + { + var result = new StringBuilder(); result.Append("t => ((t.DateValue >= Convert(Parse(\"2000/1/1 0:00:00\"), DateTime))"); - result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/3 0:00:00\"), DateTime)))"); - criteria = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Left); - Assert.Equal(result.ToString(), criteria.GetCondition().ToString()); + result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/4 0:00:00\"), DateTime)))"); - result = new StringBuilder(); - result.Append("t => ((t.NullableDateValue > Convert(Parse(\"2000/1/1 0:00:00\"), Nullable`1))"); - result.Append(" AndAlso (t.NullableDateValue <= Convert(Parse(\"2000/1/3 0:00:00\"), Nullable`1)))"); - var criteria2 = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Right); - Assert.Equal(result.ToString(), criteria2.GetCondition().ToString()); + var condition = new DateSegmentCondition(t => t.DateValue, _min, _max, Boundary.Both); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); + } - result = new StringBuilder(); + /// + /// 测试 - 获取查询条件 - 包含两边【可空】 + /// + [Fact] + public void Test_GetCondition_Both_With_Nullable() + { + var result = new StringBuilder(); result.Append("t => ((t.NullableDateValue >= Convert(Parse(\"2000/1/1 0:00:00\"), Nullable`1))"); - result.Append(" AndAlso (t.NullableDateValue <= Convert(Parse(\"2000/1/3 0:00:00\"), Nullable`1)))"); - criteria2 = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Both); - Assert.Equal(result.ToString(), criteria2.GetCondition().ToString()); + result.Append(" AndAlso (t.NullableDateValue < Convert(Parse(\"2000/1/4 0:00:00\"), Nullable`1)))"); + + var condition = new DateSegmentCondition(t => t.NullableDateValue, _min, _max, Boundary.Both); + _output.WriteLine(condition.GetCondition().ToString()); + Assert.Equal(result.ToString(), condition.GetCondition().ToString()); } } } diff --git a/framework/tests/Bing.Tests/Datas/Queries/QueryTest.cs b/framework/tests/Bing.Tests/Datas/Queries/QueryTest.cs index 3e39a57f1..e186f30d6 100644 --- a/framework/tests/Bing.Tests/Datas/Queries/QueryTest.cs +++ b/framework/tests/Bing.Tests/Datas/Queries/QueryTest.cs @@ -168,7 +168,7 @@ public void Test_Between_Date() var max = DateTime.Parse("2000-1-2 10:10:10"); var result = new StringBuilder(); result.Append("t => ((t.DateValue >= Convert(Parse(\"2000/1/1 0:00:00\"), DateTime))"); - result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/3 0:00:00\"), DateTime)))"); + result.Append(" AndAlso (t.DateValue < Convert(Parse(\"2000/1/2 0:00:00\"), DateTime)))"); _query.Between(t => t.DateValue, min, max, false); Assert.Equal(result.ToString(), _query.GetCondition().ToString()); diff --git a/modules/admin/src/Bing.Admin.EventHandlers/Implements/MessageEventHandlerBase.cs b/modules/admin/src/Bing.Admin.EventHandlers/Implements/MessageEventHandlerBase.cs index f1ce310c6..9c551d350 100644 --- a/modules/admin/src/Bing.Admin.EventHandlers/Implements/MessageEventHandlerBase.cs +++ b/modules/admin/src/Bing.Admin.EventHandlers/Implements/MessageEventHandlerBase.cs @@ -1,4 +1,9 @@ -namespace Bing.Admin.EventHandlers.Implements +using Bing.Aspects; +using Bing.DependencyInjection; +using Bing.Logs; +using Bing.Logs.Core; + +namespace Bing.Admin.EventHandlers.Implements { /// /// 消息事件处理器基类 @@ -6,13 +11,14 @@ public abstract class MessageEventHandlerBase : DotNetCore.CAP.ICapSubscribe { /// - /// 日志 + /// Lazy延迟加载服务提供程序 /// - private Bing.Logs.ILog _log; + [Autowired] + public virtual ILazyServiceProvider LazyServiceProvider { get; set; } /// /// 日志 /// - public Bing.Logs.ILog Log => _log ??= Logs.Log.GetLog(this); + protected ILog Log => LazyServiceProvider.LazyGetService() ?? NullLog.Instance; } } diff --git a/modules/admin/src/Bing.Admin.EventHandlers/Implements/TestMessageEventHandler.cs b/modules/admin/src/Bing.Admin.EventHandlers/Implements/TestMessageEventHandler.cs index 261e6a85c..c236f6959 100644 --- a/modules/admin/src/Bing.Admin.EventHandlers/Implements/TestMessageEventHandler.cs +++ b/modules/admin/src/Bing.Admin.EventHandlers/Implements/TestMessageEventHandler.cs @@ -48,16 +48,19 @@ public TestMessageEventHandler(IAdminUnitOfWork unitOfWork, IMessageEventBus mes /// /// 测试消息 /// - [CapTrace] + //[CapTrace] [EventHandler(MessageEventConst.TestMessage1)] - public async Task TestMessage1Async(TestMessage message,[FromCap]CapHeader header) + public async Task TestMessage1Async(TestMessage message, [FromCap] CapHeader header) { - if(message.ThrowException) + if (message.ThrowException) throw new NotImplementedException("主动触发,暂未生效"); + Log.Info($"测试一波CAP消息 - 0: {message.Id}"); Logger.LogDebug($"测试一波CAP消息 - 1: {message.Id}"); + var log = Bing.Logs.Log.GetLog(nameof(TestMessageEventHandler)); + log.Debug($"测试一波CAP消息 - 1 - 1: {message.Id}"); Debug.WriteLine(message.Id); await MessageEventBus.PublishAsync(new TestMessageEvent2(message, message.Send)); - if(message.NeedCommit) + if (message.NeedCommit) await UnitOfWork.CommitAsync(); } @@ -70,6 +73,8 @@ public Task TestMessage2Async(TestMessage message) { Debug.WriteLine(message.Id); Logger.LogDebug($"测试一波CAP消息 - 2: {message.Id}"); + var log = Bing.Logs.Log.GetLog(nameof(TestMessageEventHandler)); + log.Debug($"测试一波CAP消息 - 2 - 1: {message.Id}"); return Task.CompletedTask; } } diff --git a/modules/admin/src/Bing.Admin/Modules/CapModule.cs b/modules/admin/src/Bing.Admin/Modules/CapModule.cs index 27c32081e..1a0fda531 100644 --- a/modules/admin/src/Bing.Admin/Modules/CapModule.cs +++ b/modules/admin/src/Bing.Admin/Modules/CapModule.cs @@ -1,4 +1,5 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using Bing.Admin.Data; using Bing.Admin.Data.UnitOfWorks.MySql; using Bing.Admin.EventHandlers.Abstractions; @@ -8,10 +9,12 @@ using Bing.AspNetCore; using Bing.Core.Modularity; using Bing.Events.Cap; +using Bing.Tracing; using DotNetCore.CAP; using DotNetCore.CAP.Internal; -using Microsoft.Extensions.Configuration; +using DotNetCore.CAP.Serialization; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Bing.Admin.Modules { @@ -39,7 +42,10 @@ public class CapModule : AspNetCoreBingModule /// 服务集合 public override IServiceCollection AddServices(IServiceCollection services) { + // 替换CAP消费者服务选择器 services.AddSingleton(); + // 替换CAP订阅执行者 + services.AddSingleton(); LoadEvent(services); // 添加事件总线服务 services.AddCapEventBus(o => @@ -72,4 +78,52 @@ protected void LoadEvent(IServiceCollection services) services.AddTransient(); } } + + /// + /// Cap 订阅执行器 + /// + public class CapSubscribeInvoker : SubscribeInvoker + { + /// + /// 日志组件 + /// + private readonly ILogger _logger; + + /// + /// 初始化一个类型的实例 + /// + public CapSubscribeInvoker(ILoggerFactory loggerFactory, IServiceProvider serviceProvider, ISerializer serializer) + : base(loggerFactory, serviceProvider, serializer) + { + _logger = loggerFactory.CreateLogger(); + } + + /// + /// 获取实例 + /// + /// 服务提供程序 + /// 订阅上下文 + protected override object GetInstance(IServiceProvider provider, ConsumerContext context) + { + var capHeader = new CapHeader(context.DeliverMessage.Headers); + InitTraceIdContext(capHeader); + return base.GetInstance(provider, context); + } + + /// + /// 初始化跟踪标识上下文 + /// + private void InitTraceIdContext(CapHeader capHeader) + { + if (capHeader == null) + return; + if (!capHeader.TryGetValue("bing-trace-id", out var traceId)) + return; + _logger.LogDebug("Init TraceId: {0}", traceId); + if (TraceIdContext.Current == null) + TraceIdContext.Current = new TraceIdContext(traceId); + else + TraceIdContext.Current.TraceId = traceId; + } + } } diff --git a/modules/admin/src/Bing.Admin/Modules/LogModule.cs b/modules/admin/src/Bing.Admin/Modules/LogModule.cs index a9acbeacf..7c1c56455 100644 --- a/modules/admin/src/Bing.Admin/Modules/LogModule.cs +++ b/modules/admin/src/Bing.Admin/Modules/LogModule.cs @@ -4,6 +4,7 @@ using Bing.Core.Modularity; using Bing.Logging.Serilog; using Bing.Logs.NLog; +using Bing.Tracing; using Exceptionless; using Microsoft.Extensions.DependencyInjection; using Serilog; @@ -60,6 +61,7 @@ public override IServiceCollection AddServices(IServiceCollection services) { builder.Target.AddTags(traceId.ToString() ?? string.Empty); } + builder.Target.AddTags((TraceIdContext.Current ??= new TraceIdContext(string.Empty)).TraceId); return builder; }) .ReadFrom.Configuration(configuration) diff --git a/version.props b/version.props index b55fbcce9..104778dd4 100644 --- a/version.props +++ b/version.props @@ -2,7 +2,7 @@ 2 2 - 1 + 2 20220104-1 $(VersionMajor).$(VersionMinor).$(VersionPatch)