上一节主要介绍Opserver的搭建以及redis、sqlserver监控的配置,本节主要介绍异常日志的记录和监控。要实现异常日志的监控我们需要在项目中引入StackExchange.Exceptional组件,用于日志的采集和存储操作。
首先我们简单的来认识一下Opserver项目config文件夹下的ExceptionsSettings.json.example文件,
{ "warningRecentCount": "100", //警告提醒最近条目数,当超出该值在头部高亮显示警告 "criticalRecentCount": "200", //严重警告提醒最近条目数,当超出该值在头部高亮显示严重警告 "viewGroups": "StatusExceptionsRO", //安全模式“ad"下的分组查看权限设置 // You can have a simple applications list here, or a grouped structure when dealing with many apps. //"applications": [ //产生异常日志的程序 // "Core", // "Chat", // "Stack Auth", // "StackExchange.com", // "API", // "API v2", // "Area 51", // "Status", // "Push Server", // "Sockets", // "Careers", // "BackOffice", // "Control Panel" //],
//以分组在形式归类异常日志,未在groups定义的在others中显示 "groups": [ { "name": "Core Q&A", "applications": [ "Core", "Chat", "Stack Auth", "StackExchange.com", "API v2", "Sockets", "Area 51", "Open ID", "Stack Server", "StackSnippets", "Status" ] }, { "name": "Careers", "applications": [ "Careers", "BackOffice", "BackOffice", "Control Panel", "StackShop", "CareersAuth" ] }, { "name": "Mobile", "applications": [ "Push Server" ] }, { "name": "Ads & Data", "applications": [ "Prov Read API" ] } ], "stores": [ //异常日志存储位置 { "name": "New York", "queryTimeoutMs": 2000, "pollIntervalSeconds": 10, "connectionString": "Server=ny-sql03.ds.stackexchange.com;Database=NY.Exceptions;Integrated Security=SSPI;" } ] }
1、StackExchange.Exceptional引入及记录异常日志
异常日志可以有web,console,service等程序产生
web项目,需要3步配置:
- 在web项目中nuget安装StackExchange.Exceptional组件(依赖dapper)
- 在web.config中增加section “Exceptional”
<section name="Exceptional" type="StackExchange.Exceptional.Settings" /> <Exceptional applicationName="Samples.MVC4"> <ErrorStore type="Memory" />
<!--连接opserver数据库时开启-->
<!--<ErrorStore type="SQL" connectionString="Server=.;Database=Exceptions;Uid=Exceptions;Pwd=myPassword!" />--> </Exceptional>
applicatinName 产生异常日志的程序名称用于Opserve显示归类
ErrorStore 错误存储有4种实现方式,Memory,JSON,SQL,MySQL,参考官方说明
<!-- Which ErrorStore to use, if no element is declared here a Memory store with defaults will be used --> <!--<ErrorStore type="Memory" />--> <!-- Other store types, common attributes: - rollupSeconds: optional (default 600 seconds), determines how long the window is to roll up exceptions with the same stack trace - 0 to not roll up - backupQueueSize: optional (default 1000), determines how many errors to cache (excluding rollups) in memory when logging fails...every 2 seconds we'll retry logging and flush these out to the final store --> <!-- JSON: size defaults to 200, this is how many files are kept before the oldest error is removed --> <!--<ErrorStore type="JSON" path="~/Errors" size="200" />--> <!-- SQL: only a connection string or connection string name is needed, many applications can log to the same place as long as they have unique names (otherwise we can't tell them apart). --> <!--<ErrorStore type="SQL" connectionString="Server=.;Database=Exceptions;Uid=Exceptions;Pwd=myPassword!" />--> <!--<ErrorStore type="SQL" connectionStringName="MyConnectionString" />--> <!-- You can also use a MySQL Database with the MySQL ErorrStore --> <!--<ErrorStore type="MySQL" connectionString="Server=.;Database=Exceptions;Username=Exceptions;Pwd=myPassword!" />--> <!--<ErrorStore type="MySQL" connectionStringName="MyConnectionString" />-->
- 在web.config中增加handler和module,module配置后,异常日志自动记录
<system.webServer> <validation validateIntegratedModeConfiguration="false" /> <handlers> <!-- OPTIONAL: if not using a router, or you don't want to access the errors directly via this application, this is not necessary. A common scenario for this is logging all errors to a common SQL store and viewing them through another application or a dashboard elsewhere. Note: If the error list isn't exposed in the application, any errors in logging exceptions will be queued up, but not visible (since that's exposed on the error list view). --> <add name="Exceptional" path="exceptions.axd" verb="POST,GET,HEAD" type="StackExchange.Exceptional.HandlerFactory, StackExchange.Exceptional" preCondition="integratedMode" /> </handlers> <!-- Here the error log needs to be registered to catch all unhandled exceptions, these are exceptions that make it all the way to being a 500 page the user sees. --> <modules runAllManagedModulesForAllRequests="true"> <add name="ErrorLog" type="StackExchange.Exceptional.ExceptionalModule, StackExchange.Exceptional" /> </modules> </system.webServer>
console,service前两步同web项目,需要nuget安装StackExchange.Exceptional,在app.config配置section“Exceptional”,然后在main主函数中添加未处理异常记录
static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; /* ... */ } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Exception ex = e.ExceptionObject as Exception; if (ex != null) { StackExchange.Exceptional.ErrorStore.LogExceptionWithoutContext(ex); } }
如果需要自定义添加异常,可以在try...catch中记录,如:
try { throw new Exception("Just a try/catch test"); } catch (Exception ex) { // logged, but caught so we don't crash ErrorStore.LogExceptionWithoutContext(ex); }
3、异常数据存储SQL,创建表语句
USE [OpServerTest] GO /****** Object: Table [dbo].[Exceptions] Script Date: 2016/11/16 16:28:56 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[Exceptions]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [GUID] [uniqueidentifier] NOT NULL, [ApplicationName] [nvarchar](50) NOT NULL, [MachineName] [nvarchar](50) NOT NULL, [CreationDate] [datetime] NOT NULL, [Type] [nvarchar](100) NOT NULL, [IsProtected] [bit] NOT NULL, [Host] [nvarchar](100) NULL, [Url] [nvarchar](500) NULL, [HTTPMethod] [nvarchar](10) NULL, [IPAddress] [varchar](40) NULL, [Source] [nvarchar](100) NULL, [Message] [nvarchar](1000) NULL, [Detail] [nvarchar](max) NULL, [StatusCode] [int] NULL, [SQL] [nvarchar](max) NULL, [DeletionDate] [datetime] NULL, [FullJson] [nvarchar](max) NULL, [ErrorHash] [int] NULL, [DuplicateCount] [int] NOT NULL, CONSTRAINT [PK_Exceptions] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[Exceptions] ADD DEFAULT ((0)) FOR [IsProtected] GO ALTER TABLE [dbo].[Exceptions] ADD DEFAULT ((1)) FOR [DuplicateCount] GO
4、在Opserver项目中,配置 ExceptionsSettings.json文件,修改groups和stores,如:
"stores": [ //异常日志存储位置
{
"name": "ExceptionDB",
"queryTimeoutMs": 2000,
"pollIntervalSeconds": 10,
"connectionString": "Data Source=192.168.1.120;User ID=sa;Password=*******;Initial Catalog=OpserverTest;"
}
注:目前Opserver版本支持store在sql server服务器上,不支持在文件,内存,和Mysql中,如果需要mysql支持,需要修改Opserver.core代码。
在配置多个store的情况,默认第一个有效
官方示例dome和源码下载:https://github.com/NickCraver/StackExchange.Exceptional