30 changed files with 662 additions and 9 deletions
			
			
		| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,37 @@ | ||||
| # Sanhe.Abp.ExceptionHandling.Emailing | ||||
| 
 | ||||
| 基于abp框架底层的**IExceptionSubscriber**的邮件通知类型 | ||||
| 
 | ||||
| ## 配置使用 | ||||
| 
 | ||||
| 使用前需要配置**AbpExceptionHandlingOptions**定义需要发送通知的异常 | ||||
| 然后配置**AbpEmailExceptionHandlingOptions**定义具体异常类型通知方式 | ||||
| 
 | ||||
| ```csharp | ||||
| 
 | ||||
|     [DependsOn( | ||||
|         typeof(AbpEmailingExceptionHandlingModule) | ||||
|         )] | ||||
|     public class YouProjectModule : AbpModule | ||||
|     { | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             // 自定义需要处理的异常 | ||||
|             Configure<AbpExceptionHandlingOptions>(options => | ||||
|             { | ||||
|                 //  加入需要处理的异常类型 | ||||
|                 options.Handlers.Add<AbpException>(); | ||||
|             }); | ||||
|             // 自定义需要发送邮件通知的异常类型 | ||||
|             Configure<AbpEmailExceptionHandlingOptions>(options => | ||||
|             { | ||||
|                 // 是否发送堆栈信息 | ||||
|                 options.SendStackTrace = true; | ||||
|                 // 未指定异常接收者的默认接收邮件 | ||||
|                 options.DefaultReceiveEmail = "colin.in@foxmail.com"; | ||||
|                 //  指定某种异常发送到哪个邮件 | ||||
|                 options.HandReceivedException<AbpException>("colin.in@foxmail.com"); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| ``` | ||||
| @ -0,0 +1,33 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <None Remove="Sanhe\Abp\ExceptionHandling\Emailing\Localization\Resources\en.json" /> | ||||
| 	  <None Remove="Sanhe\Abp\ExceptionHandling\Emailing\Localization\Resources\zh-Hans.json" /> | ||||
| 	  <None Remove="Sanhe\Abp\ExceptionHandling\Emailing\Templates\SendEmail\en.tpl" /> | ||||
| 	  <None Remove="Sanhe\Abp\ExceptionHandling\Emailing\Templates\SendEmail\zh-Hans.tpl" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\ExceptionHandling\Emailing\Localization\Resources\en.json" /> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\ExceptionHandling\Emailing\Localization\Resources\zh-Hans.json" /> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\ExceptionHandling\Emailing\Templates\SendEmail\en.tpl" /> | ||||
| 	  <EmbeddedResource Include="Sanhe\Abp\ExceptionHandling\Emailing\Templates\SendEmail\zh-Hans.tpl" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<ProjectReference Include="..\Sanhe.Abp.ExceptionHandling\Sanhe.Abp.ExceptionHandling.csproj" /> | ||||
| 	</ItemGroup> | ||||
| 
 | ||||
| </Project> | ||||
| @ -0,0 +1,73 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing; | ||||
| 
 | ||||
| public class AbpEmailExceptionHandlingOptions | ||||
| { | ||||
|     /// <summary> | ||||
|     /// 发送堆栈信息 | ||||
|     /// </summary> | ||||
|     public bool SendStackTrace { get; set; } = false; | ||||
|     /// <summary> | ||||
|     /// 默认邮件标题 | ||||
|     /// </summary> | ||||
|     public string DefaultTitle { get; set; } | ||||
|     /// <summary> | ||||
|     /// 默认邮件内容头 | ||||
|     /// </summary> | ||||
|     public string DefaultContentHeader { get; set; } | ||||
|     /// <summary> | ||||
|     /// 默认邮件内容底 | ||||
|     /// </summary> | ||||
|     public string DefaultContentFooter { get; set; } | ||||
|     /// <summary> | ||||
|     /// 默认异常收件人 | ||||
|     /// </summary> | ||||
|     public string DefaultReceiveEmail { get; set; } | ||||
|     /// <summary> | ||||
|     /// 异常类型指定收件人处理映射列表 | ||||
|     /// </summary> | ||||
|     public IDictionary<Type, string> Handlers { get; set; } | ||||
| 
 | ||||
|     public AbpEmailExceptionHandlingOptions() | ||||
|     { | ||||
|         Handlers = new Dictionary<Type, string>(); | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// 把需要接受异常通知的用户加进处理列表 | ||||
|     /// </summary> | ||||
|     /// <typeparam name="TException">处理的异常类型</typeparam> | ||||
|     /// <param name="receivedEmails">接收邮件的用户类别,群发用,符号分隔</param> | ||||
|     public void HandReceivedException<TException>(string receivedEmails) where TException : Exception | ||||
|     { | ||||
|         HandReceivedException(typeof(TException), receivedEmails); | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// 把需要接受异常通知的用户加进处理列表 | ||||
|     /// </summary> | ||||
|     /// <param name="ex">处理的异常类型</param> | ||||
|     /// <param name="receivedEmails">接收邮件的用户类别,群发用,符号分隔</param> | ||||
|     public void HandReceivedException(Type exceptionType, string receivedEmails) | ||||
|     { | ||||
|         if (Handlers.ContainsKey(exceptionType)) | ||||
|         { | ||||
|             Handlers[exceptionType] += receivedEmails; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             Handlers.Add(exceptionType, receivedEmails); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public string GetReceivedEmailOrDefault(Type exceptionType) | ||||
|     { | ||||
|         if (Handlers.TryGetValue(exceptionType, out string receivedUsers)) | ||||
|         { | ||||
|             return receivedUsers; | ||||
|         } | ||||
|         return DefaultReceiveEmail; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Sanhe.Abp.ExceptionHandling.Emailing.Localization; | ||||
| using Volo.Abp.Emailing; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.Modularity; | ||||
| using Volo.Abp.VirtualFileSystem; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing; | ||||
| 
 | ||||
| [DependsOn( | ||||
|     typeof(AbpExceptionHandlingModule), | ||||
|     typeof(AbpEmailingModule))] | ||||
| public class AbpEmailingExceptionHandlingModule : AbpModule | ||||
| { | ||||
|     public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|     { | ||||
|         var configuration = context.Services.GetConfiguration(); | ||||
|         Configure<AbpEmailExceptionHandlingOptions>( | ||||
|             configuration.GetSection("ExceptionHandling:Emailing")); | ||||
| 
 | ||||
|         Configure<AbpVirtualFileSystemOptions>(options => | ||||
|         { | ||||
|             options.FileSets.AddEmbedded<AbpEmailingExceptionHandlingModule>(); | ||||
|         }); | ||||
| 
 | ||||
|         Configure<AbpLocalizationOptions>(options => | ||||
|         { | ||||
|             options.Resources | ||||
|                 .Add<ExceptionHandlingResource>("en") | ||||
|                 .AddVirtualJson("/Sanhe/Abp/ExceptionHandling/Emailing/Localization/Resources"); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,68 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Localization; | ||||
| using Microsoft.Extensions.Options; | ||||
| using Sanhe.Abp.ExceptionHandling.Emailing.Localization; | ||||
| using Sanhe.Abp.ExceptionHandling.Emailing.Templates; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.Emailing; | ||||
| using Volo.Abp.TextTemplating; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing; | ||||
| 
 | ||||
| public class AbpEmailingExceptionSubscriber : AbpExceptionSubscriberBase | ||||
| { | ||||
|     protected IEmailSender EmailSender { get; } | ||||
|     protected IStringLocalizer StringLocalizer { get; } | ||||
|     protected ITemplateRenderer TemplateRenderer { get; } | ||||
|     protected AbpEmailExceptionHandlingOptions EmailOptions { get; } | ||||
| 
 | ||||
|     public AbpEmailingExceptionSubscriber( | ||||
|         IEmailSender emailSender, | ||||
|         ITemplateRenderer templateRenderer, | ||||
|         IServiceScopeFactory serviceScopeFactory, | ||||
|         IOptions<AbpExceptionHandlingOptions> options, | ||||
|         IOptions<AbpEmailExceptionHandlingOptions> emailOptions, | ||||
|         IStringLocalizer<ExceptionHandlingResource> stringLocalizer) | ||||
|         : base(serviceScopeFactory, options) | ||||
|     { | ||||
|         EmailSender = emailSender; | ||||
|         EmailOptions = emailOptions.Value; | ||||
|         StringLocalizer = stringLocalizer; | ||||
|         TemplateRenderer = templateRenderer; | ||||
|     } | ||||
| 
 | ||||
|     protected override async Task SendErrorNotifierAsync(ExceptionSendNotifierContext context) | ||||
|     { | ||||
|         // 需不需要用 SettingProvider 来获取? | ||||
|         var receivedUsers = EmailOptions.GetReceivedEmailOrDefault(context.Exception.GetType()); | ||||
| 
 | ||||
|         if (!receivedUsers.IsNullOrWhiteSpace()) | ||||
|         { | ||||
|             var emailTitle = EmailOptions.DefaultTitle ?? L("SendEmailTitle"); | ||||
|             var templateContent = await TemplateRenderer | ||||
|                 .RenderAsync(ExceptionHandlingTemplates.SendEmail, | ||||
|                     new | ||||
|                     { | ||||
|                         title = emailTitle, | ||||
|                         header = EmailOptions.DefaultContentHeader ?? L("SendEmailHeader"), | ||||
|                         type = context.Exception.GetType().FullName, | ||||
|                         message = context.Exception.Message, | ||||
|                         loglevel = context.LogLevel.ToString(), | ||||
|                         triggertime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), | ||||
|                         sendstacktrace = EmailOptions.SendStackTrace, | ||||
|                         stacktrace = context.Exception.ToString(), | ||||
|                         footer = EmailOptions.DefaultContentFooter ?? $"Copyright to Sanhe © {DateTime.Now.Year}" | ||||
|                     }); | ||||
| 
 | ||||
|             await EmailSender.SendAsync(receivedUsers, | ||||
|                 emailTitle, | ||||
|                 templateContent); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected string L(string name, params object[] args) | ||||
|     { | ||||
|         return StringLocalizer[name, args].Value; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| using Volo.Abp.Localization; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing.Localization; | ||||
| 
 | ||||
| [LocalizationResourceName("AbpExceptionHandlingEmailing")] | ||||
| public class ExceptionHandlingResource | ||||
| { | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| { | ||||
|   "culture": "en", | ||||
|   "texts": { | ||||
|     "TextTemplate:ExceptionHandlingTemplates.SendEmail": "Apply the exception message sending template", | ||||
|     "SendEmailTitle": "Application exception push", | ||||
|     "SendEmailHeader": "Application exception" | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| { | ||||
|   "culture": "zh-Hans", | ||||
|   "texts": { | ||||
|     "TextTemplate:ExceptionHandlingTemplates.SendEmail": "应用异常邮件发送模板", | ||||
|     "SendEmailTitle": "应用程序异常推送", | ||||
|     "SendEmailHeader": "应用程序异常" | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| using Sanhe.Abp.ExceptionHandling.Emailing.Localization; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.TextTemplating; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing.Templates; | ||||
| 
 | ||||
| public class ExceptionHandlingTemplateDefinitionProvider : TemplateDefinitionProvider | ||||
| { | ||||
|     public override void Define(ITemplateDefinitionContext context) | ||||
|     { | ||||
|         context.Add( | ||||
|            new TemplateDefinition( | ||||
|                ExceptionHandlingTemplates.SendEmail, | ||||
|                displayName: LocalizableString.Create<ExceptionHandlingResource>("TextTemplate:ExceptionHandlingTemplates.SendEmail"), | ||||
|                defaultCultureName: "en" | ||||
|            ).WithVirtualFilePath("/Sanhe/Abp/ExceptionHandling/Emailing/Templates/SendEmail", false) | ||||
|        ); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,6 @@ | ||||
| namespace Sanhe.Abp.ExceptionHandling.Emailing.Templates; | ||||
| 
 | ||||
| public class ExceptionHandlingTemplates | ||||
| { | ||||
|     public const string SendEmail = "Abp.ExceptionHandling.SendEmail"; | ||||
| } | ||||
| @ -0,0 +1,48 @@ | ||||
| <!DOCTYPE html>  | ||||
| <html lang="en">  | ||||
|     <head>  | ||||
|         <meta charset="UTF-8">  | ||||
|         <title>{{ model.title }}</title>  | ||||
|     </head>  | ||||
|     <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">  | ||||
|         <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">  | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <br /> <b><font color="#0B610B">{{ model.header }}</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td> | ||||
|              </tr>  | ||||
|              <tr>  | ||||
|                  <td>  | ||||
|                      <ul>  | ||||
|                          <li>Type        : {{ model.type }}</li>  | ||||
|                          <li>Message     : {{ model.message }}</li>  | ||||
|                          <li>Alarm level : {{ model.loglevel }}</li>  | ||||
|                          <li>TriggerTime : {{ model.triggertime }}</li>  | ||||
|                     </ul>  | ||||
|                 </td>  | ||||
|             </tr>  | ||||
|             {{ if model.sendstacktrace }} | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <b><font color="#0B610B">Stack trace</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td>  | ||||
|             </tr>  | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">{{ model.stacktrace }}</pre>  | ||||
|                     <br /> | ||||
|                 </td>  | ||||
|             </tr>  | ||||
|             {{ end }} | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     <br />  | ||||
|                     <b style="float: right"><font color="#0B610B">{{ model.footer }}</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </table>  | ||||
|     </body>  | ||||
| </html> | ||||
| @ -0,0 +1,48 @@ | ||||
| <!DOCTYPE html>  | ||||
| <html lang="zh-Hans">  | ||||
|     <head>  | ||||
|         <meta charset="UTF-8">  | ||||
|         <title>{{ model.title }}</title>  | ||||
|     </head>  | ||||
|     <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">  | ||||
|         <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">  | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <br /> <b><font color="#0B610B">{{ model.header }}</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td> | ||||
|              </tr>  | ||||
|              <tr>  | ||||
|                  <td>  | ||||
|                      <ul>  | ||||
|                          <li>异常类型 : {{ model.type }}</li>  | ||||
|                          <li>异常信息 : {{ model.message }}</li>  | ||||
|                          <li>告警级别 : {{ model.loglevel }}</li>  | ||||
|                          <li>触发时间 : {{ model.triggertime }}</li>  | ||||
|                     </ul>  | ||||
|                 </td>  | ||||
|             </tr> | ||||
|             {{ if model.sendstacktrace }} | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <b><font color="#0B610B">异常堆栈</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td>  | ||||
|             </tr>  | ||||
|             <tr>  | ||||
|                 <td> | ||||
|                     <pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">{{ model.stacktrace }}</pre>  | ||||
|                     <br /> | ||||
|                 </td>  | ||||
|             </tr>  | ||||
|             {{ end }} | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     <br />  | ||||
|                     <b style="float: right"><font color="#0B610B">{{ model.footer }}</font></b>  | ||||
|                     <hr size="2" width="100%" align="center" /> | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </table>  | ||||
|     </body>  | ||||
| </html> | ||||
| @ -0,0 +1,3 @@ | ||||
| <Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | ||||
|   <ConfigureAwait ContinueOnCapturedContext="false" /> | ||||
| </Weavers> | ||||
| @ -0,0 +1,26 @@ | ||||
| # Sanhe.Abp.ExceptionHandling | ||||
| 
 | ||||
| 基于abp框架底层的**IExceptionSubscriber**实现二次扩展,用于自定义异常通知方式 | ||||
| 
 | ||||
| ## 配置使用 | ||||
| 
 | ||||
| 使用前只需配置**AbpExceptionHandlingOptions**定义需要发送通知的异常即可。 | ||||
| 
 | ||||
| ```csharp | ||||
| 
 | ||||
|     [DependsOn( | ||||
|         typeof(AbpExceptionHandlingModule) | ||||
|         )] | ||||
|     public class YouProjectModule : AbpModule | ||||
|     { | ||||
|         public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|         { | ||||
|             // 自定义需要处理的异常 | ||||
|             Configure<AbpExceptionHandlingOptions>(options => | ||||
|             { | ||||
|                 //  加入需要处理的异常类型 | ||||
|                 options.Handlers.Add<AbpException>(); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| ``` | ||||
| @ -0,0 +1,14 @@ | ||||
| <Project Sdk="Microsoft.NET.Sdk"> | ||||
| 
 | ||||
| 	<Import Project="..\..\..\configureawait.props" /> | ||||
| 	<Import Project="..\..\..\common.props" /> | ||||
| 
 | ||||
| 	<PropertyGroup> | ||||
| 		<TargetFramework>netstandard2.0</TargetFramework> | ||||
| 		<RootNamespace /> | ||||
| 	</PropertyGroup> | ||||
| 
 | ||||
| 	<ItemGroup> | ||||
| 		<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpVersion)" /> | ||||
| 	</ItemGroup> | ||||
| </Project> | ||||
| @ -0,0 +1,17 @@ | ||||
| using Sanhe.Abp.ExceptionHandling.Localization; | ||||
| using Volo.Abp.Localization; | ||||
| using Volo.Abp.Modularity; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling; | ||||
| 
 | ||||
| [DependsOn(typeof(AbpLocalizationModule))] | ||||
| public class AbpExceptionHandlingModule : AbpModule | ||||
| { | ||||
|     public override void ConfigureServices(ServiceConfigurationContext context) | ||||
|     { | ||||
|         Configure<AbpLocalizationOptions>(options => | ||||
|         { | ||||
|             options.Resources.Add<ExceptionHandlingResource>("en"); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,24 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using Volo.Abp.Collections; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling; | ||||
| 
 | ||||
| public class AbpExceptionHandlingOptions | ||||
| { | ||||
|     public ITypeList<Exception> Handlers { get; } | ||||
| 
 | ||||
|     public AbpExceptionHandlingOptions() | ||||
|     { | ||||
|         Handlers = new TypeList<Exception>(); | ||||
|     } | ||||
| 
 | ||||
|     public bool HasNotifierError(Exception ex) | ||||
|     { | ||||
|         if (typeof(IHasNotifierErrorMessage).IsAssignableFrom(ex.GetType())) | ||||
|         { | ||||
|             return true; | ||||
|         } | ||||
|         return Handlers.Any(x => x.IsAssignableFrom(ex.GetType())); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,66 @@ | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Logging.Abstractions; | ||||
| using Microsoft.Extensions.Options; | ||||
| using System; | ||||
| using System.Threading.Tasks; | ||||
| using Volo.Abp.ExceptionHandling; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling; | ||||
| 
 | ||||
| public abstract class AbpExceptionSubscriberBase : ExceptionSubscriber | ||||
| { | ||||
|     protected IServiceScopeFactory ServiceScopeFactory { get; } | ||||
|     protected AbpExceptionHandlingOptions Options { get; } | ||||
|     protected IServiceProvider ServiceProvider { get; set; } | ||||
|     protected readonly object ServiceProviderLock = new(); | ||||
| 
 | ||||
|     protected TService LazyGetRequiredService<TService>(ref TService reference) | ||||
|         => LazyGetRequiredService(typeof(TService), ref reference); | ||||
| 
 | ||||
|     protected TRef LazyGetRequiredService<TRef>(Type serviceType, ref TRef reference) | ||||
|     { | ||||
|         if (reference == null) | ||||
|         { | ||||
|             lock (ServiceProviderLock) | ||||
|             { | ||||
|                 if (reference == null) | ||||
|                 { | ||||
|                     reference = (TRef)ServiceProvider.GetRequiredService(serviceType); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return reference; | ||||
|     } | ||||
| 
 | ||||
|     protected ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); | ||||
|     private ILoggerFactory _loggerFactory; | ||||
| 
 | ||||
|     protected ILogger Logger => _lazyLogger.Value; | ||||
|     private Lazy<ILogger> _lazyLogger => new(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); | ||||
| 
 | ||||
| 
 | ||||
|     protected AbpExceptionSubscriberBase( | ||||
|         IServiceScopeFactory serviceScopeFactory, | ||||
|         IOptions<AbpExceptionHandlingOptions> options) | ||||
|     { | ||||
|         Options = options.Value; | ||||
|         ServiceScopeFactory = serviceScopeFactory; | ||||
|     } | ||||
| 
 | ||||
|     public override async Task HandleAsync(ExceptionNotificationContext context) | ||||
|     { | ||||
|         if (context.Handled && | ||||
|             Options.HasNotifierError(context.Exception)) | ||||
|         { | ||||
|             using (var scope = ServiceScopeFactory.CreateScope()) | ||||
|             { | ||||
|                 await SendErrorNotifierAsync( | ||||
|                     new ExceptionSendNotifierContext(scope.ServiceProvider, context.Exception, context.LogLevel)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected abstract Task SendErrorNotifierAsync(ExceptionSendNotifierContext context); | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| using JetBrains.Annotations; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using System; | ||||
| using Volo.Abp; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling; | ||||
| 
 | ||||
| public class ExceptionSendNotifierContext | ||||
| { | ||||
|     [NotNull] | ||||
|     public Exception Exception { get; } | ||||
| 
 | ||||
|     [NotNull] | ||||
|     public IServiceProvider ServiceProvider { get; } | ||||
| 
 | ||||
|     public LogLevel LogLevel { get; } | ||||
| 
 | ||||
|     internal ExceptionSendNotifierContext( | ||||
|         [NotNull] IServiceProvider serviceProvider, | ||||
|         [NotNull] Exception exception, | ||||
|         LogLevel? logLevel = null) | ||||
|     { | ||||
|         ServiceProvider = Check.NotNull(serviceProvider, nameof(serviceProvider)); | ||||
|         Exception = Check.NotNull(exception, nameof(exception)); | ||||
|         LogLevel = logLevel ?? exception.GetLogLevel(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| namespace Sanhe.Abp.ExceptionHandling; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// 需要发送异常通知的自定义异常需要实现此接口。 | ||||
| /// </summary> | ||||
| public interface IHasNotifierErrorMessage | ||||
| { | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,8 @@ | ||||
| using Volo.Abp.Localization; | ||||
| 
 | ||||
| namespace Sanhe.Abp.ExceptionHandling.Localization; | ||||
| 
 | ||||
| [LocalizationResourceName("AbpExceptionHandling")] | ||||
| public class ExceptionHandlingResource | ||||
| { | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue