Skip to content

Commit

Permalink
feat: 健康检查
Browse files Browse the repository at this point in the history
  • Loading branch information
haiweilian committed Dec 4, 2024
1 parent 51704b6 commit 2c02679
Show file tree
Hide file tree
Showing 7 changed files with 14,126 additions and 11,193 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
},
"dependencies": {
"@nestjs-modules/ioredis": "^2.0.2",
"@nestjs/axios": "^3.1.2",
"@nestjs/bull": "^10.2.2",
"@nestjs/common": "^10.4.8",
"@nestjs/core": "^10.4.8",
"@nestjs/mapped-types": "^2.0.6",
"@nestjs/platform-express": "^10.4.8",
"@nestjs/swagger": "^8.0.7",
"@nestjs/terminus": "^10.2.3",
"@nestjs/typeorm": "^10.0.2",
"@vivy-common/config": "workspace:*",
"@vivy-common/core": "workspace:*",
Expand All @@ -40,6 +42,7 @@
"@vivy-common/mybatis": "workspace:*",
"@vivy-common/security": "workspace:*",
"@vivy-common/swagger": "workspace:*",
"axios": "^1.7.7",
"bull": "^4.16.4",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
Expand Down
25,171 changes: 13,978 additions & 11,193 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions vivy-modules/vivy-system/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { CommonModule } from './common/common.module'
import { AuthModule } from './modules/auth/auth.module'
import { FileModule } from './modules/file/file.module'
import { GenModule } from './modules/gen/gen.module'
import { HealthModule } from './modules/health/health.module'
import { MonitorModule } from './modules/monitor/monitor.module'
import { SystemModule } from './modules/system/system.module'

Expand Down Expand Up @@ -77,6 +78,7 @@ import { SystemModule } from './modules/system/system.module'
GenModule,
FileModule,
AuthModule,
HealthModule,
SystemModule,
MonitorModule,
],
Expand Down
40 changes: 40 additions & 0 deletions vivy-modules/vivy-system/src/modules/health/health.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Controller, Get, ServiceUnavailableException } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import { HealthCheckService, HealthCheck, HealthCheckResult } from '@nestjs/terminus'
import { Public } from '@vivy-common/security'
import { HealthService } from './health.service'

/**
* 健康检查
* @author vivy
*/
@ApiTags('健康检查')
@Controller('health')
export class HealthController {
constructor(
private health: HealthCheckService,
private healthService: HealthService
) {}

/**
* 健康检查
*/
@Get()
@Public()
@HealthCheck()
async check(): Promise<HealthCheckResult> {
try {
return await this.health.check([
() => this.healthService.checkNetwork(),
() => this.healthService.checkMysql(),
() => this.healthService.checkRedis(),
() => this.healthService.checkDisk(),
() => this.healthService.checkMemoryHeap(),
() => this.healthService.checkMemoryRSS(),
])
} catch (error) {
// TODO: send email to the admin
return (error as ServiceUnavailableException).getResponse() as HealthCheckResult
}
}
}
13 changes: 13 additions & 0 deletions vivy-modules/vivy-system/src/modules/health/health.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { HttpModule } from '@nestjs/axios'
import { Module } from '@nestjs/common'
import { TerminusModule } from '@nestjs/terminus'
import { HealthController } from './health.controller'
import { HealthService } from './health.service'
import { RedisHealthIndicator } from './indicators/redis.health'

@Module({
imports: [TerminusModule, HttpModule],
controllers: [HealthController],
providers: [HealthService, RedisHealthIndicator],
})
export class HealthModule {}
64 changes: 64 additions & 0 deletions vivy-modules/vivy-system/src/modules/health/health.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Injectable } from '@nestjs/common'
import {
DiskHealthIndicator,
HttpHealthIndicator,
MemoryHealthIndicator,
TypeOrmHealthIndicator,
} from '@nestjs/terminus'
import { RedisHealthIndicator } from './indicators/redis.health'

@Injectable()
export class HealthService {
constructor(
private http: HttpHealthIndicator,
private db: TypeOrmHealthIndicator,
private memory: MemoryHealthIndicator,
private disk: DiskHealthIndicator,
private redis: RedisHealthIndicator
) {}

/**
* 检查网络连接
*/
async checkNetwork() {
return this.http.pingCheck('vivy', 'http://43.140.221.180:8000/')
}

/**
* 检查 MySQL 连接
*/
async checkMysql() {
return this.db.pingCheck('mysql')
}

/**
* 检查 Redis 连接
*/
async checkRedis() {
return this.redis.pingCheck('redis')
}

/**
* 检查磁盘使用情况
*/
async checkDisk() {
return this.disk.checkStorage('disk', {
path: '/',
thresholdPercent: 0.8,
})
}

/**
* 检查进程的内存堆使用情况
*/
async checkMemoryHeap() {
return this.memory.checkHeap('memory-heap', 200 * 1024 * 1024)
}

/**
* 检查进程的内存使用情况 (RSS)
*/
async checkMemoryRSS() {
return this.memory.checkRSS('memory-rss', 200 * 1024 * 1024)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common'
import { HealthIndicator, HealthIndicatorResult, HealthCheckError } from '@nestjs/terminus'
import { InjectRedis } from '@nestjs-modules/ioredis'
import Redis from 'ioredis'

@Injectable()
export class RedisHealthIndicator extends HealthIndicator {
constructor(
@InjectRedis()
private redis: Redis
) {
super()
}

async pingCheck(key: string): Promise<HealthIndicatorResult> {
try {
const result = await this.redis.ping()
if (result !== 'PONG') {
throw new Error('Invalid PING response')
}
return this.getStatus(key, true)
} catch (error) {
throw new HealthCheckError('Redis check failed', this.getStatus(key, false, { error: error.message }))
}
}
}

0 comments on commit 2c02679

Please sign in to comment.