NestJS:在 healthcheck 上呈现来自 URL 的响应内容
NestJS: present response content from URL on healthcheck
我正在尝试使用 NestJS 开发一个健康检查端点(我没有这方面的经验)。我要检查的依赖项之一是 Twilio 的 SMS 服务。到目前为止,我发现收集此信息的最佳 URL 是 https://status.twilio.com/api/v2/status.json。这里的问题是我不想仅仅 ping 这个地址,而是收集它的 JSON 响应并呈现它提供的一些信息,即这些:
是否可以使用(或不使用)Terminus 模块?在官方文档中我没有找到任何关于此的内容,只有使用 pingCheck
/ responseCheck
的更简单的示例:https://docs.nestjs.com/recipes/terminus
是的,有可能。
我从来没有用过这个,但是 HttpHealthIndicator
有 responseCheck
方法来检查取决于 API 响应消息。您可以指定一个回调函数来分析来自 API 的响应。回调函数应该 return 布尔值表示 API.
的状态
我在文档中找不到这个,但你可以看到它 here。
尽管同时此健康检查的逻辑已更改(因此此问题已过时),但这是我在它发生之前找到的临时解决方案(基本上是使用 axios 的常规端点,如其中之一所指出的那样)上面的评论):
控制器
import { Controller, Get } from '@nestjs/common';
import { TwilioStatusService } from './twilio-status.service';
@Controller('status')
export class TwilioStatusController {
constructor(private readonly twilioStatusService: TwilioStatusService) {}
@Get('twilio')
getTwilioStatus() {
const res = this.twilioStatusService.getTwilioStatus();
return res;
}
}
服务
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { map } from 'rxjs/operators';
@Injectable()
export class TwilioStatusService {
constructor(private httpService: HttpService) {}
getTwilioStatus() {
return this.httpService
.get('https://status.twilio.com/api/v2/status.json')
.pipe(map((response) => response.data.status));
}
}
当然这不是最佳解决方案,因为我必须做这个端点 + 一个单独的端点来检查 MongoDB 的可用性(常规 NestJS 健康检查,使用 Terminus),目标是健康检查将两个端点粘合在一起。
可以将任何 属性 合并到生成的对象中。您可以在 TypeScript Interface
中看到
/**
* The result object of a health indicator
* @publicApi
*/
export declare type HealthIndicatorResult = {
/**
* The key of the health indicator which should be uniqe
*/
[key: string]: {
/**
* The status if the given health indicator was successful or not
*/
status: HealthIndicatorStatus;
/**
* Optional settings of the health indicator result
*/
[optionalKeys: string]: any;
};
};
这是一个例子:
diagnostics/health/healthcheck.controller
import { Controller, Get } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { HttpService } from '@nestjs/axios'
import { HealthCheckService, HealthCheck, HealthIndicatorStatus, HealthCheckError } from '@nestjs/terminus'
@ApiTags('diagnostics')
@Controller('diagnostics/health')
export class HealthController {
constructor(
private health: HealthCheckService,
private httpService: HttpService,
) { }
@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.httpService.get('http://localhost:9002/api/v1/diagnostics/health').toPromise().then(({ statusText, config: { url }, data }) => {
const status: HealthIndicatorStatus = statusText === 'OK' ? 'up' : 'down'
return { 'other-service': { status, url, data } }
}).catch(({ code, config: { url } }) => {
throw new HealthCheckError('Other service check failed', { 'other-service': { status: 'down', code, url } })
}),
])
}
}
diagnostics/diagnostics.module.ts
import { Module } from '@nestjs/common'
import { TerminusModule } from '@nestjs/terminus'
import { HttpModule } from '@nestjs/axios'
import { HealthController } from './health/health.controller'
@Module({
imports: [
HttpModule,
TerminusModule,
],
controllers: [HealthController],
})
export class DiagnosticsModule { }
我正在尝试使用 NestJS 开发一个健康检查端点(我没有这方面的经验)。我要检查的依赖项之一是 Twilio 的 SMS 服务。到目前为止,我发现收集此信息的最佳 URL 是 https://status.twilio.com/api/v2/status.json。这里的问题是我不想仅仅 ping 这个地址,而是收集它的 JSON 响应并呈现它提供的一些信息,即这些:
是否可以使用(或不使用)Terminus 模块?在官方文档中我没有找到任何关于此的内容,只有使用 pingCheck
/ responseCheck
的更简单的示例:https://docs.nestjs.com/recipes/terminus
是的,有可能。
我从来没有用过这个,但是 HttpHealthIndicator
有 responseCheck
方法来检查取决于 API 响应消息。您可以指定一个回调函数来分析来自 API 的响应。回调函数应该 return 布尔值表示 API.
我在文档中找不到这个,但你可以看到它 here。
尽管同时此健康检查的逻辑已更改(因此此问题已过时),但这是我在它发生之前找到的临时解决方案(基本上是使用 axios 的常规端点,如其中之一所指出的那样)上面的评论):
控制器
import { Controller, Get } from '@nestjs/common';
import { TwilioStatusService } from './twilio-status.service';
@Controller('status')
export class TwilioStatusController {
constructor(private readonly twilioStatusService: TwilioStatusService) {}
@Get('twilio')
getTwilioStatus() {
const res = this.twilioStatusService.getTwilioStatus();
return res;
}
}
服务
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { map } from 'rxjs/operators';
@Injectable()
export class TwilioStatusService {
constructor(private httpService: HttpService) {}
getTwilioStatus() {
return this.httpService
.get('https://status.twilio.com/api/v2/status.json')
.pipe(map((response) => response.data.status));
}
}
当然这不是最佳解决方案,因为我必须做这个端点 + 一个单独的端点来检查 MongoDB 的可用性(常规 NestJS 健康检查,使用 Terminus),目标是健康检查将两个端点粘合在一起。
可以将任何 属性 合并到生成的对象中。您可以在 TypeScript Interface
中看到/**
* The result object of a health indicator
* @publicApi
*/
export declare type HealthIndicatorResult = {
/**
* The key of the health indicator which should be uniqe
*/
[key: string]: {
/**
* The status if the given health indicator was successful or not
*/
status: HealthIndicatorStatus;
/**
* Optional settings of the health indicator result
*/
[optionalKeys: string]: any;
};
};
这是一个例子:
diagnostics/health/healthcheck.controller
import { Controller, Get } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { HttpService } from '@nestjs/axios'
import { HealthCheckService, HealthCheck, HealthIndicatorStatus, HealthCheckError } from '@nestjs/terminus'
@ApiTags('diagnostics')
@Controller('diagnostics/health')
export class HealthController {
constructor(
private health: HealthCheckService,
private httpService: HttpService,
) { }
@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.httpService.get('http://localhost:9002/api/v1/diagnostics/health').toPromise().then(({ statusText, config: { url }, data }) => {
const status: HealthIndicatorStatus = statusText === 'OK' ? 'up' : 'down'
return { 'other-service': { status, url, data } }
}).catch(({ code, config: { url } }) => {
throw new HealthCheckError('Other service check failed', { 'other-service': { status: 'down', code, url } })
}),
])
}
}
diagnostics/diagnostics.module.ts
import { Module } from '@nestjs/common'
import { TerminusModule } from '@nestjs/terminus'
import { HttpModule } from '@nestjs/axios'
import { HealthController } from './health/health.controller'
@Module({
imports: [
HttpModule,
TerminusModule,
],
controllers: [HealthController],
})
export class DiagnosticsModule { }