feat(platform): expose vehicle service runtime health

This commit is contained in:
lingniu
2026-07-04 01:02:07 +08:00
parent 377cfcdfca
commit 3e76210d7d
6 changed files with 53 additions and 6 deletions

View File

@@ -37,7 +37,9 @@ func NewServer(cfg config.Config) http.Handler {
log.Printf("production mysql store enabled")
}
}
api := platform.NewHandler(platform.NewService(store))
api := platform.NewHandler(platform.NewServiceWithRuntime(store, platform.RuntimeInfo{
RequestTimeoutMs: int(cfg.RequestTimeout / time.Millisecond),
}))
return withRequestTimeout(static.Handler(cfg.StaticDir, api), cfg.RequestTimeout)
}

View File

@@ -195,6 +195,25 @@ func TestHandlerHistoryMileageQualityOps(t *testing.T) {
}
}
func TestHandlerOpsHealthIncludesVehicleServiceRuntime(t *testing.T) {
handler := NewHandler(NewServiceWithRuntime(NewMockStore(), RuntimeInfo{RequestTimeoutMs: 1500}))
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/ops/health", nil)
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
}
var body struct {
Data OpsHealth `json:"data"`
}
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatalf("response JSON should decode: %v body=%s", err, rec.Body.String())
}
if body.Data.Runtime.RequestTimeoutMs != 1500 {
t.Fatalf("ops health should include request timeout runtime, got %+v body=%s", body.Data.Runtime, rec.Body.String())
}
}
func TestHandlerVehicleDataAPIsResolveVehicleKeyword(t *testing.T) {
handler := NewHandler(NewService(NewMockStore()))
cases := []struct {

View File

@@ -184,4 +184,9 @@ type OpsHealth struct {
RedisOnlineKeys *int `json:"redisOnlineKeys"`
TDengineWritable bool `json:"tdengineWritable"`
MySQLWritable bool `json:"mysqlWritable"`
Runtime RuntimeInfo `json:"runtime"`
}
type RuntimeInfo struct {
RequestTimeoutMs int `json:"requestTimeoutMs"`
}

View File

@@ -36,13 +36,18 @@ type RawFrameQuery struct {
}
type Service struct {
store Store
store Store
runtime RuntimeInfo
}
func NewService(store Store) *Service {
return &Service{store: store}
}
func NewServiceWithRuntime(store Store, runtime RuntimeInfo) *Service {
return &Service{store: store, runtime: runtime}
}
func (s *Service) DashboardSummary(ctx context.Context) (DashboardSummary, error) {
return s.store.DashboardSummary(ctx)
}
@@ -282,7 +287,12 @@ func (s *Service) QualityIssues(ctx context.Context, query url.Values) (Page[Qua
}
func (s *Service) OpsHealth(ctx context.Context) (OpsHealth, error) {
return s.store.OpsHealth(ctx)
health, err := s.store.OpsHealth(ctx)
if err != nil {
return OpsHealth{}, err
}
health.Runtime = s.runtime
return health, nil
}
func (s *Service) resolveVehicleQuery(ctx context.Context, query url.Values) (url.Values, error) {

View File

@@ -174,6 +174,11 @@ export interface OpsHealth {
redisOnlineKeys: number | null;
tdengineWritable: boolean;
mysqlWritable: boolean;
runtime: RuntimeInfo;
}
export interface RuntimeInfo {
requestTimeoutMs: number;
}
export interface Page<T> {

View File

@@ -20,6 +20,11 @@ function storageReadStatus(health: OpsHealth | null) {
return health?.tdengineWritable && health.mysqlWritable ? 'ok' : 'error';
}
function formatRequestTimeout(health: OpsHealth | null) {
const value = health?.runtime?.requestTimeoutMs;
return value == null || value <= 0 ? '未限制' : `${value.toLocaleString()} ms`;
}
const emptySummary: QualitySummary = {
issueVehicleCount: 0,
issueRecordCount: 0,
@@ -125,9 +130,10 @@ export function Quality({
))}
</div>
<Row gutter={16}>
<Col span={8}><Card bordered title="Kafka Lag">{formatLag(health?.kafkaLag)}</Card></Col>
<Col span={8}><Card bordered title="Redis 在线 Key">{formatLag(health?.redisOnlineKeys)}</Card></Col>
<Col span={8}>
<Col span={6}><Card bordered title="Kafka Lag">{formatLag(health?.kafkaLag)}</Card></Col>
<Col span={6}><Card bordered title="Redis 在线 Key">{formatLag(health?.redisOnlineKeys)}</Card></Col>
<Col span={6}><Card bordered title="BFF 请求超时">{formatRequestTimeout(health)}</Card></Col>
<Col span={6}>
<Card bordered title="存储读取">
<Tag color={statusColor[storageReadStatus(health)]}>{storageReadStatus(health) === 'ok' ? '正常' : '异常'}</Tag>
</Card>