diff --git a/README.md b/README.md index 2f2e805..4fbed20 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,47 @@ -# exceptionless-webhooks 一个 Exceptionless 相关 WebHooks 项目。 -## 目标 -DingTalk(钉钉) + +# 目的 +当Exceptionless触发配置的WebHooks通知类型时,如Error、LogError,发送消息到 DingTalk(钉钉),实时感知运维报警提醒。 + +# 效果图 + +![Image text](https://github.com/justmine66/exceptionless-webhooks/blob/master/result.png) + +# 步骤 +## 1、部署 +请选择一种部署方式。 +### docker + +``` shell +docker run -d -p 8000:80 justmine/exceptionless.api.webhook:0.0.0; +``` + +### kubernetes(推荐) + +[deployment.yml](https://github.com/justmine66/exceptionless-webhooks/blob/master/k8s/web.yml) + +``` shell +kubectl apply -f https://github.com/justmine66/exceptionless-webhooks/blob/master/k8s/web.yml; +``` +## 2、配置 + +请先部署好webhook钩子。 + +### Exceptionless + +Admin => Projects => Integrations => Add Web Hook: + +![Image text](https://github.com/justmine66/exceptionless-webhooks/blob/master/config.png) + +>注意:如果你的项目Webhook配置选项没有Error、LogEroor类型,说明Exceptionless团队还没有合并我的PR,请先拉取我的项目:[后端](https://github.com/justmine66/Exceptionless)、[前端](https://github.com/justmine66/Exceptionless.UI),前后端都需要拉取最新项目代码。 + +# changes + +1. 添加容器化部署脚本,支持docker、kubernetes。 +2. 扩展事件模型,添加环境、来源等信息。 +3. 升级项目为netcoreapp2.1。 +4. 优化httpclient使用方式。 +5. 本地化事件模型时间。 + +# 如有疑惑,欢迎QQ。 +3538307147 diff --git a/build/CI.bat b/build/CI.bat new file mode 100644 index 0000000..913483c --- /dev/null +++ b/build/CI.bat @@ -0,0 +1,26 @@ +set build-base-path=../exceptionless.webhooks +set outpust-base-path=../../build +set username=justmine + +for /f "delims=> tokens=2" %%i in ('findstr ".*" version.props')do set "Major=%%i"; +for /f "delims=> tokens=2" %%j in ('findstr ".*" version.props')do set "Minor=%%j"; +for /f "delims=> tokens=2" %%h in ('findstr ".*" version.props')do set "Patch=%%h"; + +set Major=%Major:~0,1% +set Minor=%Minor:~0,1% +set Patch=%Patch:~0,1% +set Version=%Major%.%Minor%.%Patch% + +set first=Web +set version=%Version% +set imagename=exceptionless.api.webhook +set imagefullname=%username%/%imagename%:%version% + +dotnet publish %build-base-path%/%first%/%first%.csproj -o %outpust-base-path%/%first% -c release +docker build -t %imagefullname% ./%first% +docker push %imagefullname% + +rd /s /q %first% + +pause +goto EOF \ No newline at end of file diff --git a/build/version.props b/build/version.props new file mode 100644 index 0000000..7d235ef --- /dev/null +++ b/build/version.props @@ -0,0 +1,9 @@ + + + 0 + 0 + 0 + + $(VersionMajor).$(VersionMinor).$(VersionPatch) + + \ No newline at end of file diff --git a/config.png b/config.png new file mode 100644 index 0000000..05807b4 Binary files /dev/null and b/config.png differ diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Utilitys/StringUtilitys.cs b/exceptionless.webhooks/ExceptionLess.WebHook.DingTalk/Utilities/StringUtility.cs similarity index 77% rename from exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Utilitys/StringUtilitys.cs rename to exceptionless.webhooks/ExceptionLess.WebHook.DingTalk/Utilities/StringUtility.cs index 392080d..701e2a5 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Utilitys/StringUtilitys.cs +++ b/exceptionless.webhooks/ExceptionLess.WebHook.DingTalk/Utilities/StringUtility.cs @@ -1,6 +1,6 @@ -namespace Exceptionless.WebHook.DingTalk.Utilitys +namespace ExceptionLess.WebHook.DingTalk.Utilities { - public class StringUtilitys + public class StringUtility { public static string ToCamelCase(string str) { diff --git a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/Exceptionless.WebHook.Abstractions.csproj b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/Exceptionless.WebHook.Abstractions.csproj index 77e1e74..8978979 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/Exceptionless.WebHook.Abstractions.csproj +++ b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/Exceptionless.WebHook.Abstractions.csproj @@ -5,12 +5,12 @@ - - - - - - + + + + + + diff --git a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/ExceptionlessEventModel.cs b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/ExceptionlessEventModel.cs index c8109fa..26aaa6f 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/ExceptionlessEventModel.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/ExceptionlessEventModel.cs @@ -1,10 +1,12 @@ using Newtonsoft.Json; using System; -namespace Exceptionless.WebHook.Abstractions +namespace ExceptionLess.WebHook.Abstractions { - public class ExceptionlessEventModel + public class ExceptionLessEventModel { + public string Environment { get; set; } + public string Id { get; set; } public string Url { get; set; } @@ -12,11 +14,11 @@ public class ExceptionlessEventModel public DateTime OccurrenceDate { get; set; } public string Type { get; set; } + public string Source { get; set; } public string Message { get; set; } [JsonProperty("project_id")] public string ProjectId { get; set; } - [JsonProperty("project_Name")] public string ProjectName { get; set; } diff --git a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/FileTemplateService.cs b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/FileTemplateService.cs index fbadb3e..42e2c5c 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/FileTemplateService.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/FileTemplateService.cs @@ -8,14 +8,14 @@ using System.Text; using System.Threading.Tasks; -namespace Exceptionless.WebHook.Abstractions +namespace ExceptionLess.WebHook.Abstractions { public class FileTemplateService : ISingletonDependency, IDisposable { #region Field private readonly IMemoryCache _memoryCache; - private readonly PhysicalFileProvider _physicalFileProvider; + private readonly PhysicalFileProvider _fileProvider; #endregion Field @@ -24,7 +24,7 @@ public class FileTemplateService : ISingletonDependency, IDisposable public FileTemplateService(IMemoryCache memoryCache) { _memoryCache = memoryCache; - _physicalFileProvider = new PhysicalFileProvider(AppContext.BaseDirectory); + _fileProvider = new PhysicalFileProvider(AppContext.BaseDirectory); } #endregion Constructor @@ -40,17 +40,17 @@ public async Task GetContent(string templateFile, object model) var properties = model.GetType().GetProperties(); var builder = new StringBuilder(template); - var propertys = new Dictionary(); + var propCache = new Dictionary(); string GetPropertyValue(PropertyInfo property) { - if (propertys.TryGetValue(property.Name, out var value)) + if (propCache.TryGetValue(property.Name, out var value)) { return value; } value = property.GetValue(model)?.ToString(); - propertys[property.Name] = value; + propCache[property.Name] = value; return value; } @@ -72,8 +72,8 @@ private async Task GetTemplate(string templateFile) { return await _memoryCache.GetOrCreateAsync(templateFile, async entry => { - entry.AddExpirationToken(_physicalFileProvider.Watch(templateFile)); - var fileInfo = _physicalFileProvider.GetFileInfo(templateFile); + entry.AddExpirationToken(_fileProvider.Watch(templateFile)); + var fileInfo = _fileProvider.GetFileInfo(templateFile); if (!fileInfo.Exists) return string.Empty; @@ -92,7 +92,7 @@ private async Task GetTemplate(string templateFile) public void Dispose() { _memoryCache?.Dispose(); - _physicalFileProvider?.Dispose(); + _fileProvider?.Dispose(); } #endregion IDisposable diff --git a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/IWebHookProvider.cs b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/IWebHookProvider.cs index ac92ebb..6eca826 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/IWebHookProvider.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.Abstractions/IWebHookProvider.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Exceptionless.WebHook.Abstractions +namespace ExceptionLess.WebHook.Abstractions { public interface IWebHookProvider : ISingletonDependency { string Name { get; } - Task ProcessAsync(ExceptionlessEventModel model, IDictionary parameters); + Task ProcessAsync(ExceptionLessEventModel model, IDictionary parameters); } } \ No newline at end of file diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/DingTalkWebHookProvider.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/DingTalkWebHookProvider.cs index 37ff175..7e05f42 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/DingTalkWebHookProvider.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/DingTalkWebHookProvider.cs @@ -1,37 +1,45 @@ -using Exceptionless.WebHook.Abstractions; -using Exceptionless.WebHook.DingTalk.Messages; -using Exceptionless.WebHook.DingTalk.Services; +using ExceptionLess.WebHook.Abstractions; +using ExceptionLess.WebHook.DingTalk.Messages; +using ExceptionLess.WebHook.DingTalk.Services; +using Microsoft.AspNetCore.Hosting; using System; using System.Collections.Generic; using System.Threading.Tasks; -namespace Exceptionless.WebHook.DingTalk +namespace ExceptionLess.WebHook.DingTalk { public class DingTalkWebHookProvider : IWebHookProvider { private readonly FileTemplateService _fileTemplateService; private readonly MessageService _messageService; + private readonly IHostingEnvironment _environment; - public DingTalkWebHookProvider(FileTemplateService fileTemplateService, MessageService messageService) + public DingTalkWebHookProvider( + FileTemplateService fileTemplateService, + MessageService messageService, + IHostingEnvironment environment) { _fileTemplateService = fileTemplateService; _messageService = messageService; + _environment = environment; } #region Implementation of IWebHookProvider public string Name { get; } = "DingTake"; - public async Task ProcessAsync(ExceptionlessEventModel model, IDictionary parameters) + public async Task ProcessAsync(ExceptionLessEventModel model, IDictionary parameters) { parameters.TryGetValue("accessToken", out var accessToken); + + model.Environment = _environment.EnvironmentName; var content = await _fileTemplateService.GetContent("markdownTemplate.md", model); await _messageService.SendAsync( new Uri($"https://oapi.dingtalk.com/robot/send?access_token={accessToken}"), new DingTalkRequestMessage { - Data = new MarkdownDingTalkMessage("Exceptionless 有新的事件", content) + Data = new MarkdownDingTalkMessage($"[{_environment.EnvironmentName}]ExceptionLess有新事件", content) }); } diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Exceptionless.WebHook.DingTalk.csproj b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Exceptionless.WebHook.DingTalk.csproj index 7e0d93d..ee9cc48 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Exceptionless.WebHook.DingTalk.csproj +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Exceptionless.WebHook.DingTalk.csproj @@ -5,12 +5,21 @@ - - + + - + + + + + + C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.hosting.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll + + + C:\Users\justmine\.nuget\packages\microsoft.extensions.http\2.1.1\lib\netstandard2.0\Microsoft.Extensions.Http.dll + \ No newline at end of file diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkRequestMessage.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkRequestMessage.cs index 642fbc7..4093f57 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkRequestMessage.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkRequestMessage.cs @@ -1,4 +1,4 @@ -namespace Exceptionless.WebHook.DingTalk.Messages +namespace ExceptionLess.WebHook.DingTalk.Messages { public class DingTalkRequestMessage { diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkResponseMessage.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkResponseMessage.cs index f7d6db1..4f6f3ab 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkResponseMessage.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/DingTalkResponseMessage.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Exceptionless.WebHook.DingTalk.Messages +namespace ExceptionLess.WebHook.DingTalk.Messages { public class DingTalkResponseMessage { diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/MessageType.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/MessageType.cs index afc793b..b96c5bf 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/MessageType.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/MessageType.cs @@ -1,4 +1,4 @@ -namespace Exceptionless.WebHook.DingTalk.Messages +namespace ExceptionLess.WebHook.DingTalk.Messages { public enum MessageType { diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/Messages.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/Messages.cs index b44debc..2324fa3 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/Messages.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Messages/Messages.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace Exceptionless.WebHook.DingTalk.Messages +namespace ExceptionLess.WebHook.DingTalk.Messages { public abstract class DingTalkMessageBase { diff --git a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Services/MessageService.cs b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Services/MessageService.cs index 4ad96bb..4f2a171 100644 --- a/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Services/MessageService.cs +++ b/exceptionless.webhooks/Exceptionless.WebHook.DingTalk/Services/MessageService.cs @@ -1,5 +1,5 @@ -using Exceptionless.WebHook.DingTalk.Messages; -using Exceptionless.WebHook.DingTalk.Utilitys; +using ExceptionLess.WebHook.DingTalk.Messages; +using ExceptionLess.WebHook.DingTalk.Utilities; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Rabbit.Extensions.DependencyInjection; @@ -9,15 +9,17 @@ using System.Text; using System.Threading.Tasks; -namespace Exceptionless.WebHook.DingTalk.Services +namespace ExceptionLess.WebHook.DingTalk.Services { public class MessageService : ISingletonDependency { private readonly ILogger _logger; + private readonly IHttpClientFactory _httpClientFactory; - public MessageService(ILogger logger) + public MessageService(ILogger logger, IHttpClientFactory httpClientFactory) { _logger = logger; + _httpClientFactory = httpClientFactory; } public async Task SendAsync(Uri url, DingTalkRequestMessage message) @@ -25,7 +27,7 @@ public async Task SendAsync(Uri url, DingTalkRequestMessage message) if (_logger.IsEnabled(LogLevel.Debug)) _logger.LogDebug($"准备向 {url} 发送数据"); - var type = StringUtilitys.ToCamelCase(message.Type.ToString()); + var type = StringUtility.ToCamelCase(message.Type.ToString()); var data = new Dictionary { {"msgtype", type}, @@ -35,23 +37,20 @@ public async Task SendAsync(Uri url, DingTalkRequestMessage message) var json = JsonConvert.SerializeObject(data); if (_logger.IsEnabled(LogLevel.Debug)) - _logger.LogDebug($"send dingtalk json:{json}"); + _logger.LogDebug($"send dingTalk json:{json}"); string responseContent = null; try { - using (var client = new HttpClient()) - { - var result = await client.PostAsync(url, new StringContent(json, Encoding.UTF8, "application/json")); - responseContent = await result.Content.ReadAsStringAsync(); - - if (_logger.IsEnabled(LogLevel.Debug)) - _logger.LogDebug(responseContent); - - var response = JsonConvert.DeserializeObject(responseContent); - if (response.ErrorCode > 0) - _logger.LogError($"钉钉返回错误消息:{responseContent}"); - } + var result = await _httpClientFactory.CreateClient().PostAsync(url, new StringContent(json, Encoding.UTF8, "application/json")); + responseContent = await result.Content.ReadAsStringAsync(); + + if (_logger.IsEnabled(LogLevel.Debug)) + _logger.LogDebug(responseContent); + + var response = JsonConvert.DeserializeObject(responseContent); + if (response.ErrorCode > 0) + _logger.LogError($"钉钉返回错误消息:{responseContent}"); } catch (Exception e) { diff --git a/exceptionless.webhooks/Web/Dockerfile b/exceptionless.webhooks/Web/Dockerfile new file mode 100644 index 0000000..a9c15d5 --- /dev/null +++ b/exceptionless.webhooks/Web/Dockerfile @@ -0,0 +1,6 @@ +FROM microsoft/dotnet:2.1-aspnetcore-runtime +RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +WORKDIR /app +COPY . . +EXPOSE 80 +ENTRYPOINT ["dotnet", "Web.dll"] \ No newline at end of file diff --git a/exceptionless.webhooks/Web/Middleware/ExceptionlessWebhookMiddleware.cs b/exceptionless.webhooks/Web/Middleware/ExceptionlessWebhookMiddleware.cs index 68890b0..e6dd023 100644 --- a/exceptionless.webhooks/Web/Middleware/ExceptionlessWebhookMiddleware.cs +++ b/exceptionless.webhooks/Web/Middleware/ExceptionlessWebhookMiddleware.cs @@ -1,4 +1,5 @@ -using Exceptionless.WebHook.Abstractions; +using ExceptionLess.WebHook.Abstractions; +using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -10,23 +11,24 @@ namespace Web.Middleware { - public class ExceptionlessWebhookMiddleware + public class ExceptionLessWebhookMiddleware { #region Field private readonly RequestDelegate _next; private readonly IEnumerable _webHookProviders; - private readonly ILogger _logger; + private readonly ILogger _logger; #endregion Field #region Constructor - public ExceptionlessWebhookMiddleware(RequestDelegate next, IEnumerable webHookProviders, ILogger logger) + public ExceptionLessWebhookMiddleware(RequestDelegate next, IEnumerable webHookProviders, ILogger logger) { _next = next; _webHookProviders = webHookProviders; _logger = logger; + if (_logger.IsEnabled(LogLevel.Debug)) _logger.LogDebug($"全部处理程序数量:{_webHookProviders.Count()}"); } @@ -54,9 +56,8 @@ public async Task Invoke(HttpContext context) if (_logger.IsEnabled(LogLevel.Debug)) _logger.LogDebug($"接收到 Webhook 请求:{content}"); - - var model = JsonConvert.DeserializeObject(content); - + + var model = JsonConvert.DeserializeObject(content); var providers = GetProviders(request.Query); var parameters = new Dictionary(request.Query.ToDictionary(i => i.Key, i => i.Value.ToString()), StringComparer.OrdinalIgnoreCase); diff --git a/exceptionless.webhooks/Web/Program.cs b/exceptionless.webhooks/Web/Program.cs index 7ceff57..7bd1c63 100644 --- a/exceptionless.webhooks/Web/Program.cs +++ b/exceptionless.webhooks/Web/Program.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; +using NLog.Extensions.Logging; using NLog.Web; using System; using System.Collections.Generic; @@ -19,26 +20,29 @@ public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureLogging((ctx, builder) => { + var env = ctx.HostingEnvironment; IEnumerable GetNlogConfigFiles() { - yield return $"nlog.{ctx.HostingEnvironment.EnvironmentName}.config"; + yield return $"nlog.{env.EnvironmentName}.config"; yield return "nlog.config"; } string GetNlogConfigFile() { return GetNlogConfigFiles().FirstOrDefault(f => - ctx.HostingEnvironment.ContentRootFileProvider.GetFileInfo(f).Exists); + env.ContentRootFileProvider.GetFileInfo(f).Exists); } var configFile = GetNlogConfigFile(); if (configFile == null) throw new Exception("找不到nlog的配置文件"); + env.ConfigureNLog(configFile); + builder .AddConfiguration(ctx.Configuration) .AddConsole() - .ConfigureNLog(configFile); + .AddNLog(); }) .UseStartup() .UseNLog() diff --git a/exceptionless.webhooks/Web/Startup.cs b/exceptionless.webhooks/Web/Startup.cs index efa9372..1766068 100644 --- a/exceptionless.webhooks/Web/Startup.cs +++ b/exceptionless.webhooks/Web/Startup.cs @@ -2,8 +2,8 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using NLog.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using Rabbit.Extensions.DependencyInjection; using System; using System.Linq; @@ -27,34 +27,39 @@ public void ConfigureServices(IServiceCollection services) { var appSettings = Configuration.Get(); - var enableModules = new[] { "Exceptionless.WebHook.Abstractions" }.Concat(appSettings.EnableModules) + var enableModules = new[] { "ExceptionLess.WebHook.Abstractions" }.Concat(appSettings.EnableModules) .ToDictionary(name => name, name => Assembly.Load(new AssemblyName(name))); foreach (var item in enableModules.Where(i => i.Value == null)) Console.WriteLine($"无法加载模块:{item.Key}"); var assemblies = enableModules.Values.ToArray(); + services .AddLogging() .AddMemoryCache() + .AddHttpClient() .AddInterfaceDependency(assemblies) .AddMvc(); + + JsonConvert.DefaultSettings = () => new JsonSerializerSettings + { + Formatting = Formatting.Indented, + ContractResolver = new CamelCasePropertyNamesContractResolver(), + DateTimeZoneHandling = DateTimeZoneHandling.Local + }; } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, IHostingEnvironment env) { - loggerFactory - .AddNLog(); - app.UseStatusCodePages(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - app - .UseMiddleware(); + app.UseMiddleware(); } } } \ No newline at end of file diff --git a/exceptionless.webhooks/Web/Web.csproj b/exceptionless.webhooks/Web/Web.csproj index ccdaf39..289bcdb 100644 --- a/exceptionless.webhooks/Web/Web.csproj +++ b/exceptionless.webhooks/Web/Web.csproj @@ -1,21 +1,25 @@  - netcoreapp2.0 + netcoreapp2.1 - - - - - + + + + + + - - + + + + PreserveNewest + PreserveNewest diff --git a/exceptionless.webhooks/Web/appsettings.Development.json b/exceptionless.webhooks/Web/appsettings.Development.json new file mode 100644 index 0000000..e5ac623 --- /dev/null +++ b/exceptionless.webhooks/Web/appsettings.Development.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Debug", + "Microsoft": "Warning" + } + }, + "EnableModules": [ + "ExceptionLess.WebHook.DingTalk" + ] +} \ No newline at end of file diff --git a/exceptionless.webhooks/Web/appsettings.Production.json b/exceptionless.webhooks/Web/appsettings.Production.json new file mode 100644 index 0000000..9a530d5 --- /dev/null +++ b/exceptionless.webhooks/Web/appsettings.Production.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning" + } + }, + "EnableModules": [ + "ExceptionLess.WebHook.DingTalk" + ] +} \ No newline at end of file diff --git a/exceptionless.webhooks/Web/appsettings.Staging.json b/exceptionless.webhooks/Web/appsettings.Staging.json new file mode 100644 index 0000000..e5ac623 --- /dev/null +++ b/exceptionless.webhooks/Web/appsettings.Staging.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Debug", + "Microsoft": "Warning" + } + }, + "EnableModules": [ + "ExceptionLess.WebHook.DingTalk" + ] +} \ No newline at end of file diff --git a/exceptionless.webhooks/Web/appsettings.json b/exceptionless.webhooks/Web/appsettings.json index 4985bdf..e5ac623 100644 --- a/exceptionless.webhooks/Web/appsettings.json +++ b/exceptionless.webhooks/Web/appsettings.json @@ -2,11 +2,11 @@ "Logging": { "IncludeScopes": true, "LogLevel": { - "Default": "Information", + "Default": "Debug", "Microsoft": "Warning" } }, "EnableModules": [ - "Exceptionless.WebHook.DingTalk" + "ExceptionLess.WebHook.DingTalk" ] } \ No newline at end of file diff --git a/exceptionless.webhooks/Web/markdownTemplate.md b/exceptionless.webhooks/Web/markdownTemplate.md index b39cc37..d923742 100644 --- a/exceptionless.webhooks/Web/markdownTemplate.md +++ b/exceptionless.webhooks/Web/markdownTemplate.md @@ -1,9 +1,12 @@ -# {OrganizationName}.{ProjectName} 有新的事件发生 -发生时间:{OccurrenceDate} -类型:{Type} -消息:{Message} -堆标题:{StackTitle} -第一次发生时间:{FirstOccurrence} -次数:{TotalOccurrences} -IP:{IpAddress} -[查看事件详情]({Url}) \ No newline at end of file +## [{Environment}]{OrganizationName}.{ProjectName} 有新事件发生: +- 类型:{Type} +- 发生时间:{OccurrenceDate} +- 第一次发生时间:{FirstOccurrence} +- 最后发生时间:{LastOccurrence} +- 发生总次数:{TotalOccurrences} +- 来源:{Source} +- 消息:{Message} +- 堆栈摘要:{StackTitle} +- 查看事件详情:{Url} +- 查看事件统计:{StackUrl} +- IP地址:{IpAddress} \ No newline at end of file diff --git a/exceptionless.webhooks/Web/nlog.Production.config b/exceptionless.webhooks/Web/nlog.Production.config new file mode 100644 index 0000000..87d5b9c --- /dev/null +++ b/exceptionless.webhooks/Web/nlog.Production.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exceptionless.webhooks/Web/nlog.Staging.config b/exceptionless.webhooks/Web/nlog.Staging.config new file mode 100644 index 0000000..87d5b9c --- /dev/null +++ b/exceptionless.webhooks/Web/nlog.Staging.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/exceptionless.webhooks/exceptionless.webhooks.sln b/exceptionless.webhooks/exceptionless.webhooks.sln index 22b19cc..50b01a4 100644 --- a/exceptionless.webhooks/exceptionless.webhooks.sln +++ b/exceptionless.webhooks/exceptionless.webhooks.sln @@ -3,11 +3,17 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26430.13 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "Web\Web.csproj", "{0A3A9747-0A0D-47A6-AB91-6DC77670C710}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "Web\Web.csproj", "{0A3A9747-0A0D-47A6-AB91-6DC77670C710}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Exceptionless.WebHook.Abstractions", "Exceptionless.WebHook.Abstractions\Exceptionless.WebHook.Abstractions.csproj", "{37702FD2-77F9-482F-A21E-B88A33AA2D40}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionLess.WebHook.Abstractions", "Exceptionless.WebHook.Abstractions\ExceptionLess.WebHook.Abstractions.csproj", "{37702FD2-77F9-482F-A21E-B88A33AA2D40}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Exceptionless.WebHook.DingTalk", "Exceptionless.WebHook.DingTalk\Exceptionless.WebHook.DingTalk.csproj", "{DDA628F0-EB63-4C34-A87D-C1296F5970DC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionLess.WebHook.DingTalk", "ExceptionLess.WebHook.DingTalk\ExceptionLess.WebHook.DingTalk.csproj", "{DDA628F0-EB63-4C34-A87D-C1296F5970DC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7024BD80-0B3D-4586-8B3E-452BDC0ED615}" + ProjectSection(SolutionItems) = preProject + ..\build\CI.bat = ..\build\CI.bat + ..\build\version.props = ..\build\version.props + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -31,4 +37,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {80D25D1F-798A-4CFF-9780-450723F9B0A4} + EndGlobalSection EndGlobal diff --git a/k8s/web.yml b/k8s/web.yml new file mode 100644 index 0000000..cbd4414 --- /dev/null +++ b/k8s/web.yml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: default + name: exceptionless-api-weebhook + labels: + app: exceptionless-api-weebhook +spec: + replicas: 1 + selector: + matchLabels: + app: exceptionless-api-weebhook + template: + metadata: + labels: + app: exceptionless-api-weebhook + spec: + containers: + - name: exceptionless-api-weebhook + image: "justmine/exceptionless.api.webhook:0.0.0" + imagePullPolicy: IfNotPresent + ports: + - name: http + containerPort: 80 + protocol: TCP + +--- +apiVersion: v1 +kind: Service +metadata: + namespace: geekbuying-light-addons + name: exceptionless-api-weebhook + labels: + app: exceptionless-api-weebhook +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: exceptionless-api-weebhook diff --git a/result.png b/result.png new file mode 100644 index 0000000..7e2fd7f Binary files /dev/null and b/result.png differ