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

相關文章
相關標籤/搜索