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로 보내준다.

teamsmiley's profile image

teamsmiley

2019-03-01 00:00

Read more posts by this author