امروز :1403/09/24

سایت خبری ایران سی شارپ

مختصص برنامه نویسان دات نت

گزارش گیری خطاها با استفاده از Elmah در MVC

گزارش گیری خطاها با استفاده از Elmah در MVC

انتشار : 1398/12/07

در این مقاله قصد داریم نحوه استفاده از Elmah را به همراه یک نمونه شرح دهیم . Elmah یک کتابخانه رایگان است که برای ارائه گزارش از خطاهای وب سایتی که نوشته اید به شما کمک می کند .

 خطاهای رخ داده در برنامه شما را گزارش می گیرد.کار با Elmah بسیار ساده است .باید آن را به طریقی به برنامه اضافه کنید .روش های مختلفی برای افزودن آن به برنامه وجود دارد که یکی از این روش ها می تواند افزودن Dll آن از پروژه ای دیگر باشد و یا اینکه از طریق NUGET آن را به برنامه خود اضافه کنید .

به هر حال پس از افزودن آن به پروژه ، فقط کافی است تا تغییرات کمی در Web.config بدهید .پس از راه اندازی Elmah می توانید از طریق آدرس Domain خود و سپس افزودن /Elmah.axd به صفحه ای بروید که خطا ها در آن نمایش داده می شود . Elmah این قابلیت را  هم دارد که خطاها را برای شما ایمیل کند .

حال برای شروع کار ابتدا یک پروژه از نوع Asp.net MVC ایجاد می کنیم .

نوع این نمونه از نوع mvc است

بعد از ایجاد نمونه باید از طریق nugget امکان Elmah  را اضافه کنیم .

حال در داخل web.config تغییرات زیر را در قسمت <system.web> </system.web> اعمال می کنیم .

1
2
3
4
5
<!--add this--> 
    < httpHandlers > 
    < add verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > 
    < /httpHandlers> 
<!--add this--> 

و همچنین در قسمت <system.webServer></system.webServer> تغییرات زیر را انجام می دهیم

1
2
3
4
5
<!--add this--> 
    < handlers > 
    < add name = "Elmah"verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > 
    < /handlers> 
<!--add this--> 

بعد از افزودن Elmah و اعمال برخی تغییرات در داخل web.congig لازم است که در دیتابیس به ساخت جدولی بپردازیم که خطاها در آن ذخیره شود .

اسکریپت ساخت جدول به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
CREATE TABLE[dbo].[ELMAH_Error] 
   
    [ErrorId][uniqueidentifier] NOT NULL, 
   
    [Application][nvarchar](60) NOT NULL, 
   
    [Host][nvarchar](50) NOT NULL, 
   
    [Type][nvarchar](100) NOT NULL, 
   
    [Source][nvarchar](60) NOT NULL, 
   
    [Message][nvarchar](500) NOT NULL, 
   
    [User][nvarchar](50) NOT NULL, 
   
    [StatusCode][int] NOT NULL, 
   
    [TimeUtc][datetime] NOT NULL, 
   
    [Sequence][int] IDENTITY(1, 1) NOT NULL, 
   
    [AllXml][ntext] NOT NULL 
   
)

برای ذخیره اطلاعات در داخل این جدول روال هایی نوشته شده اند که در زیر می بینید

روال ذخیره شده و یا Stored Procedure مربوط به گرفتن همه خطا ها به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Create PROCEDURE[dbo].[ELMAH_GetErrorsXml] 
   
    @Application NVARCHAR(60), 
    @PageIndex INT = 0, 
    @PageSize INT = 15, 
    @TotalCount INT OUTPUT 
   
   
AS 
   
SET NOCOUNT ON 
   
DECLARE @FirstTimeUTC DATETIME 
DECLARE @FirstSequence INT 
DECLARE @StartRow INT 
DECLARE @StartRowIndex INT 
SELECT 
   
@TotalCount = COUNT(1) 
   
FROM 
   
    [ELMAH_Error] 
   
WHERE 
   
    [Application] = @Application 
SET @StartRowIndex = @PageIndex * @PageSize + 1 
IF @StartRowIndex <= @TotalCount 
   
BEGIN 
   
SET ROWCOUNT @StartRowIndex 
   
SELECT 
   
@FirstTimeUTC = [TimeUtc], 
   
    @FirstSequence = [Sequence] 
   
FROM 
   
    [ELMAH_Error] 
   
WHERE 
   
    [Application] = @Application 
   
ORDER BY 
   
    [TimeUtc] DESC, 
    [Sequence] DESC 
   
END 
   
ELSE 
   
BEGIN 
   
SET @PageSize = 0 
   
END 
   
SET ROWCOUNT @PageSize 
   
SELECT 
   
errorId = [ErrorId], 
   
    application = [Application], 
    host = [Host], 
    type = [Type], 
    source = [Source], 
    message = [Message], 
    [user] = [User], 
    statusCode = [StatusCode], 
    time = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z' 
   
FROM 
   
    [ELMAH_Error] error 
   
WHERE 
   
    [Application] = @Application 
   
AND 
   
    [TimeUtc] <= @FirstTimeUTC 
   
AND 
   
    [Sequence] <= @FirstSequence 
   
ORDER BY 
   
    [TimeUtc] DESC, 
   
    [Sequence] DESC 
   
FOR 
   
XML AUTO

روال ذخیره شده برای دریافت یک خطای خاص به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Create PROCEDURE[dbo].[ELMAH_GetErrorXml] 
   
   
    @Application NVARCHAR(60), 
    @ErrorId UNIQUEIDENTIFIER 
   
   
AS 
   
SET NOCOUNT ON 
SELECT 
   
    [AllXml] 
FROM 
   
    [ELMAH_Error] 
WHERE 
   
    [ErrorId] = @ErrorId 
AND 
    [Application] = @Application

و در نهایت روال ذخیره شده در دیتابیس برای ذخیره خطا به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Create PROCEDURE[dbo].[ELMAH_LogError] 
   
   
    @ErrorId UNIQUEIDENTIFIER,   
    @Application NVARCHAR(60),   
    @Host NVARCHAR(30),   
    @Type NVARCHAR(100), 
    @Source NVARCHAR(60),   
    @Message NVARCHAR(500), 
    @User NVARCHAR(50),  
    @AllXml NTEXT,   
    @StatusCode INT,  
    @TimeUtc DATETIME 
   
   
AS 
   
SET NOCOUNT ON 
   
INSERT 
   
INTO 
   
    [ELMAH_Error]
   
    [ErrorId],  
    [Application],  
    [Host], 
    [Type], 
    [Source], 
    [Message],   
    [User],   
    [AllXml],   
    [StatusCode],   
    [TimeUtc] 
   
   
VALUES 
   
    
   
    @ErrorId, 
    @Application,   
    @Host,   
    @Type,   
    @Source,  
    @Message,   
    @User,  
    @AllXml,  
    @StatusCode,  
    @TimeUtc 
   
)

بعد از اجرای اسکریپت های بالا شکل دیتابیس ما به صورت زیر خواهد بود

دوباره به فایل web.config برمی گریم و تغییر زیر را هم اعمال می کنیم .

1
2
3
4
5
6
7
8
9
</configuration> 
<elmah> 
    <!--. If allowRemoteAccess value is set to 0, then the error log web page can only be viewed locally. If allowRemoteAccess attribute is set to 1 then the error log web page is enabled for both remote and local visitors.--> 
    <!--add this--> 
    <security allowRemoteAccess="0" /> 
    <!--  DefaultConnection is the name of database connection string --> 
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> 
    <!--add this--> 
</elmah> 

در داخل تگ Elmah تنظیمات مختلفی مانند اینکه آیا خطاها توسط کاربران راه دور مشاهده شود یا خیر وجود دارد.اینکه خطاها در کجا ذخیره شوند را هم در این تگ مشخص می کنیم .

شکل نهایی فایل web.config به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup></configSections>
  <connectionStrings>
    <!--<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MVCExceptionLog-20160102095730.mdf;Initial Catalog=aspnet-MVCExceptionLog-20160102095730;Integrated Security=True" providerName="System.Data.SqlClient" />-->
    <add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=ELMAH_Errore;Integrated Security=True" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  <add key="elmah.mvc.disableHandler" value="false" /><add key="elmah.mvc.disableHandleErrorFilter" value="false" /><add key="elmah.mvc.requiresAuthentication" value="false" /><add key="elmah.mvc.IgnoreDefaultRoute" value="false" /><add key="elmah.mvc.allowedRoles" value="*" /><add key="elmah.mvc.allowedUsers" value="*" /><add key="elmah.mvc.route" value="elmah" /><add key="elmah.mvc.UserAuthCaseSensitive" value="true" /></appSettings>
  <system.web>
     <httpHandlers > 
    <add verb = "POST,GET,HEAD" path ="elmah.axd" type ="Elmah.ErrorLogPageFactory, Elmah" /> 
    </httpHandlers> 
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  <httpModules>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
    </httpModules></system.web>
  <system.webServer>
       <handlers > 
    <add name = "Elmah" verb ="POST,GET,HEAD" path ="elmah.axd" type ="Elmah.ErrorLogPageFactory, Elmah" /> 
    </handlers> 
    <modules>
      <remove name="FormsAuthentication" />
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" /><add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" /><add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" /></modules>
  <validation validateIntegratedModeConfiguration="false" /></system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
<elmah>
   <security allowRemoteAccess="0" /> 
    <!--  DefaultConnection is the name of database connection string --> 
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> 
  </elmah>
</configuration>

حال به صورت عمد در داخل کنترلر مربوط به Home و در داخل Action به نام contact یک کد اشتباه می نویسیم تا خطا تولید کند .کد کنترلر به صورت زیر است

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public ActionResult Index()
      {
          return View();
      }
      public ActionResult About()
      {
          ViewBag.Message = "Your application description page.";
          return View();
      }
      public ActionResult Contact()
      {
          int a = 0;
          int b;
          b = 1 / a;
          ViewBag.Message = "Your contact page.";
          return View();
      }

اگر برنامه را با آدرس …../Home/contact اجرا کنید صفحه خطای زیر را خواهید دید

به مسیر …/Account/Register رفته و F5 را فشار دهید تا برنامه در این مسیر اجرا شود

برای دیدن خطاهای رخ داده شده به آدرس Domain/Elmah.axd بروید .همان طور که می بینید کلیه خطاهای کاربران در این صفحه گزارش شده است.اما در صفحه register اگر پسورد را اشتباه وارد کنید همانجا Regular Expression به شما پیغام می دهد و دیگر جزو خطاهای exception نیست که به شما پیغام خطا در داخل elmah بدهد در واقع خطاهای سیستمی گزارش گیری می شوند.

در داخل دیتابیس هم خطاها ذخیره شده است

 

دیدگاه کاربران
0 دیدگاه
    شما هم دیدگاه خود را ارسال کنید