NestJS에 NewRelic 연동하는 법
NestJS에 NewRelic을 연동하는 법이다.
1. New Relic에 접속한 후 Add data를 누른다.

2. Data sources를 Node.js를 선택한다.
TS로 작성된 NestJS도 결국 JS로 컴파일되어서 NodeJS로 실행되기 때문에 Node.js를 선택한다.

3. Begin Installation을 클릭한다.
이때 아래 캡처본에는 안 나왔지만 방화벽 같은 것이 있을 경우 Proxy를 사용하는 법에 대해서 나와있다. 참고하자.

4. 해당하는 NodeJS 배포 환경을 고른다.

나는 EC2 인스턴스에 PM2로 NodeJS 프로세스를 올리며 관리하고 있다. 그래서 On a host (with PM2)를 선택했다.
5. Node.js Agent의 명령어를 서버에 실행한다.

이걸 실행하고 기다리다보면 API KEY같은 것을 준 것이 없어서 마지막 스텝에서 Fail할 것이다. 나중에 전부 설정하고 연동해줄 것이므로 마지막 단계는 실패해도 상관 없다!
Fail하든 말든 위 명령어의 실행이 끝날 때까지 기다린 후 우측 하단의 Node standard installation 버튼을 클릭해주자.

6. application 이름을 설정해준 뒤, configuration file을 다운받는다.
먼저 내 계정을 고른다. 만약 다른 앱(Browser application, Database instance 등)도 newrelic으로 연동된 상태이면 그것을 연동시킨 계정과 똑같은 계정으로 설정하면 된다.
①에서 내 application의 이름을 설정한다.
②는 내 NestJS 앱에서 해줄 것이기 때문에 일단의 패스한다.
③에서 주는 내 custom configuratin file을 다운받는다.

7. NestJS 앱에 ③에서 받은 설정 파일을 넣어준다.

newrelic.js라는 파일이 다운 받아졌을 것이다. 그런데 NestJS는 TS를 쓰므로 확장자를 .js에서 .ts로 바꿔준다.

그리고 ③의 안내 문구를 보면 이 파일을 Node.js의 application의 루트 디렉터리에 넣어라고 한다.
NestJS의 application의 루트 디렉터리는 "src/"이다. (package.json이 있는 "/"이 아니다.)
src 디렉터리에 확장자를 바꿘준 newrelic.ts 파일을 넣어준다.

여기에 우리 API키와 로깅 레벨 등의 세부 설정들이 들어가 있다. 나중에 필요하면 바꿔주자.
8. Intercepter로 NestJS 앱에서 일어나는 transaction을 Newrelic agent가 수집할 수 있게 한다.
저기에 나와있는 ④와 ⑤에 해당하는 단계이다. 일반적인 node.js 앱이면 저렇게하면 되겠지만 우리는 TS로 모든게 이루어져있는 NestJS 프레임워크를 쓰고 있다. 그래서 NestJS에서 제공해주는 interceptor로 연동을 해주어야 한다.

먼저 newrelic 모듈을 깔아준다. 나는 yarn을 쓰므로 다음과 같이 했다.
# newrelic module 설치 yarn add newrelic # type이 필요한 경우 @types/newrelic도 깔아주자 yarn add -D @types/newrelic
Nest Interceptor로 NewRelic Interceptor를 만들어준다.
Nest에서 Interceptor는 @Injectable()로 데코레이팅하고 NestInterceptor를 상속받아서 구현할 수 있다.
처음부터 만들 필요는 없다. New Relic에서 친절하게 코드를 제공해준다. 아래 Example을 참고해서 NewrelicInterceptor를 만들어주자.
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, } from '@nestjs/common'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; const util = require('util'); const newrelic = require('newrelic'); @Injectable() export class NewrelicInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { console.log( `트랜젝션 전: ${util.inspect(context.getHandler().name)}`, ); return newrelic.startWebTransaction(context.getHandler().name, function () { const transaction = newrelic.getTransaction(); return next.handle().pipe( tap(() => { console.log( `트랜젝션 후: ${util.inspect( context.getHandler().name, )}`, ); return transaction.end(); }), ); }); } }
서비스가 호출될 때마다 New Relic agent의 트랙젝션을 시작하고 끝내면 된다.
9. app에 우리가 만든 NewrelicInterceptor를 사용하도록 설정한다.
src/main.ts 파일을 열어서 Interceptor를 설정해주자.
app에 NewrelicIntercepter를 주입해서 사용하도록 설정해주면 된다.
10. NestJS 앱을 실행하고 ⑥의 코드를 서버에 실행한다.
NestJS 앱을 실행해주자.
그리고 ⑥에서 제공해주는 코드를 복사해서 배포용으로 쓰고 있는 원격 인스턴스에서 실행시켜주자.

실행되는 것을 기다린다.

11. ⑦의 버튼을 눌러서 데이터가 잘 수집되는지 확인한다.
10.의 코드가 성공적으로 잘 실행이되고 연동이 되었다면 이제 ⑦의 See your data 버튼이 자동으로 활성화가 될 것이다.

활성화된 See your data 버튼을 눌러서 데이터가 잘 전송이 되고 있다는 것이 확인이 되면 성공이다.
이제 내 앱의 Monitor에 가서 내 데이터들을 구경하면 된다. API를 몇 번 호출해주고 트랜젝션 탭에 가주면 다음과 같이 뜬다.

12. (선택) 서비스 관계 추가하기
사실 11.까지 했으면 백엔드 정보 수집을 위한 agent 설치와 code level로 HTTP request의 수집이 되기 시작한다.
하지만 보통 우리의 서비스가 운영되기 위해서는 여러 Entity들이 흩어져서 각자의 역할을 가지고 서로 상호작용한다. Entity별로 로그 수집을 하고 각각 흩어져 있는 로그를 읽는다면 직관적으로 정보를 분석하기 어렵다. 번갈아 보다가 중요한 정보를 놓칠 수도 있고 시간 순서에 따라 번갈아가며 분석하며 시간을 많이 소비한다.
New Relic은 자동으로 이런 관계를 파악하고 유용한 데이터를 분석해준다. 이것은 Distributed Tracing이라고 부른다.
Distributed Tracing은 분산된 로그를 Tracing하는데 도움을 주는 기능이다. New Relic을 쓰는 가장 큰 이유 중 하나라고 생각한다.
https://docs.newrelic.com/docs/distributed-tracing/concepts/how-new-relic-distributed-tracing-works
Technical distributed tracing details | New Relic Documentation
By default, each trace observer offers traces to three samplers: one looking for duration outliers, one looking for traces with errors, and one trying to randomly sample across all trace types. Each sampler keeps a target percentage of traces that match th
docs.newrelic.com
그렇기 때문에 관련해서 꼭 읽어보자.
Entity란?
NewRelic에서 쓰는 용어로 되게 넓은 의미로 쓰인다.
Browser 애플리케이션이나 데이터베이스 등 여러 서비스도 Entity고 우리가 따로 이런 것들을 뭉쳐서 Workload로 만들 수 있는데 이런 것도 Entity라고 부른다.
참고.
- https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/what-entity-new-relic/
- https://docs.newrelic.com/docs/apis/nerdgraph/examples/nerdgraph-relationships-api-tutorial/
가끔 안 되는 경우 우리가 직관적으로 순서에 따라 확인할 수 있게 관계를 직접 명시해줄 수 있다.
위의 Distributed Tracing 글을 읽으면 대충 왜 수집이 제대로 안 되는지 파악할 수 있다.
정책에 의해 header가 짤렸거나 등
만약에 관련 있는 다른 서비스도 New Relic에 연동되어 있는 경우 따라하세요.
아래의 설명은 New Relic 신 UI 기준으로 되어있다. 구버전 UI를 사용하는 경우 아래 캡처 화면과 다르게 나옵니다.
헷갈리는 경우 잠시 설정에서 신UI로 바꾸고 참고하세용.
먼저 방금 추가 해준 APM에 들어간다.

오른쪽 메뉴에 보면 Related enties라고 나오는데 거기에 있는 Add/edit related entities 버튼을 클릭한다.

적절한 관계를 추가해주면 된다.

Relation의 종류에 관해 궁금하다면 다음의 글을 참고해보자.
https://docs.newrelic.com/docs/new-relic-solutions/new-relic-one/core-concepts/what-entity-new-relic/
끝!
참고
- https://newrelic.com/blog/how-to-relic/new-relic-nestjs
- https://github.com/newrelic-experimental/newrelic-nestjs-integration
댓글을 사용할 수 없습니다.