> For the complete documentation index, see [llms.txt](https://jakekwak.gitbook.io/nestjs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jakekwak.gitbook.io/nestjs/recipes/untitled-6.md).

# Health checks (Terminus)

## Health checks (Terminus)

[terminus](https://github.com/godaddy/terminus)는 정상적인 종료에 반응하기위한 후크를 제공하며 모든 HTTP 응용 프로그램에 대한 적절한 [Kubernetes](https://kubernetes.io/) readiness/liveness 확인을 생성하도록 지원합니다. [@nestjs/terminus](https://github.com/nestjs/terminus) 모듈은 터미널 라이브러리를 Nest 에코 시스템과 통합합니다.

## Getting started

`@nestjs/terminus`를 시작하려면 필요한 의존성을 설치해야합니다.

```bash
$ npm install --save @nestjs/terminus @godaddy/terminus
```

## Setting up a health check

상태 확인은 **상태 표시기**의 요약을 나타냅니다. 상태 표시기는 서비스 상태에 관계없이 서비스 검사를 실행합니다. 할당된 모든 상태 표시기가 작동되어 실행중인 경우 상태 확인은 긍정적입니다. 많은 응용 프로그램이 유사한 상태 표시기를 필요로 하기 때문에 [@nestjs/terminus](https://github.com/nestjs/terminus)는 다음과 같은 미리 정의된 상태 표시기 집합을 제공합니다.

* `DNSHealthIndicator`
* `TypeOrmHealthIndicator`
* `MongooseHealthIndicator`
* `MicroserviceHealthIndicator`
* `MemoryHealthIndicator`
* `DiskHealthIndicator`

## DNS Health Check

첫번째 상태 확인을 시작하는 첫번째 단계는 상태 표시기를 엔드 포인트에 연결하는 서비스를 설정하는 것입니다.

```typescript
@@filename(terminus-options.service)
import {
  TerminusEndpoint,
  TerminusOptionsFactory,
  DNSHealthIndicator,
  TerminusModuleOptions
} from '@nestjs/terminus';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TerminusOptionsService implements TerminusOptionsFactory {
  constructor(
    private readonly dns: DNSHealthIndicator,
  ) {}

  createTerminusOptions(): TerminusModuleOptions {
    const healthEndpoint: TerminusEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dns.pingCheck('google', 'https://google.com'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
@@switch
import { Injectable, Dependencies } from '@nestjs/common';
import { DNSHealthIndicator } from '@nestjs/terminus';

@Injectable()
@Dependencies(DNSHealthIndicator)
export class TerminusOptionsService {
  constructor(dns) {
    this.dns = dns;
  }

  createTerminusOptions() {
    const healthEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dns.pingCheck('google', 'https://google.com'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
```

일단 `TerminusOptionsService`를 설정하면, `TerminusModule`을 루트 `ApplicationModule`로 가져올 수 있습니다. `TerminusOptionsService`는 설정을 제공하며,이 설정은 `TerminusModule`에 의해 사용됩니다.

```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { TerminusOptionsService } from './terminus-options.service';

@Module({
  imports: [
    TerminusModule.forRootAsync({
      useClass: TerminusOptionsService,
    }),
  ],
})
export class ApplicationModule { }
```

> info **힌트** 올바르게 수행되면 Nest는 GET 요청을 통해 정의 된 경로에 도달 할 수있는 정의 된 상태 점검을 노출합니다. 예를 들어 `curl -X GET 'http://localhost:3000/health'`

## Custom health indicator

경우에 따라 `@nestjs/terminus`에서 제공하는 사전 정의된 상태 표시기가 모든 상태 확인 요구 사항을 다루지 않습니다. 이 경우 필요에 따라 사용자 정의 상태 표시기를 설정할 수 있습니다.

맞춤형 상태 확인을 나타내는 서비스를 만들어 시작하겠습니다. 상태 확인이 어떻게 구성되어 있는지에 대한 기본 지식을 얻기 위해 `DogHealthIndicator` 예제를 만들 것입니다. 모든 `Dog` 오브젝트에 `goodboy` 유형이 있는 경우이 Health 표시기의 상태는 "up"이어야 합니다. 그렇지 않으면 오류가 발생하고 Health 표시기는 "down"으로 표시됩니다.

```typescript
@@filename(dog.health)
import { Injectable } from '@nestjs/common';
import { HealthCheckError } from '@godaddy/terminus';
import { HealthIndicatorResult } from '@nestjs/terminus';

export interface Dog {
  name: string;
  type: string;
}

@Injectable()
export class DogHealthIndicator extends HealthIndicator {
  private readonly dogs: Dog[] = [
    { name: 'Fido', type: 'goodboy' },
    { name: 'Rex', type: 'badboy' },
  ];

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    const badboys = this.dogs.filter(dog => dog.type === 'badboy');
    const isHealthy = badboys.length === 0;
    const result = this.getStatus(key, isHealthy, { badboys: badboys.length });

    if (isHealthy) {
      return result;
    }
    throw new HealthCheckError('Dogcheck failed', result);
  }
}
@@switch
import { Injectable } from '@nestjs/common';
import { HealthCheckError } from '@godaddy/terminus';

@Injectable()
export class DogHealthIndicator extends HealthIndicator {
  dogs = [
    { name: 'Fido', type: 'goodboy' },
    { name: 'Rex', type: 'badboy' },
  ];

  async isHealthy(key) {
    const badboys = this.dogs.filter(dog => dog.type === 'badboy');
    const isHealthy = badboys.length === 0;
    const result = this.getStatus(key, isHealthy, { badboys: badboys.length });

    if (isHealthy) {
      return result;
    }
    throw new HealthCheckError('Dogcheck failed', result);
  }
}
```

다음으로 해야 할 일은 상태 표시기를 공급자로 등록하는 것입니다.

```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { TerminusOptions } from './terminus-options.service';
import { DogHealthIndicator } from './dog.health.ts';

@Module({
  imports: [
    TerminusModule.forRootAsync({
      imports: [ApplicationModule],
      useClass: TerminusOptionsService,
    }),
  ],
  providers: [DogHealthIndicator],
  exports: [DogHealthIndicator],
})
export class ApplicationModule { }
```

> info **힌트** 실제 응용 프로그램에서 `DogHealthIndicator`는 별도의 모듈 (예: `DogsModule`)로 제공되어야하며, 그런 다음 `ApplicationModule`에서 가져옵니다. 그러나 `DogHealthIndicator`를 `DogModule`의 `exports` 배열에 추가하고 `TerminusModule.forRootAsync()`파라미터 객체의 `imports` 배열에 `DogModule`을 추가해야합니다.

마지막으로 해야 할 일은 필요한 상태 점검 엔드 포인트에 사용 가능한 상태 표시기를 추가하는 것입니다. 이를 위해 우리는 `TerminusOptionsService`로 돌아가서`/health` 엔드 포인트를 구현합니다.

```typescript
@@filename(terminus-options.service)
import {
  TerminusEndpoint,
  TerminusOptionsFactory,
  DNSHealthIndicator,
  TerminusModuleOptions
} from '@nestjs/terminus';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TerminusOptionsService implements TerminusOptionsFactory {
  constructor(
    private readonly dogHealthIndicator: DogHealthIndicator
  ) {}

  createTerminusOptions(): TerminusModuleOptions {
    const healthEndpoint: TerminusEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dogHealthIndicator.isHealthy('dog'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
@@switch
import { DogHealthIndicator } from '../dog/dog.health';
import { Injectable, Dependencies } from '@nestjs/common';

@Injectable()
@Dependencies(DogHealthIndicator)
export class TerminusOptionsService {
  constructor(dogHealthIndicator) {
    this.dogHealthIndicator = dogHealthIndicator;
  }

  createTerminusOptions() {
    const healthEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dogHealthIndicator.isHealthy('dog'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
```

모든 것이 올바르게 완료 되었다면`/health` 엔드 포인트는 `503` 응답 코드와 다음 데이터로 응답해야 합니다.

```javascript
{
  "status": "error",
  "error": {
    "dog": {
      "status": "down",
      "badboys": 1
    }
  }
}
```

`@nestjs/terminus` [저장소](https://github.com/nestjs/terminus/tree/master/sample)에서 실제 예제를 볼 수 있습니다.

## Custom Logger

`Terminus` 모듈은 상태 확인 요청 동안 모든 오류를 자동으로 기록합니다. 기본적으로 전역 적으로 정의 된 Nest 로거를 사용합니다. 글로벌 로거에 대한 자세한 내용은 [로거 챕터](https://docs.nestjs.com/techniques/logger)에서 확인할 수 있습니다. 경우에 따라`Terminus`의 로그를 명시적으로 처리하려고 합니다. 이 경우 `TerminusModule.forRoot[Async]`함수는 커스텀 로거를위한 옵션을 제공합니다.

```typescript
TerminusModule.forRootAsync({
  logger: (message: string, error: Error) => console.error(message, error),
  endpoints: [
    ...
  ]
})
```

로거 옵션을 `null`로 설정하여 로거를 비활성화 할 수도 있습니다.

```typescript
TerminusModule.forRootAsync({
  logger: null,
  endpoints: [
    ...
  ]
})
```
