Exceptionless(二) - 使用进阶

Exceptionless(二) - 使用进阶

做者:markjiang7m2
原文地址:http://letyouknow.net/exceptionless/exceptionless-tutorial-2.html
官网地址:http://letyouknow.nethtml

在上一篇文章Exceptionless - .Net Core开源日志框架中就说到如何对Exceptionless进行本地化部署,不过我也跟你们说了,仅限于能用的阶段。那今天我就继续来探讨一下如何再用好。java

后台运行服务

上次我就是直接经过脚本Start-ElasticSearch.ps1启动ElasticSearch和Kibana服务,可是你们也能看到,服务是运行起来了,同时还有两个命令窗口,若是一个不当心把窗口关闭了,服务也就关闭了,并且一旦服务器重启了,这两个服务也不会自动启动。
我这里先暂时把Kibana扔一边去,来看看ElasticSearch服务。ElasticSearch是直接有脚本支持将ElasticSearch安装为Windows服务,在后台运行。nginx

less_23_searchservicebat

就是这个elasticsearch-service.bat脚本,支持一下参数:git

  • install 将Elasticsearch做为服务安装
  • remove 删除已安装的Elasticsearch服务(并在启动时中止服务)
  • start 启动Elasticsearch服务(若是已安装)
  • stop 中止Elasticsearch服务(若是启动)
  • manager 启动一个GUI来管理已安装的服务

安装
命令行,进入到elasticsearch-service.bat所在的目录,而后执行下面的脚本github

elasticsearch-service.bat install

启动web

less_25_servicestarted

这个时候咱们能够直接在浏览器访问9200端口看看服务是否正常shell

less_26_serviceconfirm

继续使用上次部署好的Exceptionless
(如何使用IIS部署Exceptionless Web服务,请看Exceptionless - .Net Core开源日志框架c#

由于我是直接用回以前ElasticSearch的节点,并且也没有清空数据,因此能够直接用以前注册的帐号从新登陆windows

less_27_weblogin

也是成功的,ElasticSearch服务已经运行在后台了。api

自动启动
经过ElasticSearch提供的GUI能够将服务设置为自动启动

elasticsearch-service.bat manager

Startup Type选择为Automatic,再点击OK保存

less_28_serviceauto

这样,即便服务器重启了,咱们的ElasticSearch服务也会自动启动

其实,有玩过Windows服务的朋友必定知道,上面的一些操做在Windows自带的服务管理器也能完成

同时按下"WIN+R" 打开服务的命令运行窗口。在服务运行窗口中输入services.msc

在列表中也能够找到ElasticSearch服务,双击打开属性窗口,跟刚刚的GUI操做就是同样的了

less_29_windowsservice

再看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.csConfigureServices方法注入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就记录了这样的日志

less_30_brokenlinks

也能够直接在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查询

前面记录日志的时候,有添加了tagType等信息,这时候就可使用Filter进行查询了。
语法:

[FilterType]:[value1] {or} {[value2]}

or是用于查询多个该类型值的日志时使用

例如:tag:tag1

less_32_filtertag

列几个可能比较经常使用的

  • 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
http://www.javashuo.com/article/p-kwpvhlyc-ms.html

相关文章
相关标签/搜索