Sentry.io를 사용하여 로그를 원격지에 저장해보자.
로그를 원격지에 저장하여 이메일등으로 받아볼수 있는 서비스.
작업전에 sentry.io에 회원가입을 하고 이메일 확인을 한다.
dotnet core 2.2 project
누겟 패키지를 설치하자.
Install-Package Sentry.AspNetCore -Version 1.1.2
program.cs에서 다음처럼 수정하자.
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
// Add this:
.UseSentry()
.Build();
반드시 스타트업 다음에 추가해야한다.
이제 appsettings.json 에 관련 내용을 추가하자.
"Sentry": {
"Dsn": "https://6425120cdbbf4e3491f9ba08f4323333@sentry.io/1406444",
"IncludeRequestPayload": true,
"SendDefaultPii": true,
"MinimumBreadcrumbLevel": "Debug",
"MinimumEventLevel": "Warning",
"AttachStackTrace": true,
"Debug": true,
"DiagnosticsLevel": "Error"
},
UseSentry함수가 이 설정을 읽어들여서 에러가 나면 sentry로 보내준다.
이제 컨트롤러에서 에러를 발생해보자.
public async Task<IActionResult> GetApps([FromQuery] Apps vm)
{
var result2 = "aaa";
throw new Exception("asdfasdf");
return Ok(result2);
}
호출될때마다 에러가 발생할것이고 이것이 sentry에 들어오는지 보면 된다.
filter 문제
dotnet core에서는 필터라는걸 제공하는데 프로젝트에서 이 필터를 사용하여 application layer에서 에러가 난 내용을 http에 맞게 변경해서 결과값으로 보내준다. 코드는 대략 다음과 같다.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
//private readonly ILogger _logger;
// public CustomExceptionFilterAttribute(ILoggerFactory loggerFactory)
// {
// _logger = loggerFactory.CreateLogger("CustomExceptionFilterAttribute");
// }
public override void OnException(ExceptionContext context)
{
//_logger.LogError("CustomExceptionFilterAttribute");
var code = HttpStatusCode.InternalServerError;
if (context.Exception is NotFoundException)
{
code = HttpStatusCode.NotFound;
}
context.HttpContext.Response.ContentType = "application/json";
context.HttpContext.Response.StatusCode = (int)code;
context.Result = new JsonResult(new
{
error = new[] { context.Exception.Message },
});
}
}
}
NotFoundException 에러가 나면 이걸 catch해서 HttpStatusCode.NotFound 으로 바꾸어서 보내주므로 Exception이 Program.cs에 도달하지 않는다. 미리 처리해버리기 때문이다.
그럼 이런 에러를 어떻게 sentry로 보낼까?
위에 주석코드를 해제한다.
기본적으로 sentry가 log.LogError 를 서버로 보내주게 되있다. 그래서 그냥 logging만 하면 서버로 내용을 보내준다.
필요한 내용을 LogError로 로깅만 하면 서버로 보내준다.
angular
npm 패키지을 설치한다.
npm install @sentry/browser
app.module.ts에서 다음 코드 추가
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://75fd265d9e2b4088be70f7e5774916ce@sentry.io/1408842"
});
@Injectable()
export class SentryErrorHandler implements ErrorHandler {
constructor() {}
handleError(error) {
Sentry.captureException(error.originalError || error);
throw error;
}
}
@NgModule({
providers: [{ provide: ErrorHandler, useClass: SentryErrorHandler }], //프로바이더로 제공
})
이렇게 하면 끝난다. 프론트에서 에러 발생시 sentry서버로 보내준다.
우리는 Global Error Handler를 사용해서 사용법이 조금 다른다. 해보자.
기존 변경을 지우고
app.module.ts에서 다음처럼 한다.
providers: [
{ provide: ErrorHandler, useClass: AppErrorHandler }
],
이제 AppErrorHandler에서
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: "https://75fd265d9e2b4088be70f7e5ac4916ce@sentry.io/1406642"
});
handleError(error: any): void {
console.log("Global Error Handling : " + error);
console.error(error.originalError || error);
Sentry.captureException(error.originalError || error);
}
이렇게 하면 sentry로 보내준다.
끝