fix: 初验针对修改
This commit is contained in:
@@ -10,6 +10,7 @@ type AuditLog struct {
|
||||
ActorID string `gorm:"size:128;index" json:"actor_id"`
|
||||
ActorName string `gorm:"size:128" json:"actor_name"`
|
||||
Action string `gorm:"size:128;index" json:"action"`
|
||||
LogCategory string `gorm:"size:16;index" json:"log_category"`
|
||||
ObjectType string `gorm:"size:128;index" json:"object_type"`
|
||||
ObjectID string `gorm:"size:128;index" json:"object_id"`
|
||||
OperationRisk string `gorm:"size:32;index" json:"operation_risk"`
|
||||
|
||||
@@ -30,6 +30,11 @@ type LogEvent struct {
|
||||
ResourceID string `gorm:"size:128;index" json:"resource_id"`
|
||||
// ResourceName 表示关联到的资源名称。
|
||||
ResourceName string `gorm:"size:256" json:"resource_name"`
|
||||
// BusinessSystemID 关联业务系统。
|
||||
BusinessSystemID *uint `gorm:"index" json:"business_system_id,omitempty"`
|
||||
// TraceID 和 SpanID 用于从日志定位调用链。
|
||||
TraceID string `gorm:"size:32;index" json:"trace_id,omitempty"`
|
||||
SpanID string `gorm:"size:16;index" json:"span_id,omitempty"`
|
||||
// MatchMethod 表示资源命中方式(ip/hostname/none)。
|
||||
MatchMethod string `gorm:"size:32" json:"match_method"`
|
||||
// DispatchStatus 表示告警分发状态(not_applicable/pending/retrying/sent/dead)。
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
func GetAllModels() []interface{} {
|
||||
return []interface{}{
|
||||
&LogEvent{},
|
||||
&TraceSpan{},
|
||||
&AlertOutbox{},
|
||||
&ResourceMapping{},
|
||||
&ResourceEventDedup{},
|
||||
|
||||
53
internal/models/schema_version.go
Normal file
53
internal/models/schema_version.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const requiredSchemaScript = "0001_baseline.up.sql"
|
||||
|
||||
var requiredSchema = struct {
|
||||
checksum string
|
||||
tables []string
|
||||
}{
|
||||
checksum: "092328c2cbd4e6316ae0e7fe2dd0f986ba30daf712945b8fa14be7f54c01f286",
|
||||
tables: []string{"logs_events", "logs_syslog_rules", "logs_trap_rules", "logs_trace_spans"},
|
||||
}
|
||||
|
||||
// RequireSchemaVersion 确认当前数据库已经由受控迁移脚本初始化。
|
||||
func RequireSchemaVersion(db *gorm.DB, service string) error {
|
||||
if db == nil {
|
||||
return fmt.Errorf("%s 数据库连接未初始化", service)
|
||||
}
|
||||
|
||||
var count int64
|
||||
err := db.Raw(`
|
||||
SELECT COUNT(*)
|
||||
FROM public.ops_schema_migrations
|
||||
WHERE service = ? AND script_name = ? AND checksum = ? AND status = 'success'`,
|
||||
service, requiredSchemaScript, requiredSchema.checksum).Scan(&count).Error
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s 数据库版本检查失败,请先执行 migrate-all.sh up --service %s: %w", service, service, err)
|
||||
}
|
||||
if count != 1 {
|
||||
return fmt.Errorf("%s 数据库迁移版本不匹配,请执行 migrate-all.sh status --service %s", service, service)
|
||||
}
|
||||
|
||||
for _, table := range requiredSchema.tables {
|
||||
var valid bool
|
||||
err = db.Raw(`
|
||||
SELECT to_regclass(?) IS NOT NULL AND EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint c
|
||||
JOIN pg_class t ON t.oid = c.conrelid
|
||||
JOIN pg_namespace n ON n.oid = t.relnamespace
|
||||
WHERE n.nspname = 'public' AND t.relname = ? AND c.contype = 'p'
|
||||
)`, "public."+table, table).Scan(&valid).Error
|
||||
if err != nil || !valid {
|
||||
return fmt.Errorf("%s 数据库关键表结构不完整:%s", service, table)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
31
internal/models/trace_span.go
Normal file
31
internal/models/trace_span.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// TraceSpan 保存通过 OTLP 接收的标准调用链 Span。
|
||||
type TraceSpan struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
TraceID string `gorm:"type:varchar(32);not null;index;uniqueIndex:uk_trace_span" json:"trace_id"`
|
||||
SpanID string `gorm:"type:varchar(16);not null;uniqueIndex:uk_trace_span" json:"span_id"`
|
||||
ParentSpanID string `gorm:"type:varchar(16);index" json:"parent_span_id,omitempty"`
|
||||
ServiceName string `gorm:"type:varchar(255);not null;index" json:"service_name"`
|
||||
OperationName string `gorm:"type:varchar(512);not null;index" json:"operation_name"`
|
||||
SpanKind string `gorm:"type:varchar(20);not null;index" json:"span_kind"`
|
||||
StartTime time.Time `gorm:"not null;index" json:"start_time"`
|
||||
EndTime time.Time `gorm:"not null;index" json:"end_time"`
|
||||
DurationMs float64 `gorm:"type:decimal(16,3);not null;default:0" json:"duration_ms"`
|
||||
StatusCode string `gorm:"type:varchar(20);not null;index" json:"status_code"`
|
||||
StatusMessage string `gorm:"type:text" json:"status_message,omitempty"`
|
||||
BusinessSystemID *uint `gorm:"index" json:"business_system_id,omitempty"`
|
||||
ResourceUID string `gorm:"type:varchar(255);index" json:"resource_uid,omitempty"`
|
||||
HTTPMethod string `gorm:"type:varchar(16);index" json:"http_method,omitempty"`
|
||||
HTTPRoute string `gorm:"type:varchar(1024)" json:"http_route,omitempty"`
|
||||
HTTPStatusCode int `gorm:"index" json:"http_status_code,omitempty"`
|
||||
Attributes string `gorm:"type:jsonb;not null;default:'{}'" json:"attributes"`
|
||||
ResourceAttrs string `gorm:"type:jsonb;not null;default:'{}'" json:"resource_attributes"`
|
||||
IngestedAt *time.Time `gorm:"index" json:"ingested_at,omitempty"`
|
||||
}
|
||||
|
||||
func (TraceSpan) TableName() string { return "logs_trace_spans" }
|
||||
Reference in New Issue
Block a user