Exceptionless(二) - 使用进阶
Exceptionless(二) - 本地部署使用进阶
作者:markjiang7m2
原文地址:https://www.cnblogs.com/markjiang7m2/p/11100563.html
官网地址:http://letyouknow.net
在上一篇文章Exceptionless - .Net Core开源日志框架中就说到如何对Exceptionless进行本地化部署,不过我也跟大家说了,仅限于能用的阶段。那今天我就继续来探讨一下如何再用好。
后台运行服务
上次我就是直接通过脚本Start-ElasticSearch.ps1
启动ElasticSearch和Kibana服务,但是大家也能看到,服务是运行起来了,同时还有两个命令窗口,如果一个不小心把窗口关闭了,服务也就关闭了,而且一旦服务器重启了,这两个服务也不会自动启动。
我这里先暂时把Kibana扔一边去,来看看ElasticSearch服务。ElasticSearch是直接有脚本支持将ElasticSearch安装为Windows服务,在后台运行。
就是这个elasticsearch-service.bat
脚本,支持一下参数:
- install 将Elasticsearch作为服务安装
- remove 删除已安装的Elasticsearch服务(并在启动时停止服务)
- start 启动Elasticsearch服务(如果已安装)
- stop 停止Elasticsearch服务(如果启动)
- manager 启动一个GUI来管理已安装的服务
安装
命令行,进入到elasticsearch-service.bat
所在的目录,然后执行下面的脚本
elasticsearch-service.bat install
启动
这个时候我们可以直接在浏览器访问9200
端口看看服务是否正常
继续使用上次部署好的Exceptionless
(如何使用IIS部署Exceptionless Web服务,请看Exceptionless - .Net Core开源日志框架)
因为我是直接用回之前ElasticSearch的节点,而且也没有清空数据,所以可以直接用之前注册的账号重新登录
也是成功的,ElasticSearch服务已经运行在后台了。
自动启动
通过ElasticSearch提供的GUI可以将服务设置为自动启动
elasticsearch-service.bat manager
将Startup Type
选择为Automatic
,再点击OK保存
这样,即使服务器重启了,我们的ElasticSearch服务也会自动启动
其实,有玩过Windows服务的朋友一定知道,上面的一些操作在Windows自带的服务管理器也能完成
同时按下"WIN+R" 打开服务的命令运行窗口。在服务运行窗口中输入services.msc
在列表中也可以找到ElasticSearch服务,双击打开属性窗口,跟刚刚的GUI操作就是一样的了
再看Web.config
上次我只是改了Exceptionless的端口设置,其实这里面还包含很多配置信息
<add name="RedisConnectionString" connectionString="localhost:6379,abortConnect=false" />
<add name="ElasticSearchConnectionString" connectionString="http://localhost:9200" />
官方是建议大家安装和配置Redis,这样就可以同时运行多个实例,并且重启不会丢失状态,强烈建议在Linux上运行Redis 3.0+版本,RedisConnectionString
就是Redis的连接串
ElasticSearchConnectionString
是必须的,指向ElasticSearch服务,如果有多个节点,则使用,
隔开
<!-- Exceptionless Web 基础Url -->
<add key="BaseURL" value="http://localhost:50001/#" />
<!-- 是否启用ssl -->
<add key="EnableSSL" value="false" />
<!--
Dev: Use this mode when debugging. (Outbound emails will not be sent)
QA: Use this mode when deployed to staging. (Outbound emails restricted)
Production: Use this mode when deployed to production.
-->
<add key="WebsiteMode" value="Production" />
<!-- Controls whether users can signup. -->
<add key="EnableAccountCreation" value="true" />
<!-- Controls whether daily summary emails are sent -->
<add key="EnableDailySummary" value="true" />
网站模式WebsiteMode主要是限制邮件发送,默认值是Dev,不发送邮件,所以我这里设置为Production
邮件发送配置,记得跟上面的WebsiteMode一起配置
<add key="SmtpHost" value="smtp.qq.com" />
<add key="SmtpPort" value="25" />
<add key="SmtpEncryption" value="SSL" />
<add key="SmtpUser" value="xxx@qq.com" />
<add key="SmtpPassword" value="xxx" />
我在案例中使用的是自己的qq邮箱。我在qq邮箱中已经开启了SMTP服务,并且也通过一个控制台应用程序测试可以发送邮件。
但是在Exceptionless这里一样的设置就是不行,在Web中点击发送邮件,log记录错误如下:
ERROR MailMessageJob Job run "MailMessageJob" failed: 由于意外的数据包格式,握手失败。 System.IO.IOException: 由于意外的数据包格式,握手失败。
清除Url
我们现在使用的Url都会带有#!
,例如
http://localhost:50001/#!/type/error/dashboard
可以按照下面步骤清除字符#!
- 首先保证你的IIS是否已经安装了重写模块,可通过双击IIS中的
模块
查看是否包含了RewriteModule
- 更新
Web.config
文件- 释放出在
system.webServer
中的rewrite
节点 - 删除
BaseURL
值中的/#
- 注释了在
system.webServer\modules
中的<remove name="RewriteModule" />
标签
- 释放出在
- 修改
app.config.77fc9ddd679d37dc.js
文件中USE_HTML5_MODE
的值为true
进程外运行作业
默认情况下,所有作业都在当前的Web进程中运行。如果发现事件处理开始变慢的时候,可以启动并扩展多个作业实例。通过在进程外运行作业,可以确保所有作业是否正常运行。
- 首先是要配置安装Redis,这样可以保证Exceptionless与作业之间能够进行通信
- 更新
Web.config
中的RunJobsInProcess
值为false
- 更新作业的配置,有两种方法可选:
- 使用环境变量进行配置Exceptionless。新增环境变量Exceptionless_{SETTING NAME} (例如: Exceptionless_BaseURL, Exceptionless_ElasticSearchConnectionString)。这是官方推荐的方法,因为它更简单,而且当部署到azure时非常好用
- 打开App_Data\jobs文件夹,然后按照在根目录中
Web.config
的配置,再重新配置每个作业的xxx.exe.config
。
- 在每个作业文件夹中都有一个
run.bat
文件,双击它就会运行这个作业。当然,也可以将这些作业全部设置为Windows服务在后台运行
更多设置
除了上面提到的设置,Exceptionless还支持很多自定义配置,下面是全部的设置列表,大家可根据自己的需要进行定制
列表按照这个格式进行排列:设置项 (数据类型,默认值)
EnableSSL (bool)
BaseURL (string)
InternalProjectId (string, "54b56e480ef9605a88a13153")
WebsiteMode (WebsiteMode, "Dev")
AppScope (string, String.Empty)
TestEmailAddress (string)
AllowedOutboundAddresses (List<string>, "exceptionless.io")
RunJobsInProcess (bool, true)
BotThrottleLimit (int, 25)
ApiThrottleLimit (int, Int32.MaxValue)
EventSubmissionDisabled (bool)
MaximumEventPostSize (long, 1000000)
MaximumRetentionDays (int, 180)
EnableDailySummary (bool)
MetricsServerName (string, "127.0.0.1")
MetricsServerPort (int, 8125)
EnableMetricsReporting (bool)
RedisConnectionString (string)
EnableRedis (bool)
DisableSnapshotJobs (bool)
DisableIndexConfiguration (bool)
ElasticSearchConnectionString (string)
ElasticSearchNumberOfShards (int, 1)
ElasticSearchNumberOfReplicas (int)
EnableElasticsearchTracing (bool)
LdapConnectionString (string)
EnableActiveDirectoryAuth (bool)
EnableSignalR (bool, true)
Version (string)
EnableIntercom (bool)
IntercomAppSecret (string)
EnableAccountCreation (bool, true)
MicrosoftAppId (string)
MicrosoftAppSecret (string)
FacebookAppId (string)
FacebookAppSecret (string)
GitHubAppId (string)
GitHubAppSecret (string)
GoogleAppId (string)
GoogleAppSecret (string)
GoogleGeocodingApiKey (string)
EnableBilling (bool)
StripeApiKey (string)
StorageFolder (string)
AzureStorageConnectionString (string)
EnableAzureStorage (bool)
BulkBatchSize (int, 1000)
SmtpHost (string)
SmtpPort (int, 587)
SmtpEnableSsl (bool, true)
SmtpUser (string)
SmtpPassword (string)
更多日志类型
Exceptionless除了支持记录Exception,也可以记录LogMessage、Broken Links 、Feature Usages
LogMessage
LogMessage支持多种级别的日志信息
- Other
- Trace
- Debug
- Info
- Warn
- Error
- Fatal
- Off
用法也很简单,直接在你想要记录日志的地方直接加一句
ExceptionlessClient.Default.CreateLog("日志信息", LogLevel.Debug).AddTags("tag1", "tag2").Submit();
所以我们在应用的过程中,可以添加一个统一的接口
public interface ILogger
{
void Debug(string message, params string[] tags);
void Error(string message, params string[] tags);
void Fatal(string message, params string[] tags);
void Info(string message, params string[] tags);
void Off(string message, params string[] tags);
void Other(string message, params string[] tags);
void Trace(string message, params string[] tags);
void Warn(string message, params string[] tags);
}
using Exceptionless;
using Exceptionless.Logging;
public class ExceptionlessLogger : ILogger
{
public void Debug(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Debug).AddTags(tags).Submit();
}
public void Error(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Error).AddTags(tags).Submit();
}
public void Fatal(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Fatal).AddTags(tags).Submit();
}
public void Info(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Info).AddTags(tags).Submit();
}
public void Off(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Off).AddTags(tags).Submit();
}
public void Other(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Other).AddTags(tags).Submit();
}
public void Trace(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Trace).AddTags(tags).Submit();
}
public void Warn(string message, params string[] tags)
{
ExceptionlessClient.Default.CreateLog(message, LogLevel.Warn).AddTags(tags).Submit();
}
}
然后在Startup.cs
的ConfigureServices
方法注入ExceptionlessLogger
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ILogger, ExceptionlessLogger>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
这样就可以更方便地使用了
public class ValuesController : ControllerBase
{
public ILogger _logger;
public ValuesController(ILogger logger)
{
_logger = logger;
}
// GET api/values/{id}
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
try
{
_logger.Info("Test msg", "tag1", "tag2");
throw new Exception();
}
catch (Exception ex)
{
ex.ToExceptionless().AddTags("tag1", "tag2").Submit();
}
return $"value {id}";
}
}
Broken Links
记录404找不到请求的日志
像我这里没有添加favicon.ico图标,使用Chrome浏览器会自动请求这个资源,因此,Exceptionless就记录了这样的日志
也可以直接在Api服务中调用如下面语句添加这种类型的日志
ExceptionlessClient.Default.CreateNotFound("404 not found").SetType("404").SetSource($"api/values/{id}");
Feature Usages
类似的也可以添加Feature Usages日志
ExceptionlessClient.Default.CreateFeatureUsage("Feature 1").SetSource($"api/values/{id}").SetType("FeatureType").Submit();
事件
上面所说的所有日志类型,最终都会通过事件进行记录,Exceptionless也支持我们直接记录一个事件
例子如下:
var dataDic = new Exceptionless.Models.DataDictionary();
dataDic.Add("key", "value");
ExceptionlessClient.Default.SubmitEvent(new Exceptionless.Models.Event
{
Count = 1,
Date = DateTime.Now,
Data = dataDic,
Geo = "geo",
Message = "message",
ReferenceId = "referencelId",
Source = "source",
Tags = new Exceptionless.Models.TagSet() { "tags" },
Type = "type"
});
Exceptionless同时也支持我们捕获事件提交过程和事件提交后的事件,这样我们就可以在过程中做一些操作,例如可以忽略404
的请求,或者针对某些特殊日志返回某些信息
为了代码的整洁,可以将Exceptionless的配置单独放到一个cs文件中
添加一个ExceptionlessBuilderExtensions
类
public static class ExceptionlessBuilderExtensions
{
public static IApplicationBuilder UseExceptionless(this IApplicationBuilder app, IConfiguration configuration)
{
ExceptionlessClient.Default.Configuration.ApiKey = configuration["Exceptionless:ApiKey"];
ExceptionlessClient.Default.Configuration.ServerUrl = configuration["Exceptionless:ServerUrl"];
ExceptionlessClient.Default.SubmittingEvent += OnSubmittingEvent;
app.UseExceptionless();
return app;
}
private static void OnSubmittingEvent(object sender, EventSubmittingEventArgs e)
{
if (e.Event.IsNotFound())
{
e.Cancel = true;//取消事件提交
return;
}
// 修改日志信息
if (e.Event.Source == "sourceA")
{
e.Event.AddTags("systemLog");
}
//TODO:
}
private static void OnSubmittedEvent(object sender, EventSubmittedEventArgs e)
{
// 做点什么东西
if (e.Event.Source == "sourceA")
{
//TODO:
}
}
}
然后修改Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
……
app.UseExceptionless(Configuration);
……
}
Exceptionless 日志查询
Exceptionless Web站点已经帮我们做好项目、时间、日志类型的分类,大家可以很直观地进行操作查询。
我这里要关注的是Filter
查询
前面记录日志的时候,有添加了tag
、Type
等信息,这时候就可以使用Filter进行查询了。
语法:
[FilterType]:[value1] {or} {[value2]}
or是用于查询多个该类型值的日志时使用
例如:tag:tag1
列几个可能比较常用的
- source:"my log source" or "my log source"
- type:error
- level:Error
- ip:127.0.0.1
如果是要同时输入多种类型的条件:
[FilterType]:[value] {OR|AND} {[FilterType]:[value]}
例如:tag:tag1 OR ip:127.0.0.1
更多的语法可以看官网说明
https://github.com/exceptionless/Exceptionless/wiki/Filtering-Searching
总结
在这篇文章中,我基本就是顺着Exceptionless Self Hosting的介绍做了一遍,不过有一些东西因为没有实际环境,所以也没有去做,然后我这个也只是一个Demo,暂时也没有做相关的压力测试,所以也不知道这货真正在生产环境大量用起来的时候会有一些什么表现,会不会踩到什么坑。欢迎大家在留言区跟我一起交流。今天就先跟大家介绍到这里,希望大家能持续关注我们。
参考文献
本文在编写过程中引用或参考了以下文章中的部分内容,如有侵权,请联系修改或删除。
https://www.cnblogs.com/edisonchou/p/exceptionless_deployment_on_production_env_introduction.html
https://www.cnblogs.com/ants/p/8580890.html
Exceptionless(二) - 使用进阶的更多相关文章
- 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开
[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...
- 重温ASP.NET WebAPI(二)进阶
重温ASP.NET WebAPI(二)进阶 介绍 本文为个人对WebApi的回顾无参考价值. 本文内容: Rest和UnitOfWork 创建WebAPi的流程 IOC-Unity的使用 MEF ...
- amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules
amazeui学习笔记二(进阶开发5)--Web 组件开发规范Rules 一.总结 1.见名知意:见那些class名字知意,见函数名知意,见文件名知意 例如(HISTORY.md Web 组件更新历史 ...
- amazeui学习笔记二(进阶开发4)--JavaScript规范Rules
amazeui学习笔记二(进阶开发4)--JavaScript规范Rules 一.总结 1.注释规范总原则: As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性. ...
- amazeui学习笔记二(进阶开发3)--HTML/CSS规范Rules
amazeui学习笔记二(进阶开发3)--HTML/CSS规范Rules 一.总结 1.am:以 am 为命名空间 2.模块状态: {命名空间}-{模块名}-{状态描述} 3.子模块: {命名空间}- ...
- amazeui学习笔记二(进阶开发2)--Web组件简介Web Component
amazeui学习笔记二(进阶开发2)--Web组件简介Web Component 一.总结 1.amaze ui:amaze ui是一个web 组件, 由模板(hbs).样式(LESS).交互(JS ...
- amazeui学习笔记二(进阶开发1)--项目结构structure
amazeui学习笔记二(进阶开发1)--项目结构structure 一.总结 1.项目结构:是说的amazeui在github上面的项目结构,二次开发amazeui用 二.项目结构structure ...
- python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)
21.闭包 闭包:在嵌套函数内,使用非全局变量(且不使用本层变量) 闭包的作用:1.保证数据的安全性(纯洁度).2.装饰器使用 .__closure__判断是否是闭包 def func(): a = ...
- CocoaPods详解之(二)----进阶篇
CocoaPods详解之----进阶篇 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/19178709 转载请注明出处 ...
- HTML学习(二)进阶篇
在博客园中有许多大神对HTML超文本标记语言写了很多内容,总结了很多知识,这里对我看到的博客文章, 所学到的知识,做一个总结. 一)列表和表格 dl→definition list(定义列表),见备 ...
随机推荐
- Ubuntu不输入密码执行sudo命令方法介绍
作为ubuntu等桌面系统,默认登录的帐号是没有root权限的,为了提升权限来执行任务,我们一般用到sudo+命令来执行,但是不难发现我们一般都要输入密码.那么有没有什么方法可以让我们执行sudo的时 ...
- java server wrapper 和 maven assembly 插件
Java Service Wrapper工具YAJSW 简介信息 YAJSW是一个开源的Java服务包装(Java Service Wrapper)工具.YAJSW允许您把任何应用程序安装为windo ...
- Visual C++文件扩展名解读
VisualC++文件扩展名解读 [1] .APS:存储二进制资源的资源辅助中间文件(能否加快资源加载速度). [2] .BMP:位图资源文件. [3] .BSC:浏览信息文件.由浏览信息维护工具(B ...
- 从JDBC到commons-dbutils
1.前言 玩过Java web的人应该都接触过JDBC,正是有了它,Java程序才能轻松地访问数据库.JDBC很多人都会,但是为什么我还要写它呢?我曾经一度用烂了JDBC,一度认为JDBC不过如此,后 ...
- ASP.NET Core 新增用户 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 新增用户 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 新增用户 上一章节我们实现了一个注册表单,但也留了一些东西还没完成, ...
- 【UVA】11992 - Fast Matrix Operations(段树模板)
主体段树,要注意,因为有set和add操作,当慵懒的标志下推.递归优先set,后复发add,每次运行set行动add马克清0 WA了好几次是由于计算那一段的时候出问题了,可笑的是我对着模板找了一个多小 ...
- IAA32过程调用保护规则注册
因为操作系统共享性质,所以,寄存器已成为各种处理或共享资源的处理.然后,该过程发生 当所谓的.假设呼叫者使用内部寄存器值.但这个寄存器的内容,很可能在该呼叫者的执行的过程中改变,用过程执行之前,对该寄 ...
- javascript-DOM学习
javascript-DOM学习 DOM document(html) object modle document对象(DOM核心对象) dom能用来干什么? 对html元素的样式(颜色.大小.位置等 ...
- VS创建新的本地数据库
image image (localdb)\v11.0是VS内置SQL Server+版本号
- QWidget继承自QPaintDevice,这样就可以直接把QWidget传入QPainter的构造函数,比如QPainter(mylabel),然后设置QWidget的长宽后直接进行作画了
比如用QLabel在主界面上画两条虚线: bool ContentWidget::eventFilter(QObject *obj, QEvent *event) { if(obj == line_l ...